Build with thesame patternsacross the platform.

Components, tokens, conventions, and process. Everything an engineer needs to ship a page that looks like it belongs.

Components (2)Tokens (4)Conventions (3)Process (2)
Components · 2 patterns

Components

Reusable React components from @ambientintel/ui.

TopNav
Sticky top navigation. Tabs in the middle, optional CTAs on the right.
Sourcepackages/ui/src/TopNav.tsx
Usage
import { TopNav, type TopNavTab } from '@ambientintel/ui';

const TABS: TopNavTab[] = [
  { href: '/',         label: 'Overview' },
  { href: '/eng',      label: 'Engineering Center' },
  { href: '/onboarding/engineering', label: 'Onboarding' },
];

<TopNav
  tabs={TABS}
  activeHref="/eng"
  rightSlot={<SignInButton />}
/>
When to use
Every page that lives under a tabbed surface. The eng., lab., and design. subdomains all use it. tabs are per-app (different subdomains have different tab sets) — keep the array in apps/<name>/src/lib/.
Tokens · 4 patterns

Tokens

Design values exported from @ambientintel/tokens.

Color palette
Brand colors. Cream surfaces, parchment cards, brand-dark text, sage accent.
Sourcepackages/tokens/src/index.ts
Usage
import { COLORS } from '@ambientintel/tokens';

<div style={{
  background: COLORS.cream,
  color: COLORS.text,
  border: `1px solid ${COLORS.line}`,
}}>
  ...
</div>
When to use
Any time you need a color. Never hardcode hex values inline; import from the tokens package so a brand refresh propagates atomically. Edit values via lab./tokens (auto-creates a PR).
Brand fonts
Tiempos Fine (serif), Die Grotesk A Light + B Medium (sans), JetBrains Mono (mono).
Sourcepackages/tokens/src/index.ts
Usage
import { FONTS } from '@ambientintel/tokens';

<h1 style={{ fontFamily: FONTS.serif }}>
  Headline
</h1>

<p style={{ fontFamily: FONTS.sans, fontWeight: 300 }}>
  Body copy in Die Grotesk A Light.
</p>

<span style={{ fontFamily: FONTS.mono }}>
  STATUS · LIVE
</span>
When to use
Tiempos for headlines and italic accents. Die Grotesk for body, buttons, labels. JetBrains Mono for eyebrows, code, captions, status badges. Never default to Newsreader or Inter — those are not the brand.
Container width
Canonical max-width for hub and landing pages. Matches anthropic.com.
Sourcepackages/tokens/src/index.ts
Usage
import { CONTAINER_WIDTH } from '@ambientintel/tokens';

<section style={{
  margin: '0 auto',
  maxWidth: CONTAINER_WIDTH,   // 1274
  padding: '48px 24px',
}}>
  ...
</section>
When to use
Every full-width hub or landing page. Sidebar-layout pages keep their narrower main-area widths (~1200) — this constant is for the outer container.
Status badge
Pill-shaped badge for card status (Live, Coming soon, R&D).
Sourcepackages/tokens/src/index.ts
Usage
import { STATUS_BADGE, type StatusKey } from '@ambientintel/tokens';

const s = STATUS_BADGE.live;  // or 'soon', 'rnd', 'migrating'

<span style={{
  fontFamily: 'var(--font-jetbrains-mono), monospace',
  fontSize: 9.5,
  padding: '3px 9px',
  borderRadius: 999,
  background: s.bg,
  color: s.color,
  border: `1px solid ${s.border}`,
  textTransform: 'uppercase',
  letterSpacing: '0.04em',
}}>
  {s.label}
</span>
When to use
Inside cards on hub pages. Pick the variant that matches the card state. Mono font, uppercase, letter-spaced.
Conventions · 3 patterns

Conventions

How we structure pages, commits, and copy.

Hub template
The standard layout for every subdomain landing page.
Sourceapps/ambient-lab/app/page.tsx
Usage
<TopNav tabs={TABS} activeHref="/" />

