Field Notes

Architecture Decisions

Decision Rationale Alternatives Considered

Vendor JS loaded separately from bundled JS

domus-ui.js needs to run after DOM is ready but independently of upstream code. Keeping it separate avoids Browserify wrapping and simplifies debugging.

Bundle everything into site.js

Cookie persistence for theme (not localStorage)

Cookies are accessible in inline <script> before DOMContentLoaded. This is critical for FOUC prevention — head-styles.hbs reads the cookie synchronously.

localStorage (requires DOMContentLoaded to read)

CSS custom properties with data-theme attribute

Attribute selectors allow theme switching without reloading CSS. Single domus-theme.css file means one cache entry.

SCSS variables (requires rebuild per theme); separate CSS files (multiple cache entries)

Inline FOUC prevention script in head-styles.hbs

Must execute before CSS <link> tag to set data-theme before first paint. External script would require an extra HTTP request and potential race condition.

External script with async; prefers-color-scheme media query

Single domus-theme.css file for all themes

All themes load with a single HTTP request. Only the active [data-theme] rules apply; others are parsed but not rendered.

Per-theme files loaded on demand (complexity, FOUC risk, extra requests)

cssnano rule merging disabled

Theme selectors ([data-theme="dark"], [data-theme="light"]) share many property names. cssnano merges them, destroying the per-theme cascade.

Custom cssnano plugin to exclude attribute selectors (over-engineered)

Glassmorphism pill toggles (fixed position)

Non-intrusive, visible on all pages, consistent with modern UI patterns. Fixed position means they don’t interfere with document flow.

Settings page; keyboard-only; dropdown in navbar

Lessons Learned

Lesson Context

FOUC prevention requires script before CSS link tag

Early attempts placed the theme detection script in footer-scripts.hbs. This caused a visible flash as the page loaded with default styles, then re-rendered. Moving to head-styles.hbs (before the <link> tag) eliminated the flash.

highlight.js must be loaded async

Synchronous loading of the highlight bundle (43 lines, but parses many language grammars) added ~200ms to page load. Async loading defers it until after the page is interactive.

cssnano version matters for theme preservation

cssnano v4.1 with mergeRules: false works. Upgrading to v5+ changed the plugin API — the config syntax for disabling merge is different. Pinned to ~4.1 to avoid regression.

npx --prefix does not change cwd for gulp

Attempted npx --prefix /path/to/ui gulp bundle from domus-docs. Gulp resolves gulpfile.js relative to process.cwd(), not the prefix path. Must cd to the UI directory first.

npm install required after fresh clone

node_modules/ is gitignored (correctly). make build runs check-deps which verifies node_modules/ exists and fails with a clear message if missing.

CF Access requires service token, not API token

Cloudflare Access Applications use service tokens (Client ID + Client Secret pair). API tokens are for the Cloudflare API itself. Spent time debugging 403s before discovering the token type distinction.

nav-explore grouping/sorting was reverted

Attempted to add groupBy and sortBy Handlebars helpers for component grouping. The helpers worked locally but caused build failures in CI. Reverted to the flat list (commit 2053e67). Documented in CR-2026-03-25-nav-explore-redesign.adoc.

Known Quirks

Quirk Workaround

stylelint v13 reports false positives on CSS custom properties

Suppress with inline /* stylelint-disable */ comments where needed

gulp 4 task registration differs from gulp 3

Use series() / parallel() composition instead of task dependencies

browser-pack-flat can fail on circular requires

Only occurs with certain npm package combinations; current deps are clean

Theme toggle z-index (1001) can overlap modals

No modals currently in the UI; would need adjustment if added

highlight.js 9.18.3 is legacy

Pinned for compatibility with the Antora build pipeline; upgrading to v11+ requires build config changes

Backlog

Priority Item Notes

P1

Responsive navbar breakpoint tuning

Current breakpoint causes menu overflow on tablets

P1

Print stylesheet per-theme adjustments

Print currently uses base colors regardless of active theme

P2

Accessibility audit for theme contrast ratios

WCAG AA compliance check for all 7 themes

P2

Theme preview thumbnails

Show mini-preview of each theme in the toggle

P2

Migrate from gulp to esbuild

Reduce build time, modernize toolchain, smaller dependency tree

P2

nav-explore component grouping (re-attempt)

Group by category (Infrastructure, Security, etc.) — failed first attempt

P3

Automated visual regression testing

Screenshot comparison on PRs using Playwright

P3

Keyboard shortcut help overlay

Show available shortcuts (F for focus, Esc to exit) on ? key

Completed (2026-04-04)

Item Resolution

Toggle buttons inaccessible (<div> elements)

Converted to <button> with aria-label, aria-pressed, focus-visible styles

