Skip to content

Source code

Development

Requirements and setup

Use Node 24.15.0 or newer within Node 24 and Yarn 4.18.0, as declared in the root package.json. The optional .nvmrc selects the verified Node 24.20.0 runtime. nvm is not required when a compatible Node installation is already available.

Run commands from the repository root unless a procedure says otherwise:

Terminal window
# Optional, when using nvm:
nvm install
nvm use
# Enable the pinned package manager and install the locked dependencies:
corepack enable
yarn install --immutable
yarn dev

The showcase runs at http://127.0.0.1:5173/. Run yarn dev:starter in another terminal for http://127.0.0.1:5174/. Stop either process with Ctrl+C in its terminal. Both development servers bind to localhost and fail if their selected port is occupied.

Try a production build locally

After installing dependencies, run this from the repository root to build both applications and serve the production showcase:

Terminal window
yarn start

Open the production showcase. To try the already-built starter in another terminal, run yarn preview:starter and open the production starter.

You can also build and serve separately:

Terminal window
yarn build:production
yarn preview

The builds write optimized assets to src/showcase/dist/ and src/starter/dist/. Preview serves those files, so source edits appear only after rebuilding. Stop the server with Ctrl+C, then run yarn start again to rebuild and restart. Both preview commands bind to localhost and fail if their selected port is occupied. These commands serve local previews without publishing packages or deploying remotely. For production CSP, subdirectory hosting, and missing-asset acceptance checks, use maintainer verification.

Documentation and public site builds

Use yarn docs:build and yarn docs:preview for the standalone documentation site. Use yarn sites:prepare, yarn sites:images, and yarn sites:test to qualify both Docker images locally. The dedicated site build and hosting guide explains authoring, previews, generated artifacts, CI, Coolify, production eligibility, and release downloads.

Source layout

PathResponsibility
src/atrium/Shared @agon/atrium package with components, services, templates, SCSS, locales, and the HTML/icon build plugins.
src/publisher/Shared @agon/atrium-publisher application scaffolding and manifest/conflict checks.
src/showcase/Complete @agon/atrium-showcase demo with route definitions, page controllers, adapters, and fixtures.
src/starter/Portable @agon/atrium-starter consumer for a new application.
src/tests/unit/Vitest checks for state, adapters, storage, formatting, and transport contracts.
src/tests/browser/Playwright workflow, accessibility, and deployment checks.
src/tests/support/Production browser server and isolated Alpine/DOM unit-test support.
src/scripts/ci/Local GitLab runner, hosted job helpers, and shared verification contracts.
src/scripts/quality/Repository ESLint rules, source-header validation, and prose punctuation checks.
src/scripts/presentation/Versioned narration, video generation, screenshot capture, and editable-deck rendering tools.
docs/Human documentation, with task-specific agent guidance in docs/agents/.
skills/atrium-theme/Repository skill for shared UI, themes, template integration, and the application publisher.
skills/atrium-documentation-site/Repository skill for documentation content, rendering, search, and verified site artifacts.
skills/atrium-showcase-site/Repository skill for demonstration pages, adapters, fixtures, and public showcase artifacts.
skills/atrium-presentation-video/Repository skill for product-tour narration, videos, screenshots, and editable decks.

Root files contain workspace manifests, lockfiles, shared check configuration, and documentation entrypoints. Each workspace keeps its own package.json. Each application keeps its Vite configuration alongside its entry HTML so that the starter remains portable. Application directories are already under root src/ and do not contain redundant inner source directories.

Commands

