* ⚡ Build the frontend bundle once for all E2E suites Merge tests-integration, tests-composable-suite and tests-plugin-api-suite into one "CI: E2E" workflow. Each of the three ran its own full frontend/scripts/build on every PR, so one PR paid the build three times. The new build-bundle job restores actions/cache key frontend-bundle-<sha>, runs frontend/scripts/build only on a miss and saves the key before the job ends. The integration shards, the composable suite and the mocked Plugin API suite now all need build-bundle and restore the same key with fail-on-cache-miss, so none of them builds. A workflow re-run of the same SHA reuses the cached bundle instead of rebuilding it. Triggers become the union of the previous paths (frontend, common, render-wasm, plugins): the bundle embeds the built plugins, so a plugins change runs the whole set. workflow_dispatch keeps running the integration job only, as before. Job names are kept identical on purpose: they are the GitHub check contexts and branch protection may match them by name. Docs: new mem:frontend/e2e-ci-workflow records the build-once contract, referenced from mem:frontend/core and mem:frontend/testing; the composable memory and both suite READMEs are updated. AI-assisted-by: deepseek-v4.1-flash * 🐛 Fix mocked plugin suites crashing without frontend deps The mocked CI drivers shelled out to frontend/scripts/e2e-server.js, which imports express from frontend/node_modules. CI jobs install only plugins/ deps, so the import failed with ERR_MODULE_NOT_FOUND and the run timed out waiting for localhost:3000. Serve the prebuilt bundle with a zero-dependency static server built into each driver (ci/static-server.ts, kept in sync in both suites) plus node:test coverage for it. AI-assisted-by: muse-spark-1.3-contributor
4.0 KiB
Frontend Architecture and Workflow
Frontend: CLJS SPA; React/Rumext; Potok; RxJS; okulary refs; SCSS modules; shared common/; JS/TS workspace packages.
Stable namespace map
app.main.ui.*: Rumext/React UI components for workspace, dashboard, viewer, settings, auth, nitrate, etc.app.main.data.*: Potok event handlers and side effects.app.main.refs: reactive refs/lenses over store and derived workspace data.app.main.store: Potok store andemit!.app.plugins.*andapp.plugins: CLJS implementation of Plugin JS API proxies.app.render_wasm.*: frontend bridge to Rust/WASM renderer.app.util.*: DOM, HTTP, i18n, keyboard, codegen, and general frontend utilities.frontend/packages/*andfrontend/text-editor: JS/TS workspace packages consumed by the app.- Nitrate subscription/organization UI and flows live under
app.main.data.nitrateandapp.main.ui.nitrate*; backend/API behavior is covered by backend memories, and shared permission rules are incommon/src/app/common/types/nitrate_permissions.cljc. app.configexternal bridges (external-feature-flag,external-session-id,external-context-info,external-notify-register-success,initialize-external-context-info) delegate toglobalThishooks injected by the SaaS host. Never deleteexternal-feature-flag, even with zero call sites: it is the seam for future A/B tests.
Lint and Format
From frontend/:
- CLJ/CLJS lint:
pnpm run lint:clj. - JS lint currently no-ops via
pnpm run lint:js. - SCSS lint:
pnpm run lint:scss. - Format checks:
pnpm run check-fmt:clj,pnpm run check-fmt:js,pnpm run check-fmt:scss. - Format fix:
pnpm run fmt, or targetedfmt:clj/fmt:js/fmt:scss. After runningfmt:*,check-fmt:*is redundant. - Translation formatting after i18n edits:
pnpm run translations.
Before linting: if delimiter errors are suspected (after LLM edits, or
lint/compiler reports syntax errors), run scripts/paren-repair on the
affected files first. Delimiter errors produce misleading linter output.
See mem:scripts/paren-repair.
Focused memory routing
UI and packages:
- App UI components, SCSS modules, style-system boundaries, accessibility, i18n, and render performance:
mem:frontend/ui-conventions-and-style-system. - JS/TS packages, shared UI package, text editor, Storybook, and package builds:
mem:frontend/ui-packages-text-editor-workflow.
Workspace behavior:
- Workspace state, commits, persistence, undo, repo calls, and refs:
mem:frontend/workspace-state-persistence-subtleties. - Workspace transforms, modifier previews, WASM modifier integration, and transform commits:
mem:frontend/workspace-transform-subtleties. - Workspace token application/propagation:
mem:frontend/workspace-token-subtleties; shared token data/schema:mem:common/tokens-schema-subtleties.
App shell and product flows:
- Routing, root app shell, websocket, and global errors:
mem:frontend/routing-app-shell-subtleties. - Dashboard and viewer flows:
mem:frontend/dashboard-viewer-subtleties. - Plugin JS API runtime inside the frontend app:
mem:frontend/plugin-api-to-cljs-binding.
Diagnostics and validation:
- Runtime inspection and navigation:
mem:frontend/cljs-repl. - Source-edit compile/hot-reload diagnostics:
mem:frontend/compile-diagnostics. - Runtime crash recovery:
mem:frontend/handling-crashes. - Tests and live verification:
mem:frontend/testing. - CI end-to-end workflow (build-once frontend bundle, check names):
mem:frontend/e2e-ci-workflow. - Cross-cutting testing principles and anti-patterns:
mem:testing. - Real pointer/keyboard gesture reproduction:
mem:frontend/playwright-gestures.
Areas without focused memories
These frontend areas currently have no dedicated Serena memory beyond this architecture entry and nearby source/tests: clipboard, drawing tools, boolean/path operations, interactions/prototyping, color/style asset management, grid-layout editing UI, comments UI, fonts UI, and many dashboard/settings subflows. Treat work there as less memory-covered and inspect source/tests more carefully.