Choco Pie OS: a Browser-Based Operating System

by Mayur-Pagote in Design > Software

153 Views, 1 Favorites, 0 Comments

Choco Pie OS: a Browser-Based Operating System

BootIntro.gif
NeonRush-Intro.gif
IntroSpiral-Intro.gif
PiMandalaAction-Intro.gif
Canva Thumbnail.png
Canva Thumbnail (1).png

I’ve always loved Choco Pies, they’ve been my favorite snack for years. When I was around 15 or 16, I would easily choose a Choco Pie over anything else.

But my journey with “Pi” actually started earlier.

At around 13, I discovered the Raspberry Pi. The idea of a tiny, affordable computer capable of doing so much completely fascinated me. However, at that time, it cost around ₹3500–₹5000, which might not seem like much to some, but for me, it was expensive. I always wanted to get my hands on one, but I couldn’t.

Even before that, back in 6th grade, I was introduced to mathematical π (3.14…). To be honest, I didn’t enjoy math much, and working with π always felt difficult and abstract.

So over time, I had three very different experiences with “Pi”:

  1. Choco Pie — something I loved
  2. Raspberry Pi — something I was curious about but couldn’t access
  3. Mathematical π — something I struggled with

Few weeks ago I came across the All Things Pi Contest on Instructables.

That’s when everything clicked.

I decided to create something meaningful, a project that brings together all the “Pi” influences in my life. Not just something simple or conventional, but something unexpected… something people could explore, learn from, and enjoy.

So, Instead of building a regular website, I asked myself:

Why not build an entire operating system inside the browser?

An OS that: Feels like a real desktop environment, requires little to no technical knowledge to use, helps people understand how operating systems work, is enjoyable for everyone, from kids to students to curious learners

So Introducing you Choco Pie OS

Choco Pie OS is a browser-based operating system where: The UI is inspired by Raspberry Pi OS, where the theme carries the flavor of Choco Pie, and the core experience revolves around mathematical π through interactive apps and activities

It’s a system where you don’t just learn about π—you explore it, visualize it, and interact with it.


You can try Choco Pie OS directly in your browser: https://choco-pie-os.vercel.app/


This project is my way of turning something I once found difficult and inaccessible into something fun, creative, and open for everyone.

Supplies

Before writing a single line of code you need a few things installed on your computer. Think of these as the ingredients you gather before cooking.

Node.js (version 18 or newer)

Node.js is the engine that runs JavaScript on your computer — outside of a browser. You can download it from nodejs.org. Once installed, you get a tool called npm (Node Package Manager) that lets you install other tools and libraries.

A Code Editor

Visual Studio Code is the most popular free option (code.visualstudio.com). It highlights your code with colours, spots mistakes, and makes navigating files easy.

A Web Browser

Any modern browser works — Chrome, Firefox, or Edge. This is where your OS will run.

The Project Files

Unzip the Choco Pie OS Project folder to a location you can find easily — for example, your Desktop. Open that folder in VS Code.

Install Dependencies

