OneShot

← All packs

Offline Sync Engine

complex-universalverified

Local-first app core — client store, sync protocol, per-field LWW conflict resolution, offline queue, and a schema-migration story that survives queued mutations — an agent-executable blueprint with a runnable convergence proof.

How install works

  • Accounts
  • Tools

Accounts + tool install: ~15–20 minutes.

Full setup walkthrough ships in the zip after purchase.

Coming soon — $99
Execution receipt3 of 3 runs passed
Model
claude-sonnet-5
Run at
2026-08-02T05:37:20+00:00
Pack version
57649f89a561
Tokens in / out
5,672,218 / 100,294 · per-run mean · billed input includes 5,258,129 cache reads, priced far below fresh input
Wall time
13.9 min · per-run mean
Deploy
not deployed

Acceptance checks

  • node-versionPASS
  • installPASS
  • typecheckPASS
  • sim:bootstrapPASS
  • sim:first-syncPASS
  • sim:offline-edit-winsPASS
  • sim:offline-edit-losesPASS
  • sim:field-mergePASS
  • sim:delete-vs-editPASS
  • sim:undeletePASS
  • sim:hlc-observePASS
  • sim:idempotent-replayPASS
  • sim:paginationPASS
  • sim:engine-paginated-catchupPASS
  • sim:clock-skew-rejectPASS
  • sim:clock-skew-restampPASS
  • sim:clock-skew-remote-winPASS
  • sim:schema-426PASS
  • sim:outbox-migrationPASS
  • sim:compaction-410-resetPASS
  • sim:undelete-survives-compactionPASS
  • next-buildPASS

Versions lock

nextjs-dexie-postgres

node24.18.1
next16.2.12
react19.2.8
react-dom19.2.8
typescript6.0.3
dexie4.4.4
zod4.4.3
pg8.22.0
@electric-sql/pglite0.5.4
tsx4.23.1
@types/node26.1.2
@types/pg8.20.0
@types/react19.2.17
@types/react-dom19.2.4
tailwindcss4.3.3
@tailwindcss/postcss4.3.3
clsx2.1.1
tailwind-merge3.6.0

Scaffold integrity

6 scaffold files modified or deleted by the buyer-agent during verification
  • app/api/sync/pull/.gitkeep
  • app/api/sync/push/.gitkeep
  • app/page.tsx
  • components/ui/.gitkeep
  • next-env.d.ts
  • tsconfig.json

Offline-first sounds simple until two devices edit the same record while disconnected — then you're debugging clock skew, resurrected deletes, and out-of-order commits in production, usually after a user has already noticed. This pack builds a working sync core — per-field last-write-wins on Hybrid Logical Clocks, replicated tombstones, paginated pull, a schema-migration-safe offline queue — wired into a real demo notes app on Next.js 16 + Postgres. The receipt is a runnable convergence proof (`verify.sh`, run against embedded PGlite): 18 simulated conflict/delete/skew/migration scenarios that all have to converge before the build counts as done.

Example use cases

  • **A field-inspection app** for a team walking warehouses or basements with no signal — inspectors edit the same job record from different devices, then reconnect in the parking lot; edits to different fields (photos vs. notes vs. status) both survive, and same-field conflicts settle identically everywhere.
  • **An indie personal-CRM or notes app builder** who wants "just works across my phone and laptop, even offline" without pulling in a hosted sync platform's SDK and monthly bill for a single-user app.
  • **An agency re-stamping the same core across client projects** — ship the identical sync engine into five different small-business inventory or booking apps instead of re-solving conflict resolution per contract.
  • **A small internal team tool** (a handful of concurrent editors — think a shared task board or shift schedule) that needs correct multi-device conflict resolution without adopting a service dependency for what is, underneath, a CRUD app.

Why this pack

No "always" claims here — agents are stochastic, and no sync design is free of tradeoffs. This is what the pack pre-solves, what it costs, and what you give up.

Bare agent, no packSync platform (Replicache/PowerSync/ElectricSQL-class, 2026)Hand-rolled in-houseThis pack
**Cost**"Free" (agent time only)Recurring subscription or usage-based billing, scales with active users/rows syncedEngineering time — typically weeks, paid however you pay engineers$99 one-time
**Time to correct convergence**Unknown — an agent asked to "add offline support" has no reason to know these bugs exist until they surfaceFast to integrate; you're adopting their protocol and SDK, not writing sync logicSlow — these bugs are usually found by users, not tests2 sessions on a $20/mo agent plan, per the pack's own budget
**Correctness risk**High and silent — see the specific bug classes belowLow — it's their maintained protocol, actively used in production elsewhereHigh until you've independently rediscovered the failure modes belowBounded by `verify.sh`'s 18-scenario proof; published pass rate, not a claim of perfection
**Lock-in**None, but also no guardrailsReal — your client code, data model, and often your server shape bind to their SDK/protocol; migrating off later is its own projectNoneNone — it's your repo, plain Postgres, no runtime dependency on this pack or on us

