> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kazzle.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Realtime sync

> Local-first apps with offline support and automatic background sync.

## How it works

Apps with realtime sync keep a local database on the device. Reads are instant (local), writes queue locally, and everything syncs to the server in the background.

```text theme={"theme":"material-theme-darker"}
User writes -> Local database -> Upload queue -> Server -> Postgres
                                                            |
User reads  <- Local database <- Sync replication <---------+
```

The result: instant reads, no loading spinners, and an app that keeps working on bad connections or offline.

## What the AI sets up

Ask the AI to build a realtime app. It reuses a suitable active database when one exists; otherwise it creates a database, turns on the sync service, and builds a two-part app:

* **UI** - client app with a local database, live queries, and a sync connector
* **Process** - token endpoint, sync upload route, and migration runner

Credentials are stored in the [vault](/work/vault). The AI wires database env vars into the process component with the `db` tool.

Before the app is considered ready, the database must show `sync: ready`. If sync is not ready, the app may render but cross-device realtime data will not work.

## Rules of thumb

* Write locally first. Let sync upload in the background.
* Show empty states, not loading spinners, once local data exists.
* Keep user-visible state in synced tables so it survives refreshes and offline use.
* Group related local writes together so the UI updates as one step.
* Verify sync health before calling a realtime app done.

## Offline app shell

UI templates can include an offline app shell so the app can reopen after the first visit without a network. The app shell is the static HTML, JS, CSS, and icons.

* **Offline shell** makes the app open without a network
* **Sync** keeps the app data usable while offline

Together: the app opens without a network, shows the latest synced data, queues new writes, and syncs when the connection comes back.

## When to use realtime sync

| Good fit                          | Overkill                   |
| --------------------------------- | -------------------------- |
| Task managers and notes apps      | Static marketing pages     |
| Collaborative tools               | One-off form submissions   |
| Field apps with weak connectivity | Read-only brochure sites   |
| Anything that should feel instant | Apps with no offline value |

## Platform variables

Kazzle injects a small set of environment variables into every app process automatically. These are separate from your own [vault secrets](/work/vault).

| Variable                          | What it is                                    |
| --------------------------------- | --------------------------------------------- |
| `PORT`                            | The port your process should listen on        |
| `HOST`                            | The hostname to bind to (typically `0.0.0.0`) |
| `KAZZLE_API_URL`                  | Base URL used by Kazzle runtime helpers       |
| `KAZZLE_APP_COMPONENT_<NAME>_URL` | Runtime URL of a sibling component            |

### Sibling URLs

When an app has multiple components (e.g. a `web` UI and a `server` process), Kazzle can inject URLs for sibling components:

```
# In the "web" part:
KAZZLE_APP_COMPONENT_SERVER_URL=http://localhost:3001

# In the "server" part:
KAZZLE_APP_COMPONENT_WEB_URL=http://localhost:3000
```

When a sibling is already deployed, the injected value points at that deployed component. Otherwise it points at the current development address for that sibling.