Open a terminal (or VS Code's built-in terminal with Ctrl + `) and run the following command inside the project folder. This downloads all the third-party libraries the project needs.

npm install

Once that finishes, start the development server:

npm run dev

Now open your browser and visit http://localhost:3000 — you should see the Choco Pie boot screen. Congratulations, the project is alive!


The most important thing is to have a PC or laptop (Even Raspberry Pi can be used) and an internet connection.

Deciding the Goals

I defined a clear vision for what I wanted Choco Pie OS to become. Instead of building just another project, I wanted to create something that felt like a complete system.

Main Goals

  1. Build a full operating system inside the browser (React + Next.js)
  2. Implement a window manager with real-time state handling
  3. Create VS Code Lite to run Python, C, and C++ in-browser
  4. Develop Pi-based apps (simulations, art, music, exploration)
  5. Add a Game Center with multiple games
  6. Design a modular app architecture (easy to extend and scale)

What will make this unique?

Here the Choco Pie OS will be a complete platform that combines:

  1. Operating system design
  2. Education
  3. Creativity
  4. Entertainment

All within a single browser-based environment.

Building Base OS Design

Screenshot 2026-04-12 195004.png
Screenshot 2026-04-12 195616.png

Every operating system has a visual identity — a set of consistent colours, fonts, and sizing rules that make the whole thing feel like one coherent product. In Choco Pie OS, all of that identity lives in a single CSS file called globals.css, backed by a theme engine that supports both light and dark modes. This step explains how that design system was built and why it works the way it does.

Think of CSS variables like a paint palette. Instead of writing a specific colour (like #1E3A5F) in fifty different places, you write it once with a name — and then reference that name everywhere. If you ever want to change the colour, you only change it in one place and the entire OS updates instantly.

The CSS Variable System

The file app/globals.css defines the entire design language using CSS custom properties (variables). Here is a small excerpt showing how the light theme colours are structured:

:root {
--wallpaper-accent: #d7566f;
--desktop-font: "Nunito Sans", "Segoe UI", Arial, sans-serif;
--desktop-shell-bg: #111827;
--panel-fill: #f4f4f4;
--window-fill: rgba(246, 248, 251, 0.82);
--window-shadow: 0 26px 60px rgba(12, 20, 32, 0.26);
--window-title-active-bg: linear-gradient(
180deg,
rgba(255, 255, 255, 0.96),
rgba(246, 248, 252, 0.88)
);
}

The :root selector means these variables are available everywhere on the page. Notice how window-fill uses rgba with a slight transparency (0.82 opacity) — this gives the windows a frosted-glass look reminiscent of modern desktop environments.

The Dark Theme Override

The dark mode works by adding a data-os-theme attribute to the HTML element. The CSS then overrides only the variables that change — every other part of the design inherits automatically:

html[data-os-theme="dark"] {
--panel-fill: rgba(17, 24, 39, 0.92);
--window-fill: rgba(17, 24, 39, 0.9);
--window-title-active-bg: linear-gradient(
180deg,
rgba(30, 41, 59, 0.98),
rgba(15, 23, 42, 0.92)
);
--desktop-panel-text: #eef3ff;
}

The JavaScript side of this is handled in the desktop.tsx component, which watches the desktopTheme value from the global OS store and applies it like this:

useEffect(() => {
document.documentElement.setAttribute("data-os-theme", desktopTheme);
}, [desktopTheme]);

Boot Animation

When the OS first loads it shows a brief boot screen — a touch of realism. The BootScreen component fades in with a spinner and the Choco Pie logo, then disappears after 2.2 seconds, triggering a welcome notification. The duration is controlled by a single constant at the top of desktop.tsx:

const BOOT_DURATION_MS = 2200;

useEffect(() => {
const timer = window.setTimeout(() => {
setBooted(true);
pushNotification("Welcome", "Choco Pie desktop is ready.");
}, BOOT_DURATION_MS);

return () => window.clearTimeout(timer);
}, [booted]);


The wallpaper accent colour (--wallpaper-accent) is also updated dynamically whenever the user changes the wallpaper, so button highlights and active states automatically match the current background.


Note: I forgot to take the initial image of the OS, so the second image is actually of the completed OS design.

Building the Terminal

terminal1.gif
Screenshot 2026-04-12 202043.png

The Terminal is one of the most recognisable apps in any OS. In Choco Pie OS it is a visual simulation of a real Linux terminal — it looks and feels authentic (dark background, green text, bash prompt) but runs entirely in the browser with no real shell behind it. For a Pi-themed OS this is perfect: it echoes the feel of SSH-ing into a Raspberry Pi.

The key insight here is that the terminal does not need to be real to be fun and educational. A carefully curated set of fake commands creates the illusion of a working system while staying completely safe and self-contained.

The Boot Lines

When the terminal opens, it immediately prints three startup lines, just like a real Linux machine would:

const BOOT_LINES = [
"Linux chocopie 6.12.0-v8+ #1 SMP PREEMPT Debian GNU/Linux",
"Welcome to the Choco Pie OS desktop mock.",
"Type 'help' to see available demo commands.",
];

The kernel version (6.12.0-v8+) is intentionally formatted to look like a real ARM Linux build — the v8+ suffix is a genuine naming convention for 64-bit Raspberry Pi kernels.

Command Handling

Each command is matched with a simple if/else chain inside the runCommand function. Here is how a few of the more interesting ones work:

if (normalized === "neofetch") {
return [
"OS: Choco Pie OS (Web UI)",
"Kernel: 6.12.0-v8+",
"Shell: bash",
"Desktop: Choco Pie Light",
"Theme: Sunrise",
];
}

if (normalized.startsWith("sudo apt")) {
return [
"E: Unable to locate package imagination",
"This terminal is a visual mock, not a real shell.",
];
}

The sudo apt response is a clever Easter egg — it echoes the real Linux apt error format but gently reminds the user that this is a simulation. For any completely unknown command, the terminal mimics bash's standard error:

return [`bash: ${command}:
command not found`];

The Input Loop

The terminal stores every line (both commands typed and their output) in a React state array called lines. When a new command is submitted, the prompt line and the output are both appended, producing a natural scrolling history:

const output = runCommand(command);

setLines((current) => [
...current,
`${prompt} ${command}`,
...output,
]);

setInput("");


The clear command is handled separately before the runCommand call — it simply resets the lines array to empty rather than adding a new line, which is exactly how a real terminal works.

Adding the Taskbar (Panel)

Screenshot 2026-04-12 202613.png

The taskbar — called the Panel in this codebase — is the horizontal bar that sits at the top of the screen. It serves three purposes simultaneously: it is a launcher (quick access to common apps), a window manager (shows which windows are open and lets you switch between them), and a system tray (clock, network, audio). Getting all three right in a single React component requires careful state management.

The Panel Layout

The Panel is structured as a flex row with three regions: launcher buttons on the left, window task buttons in the middle, and the clock and system tray on the right. The component receives the open/close state of the Start Menu as a prop:

export function Panel({
startMenuOpen,
onToggleStartMenu,
}: {
startMenuOpen: boolean;
onToggleStartMenu: () => void;
}) {

The quick-launch section pins three apps that are always one click away — the browser, the file manager, and the terminal:

<LauncherButton
icon={<AppIcon name="terminal" className="h-7 w-7" />}
label="Terminal"
onClick={() => openApp("terminal")}
/>

Live Window Buttons

The most interesting part of the taskbar is the dynamic window list. It reads the current windows array from the global OS store and renders one button per open window. Clicking a button either focuses the window, minimises it, or restores it from minimised state — all with a single toggle:

onClick={() => {
if (isActive) {
minimizeWindow(window.id);
return;
}

if (window.minimized) {
restoreWindow(window.id);
return;
}

focusWindow(window.id);
}}

The Live Clock

The clock widget updates every second using setInterval. It uses a mounted flag to avoid a hydration mismatch — on the server, React renders a static placeholder (--:--), and only after the component mounts in the browser does the real time appear:

const [mounted, setMounted] = useState(false);
const [now, setNow] = useState(() => new Date());

useEffect(() => {
setMounted(true);

const timer = window.setInterval(() => setNow(new Date()), 1000);

return () => window.clearInterval(timer);
}, []);

// Render:
mounted
? now.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
: "--:--"


The Panel also respects a desktopBehavior setting called roundedPanelControls — when enabled, all buttons render with rounded-full (pill shapes) instead of rounded-sm (square corners). This preference is persisted to localStorage automatically.

Building the Main Menu Button

menu.gif
Screenshot 2026-04-12 201520.png
Screenshot 2026-04-12 201525.png

The Main Menu Button — the small Choco Pie logo sitting at the far left of the taskbar — is the entry point to every application in the OS. Clicking it opens the Start Menu: a two-column flyout panel that lists all available apps, organised into categories like Programming, Games, Pi Lab, and Accessories. Hovering over a category reveals its sub-menu on the right. The whole interaction is designed to feel exactly like the Application Menu in a real Linux desktop (such as LXDE or XFCE), right down to the hover-intent delay that stops the sub-menu from flickering when you move your mouse diagonally across categories.

This step covers two distinct pieces of code: the button itself (inside panel.tsx) and the full Start Menu component (start-menu.tsx). Understanding both is important because they share responsibility — the button owns the open/closed boolean state, and the Start Menu owns everything that happens inside the flyout.

Part 1 — The Button in the Taskbar

Wiring the Button

Back in panel.tsx, the Main Menu Button is built using the same LauncherButton helper component that powers the File Manager and Terminal quick-launch buttons. What makes it special is that it is the only button whose active state is controlled by a prop passed in from the parent — the startMenuOpen boolean — rather than internal component state. This is because the Desktop shell (desktop.tsx) is the true owner of whether the menu is open, and both the button and the menu need to agree on that:

// In panel.tsx — the Choco Pie logo button
<LauncherButton
icon={<AppIcon name="choco" className="h-5 w-10" />}
label="Main menu"
active={startMenuOpen} // Lit up when menu is open
onClick={onToggleStartMenu} // Owned by the parent (desktop.tsx)
rounded={desktopBehavior.roundedPanelControls}
className="w-14"
/>

Notice that the icon name is "choco" — this is the Choco Pie brand logo rendered by the AppIcon component from pi-icons.tsx. The button is deliberately slightly wider than the others (w-14 versus w-10) to give the logo room to breathe and signal that this is the most important button on the bar.


Toggling Open and Closed

In desktop.tsx, the open/close logic is a simple boolean flip. The important detail is that opening the Start Menu also dismisses any open context menu, so the two overlays never appear simultaneously:

// In desktop.tsx — the Desktop shell
const [startMenuOpen, setStartMenuOpen] = useState(false);

// Passed to the Panel:
onToggleStartMenu={() => {
setContextMenu(null); // Dismiss context menu first
setStartMenuOpen((current) => !current); // Then toggle the menu
}}

Clicking anywhere on the desktop background also closes the Start Menu. This works because the outermost <main> element in the Desktop shell has a blanket onClick handler that resets all overlay states:

// In desktop.tsx — clicking the desktop background closes everything
<main
onClick={() => {
setStartMenuOpen(false);
setContextMenu(null);
setSelectedDesktopItem(null);
}}
>


The StartMenu component itself calls event.stopPropagation() on its own onClick so that clicking inside the menu does not bubble up to the desktop and accidentally close the menu before an item has been activated.


Part 2 — The Start Menu Component

The Category Data Structure

The Start Menu is built from a data structure called categories — an array of MenuCategory objects that is defined inside a useMemo call so it is only computed once. Each category has a label, a glyph (icon name), and either an appId (for single-item categories like Run... and Shutdown...) or a submenu array of MenuLeaf items. This separation of data from rendering is what makes the menu easy to extend — adding a new app to a category is as simple as adding one object to the right submenu array:

const categories = useMemo<MenuCategory[]>(() => [
{
label: "Programming",
glyph: "programming",
submenu: [
{ label: "VSCode Lite", glyph: "vscode", appId: "vscode" },
{ label: "Terminal", glyph: "terminal", appId: "terminal" },
{ label: "Text Editor", glyph: "text-editor", appId: "text-editor" },
],
},
{
label: "Pi Lab",
glyph: "about",
submenu: [
{ label: "About π", glyph: "about", appId: "about" },
{ label: "Pi Symphony", glyph: "symphony", appId: "symphony" },
{ label: "Pi Mandala", glyph: "mandala", appId: "mandala" },
// ... 8 more Pi apps
],
},
// ... 10 more categories
], []);

The MenuGlyph Icon System

Each row in the Start Menu shows a small coloured icon on the left. These icons are drawn with inline SVG — no image files are used. The MenuGlyph component acts as a switch statement that maps a glyph name to a hand-crafted SVG. Icons are wrapped in either a CircleIcon or SquareIcon helper, which applies the correct border colour and background shape. For app-level glyphs (like "terminal" or "browser"), it delegates to the AppIcon system instead:

function MenuGlyph({ glyph }: { glyph: GlyphName | AppId }) {
// If the glyph is a known App ID, use the app's own icon
if (glyph in APP_MAP) {
return (
<AppIcon
name={APP_MAP[glyph as AppId].icon}
className="h-7 w-7"
/>
);
}

// Otherwise draw the category icon inline with SVG
switch (glyph) {
case "programming":
return (
<CircleIcon color="#79a3dc">
<svg viewBox="0 0 24 24" className="h-5 w-5">
<path
d="M9 8l-3 4 3 4M15 8l3 4-3 4M10.5 18l3-12"
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeWidth="1.8"
/>
</svg>
</CircleIcon>
);

case "games":
return (
<CircleIcon color="#8bc83a">
<svg viewBox="0 0 24 24" className="h-5 w-5">
<path
d="M7 9h10l2 8H5l2-8zm3 2v4m-2-2h4"
fill="none"
stroke="currentColor"
strokeWidth="1.8"
/>
</svg>
</CircleIcon>
);

// ... 16 more cases
}
}

The colour coding of icons is deliberate and consistent — blue circle for Programming, green circle for Games, orange circle for Help, grey circle for Shutdown. These colours mirror the icon conventions used in real desktop environments like LXDE, grounding Choco Pie OS in familiar visual language.

Hover-Intent: Preventing Submenu Flicker

One of the trickiest interactions in any nested menu is the 'diagonal problem': when the user moves their mouse from a category row diagonally towards the open submenu, the cursor briefly passes over other category rows, causing the submenu to flicker. Real operating systems solve this with a hover-intent delay — the submenu only switches if the user stays on a new category row for a short moment. Here is exactly how Choco Pie OS implements it:

const HOVER_INTENT_DELAY = 150; // milliseconds

const scheduleActiveIndex = useCallback((index: number) => {
clearHoverTimer(); // Cancel any previously scheduled switch
setPinnedIndex(null); // Hovering overrides any click-pinned submenu

if (insideSubmenuRef.current) {
// Mouse is in the submenu — delay the switch so the user
// can move diagonally without triggering a different category
hoverTimerRef.current = setTimeout(() => {
setActiveIndex(index);
hoverTimerRef.current = null;
}, HOVER_INTENT_DELAY);
} else {
// Mouse is in the category list, not the submenu —
// switch immediately for a snappy feel
setActiveIndex(index);
}
}, [clearHoverTimer]);

The insideSubmenuRef is a ref (not state) because it does not need to trigger re-renders — it is purely a flag read inside the hover timer closure. The timer is stored in hoverTimerRef for the same reason, and crucially it is cleared in the useEffect cleanup function so no stale timers fire after the component unmounts.

Click-Pinning the Submenu

Hover alone is not enough — if the user moves their mouse entirely off the menu, the submenu should stay visible if they clicked a category rather than merely hovered it. This is handled with a separate pinnedIndex state. A click sets the pin; any hover on a new row clears it. When the mouse leaves the entire menu, the active index falls back to the pinned index (or null if nothing was pinned):

// On click: pin the submenu open
onClick={() => {
if (hasSubmenu) {
setPinnedIndex(index); // Remember this was clicked
setActiveIndex(index); // Show it immediately
} else {
activateItem(category); // Single-item rows launch directly
}
}}

// On mouse-leave from the entire menu:
onMouseLeave={() => {
clearHoverTimer();
insideSubmenuRef.current = false;
setActiveIndex(pinnedIndex); // Restore the pinned category, or null
}}

Dynamic Height Clamping

On smaller screens the menu could overflow the viewport. The Start Menu listens for window resize events and clamps both the category column and the submenu column to a computed maximum height. The submenu's vertical position is also clamped so that categories near the bottom of the list still open their submenus at a visible, reachable position:

// Max heights are derived from the live viewport height
const menuMaxHeight = Math.max(
240,
viewportHeight - MENU_TOP_OFFSET - MENU_VERTICAL_MARGIN
);

const submenuMaxHeight = Math.max(220, menuMaxHeight - 8);

// The submenu's top offset is clamped so it never goes off-screen
const submenuTop = Math.max(
0,
Math.min(
activeIndex * ROOT_ROW_HEIGHT, // Ideally aligned with the active row
menuMaxHeight - submenuMaxHeight // But clamped if too near the bottom
)
);

Launching Apps from the Menu

When the user clicks a leaf item (a final destination in a submenu), the activateItem function is called. It checks whether the item has an appId and if so calls onLaunchApp (which opens the window via the OS store), then calls onClose to dismiss the menu. Items can also carry a message property instead of an appId — in that case, a desktop notification is pushed and the menu closes:

const activateItem = (item: MenuLeaf | MenuCategory) => {
if (item.appId) {
onLaunchApp(item.appId); // Opens the app window
onClose(); // Closes the Start Menu
return;
}

if (item.message) {
onNotify(item.label, item.message); // Push a notification instead
onClose();
}
};


The Start Menu opens with a brief CSS animation called animate-panel-rise, defined in globals.css. This is a short translate-Y + opacity transition that makes the menu feel like it rises from the taskbar rather than snapping into existence. It takes about 120 milliseconds — fast enough to feel instant, but present enough to feel polished.

Adding File Manager, Chromium & Control Centre

Screenshot 2026-04-13 205224.png
Screenshot 2026-04-13 205235.png
Screenshot 2026-04-13 205245.png
Screenshot 2026-04-12 204011.png

Three apps come together to give Choco Pie OS its 'real OS' feel: the File Manager (browse and manage virtual files), the Browser App (a simulated Chromium-style web browser), and the Control Centre / Settings (customise the desktop). Together they cover the three pillars of any usable desktop — files, internet, and preferences.

The Window Frame System

Before looking at the apps themselves it is worth understanding the window system that wraps them. Every app in Choco Pie OS is rendered inside a WindowFrame component. This frame handles dragging (move by clicking the title bar), resizing (grab any edge or corner), minimise, maximise, and close. Here is how dragging is implemented — it captures pointer events globally on the window object so the drag does not break if the cursor moves faster than the component can re-render:

const onMove = (moveEvent: PointerEvent) => {
const viewport = getViewportSize();

const nextBounds = clampWindowBounds(
{
x: originX + (moveEvent.clientX - startX),
y: originY + (moveEvent.clientY - startY),
width: windowItem.width,
height: windowItem.height,
},
viewport.width,
viewport.height,
windowItem.minWidth,
windowItem.minHeight
);

updateWindowPosition(windowItem.id, nextBounds.x, nextBounds.y);
};

The File Manager

The File Manager (file-manager-app.tsx) is a full sidebar-plus-content layout. The left panel shows a virtual folder tree, the right panel shows the contents of the selected folder with icons, names, and file sizes. Folders can be expanded and collapsed, files can be 'opened' (which launches the appropriate viewer app). The virtual file system is defined as a JavaScript data structure — a tree of objects — rather than real filesystem calls, which keeps everything self-contained in the browser.

The Browser App

The Browser App simulates a Chromium-style address bar with Back, Forward, and Refresh buttons. It uses an HTML iframe to embed real web content, with special handling for a curated set of internal pages (like the Pi Site pages). The navigation state is managed locally inside the component with useState, and the current URL is displayed in a styled address bar with a security padlock icon.

The Control Centre

The Settings app (settings-app.tsx) is the Control Centre. It is organised into tabbed sections: Appearance (wallpaper picker, dark/light mode toggle), Behaviour (rounded controls, compact taskbar, notifications), Display, and About. Changes are written immediately to the OS store, which persists them to localStorage — so your preferences survive a page reload.


The Context Menu on the desktop also provides quick one-click access to the Terminal, File Manager, Control Centre, and wallpaper rotation — right-click anywhere on the desktop to see it.

Building the About Pi App

AboutPi-.gif
Screenshot 2026-04-12 204535.png
Screenshot 2026-04-12 204545.png
Screenshot 2026-04-12 204549.png
Screenshot 2026-04-12 204556.png

The About Pi app is the educational heart of Choco Pie OS. It is a rich, magazine-style page that explains what π is, where it comes from, its mathematical properties, and its history — all presented with inline SVG diagrams, formula pills, and info cards. The goal is to make π feel exciting and approachable for someone encountering it for the first time.

This app (and all the remaining apps in Steps 5–14) live inside the pi-site subfolder as vanilla JavaScript pages, loaded in an iframe by the OS-level 'Pi Site' window. This means they are independently functional web pages that also happen to be apps within the OS.

The Hero Banner

The page opens with an animated hero section. On the left, the title and subtitle; on the right, a large decorative π symbol surrounded by floating formula pills. The formulas are positioned with CSS and animated with a gentle float effect to draw the eye:

<div class="hero-formula-area">
<div class="big-pi-hero">π</div>

<div class="formula-pill formula-1">C = 2πr</div>
<div class="formula-pill formula-2">A = πr²</div>
<div class="formula-pill formula-3">e<sup>iπ</sup> + 1 = 0</div>
</div>

The SVG Circle Diagram

One of the most elegant parts of the About page is a hand-crafted SVG diagram that illustrates the definition of π — showing a circle with its diameter, radius, and circumference labelled inline. This is drawn purely with SVG elements; no images or external libraries are needed:

<svg viewBox="0 0 200 200" width="168" height="168">
<circle
cx="100"
cy="100"
r="78"
fill="none"
stroke="#EC6F00"
stroke-width="2.5"
stroke-dasharray="10 5"
/>

<line
x1="22"
y1="100"
x2="178"
y2="100"
stroke="#EC6F00"
stroke-width="2"
stroke-dasharray="6 3"
/>

<text x="36" y="76" font-size="11" fill="#EC6F00">
C = 2πr
</text>

<text x="14" y="148" font-size="11" fill="#888">
C / d = π
</text>
</svg>

Below the hero, the page divides into a three-column grid of cards covering Definition, History, and Properties, followed by deeper sections on π's mathematical nature, famous formulae like Euler's Identity (e^iπ + 1 = 0), and a timeline of key milestones in the history of π computation.


The About page also contains navigation buttons that link to other sections of the Pi Site — 'Explore π' and 'Search π digits' both fire navigateTo() calls that switch the visible section without reloading the page.

Building the Pi Day App

PiDay-.gif
Screenshot 2026-04-12 204901.png
Screenshot 2026-04-12 204907.png
Screenshot 2026-04-12 204913.png

Pi Day is March 14th (3/14 in the US date format — matching 3.14, the first three digits of π). The Pi Day app is a celebratory page that tells the story of how Pi Day began, why it matters, and what people do to celebrate it. It also includes a milestone timeline and fun record facts. Think of it as a Wikipedia article that has been redesigned to be genuinely enjoyable to read.

The Feature Cards

The top of the page presents two feature cards side by side — 'Pi Fact of the Day' and 'The π Symbol'. The Fact of the Day card contains a rotating fun fact about Pi Day celebrations, while the Symbol card explains the history of the Greek letter π and who popularised it:

<div class="card piday-feature-card">
<div class="piday-card-bar">
<i class="fa-solid fa-circle-info"></i>
<span>Pi Fact of the Day</span>
</div>

<div class="piday-card-body">
<strong>
Wish someone a "Happy π Day!" at exactly 1:59 PM on March 14
</strong>
— that's 3/14 at 1:59, representing the first six digits of π:
3.14159.
</div>
</div>

The Milestone Timeline

The page includes a vertical timeline of Pi Day milestones — from Larry Shaw's first celebration at the San Francisco Exploratorium in 1988, to the US Congress recognising it as National Pi Day in 2009, to Emma Haruka Iwao's 100 trillion digit computation record in 2022. Each timeline item is a dot connected by a vertical line, styled entirely with CSS:

<div class="timeline">
<div class="timeline-item">
<div class="timeline-dot"></div>

<div class="timeline-year">1988</div>

<div class="timeline-desc">
Larry Shaw organises the first Pi Day at the
San Francisco Exploratorium.
</div>
</div>

...
</div>


The page also includes a section on 'Pi Day around the world' and a 'How to celebrate' card with suggestions like pie-eating contests, memorisation challenges, and classroom puzzles — making it useful as a genuine educational resource.

Building the Raspberry Pi App

RaspberryPi-.gif
Screenshot 2026-04-12 211741.png
Screenshot 2026-04-12 211752.png
Screenshot 2026-04-12 211801.png
Screenshot 2026-04-12 211808.png
Screenshot 2026-04-12 211817.png
Screenshot 2026-04-12 211825.png

This app is a celebration of the Raspberry Pi computer — the affordable, credit-card-sized single-board computer that shares its name with the mathematical constant. It covers the history of the Raspberry Pi Foundation, the evolution of models from the original 2012 board to the Pi 5, and the many ways people use these tiny computers around the world.

The name connection between mathematical π and the Raspberry Pi computer is one of the central themes of Choco Pie OS, so this app serves as an important bridge between the mathematical and the technological sides of the project.

The Horizontal Timeline

The Raspberry Pi page features a horizontal scrollable timeline — a more visually dynamic alternative to the vertical timeline used in the Pi Day app. Each node on the timeline has a year, an icon, and a description:

<div class="h-timeline">
<div class="h-timeline-line"></div>

<div class="h-timeline-item">
<div class="h-timeline-icon">
<i class="fa-solid fa-landmark"></i>
</div>

<div class="h-timeline-year">2008</div>

<div class="h-timeline-desc">
Raspberry Pi Foundation established in Cambridge, UK
</div>
</div>

<div class="h-timeline-item">
<div class="h-timeline-icon">
<i class="fa-solid fa-microchip"></i>
</div>

<div class="h-timeline-year">2012</div>

<div class="h-timeline-desc">
First Raspberry Pi released — sold out within hours
</div>
</div>
</div>

Model Cards

Each Raspberry Pi model gets its own card with an icon, specifications, and a brief description of what made that model significant. The cards are laid out in a responsive two-column grid and highlight key specs like processor speed, RAM, and connectivity options.


The page also includes a 'Uses' section covering the most popular Raspberry Pi applications — retro gaming emulation, home media servers, weather stations, robotics, and educational coding environments — giving readers a real sense of why these boards matter.

Building the Pi Gallery App

PiGalary-.gif
Screenshot 2026-04-12 212121.png
Screenshot 2026-04-12 212135.png
Screenshot 2026-04-12 212142.png
Screenshot 2026-04-12 212152.png

The Pi Gallery is a curated image gallery featuring 36 copyright-free images from Wikimedia Commons, organised into four categories: Raspberry Pi boards, Mathematical Pi, Famous Mathematicians, and Historical Computing. It is both a visual feast and an educational resource — every image comes with a title, a full description, and a licence attribution.

From a technical standpoint, the Gallery is the most data-driven page in the Pi Site. All 36 images are defined in a JavaScript array called RAW_GALLERY_ITEMS, and the UI is generated dynamically from that data.

The Gallery Data Structure

Each item in the gallery is an object with a consistent shape: id, category, title, description, image URL, and licence:

const RAW_GALLERY_ITEMS = [
{
id: 1,
category: "Raspberry Pi",
title: "Raspberry Pi 4 Model B",
desc: "The Raspberry Pi 4 Model B, released in 2019, is the most powerful Raspberry Pi ever made...",
src: "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f1/Raspberry_Pi_4_Model_B_-_Side.jpg/1200px-Raspberry_Pi_4_Model_B_-_Side.jpg",
license: "CC BY-SA 4.0 · Wikimedia Commons",
},
...36 items total
];

Category Filtering

A row of filter buttons at the top of the gallery lets visitors show only one category at a time (or All). Clicking a filter button updates a JavaScript variable and re-renders the visible subset of cards. This is implemented as a simple filter on the array:

function filterGallery(category) {
const filtered =
category === "All"
? RAW_GALLERY_ITEMS
: RAW_GALLERY_ITEMS.filter(
(item) => item.category === category
);

renderGalleryGrid(filtered);}

The Lightbox

Clicking any gallery thumbnail opens a full-screen lightbox modal showing the larger image, the full description text, and the Wikimedia Commons licence. The lightbox can be closed by clicking the X button or clicking anywhere outside the image.


All images link directly to Wikimedia Commons using their standard thumbnail URLs, so the gallery always serves the correct resolution for the screen size without storing any image files locally.

Building the Pi Art App

PiArt-.gif
Screenshot 2026-04-12 212453.png
Screenshot 2026-04-12 212510.png
Screenshot 2026-04-12 212527.png
Screenshot 2026-04-12 212538.png
Screenshot 2026-04-12 212554.png
Screenshot 2026-04-12 212608.png
Screenshot 2026-04-12 212617.png

Pi Art is a generative art tool that uses the digits of π as the source of randomness to create unique, beautiful line drawings on an HTML canvas. Each digit (0–9) controls a different aspect of the drawing — direction, colour, and shape — producing images that are completely deterministic (same digits always give the same picture) yet appear organic and unpredictable.

This app teaches a profound mathematical idea: that an infinite non-repeating sequence like π can serve as a source of quasi-random data for creative and computational purposes.

The Colour Modes

Seven colour modes are defined as functions that map a digit (0–9) to an HSL colour. The 'Spectral Wave' mode, for example, multiplies the digit by 36 to spread colours evenly around the full 360-degree colour wheel:

const COLOR_MODES = {
"Spectral Wave": (d) => `hsl(${d * 36}, 80%, 50%)`,
"Warm Ember": (d) =>
`hsl(${d * 18 + 10}, 90%, ${40 + d * 4}%)`,
"Ocean Depths": (d) =>
`hsl(${200 + d * 10}, 70%, ${30 + d * 5}%)`,
"Neon Pulse": (d) => `hsl(${d * 30 + 270}, 100%, 60%)`,
"Aurora": (d) => `hsl(${120 + d * 24}, 90%, 50%)`,
};

User Controls

The right-side control panel gives the user three sliders: Color Mode (a dropdown of the seven themes), Complexity (how many digits to process, from 1 to 10), and Stroke Width. A Generate button triggers a fresh draw. The canvas is sized to fill its container and rescales automatically if the window is resized:

document
.getElementById("complexity-slider")
.addEventListener("input", function () {
document.getElementById("complexity-val").textContent = this.value;
});

document
.getElementById("generate-btn")
.addEventListener("click", () => drawPiArt());


Because the drawing algorithm is seeded by the actual digits of π (which are fixed and known), you can share a specific colour mode and complexity setting with a friend and they will always see the exact same artwork — even though it looks like abstract generative art.

Building the Pi Symphony App

PiSymphony-.gif
Screenshot 2026-04-12 212848.png
Screenshot 2026-04-12 212909.png
Screenshot 2026-04-12 212919.png
Screenshot 2026-04-12 212931.png

Pi Symphony turns the digits of π into music. Each digit (0–9) is mapped to a musical note on a scale, and the app plays them in sequence at a tempo you control. The result is an eerie, non-repeating melody that will literally never loop — because π never repeats. It is one of the most memorable and surprising features of the whole project.

The audio is generated entirely in the browser using the Web Audio API — no audio files are needed. The API lets you create oscillators (electronic sound generators) and control their frequency, gain, and timing in real time.

Mapping Digits to Notes

The ten digits 0–9 are mapped to ten frequencies. These frequencies correspond to notes in a C major scale — chosen because it sounds pleasant and non-dissonant even when played in 'random' order:

const NOTE_FREQUENCIES = [
261.63, // C4 (digit 0)
293.66, // D4 (digit 1)
329.63, // E4 (digit 2)
349.23, // F4 (digit 3)
392.0, // G4 (digit 4)
440.0, // A4 (digit 5)
493.88, // B4 (digit 6)
523.25, // C5 (digit 7)
587.33, // D5 (digit 8)
659.25 // E5 (digit 9)
];

The Playback Engine

When the play button is pressed, a Web Audio API context is created and a repeating interval fires at the current tempo. Each tick creates a new oscillator, sets its frequency to the note for the current π digit, connects it to an analyser (for the waveform display), plays it for a short duration, then moves to the next digit:

symphonyInterval = setInterval(() => {
const digit = PI_DIGITS[currentDigitIndex];

const freq =
NOTE_FREQUENCIES[digit] *
Math.pow(2, symphonyOctave);

const osc = symphonyAudioCtx.createOscillator();

osc.type = "sine";
osc.frequency.setValueAtTime(
freq,
symphonyAudioCtx.currentTime
);

osc.connect(analyser);
analyser.connect(symphonyAudioCtx.destination);

osc.start();
osc.stop(symphonyAudioCtx.currentTime + noteDuration);

currentDigitIndex++;
}, intervalMs);

The Waveform Visualiser

A canvas element beside the controls shows a real-time oscilloscope-style waveform. It is drawn by reading data from the Web Audio API's AnalyserNode on every animation frame:

function drawWaveform() {
waveformRAF = requestAnimationFrame(drawWaveform);

analyser.getByteTimeDomainData(waveformData);

// ... draw sine wave from waveformData array
}


The Octave Shift control transposes the entire melody up or down by octaves (doubling or halving all frequencies). The Tempo slider controls BPM from 40 (very slow and meditative) up to 200 (fast and frantic). Together, these two controls let you hear π in a completely different emotional register.

Building the Pi Explorer App

PiExplorer-.gif
Screenshot 2026-04-12 213248.png
Screenshot 2026-04-12 213310.png
Screenshot 2026-04-12 213325.png
Screenshot 2026-04-12 213336.png
Screenshot 2026-04-12 213349.png
Screenshot 2026-04-12 213414.png

The Pi Explorer is a search and lookup tool for the digits of π. It lets you answer questions like 'where does the sequence 314 first appear in π?' or 'what is the digit at position 42?' — both incredibly satisfying things to discover. The first 1,001 digits of π are stored in a string inside the app, and all search and lookup operations run instantly in the browser with no server needed.

Two Modes

The Explorer has two tabs. Search Mode lets you type any digit sequence (like 271828, the start of Euler's number e) and find the first position where it appears in π. Indexed Mode lets you type a position number and see exactly which digit lives there — along with the surrounding context digits for reference.

let explorerMode = "search"; // 'search' | 'indexed'

function switchExplorerTab(mode) {
explorerMode = mode;

document.getElementById("search-mode-panel").style.display =
mode === "search" ? "block" : "none";

document.getElementById("indexed-mode-panel").style.display =
mode === "indexed" ? "block" : "none";
}

The Digit Stream

On the right side of the Explorer, the first 300 digits of π are displayed as a flowing stream of coloured numbers. When a search returns a result, the matching digits are highlighted in the stream so you can immediately see where the pattern appears visually:

function highlightDigitsInStream(startPos, length) {
const digits = document.querySelectorAll(".stream-digit");

digits.forEach((el, i) => {
el.classList.toggle(
"highlighted",
i >= startPos && i < startPos + length
);
});
}


The Jump to Position feature works in both modes and is a great teaching tool — a teacher can ask students to find out what digit is at position 100, or challenge them to search for their birthday digits (like 0314 for March 14th) and discover where they appear in π.

Building the Pi Simulation App

Pisimulation-.gif
Screenshot 2026-04-12 213701.png
Screenshot 2026-04-12 213719.png
Screenshot 2026-04-12 213727.png
Screenshot 2026-04-12 213736.png
Screenshot 2026-04-12 213744.png
Screenshot 2026-04-12 213805.png
Screenshot 2026-04-12 213811.png
Screenshot 2026-04-12 213819.png

The Monte Carlo Pi Simulator is one of the most beautiful demonstrations in all of mathematics: you can estimate the value of π using nothing but random numbers and a simple geometric test. The simulation drops thousands of random points onto a canvas and checks whether each one falls inside a quarter circle. The ratio of points inside to total points, multiplied by 4, gives an estimate of π that gets more accurate the more points you add.

This app makes that abstract algorithm viscerally real — you watch the estimate converge towards 3.14159 in real time, and you can feel the mathematics happening.

The Core Algorithm

The simulation state is maintained in module-level variables. Each batch of random points is processed in a loop, and for each point the Pythagorean test (x² + y² ≤ 1) determines whether it is inside the quarter circle:

// For each random point (x, y) where both are in [0, 1]:
const x = Math.random();
const y = Math.random();

if (x * x + y * y <= 1) {
insidePoints++; // Inside the quarter circle
}

totalPoints++;

// Estimate Pi:
const estimatedPi = 4 * (insidePoints / totalPoints);

The Convergence Chart

Below the main simulation canvas, a second canvas draws a line chart showing how the π estimate has changed over time as more points are added. Early in the simulation the line bounces wildly; as the point count grows it settles ever closer to the true value of π. This convergence chart is what makes the app genuinely educational rather than just visually pretty:

convergenceData.push({
n: totalPoints,
pi: estimatedPi,
});

// Redraw the convergence line chart every N batches
if (convergenceRedrawCounter % 5 === 0) {
drawConvergenceChart();
}


The batch size slider controls how many points are added per interval tick — smaller batches make the animation smoother and more watchable, while larger batches make the estimate converge faster. The trade-off between animation quality and computational speed is itself a useful concept to demonstrate.

Building the Pi Mandala

PiMandala-.gif
Screenshot 2026-04-12 214703.png
Screenshot 2026-04-12 214720.png
Screenshot 2026-04-12 214727.png
Screenshot 2026-04-12 214736.png
Screenshot 2026-04-12 214744.png
Screenshot 2026-04-12 214757.png
Screenshot 2026-04-12 214804.png
Screenshot 2026-04-12 214812.png

The Pi Mandala is the most visually spectacular app in Choco Pie OS. It draws a multi-ringed mandala on an HTML canvas where each ring represents a sequence of π digits — and the number of petals in each ring equals the value of the corresponding digit. The result is a symmetrical, flower-like pattern that is completely determined by π but appears almost impossibly beautiful and structured.

An infinite zoom feature lets you drill into the mandala's centre, revealing finer and finer detail — micro-petals inside macro-petals — mirroring the infinite depth of π itself. An ambient spin animation keeps the mandala gently rotating when the controls are idle.

The Mandala State

The mandala's visual parameters are tracked in a single state object. This makes it easy to update one property (like zoom level) without disturbing the others:

const mandalaState = {
zoom: 5, // Zoom depth multiplier
rings: 13, // Number of concentric rings
drift: 4, // Pattern drift (0 = still, 10 = wild)
seedOffset: 120, // Starting digit index into π
motion: true, // Ambient spin on/off
spin: 0 // Current rotation angle
};

Rendering Loop

The mandala is redrawn at 30 frames per second using requestAnimationFrame with a frame-rate limiter. On each frame, the spin angle is incremented slightly (if motion is enabled), and the entire mandala is redrawn from scratch — this is simpler and more reliable than trying to update only the changed parts:

function mandalaFrame(ts) {
mandalaAnimId = requestAnimationFrame(mandalaFrame);

if (ts - mandalaLastFrame < 1000 / MANDALA_FPS) return;

mandalaLastFrame = ts;

if (mandalaState.motion) {
mandalaState.spin += 0.003;
}

drawMandala();
}

Drawing the Rings

For each ring, the corresponding π digit determines how many petals are drawn. The petals are evenly spaced around a full circle (360° / digit), scaled by the zoom level, and coloured with an HSL gradient that shifts across the rings for a rainbow effect:

for (let ring = 0; ring < mandalaState.rings; ring++) {
const digitIndex = mandalaState.seedOffset + ring;
const digit = PI_DIGITS[digitIndex % PI_DIGITS.length];

const petals = Math.max(digit, 2); // Minimum 2 petals
const radius = baseRadius * (ring + 1) * mandalaState.zoom;
const angleStep = (Math.PI * 2) / petals;

for (let p = 0; p < petals; p++) {
const angle = p * angleStep + mandalaState.spin;

// Draw petal at (cx + cos(angle)*radius, ...)
}
}

The Shift Digits Button

The 'Shift Digits' button increments the seedOffset — moving the starting point further into the decimal expansion of π. This causes the ring pattern to completely change, revealing that even small shifts in the digit sequence produce dramatically different mandala shapes, elegantly demonstrating the non-repeating nature of π:

document
.getElementById("mandala-shift-btn")
.addEventListener("click", () => {
mandalaState.seedOffset += mandalaState.rings;
drawMandala();
});


The Ring Count, Zoom Depth, and Pattern Drift sliders all update the mandala in real time as you drag them — so you can interactively explore the space of possible mandalas that emerge from different sections of π's decimal expansion. Every configuration is a genuine mathematical artefact.

Building the Pi Quiz App

PiQuiz-.gif
Screenshot 2026-04-12 215012.png
Screenshot 2026-04-12 215038.png
Screenshot 2026-04-12 215046.png
Screenshot 2026-04-12 215055.png
Screenshot 2026-04-12 215105.png
Screenshot 2026-04-12 215140.png
Screenshot 2026-04-12 215147.png
Screenshot 2026-04-12 215153.png
Screenshot 2026-04-12 215205.png
Hey, at this point do you believe you have enough knowledge about different types of Pi/Pie. Why don’t you take a small quiz? Wouldn’t it be amazing to assess yourself in a fun way?


The Pi Quiz is a 10-question multiple-choice quiz drawn randomly from a bank of 75 carefully written questions about π and mathematics. Questions span five categories: Basics, History, Applications, Records, and Fun Facts. The quiz tracks your score, shows instant feedback for each answer, and presents a summary screen at the end with the correct answers for any questions you missed.

The large question bank (75 questions for a 10-question quiz) means that the quiz feels fresh every time you play it — you are unlikely to see the exact same set of questions twice. This is achieved with a Fisher-Yates shuffle.

The Question Bank

Each question is an object with an id, a category, the question text (q), four options, and the index of the correct answer (0-based):

const QUIZ_QUESTION_BANK = [
{
id: 1,
category: "Basics",
q: "What is the value of π to 5 decimal places?",
options: ["3.14159", "3.14156", "3.14169", "3.14195"],
answer: 0, // index 0, so '3.14159' is correct
},
{
id: 3,
category: "Basics",
q: "π is classified as which type of number?",
options: [
"Rational",
"Integer",
"Imaginary",
"Irrational and Transcendental",
],
answer: 3,
},
// ... 73 more questions
];

Random Selection

At the start of each quiz run, 10 questions are selected randomly from the full bank. A simple shuffle is applied first to ensure genuine randomness:

function startQuiz() {
const shuffled = [...QUIZ_QUESTION_BANK].sort(
() => Math.random() - 0.5
);

currentQuestions = shuffled.slice(0, 10);
currentQuestionIndex = 0;
score = 0;

renderQuestion();
}

Instant Feedback

When the user selects an answer, the correct option is immediately highlighted in green and (if wrong) the selected option is highlighted in red — giving immediate, unambiguous feedback before moving to the next question. The score is updated live in the header.


The five question categories ensure that even a player who knows their basic π facts well will encounter challenging questions about computing history (the ENIAC, Emma Haruka Iwao's record) and mathematical applications (Buffon's Needle, the Basel Problem, Euler's Identity).

Building VS Code Lite

VSCodeLiteDemo-.gif
Screenshot 2026-04-12 223317.png
Screenshot 2026-04-12 222829.png
Screenshot 2026-04-12 223326.png
Screenshot 2026-04-12 222915.png
Screenshot 2026-04-12 223305.png
Now here comes VS Code Lite. This part is a bit lengthy and complex. It currently supports Python, HTML, and CSS, and I plan to add more languages and technologies in the future.
You might be wondering why I’m building this in the first place. I’ve noticed that many beginner coders want to experiment, but they hesitate due to the fear of damaging their system. To solve this problem, I decided to build this tool.
While it’s not fully complete yet, you can already run full HTML and CSS files. You can also write code in C, C++, and Python, and it will run smoothly.


VS Code Lite is, without question, the most technically ambitious single feature in Choco Pie OS. It is a faithful browser-based replica of Visual Studio Code — complete with a five-panel Activity Bar, a resizable File Explorer sidebar, a tabbed editor with real syntax highlighting for eight programming languages, a Code Minimap, a bottom terminal panel with an integrated PowerShell prompt, a Command Palette, and dropdown menus for File, Edit, View, Run, and more.

Most remarkably, it actually executes code. Write a Python program and click Run — it runs. Write a C or C++ program and click Run — it compiles and runs too.

Note: The support for C and C++ is very limited.

This is not smoke and mirrors; it uses two real in-browser runtimes (Skulpt for Python, JSCPP for C/C++) loaded from a CDN. Java execution is simulated by scanning the source for System.out.println statements, which handles the most common beginner programs convincingly.

The entire application is a single self-contained HTML file: public/vscode-lite/index.html. It is loaded inside the OS via an iframe in the VsCodeLiteApp React component, which adds one elegant extra feature — the OS theme (light or dark) is pushed into the iframe in real time using the browser's postMessage API, so VS Code Lite always matches the rest of the desktop.

This step is longer than most because VS Code Lite is genuinely complex. We will work through it layer by layer: the overall layout, the dual-layer editor trick that makes syntax highlighting work, the virtual file system, the per-language highlighters, the code execution pipeline, the integrated terminal, the minimap, and the keyboard shortcuts and command palette that bring the whole experience together.


The explanation for this step is too lengthy, so instead of writing it here, I will attach a detailed explanation file for you to refer to. And I have also attached the index.html file which I used in the image.


Files Link: VS_Code_Explanation_and_Index_File

Building GamePi

Screenshot 2026-04-12 224648.png
Screenshot 2026-04-12 224714.png
Screenshot 2026-04-12 224751.png
Screenshot 2026-04-12 224800.png
Screenshot 2026-04-12 224727.png
Screenshot 2026-04-12 224735.png
Screenshot 2026-04-12 224813.png
Screenshot 2026-04-12 224830.png
Screenshot 2026-04-12 224847.png
Screenshot 2026-04-12 224858.png
Screenshot 2026-04-12 224913.png
Screenshot 2026-04-12 224932.png
Screenshot 2026-04-12 224949.png
Screenshot 2026-04-12 225711.png

GamePi is the entertainment hub of the Choco Pie OS — a fully featured, Apple Arcade-inspired game center built right into the desktop. Rather than just linking to external games, GamePi presents a polished storefront UI with a hero carousel, genre filters, a live search bar, and an "About" panel showing library statistics. Clicking any game either launches a dedicated React app (for games like Pi Snake or Pi Defender) or opens the game inside an <iframe> wrapper for HTML-based games. All ten games are registered in a single central catalog file that drives everything — the store layout, genre tags, accent colors, and launch behavior.

The Game Catalog — The Single Source of Truth

Every game in GamePi is defined in lib/game-catalog.ts. This one file describes each game's title, genre, description, cover image, accent color, and searchable tags. When you want to add a new game, you add one entry here and the entire UI updates automatically.

// lib/game-catalog.ts
export const GAME_CENTER_GAMES: GameCenterEntry[] = [
{
id: "neon-rush",
title: "NeonRush",
genre: "Action",
subtitle: "High-speed neon reflex run",
description: "Dash through a bright arcade world, dodge hazards...",
accent: "#60e6ff",
image: "/games/NeonRush/Cover_Image.png",
tags: ["Action", "Runner", "Neon"],
},
// ... all 10 games follow the same shape
];

The Store UI — Hero, Carousel & Sidebar

The GameCenterApp component (components/apps/game-center-app.tsx) reads from GAME_CENTER_GAMES and builds the full storefront. It maintains a search state that filters games in real time using useMemo, and a activeTab toggle between "Popular" and "New" orderings. The hero section always features the top two games, a horizontal carousel shows the rest, and a sidebar lists up to eight titles.

// Filtering games live as the user types in the search bar
const filteredGames = useMemo(() => {
const query = search.trim().toLowerCase();
return GAME_CENTER_GAMES.filter((game) =>
query.length === 0 ||
game.title.toLowerCase().includes(query) ||
game.tags.some((tag) => tag.toLowerCase().includes(query))
);
}, [search]);

Launching Games — Two Pathways

Games launch in one of two ways. HTML-based games (like NeonRush or Pie Ninja) are registered in HTML_GAME_APP_SOURCES and open inside a thin HtmlGameApp iframe wrapper. React-native games (like Pi Snake, Pi Defender, or Slice the Pie) are launched directly as OS apps via openApp(game.id).

// The iframe source map for HTML games
export const HTML_GAME_APP_SOURCES: Record<HtmlGameAppId, string> = {
"memory-tile": "/games/Memory%20Tile/Memory%20Tile.html",
"neon-rush": "/games/NeonRush/index.html",
"pi-piano-tiles": "/games/Pi%20Piano%20Tiles/index.html",
"pie-ninja": "/games/Pie%20Ninja/pie-ninja.html",
"riddles": "/games/Riddles/Riddles.html",
"whispering-shadows": "/games/The%20Whispering%20Shadows/index.html",
};

GamePi features 10 games; a brief description is provided below. Seven games are related to Pi/Pie, while the remaining three are purely immersive.


1. The Whispering Shadows (Horror / Adventure) A moody, atmospheric horror adventure set inside a dark haunted mansion. Players explore room by room, making choices that advance a branching narrative story. The game uses multiple background audio tracks, illustrated room scenes, and a ghost-shadow mechanic to build tension and dread as the story unfolds.

2. NeonRush (Action / Runner) A fast-paced, reflex-driven endless runner set in a glowing neon world. The player dashes forward automatically while dodging incoming hazards that appear at increasing speeds. The entire game is built from vanilla JavaScript and CSS with a striking visual style that uses bright neon colors against a dark background.

3. Riddles (Puzzle / Logic) A calm brain-teaser game that presents the player with a series of clever text-based riddles and logic puzzles. Players type or select their answers, earn points for correct solutions, and move through increasingly tricky prompts. It serves as a thoughtful, low-stress break from the action-heavy titles in the library.

4. Pi Defender (Action / Tower Defense) A tower-defense strategy game where the player must protect a central "Pi Core" from waves of incoming enemies. Players place orbital turrets around the core, manage resources, and adapt their strategy as attack patterns grow more complex with each wave. The pi theme is woven into the visual design and the enemy naming.

5. Pi Snake (Arcade / Classic) A pi-flavored twist on the classic Snake game. The player guides a fast-moving snake across a grid, collecting the digits of pi in the correct sequence to score points. The pace increases as the snake grows longer, making it a test of both memory and reflexes in a familiar but cleverly themed format.

6. Slice the Pie (Puzzle / Math) A precision-cutting puzzle game where the player must slice virtual pies into geometrically exact portions. Each level presents an angle-based objective — cut the pie into thirds, quarters, or more complex fractions — and scores the player on accuracy. The game ties math concepts to satisfying tactile gameplay.

7. Pi Games (Collection / Mini-Games) A curated mini-game hub housing several smaller pi-themed challenges under one roof. Rather than a single game, it acts as a collection of quick-play experiences covering memory, puzzles, and action challenges. It is designed for short play sessions where the player wants variety without committing to a full game.

8. Memory Tile (Puzzle / Memory) A classic memory sequence game where a pattern of tiles lights up and the player must reproduce the exact order from memory. Each successful round adds one more step to the sequence, gradually pushing the limits of the player's short-term recall. The difficulty ramps up smoothly, making it accessible but genuinely challenging.

9. Pi Piano Tiles (Music / Rhythm) A rhythm game built around the digits of pi, where falling tiles correspond to musical notes and the player must tap them in time to keep a combo alive. The game generates a surprisingly melodic experience from the digits of pi, blending math with music in a fast, satisfying tap-along challenge.

10. Pie Ninja (Arcade / Score Attack) Inspired by classic fruit-ninja style gameplay, Pie Ninja has the player swiping to slice pies that fly across the screen. Quick, accurate swipes build up a score multiplier while missed pies break the combo. The game rewards both speed and precision in a lighthearted, visually playful arcade session.

TL;DR Explanation With Project Architecture

Mermaid Diagram Final.png

Choco Pie OS is a browser-based desktop operating system built using a modular, OS-like architecture (see diagram above).

The system is composed of six key components:

1. OS Shell (The “Operating System”)

This is the primary user interface layer of the system.

  1. Manages windows (open, close, focus, minimize)
  2. Renders the desktop, taskbar, and start menu
  3. Handles notifications, context menus, and boot screen
It functions similarly to a Windows/Linux desktop environment, recreated in the browser.


2. Application System (Everything Runs as Apps)

All features are implemented as modular applications managed by the OS.

  1. System apps: File Manager, Terminal, Browser, Settings
  2. Pi apps: simulations, art, mandala, explorer, quizzes
  3. GamePi: game launcher + HTML/React games
  4. VS Code Lite: full in-browser development environment
Every feature is an application, making the system highly extensible.


3. App Dispatcher (The Brain)

A central dispatcher controls:

  1. Which application is launched
  2. How it is rendered
  3. Where it appears within the window system
This keeps the architecture decoupled and scalable.


4. State Management (Zustand Store)

All system state is centralized, including:

  1. Window positions and focus
  2. Active applications
  3. Desktop settings
This ensures consistent, real-time synchronization across the OS.


5. Core Services (Hidden Framework)

Underlying services power the system:

  1. Virtual file system (used by File Manager and VS Code Lite)
  2. Theme engine (light/dark modes and styling)
  3. Event system (communication between apps)
These act like core services in a real operating system.


6. Specialized Subsystems

Some features run in isolated environments:

  1. VS Code Lite: runs as a standalone subsystem (iframe + postMessage)
  2. Pi Site apps: independent pages embedded into the OS
  3. HTML Games: sandboxed runtime environments
This allows complex features without affecting system stability.

Making It Live and Open Source

Screenshot 2026-04-14 201349.png
Screenshot 2026-04-14 201416.png

Once the core system was ready, the next step was to make Choco Pie OS accessible to everyone and share the code openly.

Open Source (Sharing the Code)

  1. Uploaded the complete project to GitHub
  2. Organized the codebase into clear folders (app, components, lib, store, etc.)
  3. Added a README to help others understand and run the project
  4. Enabled others to explore, learn from, and contribute to the project

Deployment (Making it Live)

  1. Deployed the project using Vercel for fast and reliable hosting
  2. Connected the Git repository for automatic deployments on every update
  3. Configured the build to run a Next.js production setup
  4. Ensured the OS runs smoothly in the browser with no installation required

Questions You Might Have

1). Where can I access the live project?

You can try Choco Pie OS directly in your browser: https://choco-pie-os.vercel.app/

2). Where can I download the project files?

You can download the complete project from here: https://drive.google.com/drive/folders/1RcL1yTnELpljeQEzM97VKBQbtQIsbz0J?usp=drive_link

3). How can I contribute?

The project is open source and contributions are welcome: https://github.com/Mayur-Pagote/Choco_Pie_OS

You can: Explore the code, Suggest improvements, Add new apps or features

4). Future Scope of the Project

Choco Pie OS is still evolving. Some planned improvements include:

  1. Refactoring parts of the system into a more modular/service-based architecture
  2. Adding a surface-level kernel simulation layer
  3. Expanding VS Code Lite capabilities and language support
  4. Introducing more Pi-based educational and creative apps

5). Why is this project open source?

