In-venue

Island-mode server

An on-premise fallback server: a live replica of your site's cloud data, LAN takeover when the internet drops, and a safe flush of offline work when it returns.

Released
September 21, 2026
npx skills add timerise-ai/island-mode-server
v0.1.5
Current release
8
Reference docs
4
Non-negotiables
MIT
License

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.

  1. 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-secret shared-secret check on every ingestion endpoint (sync-flush.md).
    • Offline JWT fallback reachable while online Staff auth fell back to decode-without-verification whenever verifyIdToken threw — 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 an exp check 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 flushAll cleared 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 and effectiveStock reverted to the stale snapshot (oversell window). Shipped: per-ID delta fold-out on acknowledged syncedIds only; 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 more
    • 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 _locallyModified was patched but absent from every RxDB schema (worked only because schema validation was off); _syncConflict was written once at creation and never used by anything. Shipped: _locallyModified declared in schemas; _syncConflict dropped, with conflict handling documented as an explicit LWW decision (architecture.md, replication.md).
    • Dead persistence configuration RXDB_STORAGE_PATH existed 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 the Restart=always interaction called out (operations.md).
    • Sticky replication errors lastError was never cleared after recovery, so /status showed a replica as erroring long after it had healed. Shipped: error timestamping + clearing once replication cycles cleanly (replication.md).
Read the full record in provenance.md

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.

  1. 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.

  2. 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.

  3. Never reset local stock deltas for transactions not acknowledged as synced.

    Deltas are folded out per transaction ID on acknowledgment, so effectiveStock stays correct across a partial flush; the suite's delta fold-out tests run against a real RxDB instance.

  4. 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-server

Claude 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 directory
  • references/architecture.mdModes, the two sync paths, replication tiers, tenant scope, the seams table
  • references/replication.mdRxDB setup, schemas, custom-token auth, security rules, the checkpoint trap
  • references/sync-flush.mdReconnect flush, per-ID stock deltas, idempotent cloud ingestion, retries
  • references/network-failover.mdHeartbeat/status chain, outage detection, terminal API switching, rescan
  • references/auth.mdLocal API guards: staff tokens, kiosk key, hardware HMAC, offline gating
  • references/local-api.mdThe offline endpoints: availability, booking mutex, check-in, pricing
  • references/operations.mdOn-site deployment: systemd, nginx TLS, mDNS, env vars, runbook
  • references/provenance.mdThe ledger: what the audit changed, what was kept, what is new and not yet run
  • assets/behavior.test.tsThe vitest suite carried into the target project as regression cover

Recent releases

  1. v0.1.5September 21, 2026

    Wording release. The skill content is unchanged from 0.1.4.

  2. v0.1.4September 2, 2026

    Wording release. Templates and technical content are unchanged from 0.1.3.

  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.

  1. 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 + RxDB
  2. Our 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:

  1. Step 1

    Brief

    Tell us what the module must connect to. Takes minutes, in a chat.

  2. Step 2

    Prototype in 48 hours

    A clickable prototype of your system and a quote, at no cost.

  3. 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-server

Build 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
3 years of support included.

Generated from the skill's own files at commit b1b4d51. Every rule above links to where the repository says it. All skills