Composition patterns
Each FirstTx layer can be adopted independently. When you combine them, keep their responsibilities separate.
| Problem | Layer | Responsibility |
|---|---|---|
| Blank UI during revisit boot | Prepaint | Replay the last DOM snapshot as a non-interactive visual cache |
| Client data that survives reloads | Local-First | IndexedDB persistence and server revalidation |
| Multi-step optimistic changes and recovery | Tx | Compensate completed steps in reverse order |
Prepaint is not a data store, Local-First is not a transaction engine, and Tx does not create screen snapshots. Start with the responsibility your problem needs, then compose layers.
Connect Prepaint to current app state
Prepaint replays the previous visit's screen. It does not prove that the data is current, so the mounted React app still needs to read client state and run any required revalidation.
- Prepaint replays the visual cache during boot.
- React mounts into the existing root.
- The app reads current client data and starts required server revalidation.
- After handoff, the overlay is removed and the current UI takes control.
Scrub sensitive values with data-firsttx-sensitive or window.__FIRSTTX_SENSITIVE_SELECTORS__. Mark clocks, counters, and other unsafe stale text with data-firsttx-volatile.
See Prepaint for lifecycle details and limits.
Design Local-First models
- Separate server-backed data state from view state such as modal and hover state.
- Choose TTL per model from freshness requirements and request cost instead of using one value everywhere.
mergeapplies toreplace. Express partial changes explicitly inpatch.- When BroadcastChannel is unavailable, provide refresh or manual sync instead of assuming live cross-tab updates.
- Split models with different update cycles and consumers to control serialization and comparison cost.
See Local-First for hook return values and persistence behavior.
Combine Local-First with Tx
Capture the state required for recovery before applying an optimistic change.
- In
optimistic, keep the previous value andpatchthe Local-First model. - Run the server operation in
request. - If the request fails, restore client state from the snapshot in
rollback. - On success, commit the transaction and update any follow-up UI.
Tx compensation is not equivalent to an atomic database transaction. Compensation can also fail; a CompensationFailedError requires manual inspection.
See Tx for retry, timeout, and compensation contracts.
Use all three layers in order
For a revisited dashboard, a safe sequence is:
- Prepaint replays the last screen.
- Local-First asynchronously loads model snapshots from IndexedDB.
- Models revalidate according to their
syncOnMountand TTL policy. - User changes run through Tx and compensate only completed steps on failure.
- DevTools shows
prepaint,model, andtxcategories on one timeline.
Verification checklist
- Test cold start and revisit separately.
- Test with empty and populated IndexedDB state.
- Test BroadcastChannel fallback or unsupported environments.
- Test request failure, timeout, and compensation failure independently.
- Verify recovery does not depend on animation when reduced motion is enabled.
- Treat runtime emitters, not bridge types, as the source for payload details.
Continue with DevTools for observation and Troubleshooting for symptom-based recovery.