Skip to content

UCCA Ops Console UI Specification

Design standard for all control plane surfaces

Governing Document

This specification governs all UI development on ops.ucca.online. Read it before making any visual changes to the ops console. Deviations require explicit approval.


Section 1 — Design Philosophy

Core Model: Linear

The UCCA Ops Console follows the Linear design model: fast, keyboard-first, opinionated. Every interaction should feel immediate. Chrome is minimal. Navigation is hierarchical and predictable. The command palette is the primary navigation tool for power users.

Hybrid Approach by Layer

The four-layer control plane architecture determines UI density and polish:

Layer Name UI Model Feel
L1 UCCA Ops (God Mode) Linear Dense, fast, keyboard-first. Raw and functional.
L2 SU Overlay Linear + Vercel Toggleable panels. Clean sidebars. Debug/audit mode.
L3 World Control Plane Linear + Stripe Domain admin. Stripe polish on revenue/analytics.
L4 Client View Vercel Clean, minimal, branded. Zero UCCA fingerprinting.

Layers 1-3 share the same codebase and component library. Layer 4 is a separate branded surface per world. Visibility is determined entirely by credentials — the same URL renders different views depending on who is logged in.

Design Principles

  1. Speed over decoration. Every click, every transition, every render should feel instant. No loading spinners where data can be prefetched.
  2. Keyboard supremacy. Every action reachable via keyboard. Cmd+K is the universal entry point. Mouse is supported but never required.
  3. Density matches role. L1/L2 users see dense information. L3/L4 users see progressively cleaner views. Same data, different presentation.
  4. No dead ends. Every page has a purpose. Stubs either show useful placeholder content or are hidden until live.
  5. Consistency is mandatory. Navigation patterns, spacing, typography, colour usage — identical across all control plane surfaces.

Section 2 — Navigation Hierarchy

Current Problems

  • Worlds at the top of the sidebar — should be below platform controls
  • Two separate 'Dashboard' entries — confusing
  • 'Home' section unclear — what is Home vs Control Plane?
  • No visual distinction between platform-level and world-level navigation
  • Stubs visible with no content — makes console feel unfinished

New Sidebar Structure

The sidebar is the primary navigation surface. It is always visible and follows this exact structure:

Top Bar (Fixed)

  • UCCA logo (top left, links to platform dashboard)
  • Search trigger (Cmd+K shortcut hint, opens command palette)

Platform — always visible, always first

  • Dashboard (platform-wide overview: all worlds summary, system health, recent activity)
  • Health (full health page: surface health, status, traffic analytics)
  • Incident Status (incident.io feed)
  • Authority Catalogue
  • Access Control
  • Settings

Worlds — collapsible, below platform

Each world is an expandable section. Clicking a world name enters that world's context. The sidebar updates to show world-specific navigation:

  • RTOpacks (with flag icon, 'live' badge)
    • Dashboard (world dashboard: RTO count, enrichment, scope rows, drift)
    • RTO Explorer (live)
    • Enrichment
    • Scope Analytics
    • Provenance
    • Drift Monitor
    • Pipeline
  • US General (scaffolded — 'coming soon' badge)
  • Door (scaffolded — 'coming soon' badge)

Resources — bottom of sidebar, always visible

  • Help (external link)
  • Knowledge (external link)
  • Docs (external link)

Active State

