Update version references from Angular 20 to Angular 21 and Taiga UI to Taiga UI 5 across architecture docs. Update web/CLAUDE.md with improved Taiga golden rules: prioritize MCP server for docs, remove hardcoded component examples in favor of live doc lookups. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6.1 KiB
Architecture
StartOS is an open-source Linux distribution for running personal servers. It manages discovery, installation, network configuration, backups, and health monitoring of self-hosted services.
Tech Stack
- Backend: Rust (async/Tokio, Axum web framework)
- Frontend: Angular 21 + TypeScript + Taiga UI 5
- Container runtime: Node.js/TypeScript with LXC
- Database/State: Patch-DB (git submodule) - storage layer with reactive frontend sync
- API: JSON-RPC via rpc-toolkit (see
core/rpc-toolkit.md) - Auth: Password + session cookie, public/private key signatures, local authcookie (see
core/src/middleware/auth/)
Project Structure
/
├── assets/ # Screenshots for README
├── build/ # Auxiliary files and scripts for deployed images
├── container-runtime/ # Node.js program managing package containers
├── core/ # Rust backend: API, daemon (startd), CLI (start-cli)
├── debian/ # Debian package maintainer scripts
├── image-recipe/ # Scripts for building StartOS images
├── patch-db/ # (submodule) Diff-based data store for frontend sync
├── sdk/ # TypeScript SDK for building StartOS packages
└── web/ # Web UIs (Angular)
Components
-
core/— Rust backend daemon. Produces a single binarystartboxthat is symlinked asstartd(main daemon),start-cli(CLI),start-container(runs inside LXC containers),registrybox(package registry), andtunnelbox(VPN/tunnel). Handles all backend logic: RPC API, service lifecycle, networking (DNS, ACME, WiFi, Tor, WireGuard), backups, and database state management. See core/ARCHITECTURE.md. -
web/— Angular 21 + TypeScript workspace using Taiga UI 5. Contains three applications (admin UI, setup wizard, VPN management) and two shared libraries (common components/services, marketplace). Communicates with the backend exclusively via JSON-RPC. See web/ARCHITECTURE.md. -
container-runtime/— Node.js runtime that runs inside each service's LXC container. Loads the service's JavaScript from its S9PK package and manages subcontainers. Communicates with the host daemon via JSON-RPC over Unix socket. See container-runtime/CLAUDE.md. -
sdk/— TypeScript SDK for packaging services for StartOS (@start9labs/start-sdk). Split intobase/(core types, ABI definitions, effects interface, consumed by web as@start9labs/start-sdk-base) andpackage/(full SDK for service developers, consumed by container-runtime as@start9labs/start-sdk). -
patch-db/— Git submodule providing diff-based state synchronization. Uses CBOR encoding. Backend mutations produce diffs that are pushed to the frontend via WebSocket, enabling reactive UI updates without polling. See patch-db repo.
Build Pipeline
Components have a strict dependency chain. Changes flow in one direction:
Rust (core/)
→ cargo test exports ts-rs types to core/bindings/
→ rsync copies to sdk/base/lib/osBindings/
→ SDK build produces baseDist/ and dist/
→ web/ consumes baseDist/ (via @start9labs/start-sdk-base)
→ container-runtime/ consumes dist/ (via @start9labs/start-sdk)
Key make targets along this chain:
| Step | Command | What it does |
|---|---|---|
| 1 | cargo check -p start-os |
Verify Rust compiles |
| 2 | make ts-bindings |
Export ts-rs types → rsync to SDK |
| 3 | cd sdk && make baseDist dist |
Build SDK packages |
| 4 | cd web && npm run check |
Type-check Angular projects |
| 5 | cd container-runtime && npm run check |
Type-check runtime |
Important: Editing sdk/base/lib/osBindings/*.ts alone is NOT sufficient — you must rebuild the SDK bundle (step 3) before web/container-runtime can see the changes.
Cross-Layer Verification
When making changes across multiple layers (Rust, SDK, web, container-runtime), verify in this order:
- Rust:
cargo check -p start-os— verifies core compiles - TS bindings:
make ts-bindings— regenerates TypeScript types from Rust#[ts(export)]structs- Runs
./core/build/build-ts.shto export ts-rs types tocore/bindings/ - Syncs
core/bindings/→sdk/base/lib/osBindings/via rsync - If you manually edit files in
sdk/base/lib/osBindings/, you must still rebuild the SDK (step 3)
- Runs
- SDK bundle:
cd sdk && make baseDist dist— compiles SDK source into packagesbaseDist/is consumed by/web(via@start9labs/start-sdk-base)dist/is consumed by/container-runtime(via@start9labs/start-sdk)- Web and container-runtime reference the built SDK, not source files
- Web type check:
cd web && npm run check— type-checks all Angular projects - Container runtime type check:
cd container-runtime && npm run check— type-checks the runtime
Data Flow: Backend to Frontend
StartOS uses Patch-DB for reactive state synchronization:
- The backend mutates state via
db.mutate(), producing CBOR diffs - Diffs are pushed to the frontend over a persistent WebSocket connection
- The frontend applies diffs to its local state copy and notifies observers
- Components watch specific database paths via
PatchDB.watch$(), receiving updates reactively
This means the UI is always eventually consistent with the backend — after any mutating API call, the frontend waits for the corresponding PatchDB diff before resolving, so the UI reflects the result immediately.
Further Reading
- core/ARCHITECTURE.md — Rust backend architecture
- web/ARCHITECTURE.md — Angular frontend architecture
- container-runtime/CLAUDE.md — Container runtime details
- core/rpc-toolkit.md — JSON-RPC handler patterns
- core/s9pk-structure.md — S9PK package format
- docs/exver.md — Extended versioning format
- docs/VERSION_BUMP.md — Version bumping guide