**What a bare agent typically ships that this pack pre-solves** (these are the specific bug classes, not a claim that every agent hits every one):

  • *Collation divergence* — the HLC tiebreak compares strings byte-wise in JavaScript; if Postgres compares the same column under a locale collation (the managed-Postgres default), same-timestamp ties can sort differently in SQL than in JS, and server and client permanently disagree on which write won.
  • *Clock-skew local-cell stranding* — a device with a wrong clock either loses its own edits to values it just pulled from a correctly-clocked device (the edit visibly reverts), or, if only the outbox gets corrected and not the device's own stored cells, the device rejects every legitimate future remote update on those cells forever.
  • *The seq/commit race* — two concurrent write transactions can commit out of order; a client that paginates past the sequence number of the transaction that hasn't committed yet never sees that row, because nothing serialized commit order against sequence order.

**What sync platforms are honest about**: PowerSync, ElectricSQL, and Replicache-class services in 2026 are real, actively-maintained products with broader device/mobile SDK coverage and (in some cases) realtime push channels this pack doesn't have. The tradeoff is a recurring bill tied to usage and a client/protocol commitment that's a real migration cost later. This pack is the other point on that tradeoff: owned code, one-time cost, no protocol to be locked into — at the cost of no realtime push and no non-JS mobile SDKs out of the box.

Scale envelope

Derived from the shipped design, not aspiration — and labeled as estimates where they are estimates.

