@we/app-shell
August 27, 2026 · View on GitHub
The biggest package in the repo, and the one place framework, backend contract, and product meet. These are the rules that keep it navigable.
Layering
src/shared/is framework-neutral: no Solid imports. Platform and backend contracts live here; their implementations live with the hosts (createDesktopPlatformis the one shared implementation, because the shape is identical across desktop hosts).src/frameworks/solid/is the app. A future second framework is a sibling directory, not edits here.- Never import
@coasys/*outsidesrc/shared/backendwiring — data access goes through the ports from@we/backend-shared. The renderer, design system and modules never see a backend.
Stores
- One provider per concern, nested in
StoreProvider.tsx. The nesting order is load-bearing: a store may read stores above it, never below. A parent needing something from a child is a design smell — the existing upward callbacks (registerHistoryCallbacks,provideSpaceLookup,provideInstalledModules,setNavigateFunction) are tolerated debt, not a pattern to extend. - A store's public surface is schema-facing API. Every state member and
action is reachable from templates through an expression or
$action, extracted into the generated reference by@we/ai-context— so name members for template authors, document them inai-context/src/fragments/stores.ts, and treat removals as breaking (a stale fragment entry fails the build). - No scratch members on stores. A debug helper on the store surface is
template-reachable vocabulary (
spaceStore.testexisted; it is gone). - Async actions that schemas await (
$action+onSuccess) must reject on failure —onSuccessfiring on a failed join is a lie in the UI.
Schemas
- Built-in template schemas live in
src/shared/schemas/as.schema.tsfiles; validate withpnpm --filter @we/schema-shared validateafter any change. - Developer-only surfaces (the schema test harness) are DEV-gated at their registration site, not shipped and hidden.
UI code
- Use DS components and props (
Column/Row/we-*withgap/p/bg/…), not raw divs withstyle={{}}— thedesign-system/prefer-ds-propslint rule enforces the overlap. Rawstyleis for CSS with no DS equivalent (three.js mounts, router internals). - Logging:
console.warn/errorfor real diagnostics; anything chattier is DEV-gated. User-facing failures go through the toast service /$onError, not the console.
Tests
tests/runs against@we/backend-inmemory's ports — no executor. If a store behaviour can't be tested that way, that is a gap in the in-memory backend's conformance surface; extend it there rather than mocking around it.