Inspiration
Recipes are unusually personal data. People collect them for years, tie them to memories, and share them with their friends and families. Yet most recipe apps want to own your data and require a connection to be useful.
Mostly Recipes started from the opposite idea. Your recipe collection lives on your device, works offline, and stays portable when you want it to be. The app already used early GPT‑5 models to turn messy or unstructured cooking content into usable recipes. For OpenAI Build Week, we wanted to find out whether GPT‑5.6 could help us with a much deeper engineering problem. We tasked it with building a reusable sync system that keeps our local-first promise across an entire family of apps.
Our existing "Cloud Sync" stores full-library snapshots in Cloudflare R2. It works, but it's also specific to Mostly Recipes, doesn't scale well, and makes multi-device coordination harder than it should be. We needed a better foundation built for incremental changes, offline edits, safe recovery, and eventually cross-app data sharing.
What it does
Mostly Recipes imports recipes from cooking websites and unstructured text, then lets people organize, search, edit, plan, and use their collection even without an internet connection. Our "Chef AI" (OpenAI API) helps recover structured recipes when ordinary parsing is not enough, and can generate recipe cover images.
The major Build Week contribution is Mostly Cloud Data Sync, a shared, account-scoped synchronization module for the Mostly family of apps.
Each app continues to read and write locally. Cloud Data acts as a reconciliation and recovery layer rather than becoming the day-to-day database. It synchronizes individual records instead of repeatedly uploading an entire library, propagates deletions through permanent tombstones, replays offline changes, resolves concurrent edits deterministically, and lets a new device restore its data through a normal first pull.
We're exercising the system first in Mostly Page, our lower-risk proving ground. Mostly Recipes currently continues to use its legacy R2 snapshot system while we prepare a staged, backwards-compatible migration to the new Cloud Data module.
How we built it
GPT‑5.6 was not added as a superficial demo feature. It worked as an engineering collaborator on a production TypeScript monorepo containing multiple apps, shared packages, Cloudflare Workers, authentication, billing, local databases, and an existing sync implementation.
The major implementation began in our “Start Wave 1 implementation” Codex task. We gave GPT‑5.6 an accepted rollout document spanning accounts, entitlements, backups, local persistence, and Cloud Data. From that starting point, it helped turn the architecture into a sequence of working, reviewed changes:
- A standalone Cloudflare Worker hosts a SQLite-backed CloudDataNamespace Durable Object.
- One Durable Object is created for each account and data namespace, giving every sync scope a single, strongly consistent authority.
- A Zod-validated push/pull protocol provides incremental row synchronization, paging, idempotent retries, schema-version gates, tombstones, and deterministic last-write-wins conflict handling.
- A shared TanStack DB collection adapter captures normal local mutations without forcing product code to adopt a separate sync API.
- A durable local outbox stages changes before persistence, recovers interrupted writes, and safely replays offline mutations.
- Web Locks coordinate sync, backup, restore, sign-out, and multiple browser tabs.
- App-owned routes enforce fresh sessions, Mostly+ entitlement checks, and static cross-app access grants before reaching the Durable Object.
- Cloudflare Point-in-Time Recovery is paired with an Epoch Reset protocol so clients can recognize that the cloud authority moved backwards and safely rebuild local synchronized state.
GPT‑5.6 also adapted the implementation through detailed review. We challenged code decisions, asked it to design stronger type interfaces, reuse shared HTTP responses and coordination primitives, evaluate alternate solutions, and explain when an existing abstraction was or was not appropriate. The result came from an iterative engineering conversation, not a one-shot code generation prompt.
Mostly Recipes itself is built with React, TanStack Start, TanStack DB, Dexie and IndexedDB, TypeScript, Zod, Better Auth, Stripe, and Cloudflare services including Workers, D1, R2, Queues, and Durable Objects.
Challenges we ran into
The hardest part was preserving local-first ownership while adding reliable cloud coordination. "Push local changes and pull remote changes" sounds simple until devices go offline, browser tabs compete for leadership, responses disappear after the server has committed a write, or a stale client encounters data from a newer schema.
First synchronization was especially subtle, since existing local records may predate Cloud Data, while a fresh installation may create starter content before it knows whether cloud data exists. We had to reconcile old local rows without uploading provisional starter data or overwriting an account's real cloud state.
We also discovered that composition order mattered, such as when cloud sync wrapped persistence in the wrong direction, pulled records appeared in memory and advanced the Sync Cursor without being written to local SQLite. A refresh could therefore lose the records and never pull them again. Reversing the layers, i.e. with local persistence wrapping cloud sync, made remote changes write through durably before the cursor advanced.
Migration safety is another major challenge, since Mostly Recipes already has paying users and an established snapshot protocol. Replacing it cannot strand old clients or choose the wrong copy of a library. The migration therefore imports the winning R2 snapshot first, performs a full pull, and only then reconciles device-local rows through the new conflict rules. The old endpoints remain available during a measured compatibility window.
Accomplishments that we're proud of
We are proud that GPT‑5.6 helped turn a demanding architecture document into a working platform capability rather than an isolated prototype.
The Cloud Data worker and its SQLite Durable Object have been deployed. Automated exercises cover multi-client convergence, fresh-device restoration, offline replay, idempotent retries, paging, deletion propagation, schema-version protection, and recovery after an Epoch Reset. Independent protocol clients have converged through the real Durable Object boundary.
We also kept the app-facing interface small too. Product code continues to use ordinary TanStack DB collection operations; enabling Cloud Data is mostly collection configuration. The protocol, client runtime, outbox, authorization model, and Durable Object authority are shared infrastructure that can support Mostly Recipes, Mostly Page, and future Mostly products.
Most importantly, we achieved this without abandoning the original product principle, that local data stays useful when the network or cloud service isn't available.
What we learned
We learned that GPT‑5.6 is most valuable when it is given strong context and treated as a collaborator. Architecture decisions, domain terminology, rollout constraints, existing utilities, and verification requirements allowed it to make changes that fit the codebase instead of merely producing plausible standalone code.
We also learned that the difficult parts of a local-first sync system live at the boundaries. Between memory and durable storage, local time and server time, old and new schemas, multiple tabs, interrupted requests, and existing production data. There's a ton of stuff to consider, and a good wire protocol is only part of the solution. Bootstrap, recovery, migration, and failure behavior must be designed just as deliberately. All of this would have been almost impossible to pull-off in such a short amount of time, and to such a high standard of quality, without the assistance of GPT-5.6 to do so much of the heavy lifting.
Finally, we learned that a small custom protocol can be appropriate when its responsibilities are sharply constrained. Durable Objects provide serialization and strong consistency; SQLite gives us transactions and recovery; TanStack DB gives us the application collection seam. Our layer just connects those pieces and enforces the Mostly product invariants.
What's next for Mostly Recipes
We will close the remaining decision-gate exercises for real multi-browser leadership and Point-in-Time Recovery, then begin the staged migration of Mostly Recipes from R2 Cloud Snapshots to the Cloud Data system.
That migration will preserve existing local libraries, import each account's current cloud snapshot, keep older clients functioning during a compatibility window, and roll out gradually behind account and percentage gates.
After that the same platform can enable cross-app experiences, for example, a Mostly Page widget that reads a user's recipe library through a read-only access grant, without having to build another product-specific API.
Long term, we plan to add lightweight real-time sync notifications, stronger support tooling, account-deletion fan-out, and additional Mostly apps. The goal is for every Mostly product to remain local-first while gaining cloud recovery and cross-device continuity from one shared foundation.
Built With
- better-auth
- bun
- cloudflare
- love
- react
- sqlite
- stripe
- tanstack
- typescript
- zod
Log in or sign up for Devpost to join the conversation.