Architecture

Single entry-point for understanding ARNO at the system level. Diagrams are C4-style (L1 system context, L2 containers). Drill-down into individual containers via the linked package _index.md / INTERNALS.md.

Canonical source for why each piece exists: _index.md (master spec). This doc is the what + how-they-connect map.

Last reviewed: 2026-05-24

L1 — System context

Who interacts with ARNO and which external systems it depends on.

Key constraints (from master spec §0.3):

  • ARNO does not own approval / CI / hosting / build / auth — it leverages GitHub, Yjs/Liveblocks, Cloudflare, Sentry.
  • Source of truth split: code+TSX in git; MD specs in git (authored in ARNO); live workflow state in Yjs (Liveblocks); MD edit live state + ops metadata in Postgres.
  • All entities identified by UUID (refactor-safe).

L2 — Containers

What ships and runs separately. Each box has its own deploy unit and _index.md.

Container responsibilities

ContainerRepo pathDeploys toOwns
apps/webapps/web/CF Pages (arnomake.com)UI shell, workflow canvas, MD editor, render-adapter parent, store hooks
apps/apiapps/api/CF Workers Paid (arno-api.vadimpianof.workers.dev)REST, OAuth, GitHub App, Liveblocks auth, GDPR, URL-import API
Render-adapter iframe(lives in client repo, e.g. vadimpianov/-/arno.entry.tsx)GH Pages (vadimpianov.github.io/-/arno-bundle.js)Real React render of project's components

Shared packages

PackagePurposeUsed byHas internals doc?
@arno/sharedPure domain types + immutable mutationsweb, apiPending — see TODO
@arno/editorMD parser + stores (no React)webPending
@arno/render-adapterpostMessage protocol — single source of truth for iframe contractweb, render iframe (external repo)Pending
@arno/dbDrizzle schema + Neon HTTP driver factoryapiPending
@arno/git-providerPluggable git host abstraction; today GitHub-onlyapiPending
@arno/url-import-extractorURL-import pipeline stagesapiPending
@arno/atom-pocAtom embedding + sanitization PoC(poc only)Pending

L3 — Key flows (pointers to deep-dives)

Detailed sequence diagrams should live in each INTERNALS.md. As they're written, link them from here.

Composition propagation (killer feature)

Question: Maker edits a component spec MD — how does the change reach every screen in every project that uses that component?

  1. MD edit → PUT /api/v1/md/... (in apps/api/src/md.ts (opens in a new tab)) → writes new row in component_md_versions, updates component_md_raw.current_version.
  2. LibraryStore on connected clients invalidates cache for that spec UUID.
  3. Every screen referencing instances of that spec re-renders via useSyncExternalStore subscription.
  4. Render-adapter iframe receives new tree → re-paints.

Deep-dive owner: packages/editor/INTERNALS.md (TBD).

URL-import pipeline

Question: small-biz Maker pastes a URL — how do components arrive in the staging area?

  1. POST /api/v1/url-imports (apps/api/src/url-imports.ts (opens in a new tab))
  2. Pipeline (packages/url-import-extractor/): safe-fetch → sanitize → decompose into atoms → extract candidate components → verify (completeness matrix) → reactive vision fallback if incomplete → integrate into TSX + tokens + stories
  3. Output staged in staged_component table + Modal Volume / B2 (ADR 0016)
  4. UI lists, edits, previews, eventually promotes to a PR (V2)

Deep-dive owner: docs/url_import_spec.md (already exists, comprehensive).

Drift detection

Question: Frontend dev modifies TSX without updating the MD spec — how does ARNO surface the mismatch?

  1. Push to connected repo → GH Action arno-check.yml runs → emits Check Run with status drift_detected and details
  2. GitHub webhook (check_run event) → apps/api/src/webhooks.ts (opens in a new tab) → upsert component_drift row
  3. Liveblocks broadcast drift_detected { componentId, mismatches, status } to project:${id} room
  4. Web shows banner / indicator on affected screens

Deep-dive owner: apps/api/INTERNALS.md (TBD — split: webhook handling, sync replay).

Sync (session-branch → main snapshot)

Question: Maker finishes a workflow edit — when and how does it land in git?

  1. Yjs document quiescent → activity-based snapshot fires (§0.3 principle 5)
  2. apps/api/src/sync.ts (opens in a new tab) reads Yjs state via Liveblocks REST
  3. Commits to arno/{user-handle} session-branch via GitHub App installation token
  4. (Phase 13) Opens / updates PR to main
  5. Bundle CI runs; success → drift cleared; failure → blocks merge

Deep-dive owner: apps/api/INTERNALS.md + docs/runbooks/ operational side.


TODO: INTERNALS.md coverage

Each package needs an INTERNALS.md that explains lifecycle, invariants, and non-obvious behaviour — _index.md is currently a catalog, not an explainer. Priority order (largest knowledge gap first):

  1. apps/api — 11 source files, only ~⅓ documented in _index.md. Critical because it touches auth, webhooks, GDPR, GitHub App.
  2. packages/editorLibraryStore state machine and CompositionStore subscription model deserve a walkthrough.
  3. apps/web — store topology, route tree, render-adapter parent integration.
  4. packages/url-import-extractor — pipeline stages + extension points (spec exists, code map missing).
  5. packages/db — schema reference is auto-generated; migration discipline + Neon HTTP-driver caveats are not.
  6. packages/render-adapter — protocol versioning + cross-repo update procedure.
  7. packages/shared — small; an _index.md enhancement may be enough.
  8. packages/git-provider — small; defer until second provider added.

danger.js will continue posting warnings until INTERNALS.md exists in each package.


Related docs