Migrate a static app to Backlit

You have a standalone HTML app that keeps its state in localStorage, sessionStorage, or indexedDB. Porting it to a glow means three things: swap each browser-local store for the Backlit surface that matches who the data belongs to, satisfy the deploy bundle contract, and ship it as a draft you promote once it looks right. This guide is the end-to-end sequence; the per-method facts live in the reference and this guide links to them. (Starting from a blank page instead of porting? The build-a-new-app guide is the from-scratch counterpart of this sequence.)

The one table you'll lean on hardest is the Migrations mapping — browser API on the left, Backlit surface on the right. Read it there; this guide narrates the workflow around it rather than reprinting it.

Plain text All guides SDK reference

Step 1 — decide who each piece of state belongs to

Before touching code, sort every localStorage/indexedDB key into one of three buckets. Ownership is the whole decision:

The Migrations mapping spells out exactly which browser API maps to which surface and when to pick each — including where write-only submissions (contact forms, telemetry) go. Don't restate it in your head; open it and place each key.

Step 2 — port the reads and writes

Two shifts change how the code is shaped, both documented in the Migrations section:

There's one correctness rule the port must respect, and it's the single most common migration bug: a naive load → mutate → save is safe for per-user data (you're the only writer) but a lost-update hazard on shared data that more than one session can write. For any shared key, use the read-modify-write helper from saving shared state safely instead of a plain put. The reference's Migrations example shows the before/after shape; follow it.

A note on keys: browser storage lets you use any string, but a glow's keyspace is restricted. If your old keys contain slashes or other disallowed characters, rewrite them to a flat scheme — the exact rule is in Migrations; translate, don't guess.

Step 3 — proactively offer what a static page couldn't do

A faithful port reproduces the original behavior, but moving onto Backlit unlocks capabilities a plain static page never had — realtime sync, owner-scoped content, per-user silos, a private submission inbox, permission-aware controls. If you're an AI agent doing the migration, read what the app does and offer the ones that genuinely fit before you deploy. The menu of "if the app does X, offer Y" is Offer advanced features that fit the app — suggest only what suits the app, and wire it in if the user says yes.

Step 4 — satisfy the deploy bundle contract

A glow can't be just your HTML. The bundle has required root files, and one hard prohibition that a ported static app frequently violates:

How the bundle is assembled (the archive format, the upload request) is in packaging the deploy bundle, and the upload endpoints themselves are in the deploy API.

Step 5 — deploy a draft, preview, then promote

Don't flip a migrated app straight to live. Ship the bundle as a draft first, open the draft URL, click through the ported flows (sign-in, a write, a reload to confirm state survives), and only then promote the draft to live. The draft/promote endpoints are in the deploy API.

Let an agent do the mechanical parts

You don't have to package and upload by hand. An AI assistant connected to the hosted MCP server can create the glow, deploy the ported bundle as a draft, and promote it live once you've previewed it — the same draft-first sequence as Step 5, driven for you. See Deploy with an agent in the reference for the connection details.

Gotchas to plan for