ai-infrastructure-hugg…
Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming, embeddings, image generation,…
Local-first architecture with sync queues
$ npx -y skills add agents-inc/skills --skill web-pwa-offline-first --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/web-pwa-offline-firstContext preview
The summary Claude sees to decide when to auto-load this skill.
Local-first architecture with sync queues
name: web-pwa-offline-first description: Local-first architecture with sync queues
> **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:**
---
with no queue and no conflict resolution. Patterns 1, 4 and 6 are the whole of it.
at [examples/core.md](examples/core.md) and pick a resolution strategy from [examples/sync.md](examples/sync.md).
---
<critical_requirements>
**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:**
**Handled elsewhere:**
what the server said and expires; this skill owns records the user authored
a queue and a merge
---
<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 updatedThe 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>
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)
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<voidThe official skills marketplace for Agents Inc. 150+ 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?
Repo: agents-inc/skills
Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming, embeddings, image generation,…
LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking, virtual keys, and production…
Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client patterns
Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output, model management, and…
Replicate SDK patterns for TypeScript/Node.js -- client setup, predictions, streaming, webhooks, file handling, model versioning, deployments, and training
Together AI SDK patterns for TypeScript — client setup, chat completions, streaming, structured output, function calling, embeddings, image generation,…