CommandPurpose
yarn devStart the full showcase on port 5173.
yarn dev:starterStart the minimal application on port 5174.
yarn build / yarn build:productionBuild optimized applications into their respective src/<application>/dist/ directories.
yarn startBuild both production applications and preview the showcase on localhost port 4173.
yarn build:developmentBuild readable applications with source maps into src/<application>/dist-development/.
yarn previewPreview the built showcase on localhost port 4173.
yarn preview:starterPreview the built starter on localhost port 4174.
yarn formatFix JavaScript with ESLint, then format other maintained files with Prettier.
yarn format:checkCheck JavaScript with ESLint and other formatting with Prettier, without writing files.
yarn lintRun JavaScript style, correctness, JSDoc, and source-header checks.
yarn lint:headersCheck metadata in maintained scripts, stylesheets, templates, and comment-capable configuration.
yarn lint:proseCheck Markdown bullet endings and prose punctuation in documentation and source comments.
yarn lint:editorconfigCheck tracked files against EditorConfig.
yarn testRun the unit suite.
yarn test:coverageRequire 100% per-file coverage for statements, branches, functions, and lines, with HTML/Cobertura reports.
yarn ci:local listInspect the active allowlisted GitLab verification graph.
yarn ci:local validateValidate the local job dependency chain.
yarn ci:local fullExecute all seven GitLab verification jobs locally in Docker.
yarn checkRun formatting, EditorConfig, ESLint, unit tests with the coverage gate, and both builds.
yarn test:e2eRun browser tests against the configured running application.
yarn test:serveServe a production build for acceptance checks on port 4175.
yarn check:referenceVerify the optional reference against its recorded hashes.
yarn reference:captureGenerate the optional static visual reference snapshot.

Use yarn check before handing off repository-wide changes. Browser checks require a running server and Chromium. Follow verification for native or Docker browser commands, subdirectory hosting, and a standalone package consumer. Stop preview and fixture servers with Ctrl+C when finished.

For the same job execution as GitLab, follow local CI setup. It requires gitlab-ci-local 4.75.1, Docker, and an ignored owner-only variables file. Named actions support focused retries. full also runs production browser and packed-consumer checks with their own managed fixture servers. Coverage commands and report scope are documented in coverage reports.

The EditorConfig checker uses Git’s tracked file list. Stage new files before running it when you need those files checked, or pass explicit paths with yarn lint:editorconfig path/to/file. ESLint, Prettier, and the header checker also inspect new, non-ignored files in their respective source scopes. The checker package is a wrapper around the native EditorConfig checker and may download its platform binary on first use.

Product presentation tools

The presentation quick start and file guide identifies the scripts to edit, voice audition samples, generated showcase assets, and build entry points. Run yarn presentation:setup once, then yarn presentation:build to generate all three video bundles and rebuild the applications. Only final videos enter the showcase. Versioned JPG, VTT, TXT, and PPTX artifacts stay under docs/presentation/artifacts/. With the documented authoring runtime configured, yarn presentation:rebuild also regenerates the slides and PowerPoints. Run yarn presentation:check to validate inputs and yarn presentation:test for the isolated Python generator tests. These development tools do not add application dependencies.

Build modes

Both consumers use adminBuild({ mode, minify }) from @agon/atrium/vite. The shared policy covers JavaScript, CSS, entry HTML, and lazy page fragments:

SettingProductionDevelopment
Commandyarn build:productionyarn build:development
Output directorydist/dist-development/
Minification defaultEnabledDisabled
Source mapsDisabledEnabled
HTML metadata commentsRemoved, including without minificationPreserved unless minification is enabled
Diagnostic callsSelected calls removed by OxcPreserved

Override all three minifiers explicitly when needed:

Terminal window
ATRIUM_MINIFY=false yarn build:production
ATRIUM_MINIFY=true yarn build:development

Only true and false are accepted. Run the same commands without ATRIUM_MINIFY to restore the defaults. A single consumer can be built with yarn workspace @agon/atrium-starter build:development or its build script. Generated dist-* directories are ignored. yarn dev remains Vite’s live development server and does not create distribution files.

Production uses Vite’s built-in Oxc minifier with its policy in adminBuild under rolldownOptions.output.minify. It removes console.log, console.info, console.debug, console.warn, and debugger, retains console.error, argument side effects, and property-read side effects, and mangles local variables while preserving function/class names and public property names. Legal notices remain in generated JavaScript. Disabling production minification also disables these JavaScript reductions. Development keeps diagnostics even when minification is explicitly enabled. Applications need no separate JavaScript minifier dependency. Atrium’s HTML plugin still uses html-minifier-terser 7.2.0 for entry HTML and lazy fragments, which never enters the browser bundle.

index.html contains the shared shell and lightweight route outlets. Fingerprinted page chunks contain each compiled template and its optional controller. .vite/manifest.json records the chunk graph. The full ApexCharts renderer remains a large lazy chunk and is fetched only when a chart needs rendering. The full icon gallery also carries substantial route-only CSS. Inspect actual startup requests and use icon subsets in real applications. Arbitrarily splitting those libraries would not reduce the total code required by their feature pages. See architecture and lazy page contracts when adding routes.

