Skip to content
Development
Skill

/web-pwa-offline-first

Local-first architecture with sync queues

From plugin
skills
26200 skills

Claude Code

$ npx -y skills add agents-inc/skills --skill web-pwa-offline-first --agent claude-code

SKILL.md

web-pwa-offline-first.SKILL.md
name: web-pwa-offline-first
description: Local-first architecture with sync queues

Offline-First Application Patterns

> **Quick Guide:** Reads and writes go to a local database first and the network catches up > afterwards. IndexedDB is the store — reached through a wrapper such as Dexie (reactive queries, > larger) or idb (thin, ~1.2KB) — and every syncable record carries `_syncStatus`, `_lastModified` > and `_localVersion` so the queue knows what is outstanding. Deletes are tombstones, never > removals, or a delayed sync resurrects them. The Background Sync API is Chromium-only, so an > `online` listener is the mechanism and background sync the optimisation.

**Detailed Resources:**

  • [examples/core.md](examples/core.md) — syncable entity, repository, sync queue with backoff, connectivity detection, optimistic updates, hooks for status and mutations
  • [examples/indexeddb.md](examples/indexeddb.md) — Dexie schema and migrations, the idb alternative, multi-tab coordination, quota management
  • [examples/sync.md](examples/sync.md) — last-write-wins, field-level merge, conflict UI, version vectors, delta cursors, background sync, pull-push, status indicators
  • [reference.md](reference.md) — storage and conflict-strategy selection, troubleshooting by symptom, performance and security notes

---

Which path applies

  • **Read-mostly, writes require connectivity** — a local copy for reading, refreshed when online,

with no queue and no conflict resolution. Patterns 1, 4 and 6 are the whole of it.

  • **Full CRUD offline** — mutations queue, conflicts happen, and every pattern here applies. Start

at [examples/core.md](examples/core.md) and pick a resolution strategy from [examples/sync.md](examples/sync.md).

---

<critical_requirements>

Before writing offline-first code

**Treat the local database as authoritative.** Every read comes from it and every write lands there before anything is sent, which is what makes the UI answer instantly whatever the connection is doing.

**Give every syncable record `_syncStatus`, `_lastModified` and `_localVersion`.** Without them there is no way to ask what is outstanding, and no way to tell a conflict from a fresh write.

**Delete by writing a `_deletedAt` tombstone.** A removed row has nothing left to sync, so the next pull brings the record back.

**Queue every mutation and drain the queue on reconnect, with exponential backoff and jitter.** A transient 502 is otherwise a permanently lost write, and synchronised retries from many clients are what turn a brief outage into a long one.

**Keep an IndexedDB transaction free of any other `await`.** The transaction closes as soon as control returns to the event loop with no request pending, so an awaited `fetch` mid-transaction fails with `TRANSACTION_INACTIVE_ERR`. Fetch first, then open the transaction.

</critical_requirements>

---

**Auto-detection:** IndexedDB, indexedDB.open, IDBDatabase, IDBObjectStore, openDB, DBSchema, Dexie, useLiveQuery, dexie-react-hooks, idb-keyval, sync queue, tombstone, \_syncStatus, \_lastModified, last-write-wins, version vector, offline-first, local-first, navigator.onLine, navigator.storage.persist, BroadcastChannel, QuotaExceededError

**Applies to:**

  • Choosing and shaping a local store that survives a reload and a disconnection
  • Modelling sync metadata on records the user edits offline
  • Queueing mutations, retrying them, and reporting what is outstanding
  • Detecting real connectivity rather than a network interface
  • Resolving concurrent edits, from last-write-wins to version vectors
  • Showing the user what has saved locally and what has reached the server

**Handled elsewhere:**

  • Intercepting network requests and versioning an HTTP response cache — a response cache stores

what the server said and expires; this skill owns records the user authored

  • Precaching an application shell so the app boots without a network
  • Collaborative character-level editing, which wants a convergent replicated data type rather than

a queue and a merge

---

<philosophy>

Philosophy

The network is an enhancement. Local storage is the database, and the server is a peer it reconciles with — which inverts the usual arrangement, where local storage is a cache of the truth.

Two things follow. Writes never block on a request, so the UI responds at disk speed rather than at network speed. And every write becomes a claim that may be contested, which is why sync metadata is foundational rather than an add-on: a record with no version is a record no merge can reason about.

User action
    │
Local database  ←── the single source of truth
    │
UI updates immediately
    │
Sync queue (background)
    │
Server, when reachable
    │
Conflict resolution, if the record moved on both sides
    │
Local database updated

The user's remaining job is trust: they need to see that a change is saved, that it is queued, and that it eventually landed. Sync status is a product surface, not a debugging aid.

</philosophy>

---

<patterns>

Core patterns

Pattern 1: Syncable entity

Every other pattern reads these fields. Business data and sync metadata stay separate, with the metadata prefixed so a merge can skip it wholesale.

interface SyncableEntity {
  id: string;
  _syncStatus: "synced" | "pending" | "conflicted";
  _lastModified: number;
  _serverTimestamp?: number;
  _localVersion: string;
  _serverVersion?: string;
  _deletedAt?: number; // tombstone
}

Full code: [examples/core.md](examples/core.md)

Pattern 2: Repository

One access point for a collection, so no caller has to remember that a write is two operations. Reads filter tombstones; writes stamp metadata, save locally, then enqueue.

interface DataRepository<T extends SyncableEntity> {
  get(id: string): Promise<T | null>; // null for a tombstone
  getAll(): Promise<T[]>;
  save(item: T): Promise<void>; // local write, then enqueue
  delete(id: string): Promise<void
Read more
@agents-inc
Ships withskills

The official skills marketplace for Agents Inc. 230+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?

Stars on GitHub

Momentum

stars in total
26
Star history of agents-inc/skills on GitHub, a chart by star-history.com

Other skills on skills.

ai-infrastructure-litellm

ai-infrastructure-lite…

LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking,…

@agents-inc@agents-incInstall Skill
ai-infrastructure-modal

ai-infrastructure-moda…

Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client…

@agents-inc@agents-incInstall Skill
ai-infrastructure-ollama

ai-infrastructure-olla…

Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output,…

@agents-inc@agents-incInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills10d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react1d252k
@facebook@facebookInstall Skill

Questions about web-pwa-offline-first.

Which coding agents can use web-pwa-offline-first?
web-pwa-offline-first installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.