## What Two related bugs found while looking at why #7187's a11y check behaves differently on CI than locally. ### 21 stories were never being scanned on CI The scan tasks only depended on `install`, not `prepare`. On a fresh checkout that means the generated icon set (`editor/src/assets/material-symbols-icons.json`, gitignored) doesn't exist, so every story that reaches `LocalIcon` fails to import: ``` Failed to resolve import "../../../assets/material-symbols-icons.json" from "editor/src/core/components/shared/LocalIcon.tsx" ``` On CI that was four story files / 21 stories, every run. It works locally only because our trees already have the file from a previous build. The scan tasks now depend on `prepare`, like the `build:*` tasks do. ### The gate reported those runs as clean Worse than the missing stories: a file that fails to import produces a **failed suite with no assertions**. Every check in `a11y-check.mjs` reads assertions, so the file satisfied the manifest, contributed nothing to compare, and the run printed `✓ no a11y regressions`. An assertion-less failed suite now fails the gate and points at the scan log for the underlying resolve error. `--record` refuses in the same situation, so a baseline can't be written that quietly drops those stories. Also switched the affected-story emptiness test to single quotes, since that list now carries its own per-path quoting (it was producing `[ -z ""a" "b"" ]`). ## Testing - Deleted the generated asset to reproduce a fresh checkout: the gate **fails** with the file named and the cause explained, where before it printed `✓ no a11y regressions` and exited 0. - With the `prepare` dependency the task regenerates the asset itself and the previously-invisible files scan: 21 stories, 35 story-rule pairs, all already baselined.
Frontend
All frontend commands are run from the repository root using Task:
task frontend:dev— start Vite dev server (localhost:5173)task frontend:build— production buildtask frontend:test— run teststask frontend:test:watch— run tests in watch modetask frontend:lint— run ESLint + cycle detectiontask frontend:typecheck— run TypeScript type checkingtask frontend:check— run typecheck + lint + testtask frontend:install— install npm dependencies
For desktop app development, see the Tauri section below.
Layout
frontend/ is a workspace containing one or more apps. Today it holds the
PDF editor under frontend/editor/; new apps (the developer portal, etc.)
will sit alongside it as siblings. Shared tooling — package.json, node_modules,
.storybook/, ESLint, Prettier — lives at frontend/ so every app installs
once and lints with the same config.
Environment Variables
The editor's environment variables live in committed .env files at
frontend/editor/:
.env— used by all builds (core, proprietary, and as the base for desktop/SaaS).env.desktop— additional vars loaded in desktop (Tauri) mode.env.saas— additional vars loaded in SaaS mode
These files contain non-secret defaults and are checked into Git, so most dev work needs no further setup.
To override values locally (API keys, machine-specific settings), create an uncommitted sibling editor/.env.local / editor/.env.desktop.local / editor/.env.saas.local. Vite automatically layers these on top of the committed files.
Docker Setup
For Docker deployments and configuration, see the Docker README.
Tauri
All desktop tasks are available via Task. From the root of the repo:
Dev
task desktop:dev
This ensures the JLink runtime and backend JAR exist (skipping if already built), then starts Tauri in dev mode.
Build
task desktop:build
This does a full clean rebuild of the backend JAR and JLink runtime, then builds the Tauri app for production.
Platform-specific dev builds are also available:
task desktop:build:dev # No bundling
task desktop:build:dev:mac # macOS .app bundle
task desktop:build:dev:windows # Windows NSIS installer
task desktop:build:dev:linux # Linux AppImage
JLink Tasks
You can also run JLink steps individually:
task desktop:jlink # Build JAR + create JLink runtime
task desktop:jlink:jar # Build backend JAR only
task desktop:jlink:runtime # Create JLink custom JRE only
task desktop:jlink:clean # Remove JLink artifacts
Clean
task desktop:clean
Removes all desktop build artifacts including JLink runtime, bundled JARs, Cargo build, and dist/build directories.