Chunk-size warnings

The shared build policy keeps a 500 kB warning budget for minified JavaScript chunks. The known standalone ApexCharts renderer has a 1,100 kB budget because its current minified distribution is approximately 970 kB. It remains loaded on demand. The exception applies only to its recognized distribution modules, with no application code mixed in, and only while the chunk is exclusively dynamically imported. Other libraries, application chunks, eager chart imports, and ApexCharts growth beyond 1,100 kB still produce warnings naming the offending file and its budget.

Vite’s native build.chunkSizeWarningLimit is a single global threshold. adminBuild replaces that generic warning with src/atrium/build/chunk-warnings.js, installed through the returned rolldownOptions.plugins. Preserve those plugins when extending the returned build options. Adjust reviewed library budgets in that helper instead of raising the limit for all application code.

Sizes use decimal kB of final uncompressed JavaScript, before gzip or Brotli. CSS, video, and other assets retain their normal size reporting without this JavaScript warning. The policy does not change minification, emitted assets, loading behavior, or plugin-timing diagnostics. Unminified diagnostic builds do not emit these warnings.

Build timing diagnostics

Build timing diagnostics remain enabled through Rolldown’s defaults. Do not suppress timing reports with checks, a warning filter, or a reduced log level. The production build uses Vite’s native Oxc minification to remove the separate Terser JavaScript worker stage while preserving the tested diagnostic-removal and naming policies.

The PLUGIN_TIMINGS advisory reports elapsed time with plugin hooks active, including overlapping asynchronous work. A report such as 3.0s of this 3.1s build (98%) is not a measurement of CPU utilization. Hooks listed without individual times cannot be ranked reliably from this report. Use a CPU profile to locate expensive work before changing the build. See Rolldown’s timing documentation.

As verified on 2026-09-20, the latest published stable versions are Vite 8.3.0 and Rolldown 1.2.9. The online documentation already describes checks.bundlerTimings, while the released Rolldown accepts only checks.pluginTimings. Atrium sets neither property and retains the enabled default, so it does not rely on the deprecated alias or an unsupported future option. The report may still appear on slower machines or larger applications when Rolldown’s thresholds are met.

For a CPU profile of the showcase build, run from the repository root:

Terminal window
mkdir -p .reports/build-profiles
(
cd src/showcase
node --cpu-prof --cpu-prof-dir=../../.reports/build-profiles ../../node_modules/vite/bin/vite.js build --mode production
)

The command builds once and exits. Open the generated .cpuprofile files in a compatible JavaScript CPU profiler. They stay in the ignored .reports/build-profiles/ directory. Replace cd src/showcase with cd src/starter to profile the starter. Running inside the consumer directory matches the workspace build’s manifest paths. Node profiles JavaScript in the profiled process and supported worker threads. Native bundler work may require additional profiling, so the advisory alone is not enough to identify a bottleneck.

Icon collections

Both templates publish icons.config.mjs. Configure adminIcons({ sources: iconSources }) alongside the existing HTML plugin, then import only the virtual styles your application needs. The icon component guide covers Boxicons, Font Awesome versions, Lucide, custom collections, subsets, standalone Node generation, and the full gallery. Generated CSS and optional catalogue metadata pass through Vite without maintained generated files or a separate task runner. Iconify utilities and collection JSON are pinned dependencies of the shared build package and do not enter browser JavaScript.

Formatting and JavaScript configuration

.editorconfig provides editor defaults: UTF-8, LF endings, a final newline, no trailing whitespace, and two-space indentation. .editorconfig-checker.json adapts the sibling Agon skeleton’s checker settings and excludes archived, generated, and reference content. As in that repository, the checker leaves indentation-size validation disabled. ESLint Stylistic and Prettier enforce two-space formatting in their respective formats, while the checker enforces the other text conventions.

ESLint owns JavaScript formatting, correctness, and JSDoc checks. Prettier owns the remaining maintained formats and leaves embedded code examples unchanged. This separation preserves mandatory multiline objects and arrays. Every callable, including anonymous callbacks and test bodies, has a dedicated docblock. Source headers use the same purpose, author, and version contract. See coding standards for the exact rules and frontend guidance for the agent contract.

