Skip to content

System context diagram

Purpose: show how clients, the API, and Appwrite relate at runtime. Status: as of 2026-06-19.

flowchart TB
    subgraph Clients
        WEB["Web<br/>Next.js 16 / React 19"]
        AND["Android terminal<br/>Kotlin (offline-first)"]
    end

    subgraph Backend
        API["NestJS API<br/>+ DBOS durable workflows"]
        PSP["PSP / external services"]
        PG[("Postgres<br/>legacy non-POS via TypeORM")]
    end

    subgraph Appwrite
        DB[("Databases<br/>POS collections")]
        ACC["Account<br/>sessions / JWT / MFA / custom token"]
        TEAMS["Teams<br/>1 per merchant"]
        STO["Storage<br/>buckets + file tokens"]
        FN["Functions"]
        RT["Realtime"]
    end

    WEB -- "simple reads/writes (SDK)" --> DB
    AND -- "simple reads/writes (SDK)" --> DB
    AND -- "cache refresh" --> RT
    WEB -- "cookie session" --> ACC
    AND -- "JWT" --> ACC

    WEB -- "complex commands (REST)" --> API
    AND -- "complex commands + PIN login (REST)" --> API

    API -- "validate Appwrite token" --> ACC
    API -- "orchestrate / write" --> DB
    API -- "mint custom token (PIN)" --> ACC
    API -- "capture/refund" --> PSP
    API -- "legacy domains" --> PG

    DB -. "permissions scoped by" .- TEAMS
Web (Next.js) Android terminal (Kotlin, offline-first)
| \ / |
cookie | \ simple reads/writes (SDK) / | JWT
session | \------------> Appwrite <-------/ |
| Databases / Account / Teams / |
| Storage / Functions / Realtime |
| ^ |
| complex commands | validate token / | complex commands
| (REST) | mint PIN custom token | + PIN login (REST)
+-------------> NestJS API (+ DBOS) <-----------+
| \
PSP / external Postgres (legacy non-POS via TypeORM)
  • Direct path: clients use the Appwrite SDK for simple reads/writes and sessions.
  • Complex path: state-changing/durable commands go to NestJS, which validates the Appwrite token and may orchestrate Appwrite writes (DBOS for must-succeed flows).
  • PIN login: NestJS verifies the PIN and mints an Appwrite custom token the client exchanges for a session.
  • Tenant isolation is enforced by Appwrite document permissions tied to Teams (one per merchant).
  • Postgres/TypeORM remains only for legacy non-POS domains until their later migration.

See appwrite and ../business-rules/auth-and-multitenancy.md.