<section style={{ margin: '0 auto', maxWidth: 1274, padding: '48px 24px 28px' }}>
  <div style={{ fontFamily: 'var(--font-jetbrains-mono), monospace',
       fontSize: 10, letterSpacing: '0.16em', textTransform: 'uppercase',
       color: '#9CA3AF', marginBottom: 10 }}>
    Subdomain · Page
  </div>
  <h1 style={{ fontFamily: 'var(--font-tiempos-fine), Georgia, serif',
       fontWeight: 400, fontSize: 'clamp(48px, 6vw, 80px)',
       lineHeight: 1.0, letterSpacing: '-0.02em' }}>
    <span style={{ display: 'block' }}>Word</span>
    <span style={{ display: 'block', fontStyle: 'italic' }}>Italic</span>
    <span style={{ display: 'block' }}>Word.</span>
  </h1>
  <p style={{ /* italic Tiempos, 22px, max-width 680 */ }}>
    One-sentence scope statement.
  </p>
</section>

<Footer />
When to use
Building a new subdomain hub (eng., security., lab., design., etc.). The template: TopNav at top, stacked Tiempos H1 with italic accent, italic Tiempos subhead, mono eyebrow + card grid, Footer at bottom. ambient-lab is the reference implementation.
Conventional Commits
Enforced commit format. Scope = app or package name without the @ambientintel/ prefix.
Sourcedocs/conventions.md
Usage
feat(ambient-lab): add Code Lab card to Labs hub
fix(ambient-device): firmware sidebar engineering link
chore(deps): bump next from 16.2.6 to 16.3.0
refactor(ui): extract status badge to shared component
docs(adr): add ADR-0004 on canvas pattern strategy
When to use
Every commit. The squashed PR title becomes the commit, so PR titles follow the same format. Searching git log by scope (`git log --grep="^feat(ambient-lab)"`) is the changelog.
No em dashes in copy
Brand convention. Use periods, commas, parentheses, or colons instead.
Sourcedocs/conventions.md
Usage
// Yes
"Cybersecurity. Cloud, device, and data security for Ambient Intelligence."

// No
"Cybersecurity — cloud, device, and data security for Ambient Intelligence."
When to use
Any user-facing string. The em dash reads as ChatGPT-default; the brand voice is more precise punctuation. ASCII hyphens for ranges are fine.
Process · 2 patterns

Process

How we extract, refactor, and edit the design system.

Drift to package playbook
When two apps duplicate something AND drift, extract to packages/. Not before.
Sourcedocs/adr/0003-package-extraction-policy.md
Usage
// Decision rubric:
//
// 1. Duplication within ONE app?
//    → apps/<name>/src/lib/<thing>.ts (no package)
//
// 2. Duplication across TWO+ apps with drift observed?
//    → packages/<domain>/  +  @ambientintel/<domain>
//
// 3. "This looks reusable" but only one app uses it?
//    → Leave it. Reuse later is one PR; un-extraction is painful.
//
// Three extracted in practice so far:
//   - Footer       (cross-app component)    @ambientintel/ui
//   - TopNav       (cross-app component)    @ambientintel/ui
//   - eng-domains  (cross-app data registry) @ambientintel/eng-domains
When to use
You notice the same component or constant in multiple apps. Check the playbook before extracting. Premature extraction is more painful than living with the duplication.
Edit tokens via Token Lab
Visual editor at lab./tokens that opens a real Pull Request.
Sourceapps/ambient-lab/app/tokens/page.tsx
Usage
// 1. Open https://lab.ambienthealthgroup.com/tokens
// 2. Tweak any value with the color picker or numeric input
// 3. Watch the live preview update; check the diff panel
// 4. Optional: write a PR description
// 5. Click "Submit PR" → branch is created, PR opens
// 6. Review the diff on GitHub, merge when ready
//
// All consuming apps rebuild on their next push.
When to use
Changing a brand color, container width, or other design constant. Editing in the browser produces a clean diff and a PR you can review before merging. For schema changes (adding tokens), still edit packages/tokens/src/index.ts directly.
Missing a pattern?
Extract it when two apps need it, not before.
See ADR-0003 for the extraction policy. Add a new pattern card to this page in the same PR that introduces it to packages/.