Cynario Cynario alpha
Browse docs

Architecture

Architecture

The technical architecture for Cynario — a client-side, static web app with a Builder and a Player over one shared scenario document, plus import/export and local storage.

On this page

Design doc, evolving. This page captures the system design. Some implementation details below reflect an earlier proposed stack; the live app is built on Astro + Svelte + Svelte Flow (see the tech stack in the repo). The load-bearing shape is a client-side Builder and Player over one scenario document. Optional sharing, collaboration, catalogs, and protected sources add network infrastructure around that local-first core without making it a central plaintext scenario service.

High-level architecture

┌─────────────────────────────────────────────────────────────────┐
│                        CYNARIO WEB APP                          │
│                     (Client-Side / Static)                      │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────────────┐ │
│  │   PLAYER    │    │   BUILDER   │    │    SHARED STATE     │ │
│  │   MODE      │    │   MODE      │    │                     │ │
│  │             │    │             │    │                     │ │
│  │ • Narrative │    │ • Graph     │    │ • Current scenario  │ │
│  │   display   │    │   editor    │    │ • Player position   │ │
│  │ • Choices   │    │ • Node      │    │ • History           │ │
│  │ • Progress  │    │   editor    │    │ • Settings          │ │
│  │ • Score     │    │ • Edge      │    │                     │ │
│  │             │    │   editor    │    │                     │ │
│  └──────┬──────┘    └──────┬──────┘    └──────────┬──────────┘ │
│         │                  │                      │             │
│         └──────────────────┼──────────────────────┘             │
│                            │                                    │
│                   ┌────────▼────────┐                          │
│                   │  SCENARIO DATA  │                          │
│                   │  (JSON Schema)  │                          │
│                   │                 │                          │
│                   │ • Nodes[]       │                          │
│                   │ • Edges[]       │                          │
│                   │ • Metadata      │                          │
│                   └────────┬────────┘                          │
│                            │                                    │
│              ┌─────────────┼─────────────┐                     │
│              │             │             │                     │
│        ┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐              │
│        │  Import   │ │  Local    │ │  Export   │              │
│        │  (JSON)   │ │  Storage  │ │  (JSON)   │              │
│        └───────────┘ └───────────┘ └───────────┘              │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Tech stack

LayerTechnologyPurpose
FrameworkAstroStatic site generation
UISvelteSingle UI framework
Graph UISvelte FlowBuilder graph editor
LanguageTypeScriptType safety
StylingTailwind CSSUtility-first CSS
CollaborationTrystero / WebRTCEncrypted links and live peer sessions
EncryptionWeb Crypto APIAES-256-GCM
StoragelocalStorage + exportPersistence
HostingCloudflare PagesStatic hosting

Data flow

Player mode

┌──────────────┐     ┌───────────────┐     ┌─────────────────┐
│  Load JSON   │────▶│ Parse & Store │────▶│  Render Start   │
│  Scenario    │     │  in state     │     │     Node        │
└──────────────┘     └───────────────┘     └────────┬────────┘

                     ┌──────────────────────────────┘

              ┌─────────────┐
              │ User clicks │
              │   choice    │
              └──────┬──────┘

        ┌────────────▼────────────┐
        │  Update current node    │
        │  Push to history stack  │
        │  Update score           │
        └────────────┬────────────┘

            ┌────────▼────────┐
            │  Is ending?     │
            └────────┬────────┘

         ┌───────────┴───────────┐
         ▼                       ▼
   ┌───────────┐          ┌───────────┐
   │  Render   │          │  Show     │
   │ next node │          │  ending   │
   └───────────┘          └───────────┘

Builder mode

┌─────────────────────────────────────────────────────────────┐
│                       Graph Canvas                           │
│  ┌─────┐    ┌─────┐    ┌─────┐                             │
│  │ A   │───▶│ B   │───▶│ C   │                             │
│  └──┬──┘    └─────┘    └─────┘                             │
│     │                                                       │
│  On node click ─────────────────────────────────────────────┼───┐
└─────────────────────────────────────────────────────────────┘   │

                                    ┌──────────────────────────────┘

                           ┌───────────────────┐
                           │   Node Editor     │
                           │   Sidebar         │
                           │                   │
                           │ • Title           │
                           │ • Content (MD)    │
                           │ • Type            │
                           │ • Score/Badge     │
                           │                   │
                           │ [Save] [Delete]   │
                           └─────────┬─────────┘


                           ┌───────────────────┐
                           │  Scenario Store   │
                           │  (nodes, edges)   │
                           └─────────┬─────────┘

                   ┌─────────────────┴─────────────────┐
                   ▼                                   ▼
          ┌───────────────┐                   ┌───────────────┐
          │ Re-render     │                   │ Auto-save     │
          │ graph         │                   │ to localStorage│
          └───────────────┘                   └───────────────┘

URL structure

/                    - Home (scenario list, import)
/builder             - Builder (visual graph editor)
/player              - Player (narrative interface)

Security considerations

  • XSS in Markdown: Rendered content is sanitized before display.
  • JSON import: Validate against the schema before loading.
  • Local storage: No sensitive data stored beyond the scenario you opened.
  • Local-first core: Builder and Player do not require a central application database. Static hosts, catalog sources, signaling, relays, and containers remain ordinary network trust surfaces.

See the full trust model on the Security & trust page.

Performance considerations

  • Large graphs: Svelte Flow handles many nodes; virtualize where needed.
  • Markdown rendering: Memoize parsed content.
  • Bundle size: Tree-shake unused components.
  • Offline: Cache scenario files for offline play (PWA).