Secure Mesh Design Systems
Secure Mesh Design Systems
The Secure Mesh Design Systems page documents the Obsidian Precision design language that powers every surface of the Secure Mesh web and mobile apps — from the CSS design tokens in streaming-frontend/app/globals.css to the glassmorphic component primitives, the typography and motion rules, and the porting map that translates the HTML/CSS mockups into live routes.
Purpose and Scope
This page covers the design system layer of Secure Mesh: the visual identity, design tokens (color, surface, typography, glass effects), reusable component styling primitives, theme switching, and the interaction/motion language used by both the Next.js web client and the Expo mobile app.
Related topics are intentionally left to sibling pages:
- For the overall system topology, tech stack, and the full v19 master specification, see the Secure Mesh architecture overview.
- For the shared realtime plane (gRPC,
@securemesh/realtime-core, WebRTC/SFU), see the Unified Realtime Engine page. - For the Axum/Tonic backend, Redis signaling, and PostgreSQL persistence, see the Backend Services page.
- For authentication, E2EE (X3DH + Double Ratchet), and token rotation, see the Security Architecture page.
Overview
Secure Mesh is an end-to-end encrypted, real-time multimedia messaging and audio/video calling application designed for ultra-high scale and zero-trust security. Its user interface is built on a deliberately minimal, high-contrast design system called Obsidian Precision:
- Deep obsidian black backgrounds (
#0B0F17) create a “secure, private, low-light” canvas that visually signals the security posture of the product. - Emerald primary accents (
#10B981per spec, implemented as#4edea3in the shipped token set) are used sparingly for interactive highlights, presence, and success states. - Glassmorphism —
backdrop-filter: blur(16px)with hairline1px solid rgba(255, 255, 255, 0.08)borders — layers floating panels over blurred imagery. - Inter typography with tabular numerals keeps timestamps, counters, and message metadata aligned.
- UI-thread motion on mobile via Reanimated 4 worklets: spring slide-up message bubbles, momentum TabBar indicator, kinetic press, and an emerald pulsing status ring.
The web styling is ported verbatim into streaming-frontend/app/globals.css, and the HTML/CSS mockups for each feature surface are mapped to specific App Router routes.
The design system is implemented as CSS custom properties (design tokens) with a dark theme as the default :root scope and a light theme override, consumed by a small set of global utility classes (.glass-panel, .glass-card, .btn-primary, etc.) and by the application shell in app/layout.tsx. The design system is therefore decomposed into small, single-responsibility token and component files.
Architecture
The following diagram shows how the design source (DESIGN.md + mockups) flows into the token layer, is consumed by the component primitives and the app shell, and finally styles the feature routes:
Reading the diagram:
- Design Source — the design spec is the single source of truth for tokens and glass styling; the feature mockups are the source of truth for page-level layout.
- Design Token Layer — all token values are compiled into
app/globals.cssas CSS custom properties. The dark palette is declared on:root; the light palette overrides the same property names under a separate scope, so components that only referencevar(--surface)automatically re-theme. - Application Shell —
app/layout.tsxbinds the token layer to the DOM (bg-[var(--background)] text-[var(--on-surface)] font-sans) and wraps pages inTooltipProvider, whilecomponents.jsonconfigures shadcn/ui to emit styles into the sameapp/globals.css(layout.tsx, components.json). - Feature Surfaces — each App Router group consumes the shell + primitives; page-specific layouts come from the ported mockups.
Design Language: Obsidian Precision
The Obsidian Precision design system is defined by four pillars:
1. Obsidian Color Field
The default canvas is a near-black obsidian tone with emerald signal accents:
| Role | Spec value | Implemented token (globals.css) |
Purpose |
|---|---|---|---|
| Background | #0B0F17 |
--background: #0b0f17 |
App canvas; low-light, “secure environment” feel |
| Surface | — | --surface: #12131a, --surface-low: #1a1b22, --surface-container: #1e1f26 |
Layered elevation for cards, containers, input wells |
| Primary (emerald) | #10B981 |
--primary: #4edea3, --primary-glow: rgba(78, 222, 163, 0.25) |
Interactive accents, presence, success; glow used for emerald halo effects |
| On-primary | — | --on-primary: #003824 |
Text/icon on emerald fills (dark green for contrast) |
| On-surface | — | --on-surface: #e2e1eb, --on-surface-variant: #bbcabf |
Primary and secondary text on dark surfaces |
The spec names #10B981 as the emerald primary; the shipped token set uses the slightly lighter #4edea3 with a dedicated --primary-glow alpha token for glow effects (globals.css). This is a deliberate implementation refinement of the spec value rather than a fork of the palette — components should always reference var(--primary), never a literal hex, so a future re-alignment to the spec value is a one-line change.
2. Glassmorphism
Floating surfaces are rendered as translucent glass: backdrop-filter: blur(16px) over blurred imagery, with a hairline 1px solid rgba(255, 255, 255, 0.08) border to separate glass from the canvas. The implementation exposes this as reusable primitives (see Component Styling Primitives below), so every panel — chat pane, group drawer, story viewer, call overlay — shares identical glass physics.
3. Inter Typography
Inter (Google Font) is the single typeface, loaded with tabular number formatting so message timestamps, unread badges, and call durations do not jitter as digits change. The implementation sets font-family: 'Inter', system-ui, -apple-system, sans-serif at the body level (globals.css).
4. Motion as a Security Cue
Motion is not decorative: spring animations and the emerald status ring reinforce liveness and presence — the pulse ring signals “encrypted and live,” and kinetic press feedback confirms interaction latency is near zero because it runs on the UI thread (see Motion & Interaction Design).
Design Token Architecture
Tokens live entirely in streaming-frontend/app/globals.css as CSS custom properties. The dark theme is the default; the light theme overrides the same property names, so theming is a property-reassignment problem, not a component rewrite.
Key evidence from the implementation:
- Dark tokens are declared on
:root— the default — with--background: #0b0f17,--surface: #12131a,--surface-low: #1a1b22,--surface-container: #1e1f26,--primary: #4edea3,--primary-glow: rgba(78, 222, 163, 0.25),--on-primary: #003824,--on-surface: #e2e1eb, and--on-surface-variant: #bbcabf(globals.css). - The light theme re-declares the same names:
--background: #f8fafc,--surface: #ffffff,--surface-low: #f1f5f9,--surface-container: #ffffff,--on-surface: #0f172a,--on-surface-variant: #64748b, and adds--border-glass: rgba(0, 0, 0, 0.08)for dark-on-light hairline borders (globals.css). - The body binds the tokens globally:
background-color: var(--background); color: var(--on-surface);(globals.css).
The naming convention mirrors Material 3 semantics (surface, surface-container, on-surface, on-primary, surface-variant) so designers and developers can reason about elevation and contrast roles without knowing hex values. Notably, light-theme hairline borders use a black alpha (rgba(0, 0, 0, 0.08)) while the dark-theme spec calls for white alpha borders — the glass border token is theme-adaptive, which is exactly what a token abstraction should encapsulate.
Component Styling Primitives
The design system exposes a small set of global classes in app/globals.css that encode the glassmorphism and emerald action language:
.glass-panel— translucent floating surface usingvar(--glass-bg)as its fill; used for overlays such as call controls and story viewers (globals.css). The mockups consistently pair it withbackdrop-blur, shadow, and emerald glow utilities (e.g.,glass-panel ... emerald-glowon the local video tile in the call view)..glass-card— elevated card usingvar(--surface-container)with a1px solid var(--border-glass)hairline border; the workhorse container for chat rows, group tiles, and status cards (globals.css)..btn-primary— emerald action button:background: var(--primary); color: var(--on-primary);(globals.css). The high-contrast--on-primary: #003824guarantees readable labels on the bright emerald fill.
These primitives are intentionally class-based rather than component-library components: the design system is vanilla CSS, and shadcn/ui is configured only as a base (components.json points "css" at app/globals.css with "baseColor": "neutral") (components.json). Feature pages then compose the primitives with Tailwind utilities in the same way the mockups do — for example, the groups grid uses bg-surface-container-highest tiles with rounded-xl and hairline border-white/5.
Motion & Interaction Design
The mobile design system defines its animation language in the v19 spec — all motion executes on the UI thread via Reanimated 4 worklets (runOnUI / scheduleOnUI) to avoid JS-bridge latency:
| Motion | Spec behavior | Design intent |
|---|---|---|
| Message bubble entry | Spring slide-up + fade | Incoming messages “arrive” gently; spring feels alive without blocking reads |
| Custom TabBar indicator | Momentum spring slide | The active tab indicator glides with momentum, giving navigation physical feedback |
| Kinetic press | scale(0.97) on touch down |
Instant tactile confirmation that the tap registered — critical in a security-first app where users expect deterministic response |
| StatusRing | Emerald border pulse repeat | A breathing emerald ring signals “encrypted, live presence” — the visual heartbeat of the secure mesh |
These patterns are implemented with react-native-reanimated 4.5.1 + react-native-worklets and reused across web-adjacent UI (the StatusRing motif also appears in web mockups as emerald glow accents). Because all animation worklets run on the UI thread, the design system guarantees zero JS-bridge jank for its four canonical motions — there is no scroll/listener-driven fallback for these interactions.
Page Porting Map
Every feature surface is ported 1 from an HTML/CSS mockup to an App Router route, with the design spec supplying the shared token layer:
| Mockup | Target route | Primary surface |
|---|---|---|
| Design spec | streaming-frontend/app/globals.css |
Design tokens & glassmorphism |
| Auth flows | (auth)/signup & login |
Auth screens with btn-primary CTAs |
| Chats | (app)/chats |
3-pane chat layout |
| Groups | (app)/groups |
Group grid & drawer |
| Status | (app)/status |
Stories grid & viewer |
| Calls | (app)/calls |
Bento stats & ActiveCallOverlay |
The mockups themselves are the visual contract: they use the same surface-role class vocabulary (bg-surface-container-lowest, bg-surface-container-highest, border-white/10, glass-panel, emerald-glow) that the token system formalizes, so porting is a mechanical translation of utility classes onto the token names rather than a redesign.
Configuration Options
The design system is configured through CSS custom properties (tokens) rather than a runtime config object. The complete implemented dark-theme token set in app/globals.css:
| Token | Default value | Description |
|---|---|---|
--background |
#0b0f17 |
App canvas — deep obsidian black |
--surface |
#12131a |
Base surface elevation |
--surface-low |
#1a1b22 |
Low-elevation surface (inputs, wells) |
--surface-container |
#1e1f26 |
Container surface (cards, tiles) |
--primary |
#4edea3 |
Emerald primary accent (spec: #10B981) |
--primary-glow |
rgba(78, 222, 163, 0.25) |
Emerald halo/glow for presence rings and call overlays |
--on-primary |
#003824 |
Content color on primary fills |
--on-surface |
#e2e1eb |
Primary text on dark surfaces |
--on-surface-variant |
#bbcabf |
Secondary/variant text |
--border-glass |
(light: rgba(0,0,0,0.08)) |
Hairline glass border; dark theme uses white-alpha borders per spec |
Light-theme overrides: --background: #f8fafc, --surface: #ffffff, --surface-low: #f1f5f9, --surface-container: #ffffff, --on-surface: #0f172a, --on-surface-variant: #64748b, --border-glass: rgba(0, 0, 0, 0.08) (globals.css).
Static build configuration (components.json):
| Option | Value | Description |
|---|---|---|
css |
app/globals.css |
shadcn/ui emits component styles into the token file |
baseColor |
neutral |
shadcn base color family (neutral grays) |
rsc |
(per components.json) | React Server Components support for generated UI |
Usage Examples
Dark Theme Design Tokens (default :root scope)
The core of the design system — obsidian surfaces, emerald primary with glow, and contrast-role text tokens:
:root {
--background: #0b0f17;
--surface: #12131a;
--surface-low: #1a1b22;
--surface-container: #1e1f26;
--primary: #4edea3;
--primary-glow: rgba(78, 222, 163, 0.25);
--on-primary: #003824;
--on-surface: #e2e1eb;
--on-surface-variant: #bbcabf;
}
Light Theme Override
The same token names are reassigned for light mode; note the theme-adaptive hairline border token:
.light {
--background: #f8fafc;
--surface: #ffffff;
--surface-low: #f1f5f9;
--surface-container: #ffffff;
--on-surface: #0f172a;
--on-surface-variant: #64748b;
--border-glass: rgba(0, 0, 0, 0.08);
}
Global Body Binding
The application shell binds tokens at the body level — every descendant inherits the obsidian canvas and Inter font stack:
body {
background-color: var(--background);
color: var(--on-surface);
font-family: 'Inter', system-ui, -apple-system, sans-serif;
}
Component Primitives
The three canonical primitives — glass panel, glass card, and the emerald primary button:
.glass-panel {
background: var(--glass-bg);
}
.glass-card {
background: var(--surface-container);
border: 1px solid var(--border-glass);
}
.btn-primary {
background: var(--primary);
color: var(--on-primary);
}
Application Shell Wiring
layout.tsx consumes the tokens through Tailwind arbitrary values and wraps the app in the shadcn tooltip provider — demonstrating the token-first contract between the design system and the React shell:
<body className="min-h-full flex flex-col bg-[var(--background)] text-[var(--on-surface)] font-sans">
<TooltipProvider>{children}</TooltipProvider>
</body>
Mockup Class Vocabulary (porting contract)
The mockups already speak the token vocabulary, which is why porting is mechanical. The audio-call overlay uses bg-surface-container-lowest + hairline white borders over a blurred portrait; the local video tile in the call view composes glass-panel with emerald-glow:
<div class="absolute inset-0 bg-surface-container-lowest opacity-90 z-10"></div>
<div class="absolute bottom-xl right-xl w-64 aspect-video rounded-xl overflow-hidden glass-panel shadow-2xl z-20 border-2 border-white/10 emerald-glow group">
API Reference
The design system exposes a CSS class API rather than a programmatic API. The global classes and tokens below are the stable interface every feature page contracts against:
Global Classes
| Class | Declared behavior | Used by |
|---|---|---|
.glass-panel |
background: var(--glass-bg) — translucent floating surface |
Call overlays, story viewer, floating controls |
.glass-card |
background: var(--surface-container); border: 1px solid var(--border-glass) |
Chat rows, group tiles, status cards |
.btn-primary |
background: var(--primary); color: var(--on-primary) |
Auth CTAs, primary actions |
Parameters / behavior notes:
.glass-panel— the exact--glass-bgalpha value is defined in the dark theme’s glass token family; components must not hardcodergba()fills..glass-card— inherits its border color from--border-glass, which is theme-adaptive (white-alpha in dark, black-alpha in light)..btn-primary— text color comes from--on-primary(#003824), not from--on-surface; do not override with Tailwind text utilities or contrast breaks.
CSS Custom Properties (tokens)
All tokens are read via var(--token-name). There is no JavaScript getter/setter — theming is pure CSS cascade:
| Token | Type | Theme default | Throws / fallback |
|---|---|---|---|
--background |
color | #0b0f17 (dark) / #f8fafc (light) |
Inherits if missing (no runtime error) |
--primary |
color | #4edea3 (dark, spec #10B981) |
Inherits if missing |
--primary-glow |
color | rgba(78, 222, 163, 0.25) |
Inherits if missing |
--on-primary |
color | #003824 |
Inherits if missing |
--on-surface |
color | #e2e1eb (dark) / #0f172a (light) |
Inherits if missing |
--on-surface-variant |
color | #bbcabf (dark) / #64748b (light) |
Inherits if missing |
--border-glass |
color | white-alpha (dark, per spec) / rgba(0,0,0,0.08) (light) |
Inherits if missing |
Because tokens are standard CSS custom properties, the “API” contract is: always reference the variable, never the literal value — this is what keeps theme switching and the future spec-value alignment (#10B981) to a one-line change.
Failure Modes, Edge Cases & Concurrency
The design system is CSS-first, so its failure modes differ from runtime code. Source-backed observations:
- Literal-hex drift (design debt): The spec names emerald primary
#10B981while the shipped token is#4edea3(globals.css). If any component hardcodes either literal instead ofvar(--primary), re-aligning the palette silently breaks that component — the canonical failure mode for token systems. The mitigation is the documented rule: components may only referencevar(--primary). - Token shadowing / cascade conflicts: Light-theme overrides reassign the same property names (globals.css). If a page wraps content in a theme scope with a different selector specificity than intended, tokens silently resolve to the wrong palette. Because there is no runtime validation (no “token lint” step found in the repo), this class of bug surfaces only visually.
- Missing-token fallback: CSS custom properties have no error path — an undefined
var(--surface-container)makesbackground: var(--surface-container)resolve tounset, producing transparent surfaces that can look like intentional glass on dark canvases. Consumers must rely on the single source of truth inapp/globals.cssrather than re-declaring tokens per page. - Contrast on emerald fills:
.btn-primarypairs--primarywith--on-primary: #003824(globals.css); using--on-surface(near-white) on the emerald fill would produce poor contrast. The primitive encodes the correct pairing, which is why page code should prefer.btn-primaryover ad-hoc button styling. - Concurrency / shared-shell contention: All feature surfaces render inside one
bodybound to the design tokens, and shadcn emits into the sameglobals.css(components.json). A utility class collision or a late-loaded stylesheet that re-declares.glass-card/.btn-primaryaffects every page simultaneously — the design system is a single shared mutable namespace, so styling changes are cross-cutting by construction (this is a deliberate trade-off of the vanilla-CSS approach, not an oversight). - Theme-switch flash: With dark as the
:rootdefault and light as an override, any client-side theme toggle that applies after first paint will briefly render dark-mode surfaces; the spec’s “secure, low-light” default means this is the intended initial state, but a persisted light preference requires pre-hydration token injection to avoid flicker.
Performance & Operational Considerations
- Glassmorphism cost:
backdrop-filter: blur(16px)is GPU/CPU-expensive when layered over large or frequently re-rendered areas (long chat scroll, group grids). The design confines glass to panels and overlays, and mockups usebackdrop-blur-md/opacitymodifiers sparingly; keep glass off scrolling list rows to preserve frame rate. - UI-thread motion: Mobile animations (bubble spring, TabBar momentum, kinetic press
scale(0.97), status-ring pulse) run on the UI thread via Reanimated 4 worklets (runOnUI/scheduleOnUI). This removes JS-bridge latency from interaction feedback but means animation worklets must not depend on JS-bound values that change mid-gesture. - Single font, tabular numerals: One typeface (Inter) with tabular figures keeps message timestamps and counters stable and avoids cumulative layout shift from digit-width changes.
- Token footprint: The entire design system is a single
app/globals.cssconsumed by every route; changes to tokens propagate instantly, keeping the file small and cache-friendly.
Extension Points
- New tokens: Add a new custom property to the dark
:rootblock and mirror it in the light override; any component can then consumevar(--new-token). Follow the Material-3-style naming (--surface-container-*,--on-*,--*-variant) used by the existing set. - New primitives: Add global classes (e.g.,
.btn-secondary,.glass-input) next to.glass-panel/.glass-card/.btn-primaryinapp/globals.css, composing existing tokens — do not introduce new literal colors. - Theme scopes: The light override demonstrates the pattern: wrap a subtree in a theme class and reassign token names. Additional themes (e.g., a high-contrast accessibility theme) are pure additions of new scopes.
- Palette alignment: To adopt the spec’s exact emerald (
#10B981), change only--primary(and optionally--primary-glow/--on-primary) in both scopes — every consumer updates automatically. - shadcn/ui integration:
components.jsonalready targetsapp/globals.csswith a neutral base (components.json); generated shadcn components inherit the token system without additional wiring.
Tests
Implementation details of automated tests for the design system were not found in the repository source at the time of writing. The verifiable quality gates are structural instead:
- The single-responsibility decomposition keeps the token/primitive files small and reviewable — an enforced, mechanical substitute for style-lint test suites.
- The mockup-to-route porting map acts as a visual regression contract: a route that diverges from its source mockup is detectable by design review against the HTML/CSS originals.
- The token-only rule (components must reference
var(--token), never literals) is the primary maintainability invariant; teams should consider adding a stylelint rule that bans raw hex values outsideglobals.cssas a first automated test.
Related Links
- Secure Mesh Architecture Overview — system topology, tech stack, and the full v19 master spec.
- Unified Realtime Engine — gRPC realtime plane,
@securemesh/realtime-core, WebRTC/SFU. - Security Architecture — E2EE (X3DH, Double Ratchet, Sender Keys), token rotation, zero-trust model.
- Token implementation: streaming-frontend/app/globals.css.
- App shell wiring: streaming-frontend/app/layout.tsx.