This project is open source to:

  1. Help others learn system design and web-based OS concepts
  2. Encourage collaboration and innovation
  3. Make the platform accessible for students and developers worldwide

6). Why is this categorized as “Software” and not “Website”?

Although it runs in a browser, Choco Pie OS is designed as a complete software system, not just a website.

It includes:

  1. A window manager
  2. Application runtime system
  3. State management
  4. OS-like architecture

This makes it closer to a software platform than a traditional website.

7). How does this add value to users?

Choco Pie OS provides value by:

  1. Making π interactive and engaging through simulations, art, and music
  2. Helping users understand how operating systems work
  3. Providing a safe space to experiment with coding (VS Code Lite)
  4. Offering a platform that is fun, educational, and accessible to all age groups


Conclusion

Choco Pie OS transforms π from an abstract concept into an interactive, living experience.

By combining creativity, education, and system design, it brings “All Things Pi” into one unified platform.

It shows how even the simplest idea—π—can become something powerful and fun.

Pico Playground & RPi 5 Simulator (Update)

PISimulator.gif
picosim.gif

I have added two new features Pico Playground (Where you can code and attach sensors and play with Raspberry Pi Pico all around) and Raspberry Pi 5 Simulator (It is a detailed 3D model of RPi 5 where you can have a 360 degree view of it and learn about it in an interactive way.)