Clipboard API missing error handler

Added .catch() with fallback aria-label message

No prefers-color-scheme auto-detection

JS now defaults to light or dark based on OS preference when no cookie exists

Inline styles in JS (87-char style.cssText strings)

Extracted to .domus-toggle, .domus-toggle-icon, .domus-toggle-label, .code-toolbar, .lang-badge, .copy-btn CSS classes

Missing <main> landmark in default.hbs

Added <main id="main-content"> wrapper

Burger button missing aria-controls

Added aria-controls="topbar-nav" and improved aria-label

Cookie parsing used naive regex

Replaced with split('; ') + decodeURIComponent() parsing; reduced cookie expiry from 1 year to 90 days

Focus toggle active state used inline styles

Extracted to #focusToggle.is-active CSS class with classList.toggle()

Scope Creep Log

Date Item Outcome

2026-03-25

nav-explore redesign with groupBy/sortBy

Reverted — Handlebars helpers caused CI failures. Documented in CR.

2026-03-26

Aurora + Ocean themes

Shipped. Originally planned only Royal as the next theme.

2026-04-01

Ember theme

Shipped. User requested a warm-toned option for late-night reading.

2026-03-28

MathJax v3 integration

Shipped. Added for Gabriel’s mathematics documentation (LaTeX support).

2026-03-27

Expanded runbooks + tools navbar dropdowns

Shipped. Grew from 8 links to 28 as runbook count increased.

2026-04-04

Accessibility + robustness audit

Shipped. 8 fixes: semantic buttons, ARIA, clipboard error handling, prefers-color-scheme, inline style extraction, main landmark, cookie hardening.

Improvement Proposals

Proposals from full UI + ecosystem audit — 2026-04-04. For team review and prioritization.

CSS & Theming

Priority Proposal Rationale Effort

P1

Refactor 758 !important declarations

Specificity wars make cascade-based overrides impossible. Accounts for ~32% of all declarations in domus-theme.css.

L

P1

Responsive navbar breakpoint tuning

Current breakpoint causes menu overflow on tablet-width viewports. Dropdowns clip off-screen.

M

P2

Extract 316 hardcoded hex colors to CSS variables

35 instances of #0077B6 alone scattered across theme blocks. Theme updates require global find/replace instead of variable changes.

L

P2

WCAG AA contrast audit across all 7 themes

No documented contrast ratios. Some theme combinations (Ember muted text, Aurora low-saturation accents) may fall below 4.5:1.

M

P2

Responsive table styling for mobile

Tables overflow horizontally on small screens with no scroll wrapper. Enterprise docs are table-heavy.

M

P2

Expand print stylesheet (table borders, page breaks)

Current print.css (88 lines) lacks table border rendering, orphan/widow control, and figure page-break avoidance.

M

P1

Document PDF theme ↔ web theme relationship

Three asciidoctor-pdf themes exist in domus-docs/scripts/themes/ (dark, light, catppuccin) that are decoupled from the Antora UI CSS. Color drift is inevitable without a shared variable source. Document the mapping between CSS custom properties and PDF theme YAML values so both can be updated in sync.

S

P1

PDF monospace font lacks Unicode box-drawing + Greek characters

PDF renders ╱╲ as ¬ in ASCII art diagrams and δγφ as ¬ in body text. The default PDF theme monospace and body fonts need replacement with fonts that cover Unicode box-drawing (U+2571-2572), Greek (U+03B1-03C9), and mathematical symbols. Candidates: Noto Sans/Mono, DejaVu Sans/Mono. Affects all asciidoctor-pdf output across domus-* repos. The adoc-stem preprocessor works around this for LaTeX by rendering to SVG, but body text Unicode is still broken.

M

Toolchain & Dependencies

Priority Proposal Rationale Effort

P2

Upgrade highlight.js 9.18.3 to 11.x

4 major versions behind (2019 vintage). Missing language support for Terraform, Go, Rust, Kotlin. Security patches unavailable.

M

P2

Migrate from gulp to esbuild

Gulp 4 + Browserify + PostCSS chain is 6 years old. esbuild reduces build time from 1.6s to ~200ms with a fraction of the dependency tree.

L

UX Enhancements

Priority Proposal Rationale Effort

P3

Image lightbox/zoom for screenshots and diagrams

Documentation contains architecture diagrams and screenshots that are unreadable at inline size. Lightbox enables full-screen viewing.

S

P3

Back-to-top button for long pages

Pages like thinkpad-t16g phases are 1000+ lines. A sticky "back to top" button reduces scroll fatigue.

S

P3

Dark mode image handling

Images with light backgrounds are harsh in dark themes. CSS filter (opacity reduction or inversion) improves visual comfort.

S