Skip to content

Offline capabilities

Syndik8 is offline-first. The app keeps a local copy of your syndicate data in an on-device SQLite database and uses it for almost everything the UI shows. Reads and writes work without an internet connection; writes queue and sync on reconnection.

The sync engine is PowerSync. The data flow is: your device ↔ PowerSync service ↔ Supabase Postgres. PowerSync replicates a filtered view of the Postgres tables to the local SQLite and pushes local writes back.

Every member, on every supported platform. Offline behaviour is not opt-in and there is no per-user toggle.

  • The behaviour is part of every screen. You do not navigate to an “offline mode”.
  • The traffic-light profile avatar in the navigation chrome is the live indicator:
ColourState
GreenConnected and receiving real-time updates.
AmberReconnecting.
RedOffline — no PowerSync session and no network.

Syndik8 syncs around twenty tables locally. These carry almost all of the day-to-day UI:

AreaSynced tablesWrites
Coresyndicates, memberships, user_profilesOffline
Assetsassets, asset_types, asset_billing_configsMixed — config writes go online via repository
Calendarbookings, eventsOffline
Usage and maintenanceusage_logs, maintenance_items, maintenance_templates, maintenance_logs, squawksOffline
Finance — read-only projectionstransactions, expenses, billing_schemesOnline-only writes. Members can see balances, expenses, and the configured rate schemes without a connection; changes to those tables go through the server.
Payments — read-only projectionsmandates, member_funds, advance_noticesOnline-only writes. Direct-debit mandate, member loan / goodwill / refund-as-credit, and “debit incoming” cards visible offline; setup and changes go through provider Edge Functions.
NotificationsnotificationsOffline

The authoritative list lives in internal-docs/ARCHITECTURE.md (“Synced Tables Reference”) and the client schema at lib/data/powersync/schema.dart.

Sync follows active membership. Each device only receives data for syndicates where the user’s membership status is active. The moment a member leaves or an admin removes them, the syndicate’s tables stop syncing to their device and the offline cache no longer refreshes — past entries already on the device remain until the next clean sync clears them.

TableWhy online-only
settlements, reversals, disbursements, payment_eventsLedger sources of truth — money conflicts are unacceptable.
invitesDepends on server-side auth checks.
notification_preferencesPer-user setting read rarely.
member_balances (view)Computed from synced transactions — no row to sync.
asset_scheme_rate_overridesRead on demand.
CapabilityBehaviour
View synced dataCalendar, bookings, usage, maintenance, squawks, members, balances — all read from the local SQLite.
Maintenance check before bookingComputed locally from synced maintenance items, asset meter, and recent usage logs. ~10 ms typical; no network round-trip.
Create a bookingSaved locally; syncs as pending or confirmed on reconnection. Snackbar reads Booking created — will sync when you’re back online.
Approve, reject, confirm, or cancel a bookingSaved locally; syncs on reconnection. Snackbars carry the same “will sync” suffix offline.
Log usageStored locally with photo URLs pointing at uploaded evidence (the photo itself uploads when online).
Report a squawkStored locally; syncs on reconnection.
Read transactions and statementsFinancial reads are offline-capable from the synced transactions table.
Submit an expenseStored locally; syncs on reconnection. Receipt photo uploads when online.

These actions are gated by a button that disables when the device is offline. Tapping (or hovering on web) shows the reason snackbar listed below.

ActionReason snackbarWhy blocked
Create or revoke an inviteInvites need a connection — try again when you’re online.Server-side auth flow.
Finalise a booking (single or bulk)Settlements need a connection — try again when you’re online.Calls the finalise_booking / bulk_finalise RPC, which writes the per-log charges, shortfall transactions, and flips the booking status. Money conflicts are unacceptable, so the action cannot be queued.
Approve or reject an expenseApproval needs a connection — try again when you’re online.Writes an expenseCredit (or rejection) to the financial ledger.
Start payment provider setup (Stripe / UniPaaS)Payment setup needs a connection — try again when you’re online.Hits external Edge Functions that have no offline contract.
Update notification preferencesn/a — page itself fetches onlineRead from / written to user_profiles.notification_preferences online.
Payment checkoutn/aWeb-only, opens the checkout URL in a new tab (see upgrade prompt).
Load a legal document not yet cachedn/aTerms of Service and Privacy Policy are fetched from the server; a not-yet-cached copy is unavailable offline.
  • Writes queue locally. A booking, usage log, or squawk created offline is written to the local SQLite immediately and appears in the UI. PowerSync pushes the change when the device reconnects.
  • Last-write-wins for most conflicts. If two devices edit the same record offline and reconnect, the later write replaces the earlier one. There is no three-way merge.
  • Overlapping bookings are rejected on the server. Two members who create overlapping confirmed bookings offline will both see them locally; when sync runs, the one that reaches the server first is accepted and the other is rejected by the database exclusion constraint and surfaces as a sync error.
  • Tentative bookings do not conflict. Multiple tentative bookings can coexist on the same slot — the database constraint covers confirmed only.
  • Photos upload separately. A usage-log photo is staged on the device and uploaded to Supabase Storage when online. The log itself appears immediately; the photo is available when it finishes uploading.
  • The traffic-light indicator reacts in seconds. OS-level network callbacks flip the colour to red as soon as the device loses connectivity, rather than waiting for a WebSocket heartbeat timeout.
  • First-sync-on-signin. On a fresh signin, PowerSync clears any prior local data and re-hydrates from scratch. Network outages during that first pass mean the UI is usable only for the tables that completed before the outage.
  • Online-only buttons disable themselves and explain why. Booking finalisation, expense approve/reject, invite generation, and payment-provider setup all watch the connectivity stream. When the device is offline, the button is disabled; tapping it shows a short reason snackbar (e.g. Settlements need a connection). The button re-enables automatically when connectivity returns.
  • PowerSync-backed write success messages adapt to connectivity. When you create or edit something while offline, the success snackbar appends — will sync when you’re back online on a second line so it’s clear the change is queued, not delivered.
  • Maintenance check before booking is computed locally. When you open the booking dialog, Syndik8 evaluates the asset’s open maintenance items (hours-based and calendar-based) against the synced meter reading and recent usage logs in around 10 ms — no network call. The amber/red warning surfaces in the dialog whether the device is online or offline.
  • Web sessions clear local data when the tab closes. The web build does not background-sync closed tabs. iOS and Android keep local data across app launches until sign-out.

For the reasoning behind offline-first, see Offline-first architecture.