Style Guide
intent
This is the canonical, product-agnostic visual and interaction standard for web applications and future mobile clients. It supports a consistent product family without forcing every surface into the same navigation model.
| Mode | Typical use | Shell |
|---|---|---|
| Workspace | Extranet, intranet, admin, operations, authenticated apps | Five-zone application shell |
| Public site | Internet-facing Astro or similar public website | Public navigation; shared visual language |
| Mobile | Android/iOS or cross-platform clients | Native/mobile navigation; shared visual language |
Workspace is the default for dynamic operational applications. Public site reuses tokens, typography and components without forcing the workspace rail/status-bar layout. Mobile reuses the same design language with platform-appropriate navigation and offline/sync states.
canonical implementation location
Canonical document:
docs/canonical/style-guide.md
Recommended frontend mapping:
front-end/
└── src/
├── components/ # reusable UI
├── features/ # feature-specific UI
└── styles/
├── tokens.css # colour, spacing, sizing
├── themes.css # Light, Dark, Event
├── layout.css # shell and page layout
└── controls.css # controls and states
Framework-specific folders such as Astro public/, Next.js app/, or generated route folders are added only when the chosen framework needs them. Do not duplicate this guide inside features. Product-specific exceptions should reference this canonical document.
workspace mode
canonical desktop shell
+----------------------+--------------------------------------+
| App info / brand | Top menu / page context |
+----------------------+--------------------------------------+
| Left navigation | Main content |
| (scrollable region) | (owns vertical page scroll) |
+----------------------+--------------------------------------+
| Settings | Bottom status bar |
+----------------------+--------------------------------------+
The five structural zones are app info, left navigation, Settings, top menu/page context, and bottom status bar. They are shell chrome, not page content.
shell layout
- Use the full desktop viewport rather than a narrow centred application wrapper.
- Use a strict two-column, three-row shell: rail + workspace; fixed top/bottom rows; flexible middle row.
- Use
height: 100dvh; min-height: 0on the shell. - Main content owns page scrolling; the navigation list may scroll independently.
- Settings stays pinned at the bottom of the rail.
- Top menu and bottom status bar start exactly at the rail edge.
- Settings footer and bottom status bar share one row height and horizontal baseline.
- The rail runs continuously from viewport top to bottom.
- Remove framework-generated margins, padding, gaps or hidden wrapper height that distort the shell.
- Test short desktop heights as well as wide widths.
Reference calibration:
| Measure | Default |
|—|—:|
| Rail | 14.5% |
| Main workspace | 85.5% |
| Top row | 10.0% |
| Middle row | 85.1% |
| Bottom row | 4.9% |
These are house defaults, not universal web standards.
navigation
Homeis first;Dashboardis its first child.- Main workflows follow Home in frequency/business priority.
Settingslives in the dedicated bottom-left zone, never in the scrolling nav.- Prefer fewer top-level areas over deep trees.
- Show child pages only when useful for regular navigation.
- Expandable parents start collapsed and toggle only on explicit action.
- Expandable parents show a visible chevron/equivalent and expose
aria-expanded. - Submenu items are visibly indented.
- Active state is obvious in expanded and collapsed rail states.
- The collapse control must also restore the expanded rail.
- Persist rail state locally where appropriate.
page model
- Top-level areas are routed pages, not primary tabs.
- Known routes must support direct load and browser refresh.
- Pages open into titled panels/sections rather than long unstructured columns.
- Prefer panels, accordions and in-page sections before deeper navigation.
- Primary navigation changes pages;
scrollIntoViewis only for explicit in-page actions.
Home / Dashboard
The dashboard should surface the application’s most important live state using status cards, summaries, charts or operational graphics. Examples: service readiness, environment, sync/connection, jobs/queues, approvals/backlog, latency, CPU/GPU/RAM/storage, errors, or equivalent domain metrics. It should feel like a control surface, not a text dump.
top menu
Normally show workspace/section context, current page title, route/breadcrumb and primary global status. The top menu belongs only to the workspace column and never extends behind the rail.
bottom status bar
Use for compact persistent workspace/environment, connection/sync, service/session and runtime/domain status. It is docked shell chrome, not a floating card or page-local footer. Secondary metrics may hide when space is tight but must not grow the bar height.
public-site mode
Internet-facing public sites, including Astro static sites, do not need the five-zone Workspace shell.
Reuse:
- typography and design tokens
- spacing rhythm
- control styling
- accessible interaction states
- reusable component styling
- kebab-case page/route slugs
A public site may use conventional top navigation, footer and content layout. Do not force Settings, runtime bars or operational dashboards into a public information/marketing site. Where public and authenticated surfaces connect, keep the visual family recognisable even though navigation differs.
mobile mode
- Reuse typography, semantic colours, controls and status language.
- Use native/platform-appropriate navigation.
- Never force desktop rail geometry onto mobile.
- Use drawers, bottom navigation or native patterns as appropriate.
- Surface offline, connection and synchronisation state when relevant.
- Use mobile-appropriate touch targets and spacing.
- If the client has a local database/cache, visible sync/offline states use the same semantic status language as the web app.
routing and naming
Routes should be resource-shaped and use kebab-case slugs.
Reference:
https://example.com/v1/pages/123/home/456/activity
Rules:
- top-level and child page slugs use kebab-case
- stable identifiers are used where required
- client navigation updates the browser URL
- direct reload restores the same page
- JavaScript/TypeScript UI filenames use kebab-case where tooling allows
- Python implementation filenames follow Python conventions
visual direction
- Prefer restrained operational design over marketing decoration.
- Use low-chroma surfaces, quiet borders, rounded panels and simple line icons.
- Reserve bright colours for semantic emphasis/active state.
- Avoid loud gradients and unnecessary visual noise in working interfaces.
- Use spacing, tonal contrast and subtle elevation for hierarchy.
- Status graphics are informative first, decorative second.
theme system
Use one component hierarchy with token-driven themes.
Light
| Token | Value |
|---|---|
--app-bg |
#f7f7f8 |
--panel-bg |
#ffffff |
--panel-alt |
#f0f2f4 |
--panel-elev |
#ffffff |
--text |
#1f2a29 |
--muted |
#5b6b78 |
--faint |
#8a98a3 |
--border |
rgba(18,32,45,0.12) |
--border-soft |
rgba(18,32,45,0.07) |
--accent |
#1098ad |
--accent-hover |
#0c7d8e |
--accent-soft |
rgba(16,152,173,0.12) |
Dark
| Token | Value |
|---|---|
--app-bg |
#0d0d0d |
--panel-bg |
#171717 |
--panel-alt |
#1f1f1f |
--panel-elev |
#232323 |
--text |
#ececec |
--muted |
#9a9aa5 |
--faint |
#6e6e80 |
--border |
rgba(255,255,255,0.10) |
--border-soft |
rgba(255,255,255,0.06) |
--accent |
#6cd7ff |
--accent-hover |
#9ee5ff |
--accent-soft |
rgba(108,215,255,0.14) |
Event
Event uses Dark surfaces with warm amber/rust emphasis.
| Token | Value |
|—|—|
| --app-bg | #0d0d0d |
| --panel-bg | #171717 |
| --panel-alt | #1f1f1f |
| --panel-elev | #232323 |
| --text | #ececec |
| --muted | #9a9aa5 |
| --faint | #6e6e80 |
| --border | rgba(255,255,255,0.10) |
| --border-soft | rgba(255,255,255,0.06) |
| --accent | #d49035 |
| --accent-strong | #9b3d18 |
| --accent-soft | rgba(212,144,53,0.14) |
| --success | #2d5852 |
| --danger | #a64236 |
typography and density
- Prefer
Inter, thensystem-ui,-apple-system,Segoe UI, Roboto and sans-serif. - Use monospace such as
IBM Plex Mono,Cascadia Codeor Consolas for routes, IDs, commands and technical values. - Default body size about
15px, line-height about1.5. - Use restrained heading weights/sizes and uppercase overlines sparingly.
- Spacing rhythm:
8px, 12px, 16px, 20px, 24px, 28px, 32px. - Suggested radii:
10pxcompact controls,14pxstandard panels,20pxfeatured surfaces. - Prefer hairline borders and tonal contrast over heavy outlines.
controls and accessibility
Every theme defines:
| Token | Purpose |
|—|—|
| --control-bg | input/secondary-control background |
| --control-bg-hover | hover background |
| --control-border | control border |
| --control-text | entered/control text |
| --control-placeholder | placeholder/helper text |
| --control-focus | keyboard focus |
| --control-disabled | disabled treatment |
| --primary-bg | primary action background |
| --primary-text | text on primary action |
Core values:
| Theme | Control bg | Text | Placeholder | Primary bg | Primary text |
|—|—|—|—|—|—|
| Light | #ffffff | #1f2a29 | #5b6b78 | #1098ad | #ffffff |
| Dark | #1f1f1f | #ececec | #b8b8b8 | #6cd7ff | #071017 |
| Event | #1f1f1f | #ececec | #b8b8b8 | #d49035 | #211c18 |
Accessibility:
- Normal text: WCAG AA 4.5:1 minimum.
- Large/bold display text: 3:1 minimum.
- Placeholder/helper text should remain at least 4.5:1.
- Controls have explicit default, hover, focus-visible, disabled and error states.
- Do not use opacity as the primary readable-text treatment.
- Icons inherit the readable foreground colour of their control.
- Theme framework wrappers, labels, helper text and validation messages, not only native inputs.
- Audit rich controls such as uploads, recorders and framework widgets through the complete generated DOM.
component rules
- Reusable UI:
front-end/src/components/. - Feature-specific UI:
front-end/src/features/<feature>/. - Theme/shell styles:
front-end/src/styles/. - Reuse existing components before creating duplicates.
- Navigation buttons are compact, left-aligned and clearly active.
- Panels feel like working surfaces, not promotional cards.
- Primary buttons use
--primary-bg+--primary-text. - Secondary controls use control tokens.
- Labels use readable primary text; helper text uses the helper/placeholder token.
- Status chips are compact and scan-friendly.
- Dashboard cards use stronger hierarchy than ordinary panels.
framework integration
Framework defaults must not override the canonical design. When a framework generates nested wrappers:
1. set global theme variables where available
2. scope overrides to the complete component family
3. style wrapper, label, input, placeholder, button, icon, helper text and validation message
4. verify wrappers do not introduce shell gaps or extra scrolling
Do not change backend, database or deployment architecture merely to work around frontend styling.
adoption rules
For a new or reviewed project:
- identify the surface as Workspace, Public site or Mobile
- keep this file as the canonical style source
- map tokens into the project’s frontend/client styles
- reuse components before creating new ones
- keep product labels/domain content separate from the generic shell
- document deliberate deviations instead of silently drifting
- keep UI changes inside the owning frontend/client codebase
- do not edit neighbouring repositories merely to make a local UI change
Workspace applications additionally:
- preserve the five-zone shell
- keep Home first and Settings pinned
- use routed pages rather than primary top tabs
- preserve shared top/bottom row alignment
- keep global status in shell chrome
non-goals
This guide does not require the Workspace shell on a public Astro site, the desktop rail on mobile, a particular JavaScript framework, Docker, a particular deployment platform, backend architecture changes for styling, or identical domain content across products.
Do not:
- reintroduce primary top-tab navigation into Workspace apps
- hide important global status inside one page
- break direct-route reload
- let Settings float above the Workspace rail bottom
- let the bottom status bar become a detached card
- merge app info into the Workspace top menu
- merge Settings into the scrolling nav
- duplicate this canonical guide inside individual features