Technical Details

A primary design constraint was to keep the app in a single file. To achieve this, I explored treating the sophisticated database built into all browsers, IndexedDB (IDB), as a first class database. Most web applications use IDB either as an offline cache of server data or as temporary storage for UI state. In both cases, the server remains the source of truth.

This application has no server in the data model at all.

The Core Architectural Insight

This is a local first system where the browser effectively takes on the role of the server. IndexedDB is not replacing a cache layer, it is replacing a database.

That shift drives the need for migration strategies, structured schemas, coordinated reads, and disciplined write behavior. The complexity is not incidental, it is a direct result of removing the backend.

IDB as the Sole Persistence Layer

There are no API calls and no remote synchronization. IndexedDB is not supporting a backend, it is the backend. All user actions are written directly to local storage, and the application depends entirely on that persistence.

If data is lost from IndexedDB, it cannot be recovered. This creates a fundamentally different trust model compared to systems where local data is just a cache.

Multi-Entity Relational Design

The data is organized across multiple object stores, each representing a distinct domain of the application. Rather than storing a single serialized blob, the system models relationships between entities and manages them explicitly.

Some stores behave like structured tables, while others act more like flexible key value layers. Together, they form a schema that more closely resembles a traditional database than a typical client side storage setup.

Preference Cascade as a Query Layer

Preferences are resolved through a layered system that prioritizes instance level values, then global values, and finally defaults. This introduces a read path that behaves like a lightweight query engine rather than simple key lookup.

The result is a structured approach to configuration that mirrors patterns typically found in backend systems.

Transactional Thinking in the Browser

Data access is designed with coordination across multiple stores in mind. Reads and writes are grouped to maintain consistency, and the system accounts for partial failures in a controlled way.

These patterns are more commonly associated with server side database interactions than with frontend state management.

Tradeoffs

The system does not include synchronization, automatic backups, or recovery mechanisms if storage is cleared. Data durability depends entirely on the client environment.

In exchange, the application gains immediate responsiveness, full offline capability, no infrastructure overhead, and strong privacy guarantees. The entire system runs locally, with no external dependencies.

One File, Thousands of Tests

Warmup ships as a single HTML file, roughly 60,000 lines and 2.5 MB unminified. That would be too heavy to serve over the web, but as a desktop file it is perfectly fine, about the size of a typical photo, and minification cuts it roughly in half.

Behind the scenes, over 4,700 tests (about 14% property-based) and full JSDoc typing keep the code honest. What ships is just that one file: no frameworks, no dependencies, no build step.