DEV Community

Ekong Ikpe
Ekong Ikpe

Posted on

Tabs are apps. The OS just never told the browser 🤷

You have five tabs open right now.

Binance on tab 1. Gmail on tab 2. Scrabble on tab 3. Excalidraw on tab 4. Tab 5 — Gnoke Council — four AIs deliberating together, you as the human moderator, Claude and Gemini and GPT-4o and Grok each building on what the others said. One HTML file. No backend. No API key. Just a tab.

You're switching between them like apps. Because that's exactly what they are — apps. Web apps. Running in a browser that was designed to forget them the moment the OS decides to free some RAM.

And when that happens? Gone. Half-typed message. Lost diagram. Wrecked game state. A deliberation mid-thought.

That's not a browser limitation. That's a missing abstraction. 🧩


The thought that started this 🤔

If a browser can recover a file after a crash, why can't it recover the whole session?

Not autocomplete. Not localStorage you wire up yourself every single time. The whole thing — form state, scroll position, focused field — restored silently, before first paint, as if nothing happened.

That's what gnoke-spirit does.


What it isn't 🙄

This isn't localStorage. That's dumb key-value. You put a string in, you get a string back. You manage everything manually — what to save, when to save, when to clear. Every app reinvents the same plumbing from scratch.

This isn't browser session restore either. That's passive, unpredictable, scoped to the browser's mood. Clears on hard reload. You can't name it, query it, or kill it deliberately.


What it actually is 😎

A process model for the browser.

gnokeSpirit.wake();
Enter fullscreen mode Exit fullscreen mode

One line. The tab is now a process. It has an identity — pid defaults to location.pathname, so each route is its own isolated process. It has memory (IndexedDB). It knows what to persist and what to never touch.

Kill the tab. Reopen it. It picks up exactly where it left off.

await gnokeSpirit.wake('/editor');    // Tab 1 — its own process
await gnokeSpirit.wake('/settings');  // Tab 2 — isolated, independent
// Kill either. Both come back. Neither knows the other crashed.
Enter fullscreen mode Exit fullscreen mode

What gets persisted. What never does.

Persisted Never
Text inputs Passwords
Textareas Tokens / secrets
Select values Auth state
Scroll position Anything sensitive
Active field focus

The sensitive filter isn't optional. It's baked in. You can't accidentally persist a password field. Security by default, not by configuration.


The engineering decisions that matter

One DB connection, cached for the page lifetime.
No repeated indexedDB.open() calls. One connection, reused. This matters on mobile — battery and latency both.

Schema versioning from day one.
Empty migration hook now. But when the state shape changes in v2, existing users don't lose their processes. Most people skip this and regret it.

Awaited writes everywhere.
The visibility handler — the last write before the OS kills the tab — is awaited. That's the survival write. It has to land.

Zero dependencies. No build step. 2kb.
Drop a script tag. Call wake(). Done.


The API

await gnokeSpirit.wake(pid?, formEl?)
// Start the spirit. Restores last state immediately.
// pid defaults to location.pathname — each route is its own process.

await gnokeSpirit.kill(pid?)
// Wipe process memory.

await gnokeSpirit.list()
// Returns all active process IDs. Your process table.
Enter fullscreen mode Exit fullscreen mode

Where this goes next 👀

Right now each tab is its own isolated process. That's already useful.

But imagine two tabs coexisting in a split UI — Excalidraw on the left, your notes on the right — each holding its own memory, neither crashing the other out when the OS gets impatient. Drag a tab into the perimeter. It brings its state with it. No reload. No memory loss.

That's the next layer. The browser as an actual OS. Tabs as actual apps.


What this actually is

localStorage stores values.

gnoke-spirit preserves where a user was.

Those are different things. One is plumbing. The other is a contract — ship it with any webapp and tabs become resumable. The developer stops thinking about storage. The user never notices. It just works. 🔥

The browser is an OS. Tabs are apps. gnoke-spirit is the missing layer between them.


What do you think — is the browser finally ready to be treated like an OS? Or are we still stuck thinking in pages?

Live demo: edmundsparrow.github.io/gnoke-spirit

Source: github.com/edmundsparrow/gnoke-spirit — MIT


Thanks to @sylwialaskowska whose engagement on the first post gave this legs.

Tabs Are Processes
Part of the Gnoke Suite by Edmund Sparrow © 2026

Top comments (0)