You are browsing as a guest. Sign up (or log in) to start making projects!

Mokila

@Mokila

Joined June 11th, 2026

  • 4Devlogs
  • 3Projects
  • 1Ships
  • 0Votes
Ship

I created a simple operating system with HTML, CSS, and Javascript that runs on you web browser. It has a nostalgic look and feel with old-styled buttons and looks. To make it more like an OS, a calculator and a notepad have been created and implemented in the app. Moreover, to allow the user to personalise as much as they want, many settings have been included, from custom wallpapers to wallpapers that come from NASA itself and more.

This was my first large scale project that I have coded so it's an interesting experience for me. Before this, I only used to do challenges on platforms like Codewars and other than some small side projects, I don't have a practical experience. Therefore, i think this project has taught me a lot on how to built stuff yourself.

I hope you like my project :)

Try project → See source code →
Open comments for this post

39m 33s logged

Devlog #3: Onboarding and Eliminating FOUC

Before shipping the WebOS 1 project and moving on to WebOS 2 project, I needed to implement an Onboarding/Welcome Screen to introduce users to the OS environment. This required a full-screen dark overlay.

this is what i did:

  1. Z-index mismatch
    Because my custom Drag Engine automatically increments the zIndex of any .window it touches, the moment I clicked the Welcome Screen, the engine overwrote its god-tier Z-Index (99999). This caused an immediate Z-Index collapse, burying the modal underneath the desktop icons and the dark overlay.
    The Fix: I had to implement a strict exception in the JavaScript mousedown event listener to protect the Welcome Screen’s ID from being overwritten.
    DOM Reordering: To guarantee that the Welcome Screen will be at the very top,, I moved the Welcome Screen to the absolute bottom of the document. This means it will naturally sit on top of the other elements.

  2. Eliminating the FOUC
    I used the localStorage API so users could check a “Don’t show this again” box, saving their preference to the hard drive. However, this caused a massive FOUC bug.
    The Problem: HTML renders faster than JavaScript executes. On boot, the browser would instantly paint the Welcome Screen to the monitor. A few milliseconds later, JavaScript would read the hard drive, realize the user disabled the screen, and violently delete it—causing an ugly flicker.
    Fix: I basically just inverted the rendering logic. I hardcoded ‘display: none;’ directly into the HTML so the modal is completely invisible by default. Now, the browser paints nothing. JavaScript checks the hard drive, and only turns the welcome screen on if it confirms the user actually wants to see it. Now it’s much better.

Ig this is the end of my WebOS 1 project. I will be shipping this project and then moving on to WebOS 2 where I’ll be implementing File Management, In-browser-browser?, and maybe some other built in tools. That’s the plan for now.

Devlog #3: Onboarding and Eliminating FOUC

Before shipping the WebOS 1 project and moving on to WebOS 2 project, I needed to implement an Onboarding/Welcome Screen to introduce users to the OS environment. This required a full-screen dark overlay.

this is what i did:

  1. Z-index mismatch
    Because my custom Drag Engine automatically increments the zIndex of any .window it touches, the moment I clicked the Welcome Screen, the engine overwrote its god-tier Z-Index (99999). This caused an immediate Z-Index collapse, burying the modal underneath the desktop icons and the dark overlay.
    The Fix: I had to implement a strict exception in the JavaScript mousedown event listener to protect the Welcome Screen’s ID from being overwritten.
    DOM Reordering: To guarantee that the Welcome Screen will be at the very top,, I moved the Welcome Screen to the absolute bottom of the document. This means it will naturally sit on top of the other elements.

  2. Eliminating the FOUC
    I used the localStorage API so users could check a “Don’t show this again” box, saving their preference to the hard drive. However, this caused a massive FOUC bug.
    The Problem: HTML renders faster than JavaScript executes. On boot, the browser would instantly paint the Welcome Screen to the monitor. A few milliseconds later, JavaScript would read the hard drive, realize the user disabled the screen, and violently delete it—causing an ugly flicker.
    Fix: I basically just inverted the rendering logic. I hardcoded ‘display: none;’ directly into the HTML so the modal is completely invisible by default. Now, the browser paints nothing. JavaScript checks the hard drive, and only turns the welcome screen on if it confirms the user actually wants to see it. Now it’s much better.

Ig this is the end of my WebOS 1 project. I will be shipping this project and then moving on to WebOS 2 where I’ll be implementing File Management, In-browser-browser?, and maybe some other built in tools. That’s the plan for now.

Replying to @Mokila

0
5
Open comments for this post

40m 56s logged

Devlog #2: Debugging + Icon dragging features + localStorage implementation