The architecture serializes every push commit through one global `pg_advisory_xact_lock` (this is deliberate: it's what turns "two transactions committed out of order" from a correctness bug into a non-issue — sequence order becomes commit order by construction, at the cost of throughput). That lock is the ceiling to reason about:

  • **Push throughput (estimate, not load-tested in the receipt):** a serialized push transaction (acquire lock → per-cell LWW upsert → commit) on managed Postgres in the same region typically completes in tens of milliseconds. That puts a rough order-of-magnitude ceiling around the low hundreds of push transactions per second, sustained. Each transaction can batch up to 500 cell-writes, so this is a ceiling on *concurrent distinct push commits*, not on total edits — a burst of 500 field edits from one client is one transaction against that budget.
  • **Concurrent syncing clients:** sync runs on a 15-second interval plus on-reconnect and manual triggers, not a constant stream — clients aren't all pushing in the same second. Even at the low end of the estimate above, that comfortably covers hundreds to low thousands of active clients whose writes are naturally spread out, which is the shape of field-team, personal-app, and small-team usage, not a scenario where thousands of users all commit in the same instant.
  • **Rows:** the cell store holds one row per currently-live `(table, row, column)` triple — no append-only history log, so storage is O(live data). Millions of live cells is an ordinary Postgres table size for this schema; it isn't the constraint.
  • **First ceiling:** the single global advisory lock key. Every push, across every table and every client, serializes through it. As concurrent push volume approaches the transaction-rate estimate above, pushes start queuing — added latency, not incorrect behavior, but a real ceiling.
  • **Upgrade path (v2, not shipped):** partition the lock key — for example, hash a tenant or shard id into the advisory-lock key so unrelated datasets serialize independently instead of sharing one global lock. (This pack ships a single-dataset model; multi-tenancy is a documented seam, not a feature, of the current build.) The architecture's own fallback, if you need it before building tenancy, is fencing pulls at the oldest in-flight transaction instead of removing the lock — a bigger change than it sounds, not something to do casually.

**What this comfortably covers as shipped:** field teams (dozens of devices syncing opportunistically), personal multi-device apps (a handful of clients per user), small-team internal tools (a team's worth of concurrent editors). **What it isn't sized for out of the box:** a multi-tenant consumer SaaS with thousands of organizations all writing to one deployment simultaneously — that's the v2 path above, not this build.

**What it costs to skip the pack (modelled, not measured):** building this yourself the way most people actually work — one agent on a top-tier model, no cheap-tier routing, no parallel subagents, no prompt-caching discipline — models out at roughly **$45–185 in API tokens, likely around $95**. That's this pack's own measured build volume repriced at Opus-class rates, multiplied by an exploration factor for the conflict-resolution decisions this pack pre-makes; the pack-guided build itself measured ≈$5 of tokens per verification run (August 2026 rates), because tasks route down to cheaper tiers. Honest reading: at the likely figure that's about the same as the $99 price, and at the low end it's less — the token math alone doesn't pay for this pack. What it buys is the 18-scenario convergence proof that already passed, 3 of 3, before you spent the weekend.

Verified against

  • claude-opus-5
  • claude-sonnet-5
  • claude-haiku-4-5

Supported stacks

  • nextjs-dexie-postgres
    node24.18.1
    next16.2.12
    react19.2.8
    react-dom19.2.8
    typescript6.0.3
    dexie4.4.4
    zod4.4.3
    pg8.22.0
    @electric-sql/pglite0.5.4
    tsx4.23.1
    @types/node26.1.2
    @types/pg8.20.0
    @types/react19.2.17
    @types/react-dom19.2.4
    tailwindcss4.3.3
    @tailwindcss/postcss4.3.3
    clsx2.1.1
    tailwind-merge3.6.0

Estimated buyer token cost

510,000 tokens for one build pass (estimate, not a guarantee).

FAQ

What if the build fails?

`verify.sh` is the arbiter, and it's deterministic. Full refund within 14 days of purchase if `verify.sh` fails on a supported configuration (the pinned stack and a model from the pack's matrix) — reply to your Stripe receipt email with the verify output or `FAILURE-REPORT.md` attached. If your agent modified a frozen file or swapped a dependency version to get past a check, that's outside the receipt's guarantee — the fix is to fix the implementation, not the test, per the pack's own verify prompt.

What models does this need?

Verified against `claude-opus-5`, `claude-sonnet-5`, and `claude-haiku-4-5`. Tasks are pre-tagged `cheap`/`standard`/`capable` in `TASKS.md` and routed accordingly; three tasks (the server sync core, the client engine, and the verify/fix pass) are Opus-tier, which is what forces a session split on a $20/mo plan rather than raw token volume — and since Anthropic doesn't publish an exact token-per-window figure for Pro's rolling-window and weekly caps, treat the session count as an expectation, not a guarantee. PRD-stated expectation: 2 sessions, occasionally 3. Plan on **~510k fresh tokens** (input + output) for one full build pass, measured; the receipt separately reports ~5.7M tokens of total billed input (93% cache reads, billed near a tenth of fresh-input price) and a measured **$4.76 per verification run** — the most reliable of the three numbers.

Can I customize it after the build?

Yes. The engine is generic over any table/row/column, not notes-specific. Documented seams you're meant to extend: auth/tenancy (one `WHERE` clause and a session check in the route handlers — not built in), the 90-day tombstone retention window (a constant), and a realtime push channel (sync is pull-based by design; WebSocket/SSE wake-up is a noted extension point, not shipped).

Do I own the code?

Yes. It's your repo once built, plain TypeScript and SQL, no runtime call to any third-party sync service or to us. No recurring license.

Why not use a CRDT library (Yjs/Automerge) instead of last-write-wins?

Because it's deliberately simpler, and that's a real tradeoff, not a shortcut. Per-field LWW is the right choice when your unit of conflict is a whole field — a title, a status, a tag list — which covers most CRUD-shaped data. It's the *wrong* choice if you need two people's concurrent keystrokes in the same text field to both survive character-by-character; that's collaborative rich text, squarely CRDT territory (Yjs/Automerge), and it's an explicit non-goal of this pack, not an oversight.

What's the deletion guarantee, exactly?

"Deleted stays deleted" holds within a 90-day tombstone retention window. A device that stays offline longer than 90 days with a queued edit to a record deleted (and since compacted) elsewhere will re-create that record as a partial when it finally reconnects — the tombstone that would have stopped it no longer exists by then. This is a documented bound, not a hidden edge case; the retention window is a constant you can widen if your domain needs a longer guarantee.

Does it handle realtime multiplayer (live cursors, instant push)?

No. Sync is pull-based — a 15-second interval, on-reconnect, and a manual button — not a WebSocket/SSE push channel. That's a stated non-goal, with a documented extension seam if you build one later.

What if I'm not using Next.js or Postgres?

The shipped stack is Next.js 16 + Postgres, pinned for verification. The sync engine's core logic (the HLC clock, the storage interface, the server sync functions) is framework-agnostic TypeScript; porting the two HTTP route handlers to another framework is mechanical but is your own project from there — it's outside what this pack's `verify.sh` checks.

Specific problems this pack pre-solves

Prescribed services

Disclosure: some links on this page are affiliate links. We may earn a commission if you sign up through them, at no extra cost to you. We only link to services the pack actually verified against.