The Local-First Manifesto

For fifteen years the industry told us that the cloud was the destination. Every app became a thin client for a database you could never touch, in a data center you would never see, governed by a terms-of-service you never read. This note is a long argument for the opposite premise: that the most durable, fastest, and most humane software keeps your data on your device first, and treats the network as an optimization rather than a dependency.

"A tool you cannot use without permission is not a tool. It is a subscription to someone else's tool."

Why "local-first" is more than offline mode

Offline mode is a feature. Local-first is an architecture. The distinction matters:

  • Offline mode caches a slice of server state so a spinner appears less often. The server is still the truth; the cache is a courtesy.
  • Local-first inverts the ownership. The device holds the full corpus. The server exists to synchronize copies between your devices and, when you choose, to publish a document to others.

The seven ideals — as first framed by the Ink & Switch essay that named the movement — are worth restating in plain language:

  1. No spinners. Reads and writes hit local storage, so they are instant.
  2. Your work is not trapped on one device. Sync fans your data out to every device you own.
  3. The network is optional. A plane, a tunnel, a dead Wi‑Fi router — none of it stops you.
  4. Collaboration without a central bottleneck. Merges happen at the edges.
  5. The Long Now. Your notes should outlive the company that made the app.
  6. Security and privacy by default. Data at rest is yours; sharing is a deliberate act.
  7. You retain ultimate ownership. Export is a right, not a favor.

How this notebook implements it

Every note you are reading right now was rendered from a copy sitting in your browser's IndexedDB, not fetched from a server on demand. The read path is deliberately boring:

// Simplified: the owner's read path never blocks on the network.
async function openNote(slug: string): Promise<Note | null> {
  const local = await store.getNote(slug);   // IndexedDB — microseconds
  if (local) return local;                    // the common case
  return fetchFromServer(slug);               // cold cache / shared link only
}

Writes are optimistic. When you pin a note, the pin is true before the request leaves your machine:

async function pin(slug: string) {
  await store.update(slug, { pinned: true }); // instant, local
  outbox.enqueue({ op: 'pin', slug });        // durable queue
  scheduleSync();                             // invisible, background
}

If the tab closes mid-sync, the outbox survives. The next launch drains it. You never see a half-committed state, because the local copy is the state.

The hard part: identity boundaries

Local-first has a sharp edge that cloud-first apps never face: the data lives on a shared device. If two people sign into the same browser, the second person must never see the first person's corpus. The fix is not a permission check bolted onto the read path — a check that races the render always loses. The fix is structural: each account opens a physically separate local database, and signing out purges the store.

Concern Cloud-first answer Local-first answer
Where is the truth? The server Your device
First read latency A network round-trip A memory read
Works on a plane? No Yes
Who can read the cache? N/A (no cache) Only the signed-in account
What happens on logout? Cookie cleared Cookie cleared and store purged

When the cloud still earns its place

Local-first is not anti-cloud. It is cloud-as-a-feature. Three jobs are genuinely better centralized:

  • Sync — reconciling copies across your laptop, phone, and tablet.
  • Publish — turning a private note into a public URL like the one this note lives at.
  • Share — handing a single document to a specific person without opening your whole notebook.

Notice that all three are opt-in verbs. The default is private and local. See also The Power of Local-First Apps for the shorter version of this argument, and Product Design Philosophy for the values underneath it.

Closing

The measure of a tool is what happens when the company behind it disappears. A cloud-first app becomes a login screen to nowhere. A local-first app becomes a folder of files you still own. Build for the second outcome.

Written on a train, with the Wi‑Fi off, saving after every sentence.