Pico Playground (PicoSim v4)

This is a browser-based simulator for the Raspberry Pi Pico — a small microcontroller board. It lets you build virtual circuits and run MicroPython code on them without needing any real hardware.

How it works, step by step:

1. The Visual Board Canvas The app draws an SVG (scalable graphic) representation of the Pico board with all its 40 pins labeled. Each pin is precisely positioned so wires can snap to them accurately.

const LEFT_PINS = [
{id:'GP0', label:'GP0', func:'UART0 TX / I2C0 SDA', num:1, type:'io', gpio:0},
{id:'GP1', label:'GP1', func:'UART0 RX / I2C0 SCL', num:2, type:'io', gpio:1},
...
];

2. Adding Components You pick a component (LED, Button, Buzzer, Servo, etc.) from a dropdown and click "Add." Each component has a defined shape and a set of connection pins with exact pixel positions. The app draws them as SVG graphics on a draggable canvas.

const COMP_DEFS = {
led: { label:'LED', w:56, h:80, pins:[
{id:'anode', label:'A(+)', rx:16, ry:68},
{id:'cathode', label:'K(−)', rx:40, ry:68},
]},
...
}

3. Drawing Wires You click one pin then another to draw a wire between them. The wire is a smooth curved path (a bezier curve) drawn in SVG, colour-coded by purpose (green = signal, red = power, grey = ground, etc.).