Repository-specific rules, the cross-format header checker, and the syntax-aware prose checker live in src/scripts/quality/. Their unit tests exercise callback attachment, exception boundaries, header validation, and formatter stability. Run yarn format to apply safe fixes. Missing documentation and deliberate exception handling still need a human-quality edit. Run yarn lint to enforce the full contract, and yarn check for all quality gates.

An .mjs file is explicitly an ES module. A .js file is also an ES module here because the relevant package.json declares "type": "module". Both extensions support ESLint’s flat configuration with the same behavior in this repository. The explicit .mjs suffix makes configuration independent of implicit package mode and aligns with the other Agon JavaScript application. Runtime source stays .js.

Helper ownership

The former tooling/ folder contained development helpers, not application runtime code. Its responsibilities now have explicit homes:

  • src/tests/support/serve-fixture.js: Serves built assets with production CSP, history fallback, and genuine missing-asset errors. It accepts DIST_DIR, BASE_PATH, and PORT. This test fixture binds to 0.0.0.0 so Docker browsers can reach it, and is intended only for local verification.
  • src/scripts/ci/run-local-ci.js: Runs the GitLab verification jobs through an allowlisted emulator wrapper. Its shared modules own argument parsing, graph checks, and process cleanup. Hosted job scripts remain under src/scripts/ci/helpers/.

These helpers are excluded from the archive contents of @agon/atrium.

Adding or extending a feature

Read architecture for ownership and lifecycle, then component contracts for extension points. Add reusable behavior to src/atrium/, demonstrate it in the showcase, and keep the starter usable independently. Use theming for palette and layout changes and integration for real backend adapters.

Update tests for changed behavior, synchronize affected documentation, and add a concise entry under the current UNRELEASED section of CHANGELOG.md. Its required syntax and keywords are documented in AGENTS.md. Git work starts from the develop branch. Commits and external delivery remain explicit maintainer actions.

Generated files and dependencies

Use the latest published stable release of every development and production library. Verify versions against the registry, pin direct dependencies exactly, and validate upgrades together with the quality and applicable browser/package checks. Avoid prereleases and floating latest manifest entries. Document any upstream compatibility constraint and obtain approval for a temporary version exception. Refresh transitive dependencies within their parent packages’ supported ranges instead of forcing incompatible majors with resolutions.

The approved compatibility exception dated 2026-09-20 pins TypeScript to 6.0.3, the latest stable release supported by the current lint tooling. @typescript-eslint/utils 8.70.0, brought in by eslint-plugin-jsdoc, requires >=4.8.4 <6.1.0, which excludes TypeScript 7.0.2. Keep ESLint and eslint-plugin-jsdoc on their latest stable releases. Revisit this pin when the latest stable typescript-eslint packages declare support for TypeScript 7, then upgrade and rerun yarn install --immutable and yarn check. Preserve upstream peer requirements and resolve compatibility warnings without suppressing them.

Commit yarn.lock with intentional dependency changes. Use yarn install --immutable for ordinary setup and verification. Use yarn install when deliberately updating workspace metadata or dependency declarations, then inspect the lockfile change.

Git ignores dependencies, Yarn’s local cache, builds, archives, browser reports, environment files, editor state, and optional reference snapshots. .gitattributes keeps text as LF and marks binary assets appropriately. Do not copy local credentials or generated output into source directories for distribution. The root is private. Four synchronized packages are released: @agon/atrium, @agon/atrium-publisher, @agon/atrium-starter, and @agon/atrium-showcase. Template packages contain explicit source allowlists and thin commands backed by the publisher. See CI and package releases for hosted registry publication and integration for remote installation followed by local application publication.

Component development

Begin with your first page and the component guides. The showcase declares component links in src/showcase/config/components.js and keeps one lazy example page per component in src/showcase/pages/components/. Shared demonstration partials remain in src/showcase/partials/components/, lightweight example state in src/showcase/pages/components.js, and additional translations in src/showcase/locales/. Native map, video, terminal, and noVNC controllers live beside their page templates. Shared integrations and native library lifecycle helpers belong to src/atrium/. Keep the corresponding guide and production example synchronized when adding a component.

Author

Laurent Declercq l.declercq@agon-innovation.ch

License

Unless otherwise stated all source code is licensed under LGPL 2.1 and has the following copyright:

© 2026, Agon Partners Innovation AG, All rights reserved.

The design material and the “Agon Ātrium” trademark is the property of their authors. Reuse of them without prior consent of their respective authors is strictly prohibited.

Version

Version: 20260921