Skip to main content

Getting started with a generated lofi app

This guide begins after installing Deno 2.9 or newer.

Create and run the app

deno run -A jsr:@nzip/lofi/create my-app
cd my-app
deno task dev

Open the URL printed by Astro. The starter contains a task list, an account panel when sync is available, and device/runtime diagnostics.

Verify the local-first baseline before changing anything:

The default app is local-only. It does not require an .env, an account ceremony, or a backend.

Run the project checks

deno task doctor
deno task test
deno task build
deno task preview

doctor checks the project layout, configuration, manifest, and referenced install assets without printing values. test runs the fast, deterministic suite. build creates the production PWA in dist/, then verifies its base-aware HTML links, manifest, worker, build identity, and precache as one artifact. preview serves that exact output at http://127.0.0.1:4321/ by default.

Know which files to change

File or directoryPurpose
src/schema.tsTables and typed fields
src/permissions.tsRead and mutation policies
src/app.tsApp name, database name, stable origins, and repository URL
src/pages/Astro pages and shell composition
src/islands/Preact hooks and interactive UI
src/styles/Application styling
public/Manifest, icon, and other product assets
tests/Application and local-first browser tests

Application hooks import supported runtime seams from @nzip/lofi, as the generated use-tasks.ts does. The boundary keeps Jazz networking and storage machinery out of product components while allowing framework fixes to arrive through a package upgrade.

The final package map is intentionally small:

ImportSupported use
@nzip/lofiApp configuration, runtime, session, stores, PWA
@nzip/lofi/accessPrivate, direct-share, and fixed-role group helpers
@nzip/lofi/preactPackage-owned Preact hooks and diagnostic UI
@nzip/lofi/astroPackage-owned Astro/Vite integration
@nzip/lofi/recipes/file-handlerOptional validated installed-app file import drafts
@nzip/lofi/recipes/launch-handlerOptional safe installed-window launch routing
@nzip/lofi/recipes/protocol-handlerOptional allow-listed custom-protocol item links
@nzip/lofi/recipes/related-app-discoveryOptional presentation-only companion discovery
@nzip/lofi/recipes/scope-extensionOptional reciprocal cross-origin app-window scope
@nzip/lofi/recipes/web-shareOptional inbound/outbound text and link sharing
@nzip/lofi/recipes/window-controls-overlayOptional desktop titlebar geometry observation
@nzip/lofi/testingLocal-first Playwright helpers
@nzip/lofi/{create,dev,...}Generator and generated-project command entrypoints

All of these imports resolve through the single version pinned in deno.json. Upgrade that pin to receive framework fixes; do not copy package files into src/ or import unpublished internal paths. Direct vendor access is an unsupported escape hatch: isolate it from ordinary product files and do not expect lofi compatibility guarantees for it.

Customize the application identity first

Before accumulating local data, update src/app.ts:

  • name is the human-facing application name.
  • databaseName namespaces durable browser storage.
  • repositoryUrl controls the starter footer link.
  • credentialOrigins lists hostnames you intend to keep stable if you use device credentials.

Also update public/manifest.webmanifest, public/favicon.svg, the page title, and starter copy.

Changing databaseName later points the browser at a different local database. Choose it early so a cosmetic rename does not make existing device data appear to disappear.

Replace the task example

The fastest path is to change one layer at a time while keeping the app runnable:

Continue with Data and UI for the table-to-island pattern and Permissions before exposing new data.

Add sync only when you need it

Local-only development is the normal starting point. To add managed Jazz sync and account recovery:

deno task jazz:provision

Then follow Sync and recovery. Provisioning makes sync available; each user still chooses whether their existing local account should begin syncing.