Coding standards
These conventions apply to all maintained JavaScript, including application code, shared components, scripts, tests, and configuration. Source headers also apply to CSS/SCSS, HTML, YAML, and the comment-capable root configuration files. Reference, generated, and dependency files are excluded.
Formatting ownership
ESLint Stylistic owns JavaScript formatting. Prettier owns the other maintained formats and does not reformat embedded code examples. Markdown uses proseWrap: preserve to keep table columns aligned even when a table exceeds the line width. Keep prose paragraphs and list items on one physical line. Run yarn format for automatic fixes and yarn lint to check the complete JavaScript, source-header, and prose contract. yarn check also runs EditorConfig, unit tests, and production builds.
Never bypass a rule for tests or configuration. Fix missing documentation manually with a meaningful explanation of the function’s purpose and contract. Keep formatting idempotent: a second pass must leave the source unchanged.
Layout
- Use two-space indentation, single-quoted strings where escaping permits, and semicolons. Forbid trailing commas in arrays, objects, destructuring, imports, exports, function parameters, and calls, including multiline forms.
- Always put control-flow bodies inside braces and on separate lines, including single-statement guards and loops.
- Allow compact arrays, objects, destructuring, named exports, function parameters, and arguments wherever they stay readable. Use spaces inside nonempty array brackets and object braces, such as
[ 'orange', 'blue' ]and{ enabled: true, mode: 'compact' }. Empty containers remain{}and[]. Apply the same object policy to standalone declarations, signatures, calls, conditions, and return values. - Prefer compact expressions around a 100-character line target. Expand long, nested, or commented structures for readability. Keep opening and closing delimiter breaks consistent. In expanded arrays and object literals, separate members consistently rather than mixing packed and separated rows. This is a readability target, not a hard line-length limit. ESLint accepts intentional compact or expanded layouts and does not automatically collapse every existing multiline structure.
- Keep each complete import declaration on one line, including named imports:
import { dataTable } from '@agon/atrium';. Multiple bindings, aliases, default imports, and namespace imports follow the same rule. Move explanatory comments above the import when needed. ESLint enforces this convention and fixes ordinary wrapped imports. Short named exports remain compact, such asexport { dataTable, chart };. Long exports may wrap with consistent brace placement. - Separate independent control-flow statements and function declarations from their neighboring statements with one blank line. Always separate variable declarations from following control flow.
- Separate multiline variable declarations from their neighboring statements. Keep short, related declarations together when that improves readability.
- Keep
else,catch, andfinallyattached to their owning chain. An action immediately followed byreturnmay remain one logical exit sequence. - Use parentheses around arrow-function parameters. Expression bodies are allowed, with the same docblock requirement as functions with block bodies.
const options = { enabled: true, palettes: [ 'orange', 'blue' ] };const { enabled, palettes } = options;
if (enabled) { activate({ palettes, mode: 'compact' });}
if (needsRefresh) { refresh();}Callable documentation
Every function and method needs its own attached multiline JSDoc. This includes named helpers, constructors, getters/setters, anonymous functions, arrow functions, callbacks, test and suite bodies, configuration factories, fixtures, and empty functions. A surrounding component or test-suite description never substitutes for the nested callable’s documentation.
Start with a clear, punctuated purpose. Leave one empty comment line before the tags. Document each parameter with its type and meaning, the return contract, and stable failures where applicable. Preserve JSDoc type/property annotations for component state alongside callable documentation.
/** * Select the records that are available to the current view. * * @param {Array<object>} records - Candidate records. * @returns {Array<object>} Active records in their original order. */function activeRecords(records) { return records.filter( /** * Recognize a record whose status permits display. * * @param {object} record - Candidate record. * @returns {boolean} Whether the record is active. */ (record) => record.status === 'active' );}Use eslint-plugin-jsdoc for the contract and comment layout. The repository’s additional function-docblock rule requires direct attachment, covering callbacks that an enclosing-comment lookup would otherwise accept.
ESLint execution environments
Keep shared ECMAScript parsing and correctness rules independent of environment globals. Browser globals apply to Atrium components, services, and browser entry points, showcase runtime modules, and starter runtime modules. Node globals apply to root and application configuration, Atrium build helpers, the publisher, application launchers, scripts, and test runners. Node files are ES modules and use globals.nodeBuiltin, which does not admit CommonJS-only names such as require, module, or __dirname.
Unit tests use Node by default. Only tests with the explicit Happy DOM environment and their DOM provider helper also receive browser globals. Playwright specifications and the presentation capture script intentionally receive both environments because their Node modules contain browser-evaluated callbacks. File-level globals cannot distinguish the callback runtime from its surrounding module. Keep this exception confined to browser automation. The ESLint configuration tests verify representative runtime boundaries, continued correctness and documentation enforcement, and alignment with the declared unit-test environments.
Register each plugin once in its applicable configuration scope. Keep the generic JSDoc and repository documentation rules together because their contracts differ. Generic rules validate tags, parameter and return contracts, classes, and overview tag placement and duplication. Repository rules enforce directly attached callable documentation and exact header structure, author identity, and valid calendar dates. The former expanded-bindings rule is removed because mandatory expansion conflicts with compact destructuring and exports.
Prose punctuation
Use a period instead of a semicolon in every Markdown sentence, source comment, and JSDoc description. Begin the next sentence with an uppercase letter. End every Markdown list item with a period, including nested items and parents that introduce a sublist. This also applies to the historical audit.
yarn lint:prose parses Markdown and source comments. It checks new and tracked files, rejects prose semicolons and unfinished list items, and runs in yarn lint, yarn check, and the hosted/local frontend lint job. Inline code, fenced examples, explicit JSDoc @example code, executable statements, strings, URL destinations, and HTML entities retain their language syntax. Sentence capitalization still requires editorial review.
Exception boundaries
Do not explicitly throw inside the protected body of a try statement. Validate expected conditions before entering the protected operation, or inspect the operation’s result afterward. Calls within try may fail naturally. A catch handler may translate an external failure, provided that handler is not itself inside another protected try body.
Functions declared inside a try retain their own exception boundary. The rule checks explicit statements in the protected body, not whether a called function might throw. Do not introduce helper functions merely to evade the rule.
The production test server, for example, checks whether a resolved path is a file and then chooses a response or history fallback. It does not throw an artificial exception to enter its own catch branch.
File headers
Use a clear file purpose, one blank comment line, the exact author line below, and a valid YYYYMMDD version. Update the version when modifying a maintained file. JavaScript, CSS, and SCSS use this format:
/** * Describe this file's responsibility clearly. * * @author Laurent Declercq l.declercq@agon-innovation.ch * @version 20260921 */HTML uses the same content inside <!-- ... -->. YAML, EditorConfig, Git configuration, and formatter ignore files use # comment lines. JSON and .nvmrc preserve their required comment-free syntax. Partial documentation examples do not need file headers. Production HTML output removes comments, including description, author, and version headers, even when minification is disabled. Maintained source keeps its headers. Development builds preserve them unless explicitly minified.
yarn lint:headers checks both tracked and new files in the maintained source paths. It never enters dependency directories, or build output. Header structure, authorship format, and valid calendar dates are tested alongside the JavaScript-specific rule.
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