function wPath(x1, y1, x2, y2) {
const cx = Math.max(dx * .45, Math.min(100, dx));
return `M${x1},${y1} C${x1+sx*cx},${y1} ${x2-sx*cx},${y2} ${x2},${y2}`;
}

4. Writing Code The left panel has a full code editor (CodeMirror) with Python syntax highlighting. You write MicroPython — the same language you'd use on a real Pico — directly in the browser.

5. Running the Simulation When you press ▶ Run, the app reads your code and uses pattern matching to figure out which GPIO pins you used and what they should do. It doesn't actually execute Python — it reads the code structure and acts on it.

[...code.matchAll(/(\w+)\s*=\s*Pin\((\d+)/g)].forEach(m => {
pinMap[m[1]] = parseInt(m[2]); // e.g. led = Pin(15) → GPIO 15
});
if (/while\s+(True|1)\s*:/.test(code)) {
animateLoop(loopBody, pinMap); // simulates repeated execution
}

6. Components React in Real Time Once running, connected LEDs light up, buzzers activate, buttons become clickable, and sensors (like the temperature DHT22) show sliders you can drag to simulate readings — all reflected visually on the canvas and logged in a serial console below the editor.


Raspberry Pi 5 Simulator (3D Model)

This is a fully interactive 3D model of the Raspberry Pi 5 board rendered inside a web browser. It's not a code simulator — it's a visual reference tool that lets you explore the physical board in 3D.

How it works, step by step:

1. 3D Rendering Engine The entire board is built using Three.js, a JavaScript library that uses your browser's WebGL (GPU-powered graphics). A scene, camera, and renderer are set up — like a virtual photography studio for the board.

const scene = new THREE.Scene();
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.toneMapping = THREE.ACESFilmicToneMapping; // cinematic lighting
renderer.toneMappingExposure = 1.3;

2. The Board is Built from Geometric Shapes Every component on the Pi 5 — the CPU chip, RAM, USB ports, GPIO header, HDMI connectors — is constructed from 3D box and cylinder shapes with realistic materials and colours. There's no imported 3D file; the geometry is generated entirely in code.

// Example: USB 3.0 port geometry built from boxes
new THREE.BoxGeometry(0.015, 0.016, 0.030) // width × height × depth in metres

3. Camera Controls (Orbit, Zoom, Pan) A custom orbit controller lets you rotate the board by dragging, zoom with scroll, and pan by right-clicking and dragging. It also supports touch gestures (one-finger rotate, two-finger pinch to zoom) for mobile.

el.addEventListener('mousemove', e => {
if (o._btn === 0) { o._sd.theta -= dx * .0055; o._sd.phi -= dy * .0055; } // orbit
else if (o._btn === 2) { o._pan.add(...) } // pan
});

4. Hover Tooltips When you hover over any part of the board, the app uses raycasting — shooting an invisible ray from the camera through the mouse position into the 3D scene — to detect which component you're pointing at, then shows a floating tooltip with its name, description, and spec.

5. View Modes Four special viewing modes can be toggled from the bottom toolbar: Wireframe (see the board as outlines), X-Ray (semi-transparent so you can see through layers), Explode (components spread apart so you can see each individually), and Labels (floating name tags on each chip).

6. Specs Panel & Component Legend On the right side is a live specs panel showing the Pi 5's real hardware details (BCM2712 chip, 4-core CPU at 2.4GHz, etc.), and on the left is a colour-coded legend matching each board section to what it does — making it easy to learn the board layout visually.