The core window manager is working properly so this second session was all about polishing the UI and UX aspects. But there were some challenges:

  1. The faulty dragging
    I transitioned the desktop icons from a static flexbox grid to absolute positioning so they could be freely dragged around the screen (like an actual operating system). However, this immediately triggered native browser collisions.

The Problem: When clicking and dragging an icon, the browser saw the action as trying to highlight text or drag an image to a new tab. This triggered a native HTML “ghost drag,” completely overriding my custom JavaScript drag engine and leaving the icon permanently stuck to the cursor.

The Solution: I just basically implemented multiple stuff to solve this:

  1. Applied ‘-webkit-user-select: none’ and ‘user-select: none’ to prevent highlighting.

  2. Injected ‘draggable=“false”’ natively into the HTML.

  3. Applied ‘pointer-events: none’ on the inner emoji and label text. This forces the mouse click to pass through the text and hit the icon container directly, ensuring my custom e.preventDefault() mousedown event works properly every time.

  4. State Persistence (The Local Storage API)
    An OS is useless if it resets every time you turn it on. I wired up the browser’s native localStorage API so it saves some of the stuff that the user did. So far it’s only the position of the icons, but I’m planning to add more stuff to the localStorage. Here are the changes:

Upgraded the mouseup event listener to capture the exact X and Y coordinates of an icon the moment it is let go after dragging.

Built a boot sequence that loops through .desktop-icon elements on page load, fetches their saved coordinates , and implementes them.

  1. Wallpaper changing bug

The NASA API integration was fetching data successfully, but massive high-res images were causing visual lag, leading to a blank blue screen while the image downloaded in the background.

Made a new thing where the newImage() is inserted into the virtual memory of the js.

The UI now triggers a document.body.style.cursor = ‘wait’ loading wheel and displays a “Downloading…” status.

JavaScript intentionally halts the DOM update until the virtual image’s ‘.onload’ event fires, ensuring the wallpaper only gets applied to the screen exactly when it is 100% ready.

Lastly, I also added a setting in the settings tab where the user can choose if the icon labels are hidded or shown.

What’s Next?
The desktop environment is now completely stable, personalized, and persistent. Next up: More UI and UX refinements before shipping for WebOS 1. Gonna implement File Management for WebOS 2 :)

Devlog #2: Debugging + Icon dragging features + localStorage implementation

The core window manager is working properly so this second session was all about polishing the UI and UX aspects. But there were some challenges:

  1. The faulty dragging
    I transitioned the desktop icons from a static flexbox grid to absolute positioning so they could be freely dragged around the screen (like an actual operating system). However, this immediately triggered native browser collisions.

The Problem: When clicking and dragging an icon, the browser saw the action as trying to highlight text or drag an image to a new tab. This triggered a native HTML “ghost drag,” completely overriding my custom JavaScript drag engine and leaving the icon permanently stuck to the cursor.

The Solution: I just basically implemented multiple stuff to solve this:

  1. Applied ‘-webkit-user-select: none’ and ‘user-select: none’ to prevent highlighting.

  2. Injected ‘draggable=“false”’ natively into the HTML.

  3. Applied ‘pointer-events: none’ on the inner emoji and label text. This forces the mouse click to pass through the text and hit the icon container directly, ensuring my custom e.preventDefault() mousedown event works properly every time.

  4. State Persistence (The Local Storage API)
    An OS is useless if it resets every time you turn it on. I wired up the browser’s native localStorage API so it saves some of the stuff that the user did. So far it’s only the position of the icons, but I’m planning to add more stuff to the localStorage. Here are the changes:

Upgraded the mouseup event listener to capture the exact X and Y coordinates of an icon the moment it is let go after dragging.

Built a boot sequence that loops through .desktop-icon elements on page load, fetches their saved coordinates , and implementes them.

  1. Wallpaper changing bug

The NASA API integration was fetching data successfully, but massive high-res images were causing visual lag, leading to a blank blue screen while the image downloaded in the background.

Made a new thing where the newImage() is inserted into the virtual memory of the js.

The UI now triggers a document.body.style.cursor = ‘wait’ loading wheel and displays a “Downloading…” status.

JavaScript intentionally halts the DOM update until the virtual image’s ‘.onload’ event fires, ensuring the wallpaper only gets applied to the screen exactly when it is 100% ready.

Lastly, I also added a setting in the settings tab where the user can choose if the icon labels are hidded or shown.

What’s Next?
The desktop environment is now completely stable, personalized, and persistent. Next up: More UI and UX refinements before shipping for WebOS 1. Gonna implement File Management for WebOS 2 :)

Replying to @Mokila

0
1
Open comments for this post

4h 59m 46s logged

