The problem
What problem does Island-mode server solve?
A shop, gym or clinic cannot stop when the internet drops. The cloud system is unreachable, but customers are at the counter, stock is moving and doors need to open.
This skill builds a small server that runs at the site and keeps a live copy of the site's data. While the connection is up it stays invisible. When the connection drops, kiosks and staff terminals on the local network switch to it. The site keeps taking bookings, moving stock and opening doors. When the connection returns, the offline work flushes back to the cloud exactly once.
Node on the local box, Firestore in the cloud. Hardware authenticates with HMAC. The on-site operations (systemd, nginx) are written down.
The module
What does the skill build?
An agent with this skill builds one module as a Node.js server at your site, next to your cloud app, on your stack. For Island-mode server that module consists of:
- 1. Live RxDB replica of a site's Firestore slice
- 2. LAN takeover when the internet drops
- 3. Idempotent reconnect flush
- 4. HMAC hardware auth
Provenance
Where do the rules come from?
The skill was written by the engineers who have shipped this module; the earlier implementation it was audited against was the on-premise fallback of a multi-location venue booking system. The templates hold four properties: a live replica that takes over the LAN when the internet drops, a reconnect flush the cloud can apply any number of times with one result, hardware calls that are HMAC-verified with a replay window, and offline staff tokens that expire. The vitest suite in assets/ verifies the trust-critical logic, and `references/provenance.md` is the record of what the audit changed, what was kept and what is new.Written by the engineers who have shipped this module. The earlier implementation it was audited against is a NestJS + RxDB local server replicating Firestore collections for a Next.js cloud app, with kiosk/staff PWA terminals and HMAC-authenticated lock hardware. Templates are hardened: they are that design with the audit findings below fixed in place. Everything not listed under "Added" ran in production in the earlier implementation.
The ledger separates what the audit changed, what was kept on purpose, and what has not run in production yet.
Fixed in the templates
- Cloud sync-ingestion endpoints had no authentication The earlier implementation's
/api/sync/*routes (bookings, inventory-transactions, lock-logs) accepted unauthenticated POSTs on the public internet — anyone could inject confirmed bookings, apply arbitrary stock increments, or forge audit logs. Shipped:x-sync-secretshared-secret check on every ingestion endpoint (sync-flush.md). - Offline JWT fallback reachable while online Staff auth fell back to decode-without-verification whenever
verifyIdTokenthrew — including for forged tokens while fully online, making signature verification unenforceable. Expiry was never checked. Shipped: fallback gated on the network monitor reporting offline, plus anexpcheck on the offline path (auth.md). - Non-idempotent stock apply under at-least-once delivery The ingestion route applied
FieldValue.increment()per transaction with no already-applied check; a retried flush (lost ack, crash between apply and mark-synced) double-decremented stock and duplicated logs. Shipped: Firestore transaction doing existence-check + increment + log atomically, keyed on the client-generated transaction ID (sync-flush.md). - Wholesale delta reset after a possibly-failed flush
flushAllcleared the entire local stock-delta map after flushing, but the per-collection flush methods swallowed their own errors — so a failed flush still wiped the deltas andeffectiveStockreverted to the stale snapshot (oversell window). Shipped: per-ID delta fold-out on acknowledgedsyncedIdsonly; no wholesale reset (sync-flush.md). - Flush only ran on the offline→online transition A flush that failed right after reconnect was not retried until the next outage cycle; unsynced work could sit indefinitely while online. Shipped: a 60 s retry timer that flushes whenever unsynced work remains (sync-flush.md).
Show 5 moreShow fewer
- Client never rescanned for the local server while offline The terminal-side manager searched for the local server once, at the online→offline transition. A local server that booted after that moment was never found until the cloud recovered and failed again. Shipped: rescan on every offline tick (network-failover.md).
- Island availability ignored site config Slot generation hardcoded 10:00–20:00 and derived "today" from UTC ISO strings, diverging from the cloud's opening-hours-driven availability (and shifting the day boundary for non-UTC sites). Shipped: hours derived from the replicated site document; site-timezone
todayAtSite()helper (local-api.md). - Undeclared and dead meta-fields
_locallyModifiedwas patched but absent from every RxDB schema (worked only because schema validation was off);_syncConflictwas written once at creation and never used by anything. Shipped:_locallyModifieddeclared in schemas;_syncConflictdropped, with conflict handling documented as an explicit LWW decision (architecture.md, replication.md). - Dead persistence configuration
RXDB_STORAGE_PATHexisted in config, env examples, and the deployment guide (which instructed operators to provision a data directory) while the code unconditionally used memory storage — operators believed offline data survived restarts; it did not. Shipped: the config removed; the memory-vs-persistent trade-off stated loudly with options (replication.md), and theRestart=alwaysinteraction called out (operations.md). - Sticky replication errors
lastErrorwas never cleared after recovery, so/statusshowed a replica as erroring long after it had healed. Shipped: error timestamping + clearing once replication cycles cleanly (replication.md).
- Cloud sync-ingestion endpoints had no authentication The earlier implementation's
Non-negotiables
What are the 4 rules the module never breaks?
Every module built from this skill holds these, whoever builds it. The same list is in the skill's README and SKILL.md, so the agent reads it before it writes a line.
Never expose the cloud sync-ingestion endpoints without auth.
They apply stock increments and inject orders, so they are reachable only with a shared-secret header at the minimum; the reference route handlers check it before touching Firestore.
Never verify offline staff tokens leniently while online.
Decoding without verification is an accepted LAN-only trade-off, so it is gated on the server actually being offline; the suite's offline token tests cover the gate.
Never reset local stock deltas for transactions not acknowledged as synced.
Deltas are folded out per transaction ID on acknowledgment, so
effectiveStockstays correct across a partial flush; the suite's delta fold-out tests run against a real RxDB instance.Never let the local server invent business rules the cloud owns
(opening hours, pricing). The local server replicates the config and computes from it, so island-mode behaviour matches the website.
Fit
When should you use it, and when not?
Use it for
- A site must survive internet outages with real writes (bookings, stock, hardware control), not just cached reads.
- Terminals are browser-based (PWA/kiosk) and must fail over transparently.
- Firestore is the cloud source of truth and stays that way.
Not for
- Cached reads, or a PWA that only needs offline persistenceInsteadThe Firebase SDK's built-in offline mode, no server needed
- Supabase, Postgres or another cloud databaseInsteadThe tier concept travels; every template here is Firestore-specific
- Multi-master sync between peer sitesInsteadThis design is strictly hub-and-spoke, cloud as source of truth
- The kiosk terminal itselfInsteadThe sibling `booking-kiosk` skill, which defines the client-side failover contract against this server
Build it yourself
How do I install it?
One command. The skills.sh CLI installs the skill into every skills-compatible agent it finds.
$ npx skills add timerise-ai/island-mode-serverClaude Code
Invoke with /island-mode-server
Codex CLI
Invoke with $island-mode-server
Gemini CLI
Invoke with /skills
Name the agents instead with -a, for example npx skills add timerise-ai/island-mode-server -a claude-code -a codex. Or clone the repository into your agent's skills folder. Nothing in it is agent-specific.
What is inside the repository (10 entries)
SKILL.mdEntry point: the architecture diagram, six critical facts, four hard rules, the quick start, and the reference directoryreferences/architecture.mdModes, the two sync paths, replication tiers, tenant scope, the seams tablereferences/replication.mdRxDB setup, schemas, custom-token auth, security rules, the checkpoint trapreferences/sync-flush.mdReconnect flush, per-ID stock deltas, idempotent cloud ingestion, retriesreferences/network-failover.mdHeartbeat/status chain, outage detection, terminal API switching, rescanreferences/auth.mdLocal API guards: staff tokens, kiosk key, hardware HMAC, offline gatingreferences/local-api.mdThe offline endpoints: availability, booking mutex, check-in, pricingreferences/operations.mdOn-site deployment: systemd, nginx TLS, mDNS, env vars, runbookreferences/provenance.mdThe ledger: what the audit changed, what was kept, what is new and not yet runassets/behavior.test.tsThe vitest suite carried into the target project as regression cover
Recent releases
- v0.1.5September 21, 2026
Wording release. The skill content is unchanged from 0.1.4.
- v0.1.4September 2, 2026
Wording release. Templates and technical content are unchanged from 0.1.3.
- v0.1.3September 2, 2026
Wording release. Templates and technical content are unchanged in behaviour from 0.1.2.
After installing
What do I tell my agent?
Say what you need in your own words; the skill supplies the how. These are starting points.
Our climbing gym's front desk must keep taking bookings when the internet drops. Build a local server that replicates our Firestore data, takes over the LAN, and syncs back when the connection returns.
Firestore + RxDBOur kiosks run in the browser. Make them switch to the local box on their own when the cloud is unreachable, without staff doing anything.
Firestore + RxDB
Build it with Timerise
How long does it take, and what does it cost?
We quote this module per project. The price depends on what it has to connect to. The path to a number is short and free:
Step 1
Brief
Tell us what the module must connect to. Takes minutes, in a chat.
Step 2
Prototype in 48 hours
A clickable prototype of your system and a quote, at no cost.
Step 3
Build and handoff
One project price. Source code, documentation and IP are yours.
Two ways to get Island-mode server
Build it yourself
Install the skill. Your own agent builds the module.
- MIT licensed, no strings
- Runs in Claude Code, Codex CLI and Gemini CLI
- The same rules our engineers build by
$ npx skills add timerise-ai/island-mode-serverBuild it with Timerise
Send a brief. We build Island-mode server into a system you own.
- Clickable prototype and a quote within 48 hours, free
- One project price, no subscription, no commission
- Source code, documentation and IP handed over
Generated from the skill's own files at commit b1b4d51. Every rule above links to where the repository says it. All skills