The active page is visually highlighted in the sidebar with a left border accent and background tint (matching Cloudflare's active state pattern). Parent sections expand automatically when a child is active. Collapsed sections show a count badge if they contain alerts or actionable items.

World Context Switching

When a user clicks into a world, the sidebar enters 'world context'. The world name appears as a breadcrumb above the world-specific navigation. A back arrow or breadcrumb returns to platform level. The URL reflects the context: /w/au-vet/dashboard, /w/au-vet/enrichment, etc.

Stub Policy

Pages that are not yet implemented:

  • If architecturally planned: Show in sidebar with a subtle 'stub' badge. Page content shows a meaningful description of what will be built, not an empty page.
  • If speculative: Hide from sidebar entirely until committed to.

Section 3 — Command Palette (Cmd+K)

The command palette is the single most important UI component in the console. It is inspired by Linear's command menu and follows the same interaction model seen in Cloudflare, Vercel, Notion, and Stripe dashboards.

Activation

  • Cmd+K (macOS) / Ctrl+K (Windows/Linux)
  • Click the search area in the top bar
  • Always available from any page

Capabilities

  • Navigation: Type any page name to jump directly. 'Health', 'RTOpacks Dashboard', 'Authority Catalogue'.
  • Search: Search across RTOs by name, code, or ABN. Search across enrichment records. Search across authority objects.
  • Actions: 'Declare Incident', 'Run Backup', 'Switch World'. Prefix with > for action mode (like VS Code).
  • Recents: Show recently visited pages and recently searched items before the user types.

Search Tips

When the palette opens with no input, show search scope hints (matching Cloudflare's pattern):

Prefix Scope
rto: Search RTOs
d1: Search D1 databases
access: Search Access policies
> Run a command

Implementation

Use a portal/overlay component. Trap focus inside the palette when open. Escape closes. Arrow keys navigate results. Enter selects. Debounce search input at 150ms. Results appear instantly from a local index, with async remote results appended.

Search Result Display

Hard Rule

Search results show ONLY icon + breadcrumb path. No descriptions, no subtitles, no purpose lines. The command palette is a high-speed navigation tool, not a discovery tool. The breadcrumb IS the description. Match Cloudflare's search result density exactly.

Each result row contains:

  • Icon — matching the page's sidebar icon (e.g. shield for Health, database for RTO Explorer)
  • Breadcrumb path — hierarchical path to the destination (e.g. Platform > Health, RTOpacks > RTO Explorer)
  • Nothing else. No description text. No "purpose" lines. No secondary information.

This keeps the result list dense and scannable. A user typing "heal" should see the result and hit Enter in under 500ms. Any visual clutter in the result list slows this down.


Section 4 — User Identity & Roles

Current State

Cloudflare Access provides authentication via OTP to admin@ucca.online. There is no user identity display in the console, no role system, and no way to distinguish between operators.

Identity Display

Top right corner of every page:

  • User avatar (initial-based, e.g. 'T' for Tim, 'J' for Jimmy)
  • User name
  • Role badge (Admin, Operator, Viewer)
  • Click opens a dropdown: Profile, Theme toggle, Sign out

Role Model (Phase 1 — Simple)

Three roles, hardcoded initially. Migrate to database-driven roles when user management is built.

Role Layer Access Capabilities
Admin L1 + L2 + L3 Full access. Infrastructure, all worlds, all controls. Tim and Alex.
Operator L2 + L3 SU overlay into worlds. Business data, analytics, enrichment. Cannot modify infrastructure. Jimmy.
Viewer L3 (scoped) Read-only access to a specific world. Future world admins, auditors.

Authentication Flow

Cloudflare Access remains the perimeter gate. Behind it, the ops console checks the authenticated email against a user table (initially a hardcoded map in the codebase, later D1-backed). The email determines the role, which determines sidebar visibility and page access.

  • Phase 1: Hardcoded user map in the codebase (Tim = Admin, Jimmy = Operator, Alex = Admin).
  • Phase 2: D1-backed user table with role management in the Access Control page.
  • Phase 3: World-scoped roles (a user can be Admin in RTOpacks but Viewer in US General).

Cloudflare Access Configuration

Add Jimmy's email and Alex's email to the Cloudflare Access policy for ops.ucca.online. Each person authenticates with their own email OTP. The console then maps their email to a role.


Section 5 — Theme System (Light / Dark)

Implementation

Tailwind CSS dark: variant provides the theme toggle. All components must support both themes from day one. No component ships without dark mode styles.

Colour Tokens

Define semantic colour tokens, not raw hex values. All colours reference tokens:

Token Light Dark
--bg-primary white (#FFFFFF) slate-950 (#020617)
--bg-secondary slate-50 (#F8FAFC) slate-900 (#0F172A)
--bg-tertiary slate-100 (#F1F5F9) slate-800 (#1E293B)
--text-primary slate-900 (#0F172A) slate-50 (#F8FAFC)
--text-secondary slate-500 (#64748B) slate-400 (#94A3B8)
--text-muted slate-400 (#94A3B8) slate-500 (#64748B)
--border-default slate-200 (#E2E8F0) slate-700 (#334155)
--accent-primary blue-600 (#2563EB) blue-500 (#3B82F6)
--status-healthy green-600 (#16A34A) green-500 (#22C55E)
--status-warning amber-600 (#D97706) amber-500 (#F59E0B)
--status-error red-600 (#DC2626) red-500 (#EF4444)

User Preference

  • Default: follow system preference (prefers-color-scheme)
  • Override: user can set Light, Dark, or System in the profile dropdown
  • Preference stored per user (initially localStorage, later user table)

Rule

No component ships without both light and dark styles. This is not optional.


Section 6 — Component Standards

Component Library

Use shadcn/ui as the base component library. It provides unstyled, accessible primitives that work with Tailwind. Do not introduce additional component libraries (no Material UI, no Chakra, no Ant Design).

Typography

Element Font Size Weight
Page title Inter / system-ui 24px (text-2xl) Semibold (600)
Section heading Inter / system-ui 18px (text-lg) Semibold (600)
Card title Inter / system-ui 14px (text-sm) Medium (500)
Body text Inter / system-ui 14px (text-sm) Normal (400)
Caption / label Inter / system-ui 12px (text-xs) Medium (500)
Code / mono JetBrains Mono / monospace 13px Normal (400)

Spacing

Use Tailwind's spacing scale consistently. Standard gaps:

Element Class Value
Page padding p-6 24px
Card padding p-4 16px
Section gap gap-6 24px
Inline gap gap-2 or gap-3 8px or 12px
Sidebar width w-64 256px
Sidebar collapsed w-16 64px

Cards

Cards are the primary content container. Every card follows this pattern:

  • Rounded corners: rounded-lg (8px)
  • Border: 1px solid --border-default
  • Background: --bg-primary
  • Shadow: none (flat) or shadow-sm on hover
  • No gradient backgrounds. No coloured borders except for status indicators.

Status Indicators

Three-state system used everywhere:

  • Healthy / Active / Good — green dot + text
  • Warning / Degraded / Review — amber dot + text
  • Error / Down / Critical — red dot + text

Always use both colour AND text. Never rely on colour alone.

Tables

Data tables follow Linear's pattern: compact rows, hover highlight, sortable headers, inline actions. Use 14px body text, 12px headers. Row height: 40px minimum. Alternating row colours are optional (use --bg-secondary on even rows in dense tables).

Badges

Used for status, roles, and tags. Consistent sizing: text-xs, px-2, py-0.5, rounded-full. Colour matches status system (green/amber/red) or neutral (slate) for informational badges like 'live', 'stub', 'airlock'.


Every control plane page has a consistent footer strip. Thin, unobtrusive, identical everywhere.

Contents

  • Left: UCCA (c) 2026 (or current year)
  • Centre: Status | Docs | Knowledge | Support
  • Right: Version number (e.g. v0.1.0) | Environment badge (production / staging)

Behaviour

  • Fixed at bottom of viewport when page content doesn't fill the screen
  • Scrolls with content when page exceeds viewport
  • Status link points to status.ucca.online
  • Docs and Knowledge open in new tabs

Section 8 — Keyboard Shortcuts

Global Shortcuts

Available on every page:

Shortcut Action
Cmd+K Open command palette
Cmd+/ Show keyboard shortcuts overlay
G then D Go to Dashboard
G then H Go to Health
G then W Go to Worlds list
G then S Go to Settings
Escape Close any overlay, modal, or palette
? Show keyboard shortcuts (alternative)

Within Data Tables

Shortcut Action
J / K Move selection down / up
Enter Open selected item
/ Focus search/filter within table

Section 9 — Responsive Behaviour

The ops console is primarily a desktop tool. Mobile support is secondary but should not be broken.

Breakpoints

Range Behaviour
Desktop (>1280px) Full sidebar, full content area
Tablet (768-1280px) Collapsible sidebar (icon-only mode), full content
Mobile (<768px) Sidebar hidden behind hamburger menu. Content takes full width. Command palette remains accessible.

On tablet, the sidebar collapses to icon-only mode (w-16). Hovering expands it temporarily. User can pin it open. Preference is persisted.


Section 10 — Implementation Phases

This specification is implemented in phases. Each phase is a complete, deployable unit.

Phase 1: Foundation (Priority)

Navigation hierarchy, sidebar restructure, active state highlighting, stub policy enforcement.

  • Restructure sidebar per Section 2
  • Implement active state highlighting
  • Remove or improve stubs per stub policy
  • Add consistent footer strip
  • Deploy and validate

Phase 2: Command Palette

Build the Cmd+K command palette per Section 3.

  • Overlay component with focus trap
  • Navigation search (all pages indexed)
  • RTO search integration
  • Action mode (> prefix)
  • Recent items

Phase 3: Identity & Roles

User identity display and role system per Section 4.

  • Add identity component (top right)
  • Hardcoded user map (Tim = Admin, Jimmy = Operator, Alex = Admin)
  • Add Jimmy and Alex to Cloudflare Access policy
  • Role-based sidebar visibility
  • Profile dropdown with theme toggle

Phase 4: Theme System

Dark/light mode per Section 5.

  • Define colour tokens
  • Implement dark: variants across all components
  • Theme toggle in profile dropdown
  • System preference detection
  • Persist user preference

Phase 5: Component Standardisation

Audit all existing components against Section 6 standards. Refactor to consistency.

  • Typography audit and standardisation
  • Card component standardisation
  • Table component standardisation
  • Badge and status indicator standardisation
  • Spacing audit

Section 11 — What Not to Do

Hard Rules

Violating these creates technical debt that compounds.

  • DO NOT introduce additional component libraries (no MUI, no Chakra, no Ant Design)
  • DO NOT use inline styles. All styling via Tailwind utility classes.
  • DO NOT ship a component without dark mode support
  • DO NOT create one-off navigation patterns. Every page uses the standard sidebar.
  • DO NOT use colour alone to convey meaning. Always pair with text or icons.
  • DO NOT add loading spinners where data can be prefetched or skeletonised
  • DO NOT create modal dialogs for navigation. Modals are for confirmations and destructive actions only.
  • DO NOT hard-code world-specific logic in shared components. Use the world context system.
  • DO NOT expose Layer 1/2 controls to Layer 3/4 users. Permissions are not optional.

Section 12 — Reference Implementations

When building new components, study these implementations:

Pattern Reference What to Study
Command palette Linear, Vercel, VS Code Overlay, focus trap, search scoping, action mode
Sidebar navigation Cloudflare Dashboard Hierarchy, active state, expandable sections, icon-only collapse
Data tables Linear, Stripe Compact rows, inline actions, sortable headers, keyboard navigation
Identity display Cloudflare, Vercel Top-right avatar, dropdown menu, role badge
Footer strip Cloudflare Thin, consistent, links to status/docs/support
Status indicators incident.io, Vercel Three-state (green/amber/red), dot + text, consistent everywhere
Theme toggle Linear, Notion System/Light/Dark options, immediate switch, no flash
World context switch Cloudflare (zone switch) Breadcrumb, sidebar context change, URL reflects context

Section 13 — Page-Level Design Rules

These rules apply to every page in the ops console. They are non-negotiable.

Rule 1: Every Page Earns Its Existence

A page exists because it solves a problem or answers a question. If a page cannot articulate its purpose in one sentence, it should not exist. Stub pages must explain what they will do when built — a blank page with a title is not acceptable.

Rule 2: Information Hierarchy Is Mandatory

Every page must have a clear visual hierarchy. The most important information is largest and highest on the page. Secondary information is smaller and lower. The user's eye should flow naturally from the page title through the key metrics to the detail sections. If a user cannot identify the most important element within 2 seconds of landing on the page, the hierarchy has failed.

Rule 3: Cards Are Content Containers, Not Decoration

A card groups related information. Every card must contain meaningful content. Empty cards, placeholder cards, and decorative cards waste space and train users to ignore the card pattern. If a section has no content yet, it should either not exist or show a compact stub — not a full-sized empty card.

Rule 4: Metrics Are Not Art

Dashboard metrics (KPIs, counters, status indicators) must be readable at a glance. This means: large, clear numbers. Short labels. Consistent formatting. No decorative charts that obscure the actual value. A metric card should answer one question in under 1 second. If you need to study it, it has failed.

Rule 5: Tables Are for Comparison, Not Display

A data table exists so users can compare rows and find patterns. This means: consistent column widths, sortable headers, aligned numbers, scannable text. A table that wraps text, has inconsistent alignment, or lacks sorting is not a table — it is a list pretending to be a table.

Rule 6: Empty States Are Informative, Not Apologetic

When a section has no data (no incidents, no drift detected, no enrichment queued), the empty state must:

  • State clearly what would appear here when data exists
  • Indicate whether 'empty' is good (e.g. 'No active incidents' = healthy) or just means 'no data yet'
  • Be compact — do not let empty states dominate the page

Never use sad-face illustrations, apologetic language ('Sorry, nothing to show'), or large empty areas. A clean, informative one-liner is always better.

Rule 7: Clickable Things Look Clickable

Every interactive element must have visible affordance: hover state, cursor change, and an affordance (chevron, arrow icon). If a card is display-only, it must NOT have a hover state. The user must never wonder 'can I click this?'. Consistency is critical — if some cards in a grid are clickable and others aren't, they must be visually distinguishable.

Rule 8: White Space Is Intentional, Not Accidental

Large empty areas on a page signal either incomplete implementation or poor layout. If a section has minimal content (e.g. 'no incidents'), the section should be compact — not a large empty card consuming screen real estate. White space is used to separate logical groups, not to fill a grid that has nothing to show.


Section 14 — Self-Documenting Pages

Every page in the ops console must communicate its purpose. This is especially critical for stub and airlock pages, but applies to all pages.

Page Header Standard

Every page has a consistent header block:

  • Page title (e.g. 'Enrichment')
  • Purpose line (one sentence explaining what this page does and why it exists)
  • Status badge (live, stub, airlock, beta) — right-aligned

Stub Pages

When a page is architecturally planned but not yet implemented, it must show:

  • What it will do: A clear 2-3 sentence description of the page's purpose
  • What problem it solves: Why this page exists in the system
  • Where it fits: Its position in the pipeline or workflow (e.g. 'Enrichment runs after RTO discovery and before Scope Analytics')
  • What's needed: What must be built before this page goes live

Airlock Pages

Pages gated behind a readiness check (e.g. Pipeline) follow the same pattern but add:

  • Readiness criteria: What conditions must be met to unlock this page
  • Current status: Which criteria are met and which are pending

Page Descriptions (Current Console)

The following descriptions should appear on each page:

Page Purpose Line
Platform Dashboard Aggregate view across all worlds: system health, recent activity, key metrics.
Health SLA evidence: live platform status, surface endpoint health, and traffic analytics.
Incident Status Public incident feed from status.ucca.online. Declare and track incidents.
Authority Catalogue Browse and inspect authority objects (units, qualifications, standards) across all worlds.
Access Control Manage who can access the control plane and at what permission level.
Settings Platform-wide configuration: API keys, integration settings, notification preferences.
RTOpacks Dashboard World overview: RTO count, enrichment progress, scope coverage, drift alerts.
RTO Explorer Search, browse, and inspect individual RTOs. Enrichment data, scope rows, contact details.
Enrichment Monitor and manage the auto-enrichment pipeline. View enrichment queue, success rates, data sources (TGA, ABN Lookup).
Scope Analytics Analyse training product scope across RTOs. Coverage gaps, popular qualifications, market analysis.
Provenance Trace the origin and transformation history of every data point. Audit-grade evidence chain.
Drift Monitor Detect when RTO data diverges from authoritative sources. Alert on stale or changed records.
Pipeline Manage ingestion and processing pipelines. Run, schedule, monitor, and replay data flows.

Section 15 — Claude Code Governance

This section defines how Claude Code interacts with the UI specification during development.

Hard Rule: Read Before Building

Claude Code must read the UI Specification before making any visual change to the ops console. This is non-negotiable.

The following instruction is in CLAUDE.md:

All UI development on ops.ucca.online must conform to the UI Specification (architecture/ui-specification.md). Read it before making any visual changes to the ops console. If the spec does not cover a case, present options to Tim before implementing. Never guess at visual design — ask.

Decision Protocol

When Claude Code encounters a UI decision not covered by this spec:

  1. Stop. Do not implement a visual design choice without guidance.
  2. Identify the gap. What specific decision is needed? (layout, colour, component, interaction)
  3. Present options. Show 2-3 concrete alternatives with rationale for each.
  4. Wait for Tim. Implement only after direction is given.
  5. Update the spec. Once a decision is made, add it to this specification so it's captured for next time.

What This Prevents

  • Random component choices that don't match existing patterns
  • Inconsistent spacing, typography, or colour usage
  • Pages that 'work' but don't communicate
  • Design debt from ad hoc decisions that compound over time

Spec Evolution

This specification is a living document. As new patterns emerge and decisions are made, they are added here. The spec grows with the product. Every visual decision should eventually have a home in this document.


Version History

Version Date Change Author
1.0 2026-03-03 Initial specification. Linear model, four-layer architecture, five implementation phases. Tim Rignold / Claude
1.1 2026-03-03 Added page-level design rules (S13), self-documenting pages (S14), Claude Code governance (S15). Command palette search result display clarification (S3). Tim Rignold / Claude