Devlog #1: Booting Up - Building a Custom Window Manager & Desktop Environment from Scratch

Today marks the official first boot of my WebOS project. I’ve had coding experiences before but not to this extent. I’ve never gone outside of challenges on stuff like Codewars and aside from some small side projects, I’ve never actually built a big project like I am now, so this’ll be a new experience.

I’m trying to build a full OS that runs in the Web Browser directly using HTML, CSS, and Vanilla JavaScript. It acts like an actual operating system, like windows for example, but the only difference is the way it looks, it’s identity and that it runs in your web browser.

Over the past few hours, I changed the project from a static layout into a fully interactive environment. Here is a breakdown of the core engine and features that I currently built.

  1. The Custom Window Manager
    The hardest part of making an OS is handling window states. I built a universal Drag-and-Drop engine with dynamic Z-Index management.

The Problem: Windows would get stuck behind each other, or the browser would lose track of the mouse if the user dragged too fast or threw the window off-screen, so i wouldn’t be able to drag it back.

The Solution: I implemented an event elegation system attached to the document root, calculating mouse offsets relative to the title bars. This means wherever the mouse moves, the title bars move to keep that offset difference the same, which is essentially what the drag and drop function is. I also engineered physical constraints so windows can never be dragged out of the viewport.

  1. The Desktop Environment
    To not make seem like this is just a website, I completely changed the browser’s default behavior.
    I Implemented double-click event listeners for desktop icons and then overrode the native browser right-click menu (e.preventDefault()) and built a custom OS context menu this makes it feel more unique.

  2. Core Applications
    Notepad: A fully resizable text editor using CSS flexbox so the typing area automatically expands with the window.
    Calculator: Quite self-explanatory. Engineered the math logic from scratch.

Settings (NASA API): Built a customization menu that toggles a global 12hr/24hr clock state, and fetches real-time data from NASA’s APOD API to dynamically change the desktop wallpaper based on the NASA Picture of the Day.

What’s Next?
The UI feels like an OS, but it lacks permanence. Next on the roadmap: File Management. I’ll be engineering a system to actually save the data typed into the Notepad so it survives page refreshes. Also, I want to create a web browser with actual internet access to really bring that OS feeling. That’s all I have planned out.

p.s. I’ve attached some pictures of my website below - hope you like it :)

Stay tuned.

Devlog #1: Booting Up - Building a Custom Window Manager & Desktop Environment from Scratch

Today marks the official first boot of my WebOS project. I’ve had coding experiences before but not to this extent. I’ve never gone outside of challenges on stuff like Codewars and aside from some small side projects, I’ve never actually built a big project like I am now, so this’ll be a new experience.

I’m trying to build a full OS that runs in the Web Browser directly using HTML, CSS, and Vanilla JavaScript. It acts like an actual operating system, like windows for example, but the only difference is the way it looks, it’s identity and that it runs in your web browser.

Over the past few hours, I changed the project from a static layout into a fully interactive environment. Here is a breakdown of the core engine and features that I currently built.

  1. The Custom Window Manager
    The hardest part of making an OS is handling window states. I built a universal Drag-and-Drop engine with dynamic Z-Index management.

The Problem: Windows would get stuck behind each other, or the browser would lose track of the mouse if the user dragged too fast or threw the window off-screen, so i wouldn’t be able to drag it back.

The Solution: I implemented an event elegation system attached to the document root, calculating mouse offsets relative to the title bars. This means wherever the mouse moves, the title bars move to keep that offset difference the same, which is essentially what the drag and drop function is. I also engineered physical constraints so windows can never be dragged out of the viewport.

  1. The Desktop Environment
    To not make seem like this is just a website, I completely changed the browser’s default behavior.
    I Implemented double-click event listeners for desktop icons and then overrode the native browser right-click menu (e.preventDefault()) and built a custom OS context menu this makes it feel more unique.

  2. Core Applications
    Notepad: A fully resizable text editor using CSS flexbox so the typing area automatically expands with the window.
    Calculator: Quite self-explanatory. Engineered the math logic from scratch.

Settings (NASA API): Built a customization menu that toggles a global 12hr/24hr clock state, and fetches real-time data from NASA’s APOD API to dynamically change the desktop wallpaper based on the NASA Picture of the Day.

What’s Next?
The UI feels like an OS, but it lacks permanence. Next on the roadmap: File Management. I’ll be engineering a system to actually save the data typed into the Notepad so it survives page refreshes. Also, I want to create a web browser with actual internet access to really bring that OS feeling. That’s all I have planned out.

p.s. I’ve attached some pictures of my website below - hope you like it :)

Stay tuned.

Replying to @Mokila

0
1

Followers

Loading…