Loadout — System Design Reference
Quick Navigation
| What you need | Load |
|---|---|
| Two-process overview, file map, state flow, build pipeline | references/architecture.md |
| Extension entry, src/ modules, data.js API, security model | references/extension-host.md |
| Angular 21, state services, DataSyncService, shared primitives | references/webview-angular.md |
| Full message catalogue (WebviewMessage + ExtensionMessage types) | references/messaging-protocol.md |
| Domain types, storage paths, profiles, hash/sync mechanics | references/domain-storage.md |
| File size limits, CommonJS rules, Angular rules, git, formatting | references/coding-rules.md |
| Design tokens, color palettes, SCSS mixins, animations, a11y | references/ui-design-system.md |
Non-negotiable invariants
These apply everywhere, always — no exceptions.
- No VSCode API in webview — never
import vscodeor usefs/path/osfrom any file underwebview/. - All filesystem mutations go through
data.js— no ad-hocfs.writeFileSyncinsrc/modules. - Every Angular component:
standalone: true+ChangeDetectionStrategy.OnPush— no exceptions. - State in
core/state/*.state.tssignal services only — components are dumb views; no component-local mutable state for domain data. - Signals for state, RxJS only for the bridge stream — no
BehaviorSubject/ReplaySubjectfor state. - File size cap ~400 lines — split into a new
src/module or Angular subcomponent when approaching this. - Profiles store filenames only — never copy file content into
profiles.json. - Icons:
lucide-angularonly — no SVG file imports, no inline<svg>. - CommonJS in extension host —
require()/module.exportsin all.jsroot files;update-claude.mjsis the sole ESM exception. - Build
webview-dist/before committing UI changes — runcd webview && npm run build.
Feature implementation checklist
When adding a new feature end-to-end, follow this order:
- Domain — add or extend types in
webview/src/app/core/messages.ts(single source of truth for all shared types). - Storage — decide persistence:
profiles.json,ui-state.json, or a newdata.jsfunction. Updatedata.jsandsrc/snapshot.js::buildInitialDataifInitialDatachanges. - Extension messages — add the
WebviewMessageunion variant and/orExtensionMessagevariant tomessages.ts; handle the new case insrc/message-handler.js. - data.js — implement the filesystem operation (pure I/O, no VSCode API, no side effects beyond fs).
- State service — update the relevant
core/state/*.state.tsto expose new signals or a setter; updateDataSyncService.applyData()ifInitialDatafields changed. - Component — create a standalone
OnPushcomponent or extend an existing feature. Inject the state service; never own domain state locally. Send actions viabridge.send()in methods, not templates. - Validators — if new user-supplied input crosses the bridge, add a guard in
src/validators.jsand call it inmessage-handler.jsbefore acting. - Build — run
cd webview && npm run build, verifywebview-dist/is updated. - Git — stage specific files by name; conventional commit in imperative mood.