The foundational layer that powers every Mémoire-generated interface. Tokens, primitives, components, and patterns - all built for autonomous reskinning while preserving developmental integrity.
Every component is classified atom through template. No exceptions.
Token-driven
All visual decisions are tokens. Swap them, swap the skin.
Agent-native
Claude reads, generates, and validates every component autonomously.
Presentable
Every output is portfolio-grade. Preview gallery by default.
Light-first
Blank white surfaces, black typography, rose action, and sunset warmth. Color stays floral and purposeful.
Restrained
Gradients are reserved for brand atmosphere, focus, and premium moments. Reading surfaces stay quiet.
Design philosophy
Mémoire's visual language draws from terminal precision, blank architectural surfaces, and rose-sunset atmosphere. Monospace fonts handle data and system labels. Serif italic adds editorial warmth. Rose and soft sunset tones appear as a controlled floral signal layer over black and white.
The system is deliberately sparse. Every element must earn its pixels - no decorative borders, no gratuitous shadows, no animation without purpose. This restraint is the design decision, not a limitation. When an interface is 90% negative space and typography, every remaining element carries maximum weight.
DESIGN TOKENS
The semantic layer
Tokens are the single source of truth for all visual decisions. Mémoire extracts them from Figma variables and exports as CSS custom properties, Tailwind config, or raw JSON. Every generated component references tokens - never raw values. The default palette is blank white, black, and rose-sunset accents.
motion.*Duration and easing - fast, normal, slow, spring
Rose sunset base tokens
The default Mémoire aesthetic is now blank white architectural surfaces with a black and rose-sunset accent system. Reading surfaces stay quiet; rose marks action, focus, selection, and atmosphere.
--color-surface
#fffefd
--color-surface-raised
#ffffff
--color-surface-sunken
#f8f5f2
--color-night-sky
#090808
--color-foreground
#11100f
--color-foreground-muted
#5f5552
--color-border
#e8e0dc
--color-accent
#c85f78
--gradient-liquid-sunset
black / rose / blush / sunset
Atomic level badges
Each atomic level has a fixed color used across the dashboard, preview, and generated documentation.
atomRose - primitive UI surface
moleculeBlush - composed primitive surface
organismSunset - stateful feature surface
templateInk - layout and page skeleton
shadcn token mapping
Figma tokens are auto-mapped to shadcn CSS variables via regex in tailwind-tokens.ts. Values are converted to HSL for shadcn compatibility.
--primaryprimary, brand
--secondarysecondary
--accentaccent
--backgroundbackground, bg
--foregroundforeground, text
--mutedmuted
--destructivedestructive, error, danger
--borderborder
--ringring, focus
--cardcard
--popoverpopover
--inputinput
Export formats
TERMINAL
# Export as CSS custom properties
memi tokens --format css
# Export as Tailwind config
memi tokens --format tailwind
# Export as raw JSON
memi tokens --format json
TYPOGRAPHY
Two faces, one system
Mémoire uses a deliberate dual-font pairing. The monospace stack - SF Mono, Fira Code, JetBrains Mono - for all interface text: data, labels, code, navigation. Cormorant Garamond for display moments only: titles, brand, editorial.
Mémoire uses blank white surfaces and a deep black base, then reserves rose and sunset warmth for action, focus, selection, hero atmosphere, and high-value moments. The gradient is a brand atmosphere, not a default fill.
Background
#fffefd - blank canvas, primary reading surface
Card
#ffffff - elevated card and navigation surface
Inset
#f8f5f2 - code, inset, and low-emphasis surfaces
Night
#090808 - hero base, logo contrast, and dark feature panels
Foreground
#11100f - headings and primary body text
Rose
#c85f78 - primary action, link, and focus anchor
Bloom
#d94f7d - creative highlight and selected reference bloom
Sunset
#e58b6d - ambient warmth and CTA glow, not the only active color
SOUL.MD RULE
No color without semantic meaning. Liquid gradients are for hero atmosphere, focus, and high-value actions. No animation longer than 400ms for UI (cinematic excepted). From .memoire/SOUL.md.
SPACING + GRID
4px base unit
All spacing derives from a 4px base. Components use semantic spacing tokens rather than raw pixel values. Grid layouts use CSS Grid with named areas for template-level composition.
1 - 4px
2 - 8px
3 - 12px
4 - 16px
6 - 24px
8 - 32px
12 - 48px
16 - 64px
Grid system
Sidebar + Content240px fixed sidebar, 1fr main - docs, design system
Dashboard Grid12-column grid with named areas for card placement
Full BleedEdge-to-edge hero sections with centered content
ATOMS
Primitives - components/ui/
The smallest building blocks. Atoms map directly to shadcn/ui primitives. The auto-spec engine infers atomic level from component names via regex pattern matching in auto-spec.ts. All 21 shadcn components are mapped in shadcn-mapper.ts.
shadcn/ui component map (21)
Button
ui/button.tsx
Badge
Badge
ui/badge.tsx
Input
ui/input.tsx
Label
Label
ui/label.tsx
Card
ui/card.tsx
Separator
ui/separator.tsx
Full shadcn map from SHADCN_IMPORTS in the codegen engine:
Atoms never compose other specs. composesSpecs must be empty in the JSON spec. If no pattern matches, the engine uses a heuristic: 6+ props or 5+ variants = organism, 3+ props or 2+ variants = molecule, else atom.
MOLECULES
Composed primitives - components/molecules/
Molecules combine 2-5 atoms into a functional unit. They map to auto-spec patterns like form-field, stat, metric, card. Output goes to components/molecules/.
Organisms are complex components with real state and behavior. They compose molecules and atoms, handle data fetching, and manage interaction flows. This is where business logic lives in the component tree.
SidebarNavItems + brand + section groups - app navigation
SpecViewerCode block + metadata + validation status - spec inspector
Templates define page structure without content. They specify grid areas, responsive breakpoints, and slot positions. Content is injected by page specs - templates are purely structural.
SplitTemplate50/50 panes for comparison, editor, or preview views
sidebar
header
card
card
card
card - wide
card
card
DashboardTemplate - grid-template-areas
SPEC TYPES
Five specs, one system
Every artifact in Mémoire starts as a typed JSON spec validated by Zod. The spec is the single source of truth - code generation, validation, and preview all derive from it. Defined in src/specs/types.ts.
Every ComponentSpec has a codeConnect field that maps Figma components to codebase files. When Figma MCP returns Code Connect snippets, the codegen engine uses the mapped component directly instead of generating from scratch.
get_code_connect_mapRead existing component-to-code mappings from Figma
add_code_connect_mapRegister a new codebase component to a Figma component
get_code_connect_suggestionsAI-suggested mappings based on name matching
LAYOUT PATTERNS
Repeatable structures
PageSpec defines six layout types. These map to CSS Grid structures that templates implement. Section-level layouts control card placement within each page section.
half / third / quarterFractional widths within a row
grid-2 / grid-3 / grid-4Equal-column grids
stack / inlineVertical stack or horizontal inline flow
Responsive defaults (PageSpec.responsive)
mobilestack - single column, collapsible sidebar
tabletgrid-2 - two-column where possible
desktopgrid-4 - full multi-column layout
INTERACTION
Motion and state
Interactions are minimal and purposeful. Transitions use 150-200ms durations with cubic-bezier(0.4, 0, 0.2, 1) easing. No spring physics, no bounces - direct, fast, and honest feedback. Every interactive element has three states: rest, hover, active.
Hash routingDeep links via URL hash (#section-id). Auto-switches to correct tab on load.
Mobile hamburgerTwo-line icon rotates 45deg to X. Dropdown uses frosted glass backdrop-filter.
Feedback patterns
Skeleton loadingAnimated pulse on placeholder shapes. Same dimensions as final content.
Progress barsBlock-fill animation left to right. Success fill uses --color-success; the empty track uses --color-border.
Toast notificationsSlide in from top-right. Auto-dismiss after 4s. No stacking - newest replaces.
Validation statesErrors use --color-danger, success uses --color-success. Inline message below.
Glassmorphism
The frosted glass effect is used sparingly on elevated surfaces: nav bar, card backgrounds, and mobile overlays. It uses backdrop-filter: blur(20px) saturate(1.6) with semi-transparent white backgrounds.
Nav barbackdrop-filter plus --color-surface-overlay
Card surfacesblurred surface with --color-surface-raised
Mobile overlayblurred overlay with --color-surface and --color-overlay-dim
TIMING RULES
150ms for color and opacity changes. 200ms for transform and layout shifts. 300ms for nav panel open/close. 400ms absolute maximum for any UI transition. Easing: cubic-bezier(0.4, 0, 0.2, 1) for enters, cubic-bezier(0, 0, 0.2, 1) for exits.
DATA DISPLAY
Visualizing system state
Mémoire generates dataviz from DataVizSpec using Recharts by default (also supports d3, visx, custom). Each chart is wrapped in a shadcn Card. Interactions and accessibility are defined in the spec.
Chart types (DataVizSpec.chartType)
lineTime-series, trends - single stroke, no fill by default
heatmapDensity visualization - grid-based color intensity
sankeyFlow diagrams - source to destination with volume
gaugeProgress/threshold indicator - single value against range
sparklineInline trend indicator - compact, no axes
composed / customMulti-chart overlay or fully custom rendering
Chart interactions
hover-tooltipDefault - shows data point values on hover
click / drill-downNavigate into data segments
zoom / brush / panRange selection and navigation
legend-toggleShow/hide series via legend
crosshair / exportData inspection and download
AGENTICUI BASE STRUCTURE
The autonomous design engine
AgenticUI is defined by .memoire/SOUL.md - the design soul file. It is not a brand, it is a structural foundation any brand can sit on. Light-first, monospace-native, tight spacing, and token-only color.
Voice (from SOUL.md)
Minimal, precise, monospace-native - no marketing speak, no filler
Technical but warm - like good documentation
Visual language
Light-first - off-white canvas, deep text, night panels when focus is needed
Monospace typography as primary - JetBrains Mono, SF Mono, Fira Code
Rose accent system - rose for action, floral pink for creative selection, sunset warmth for atmosphere
2px radius, tight spacing - no decorative elements, every pixel earns its place
Interaction principles
Immediate feedback - on all actions, no loading spinners without progress
Keyboard-first, mouse-friendly - every action has a keyboard path
Progressive disclosure - show less, reveal on demand
Respect prefers-reduced-motion - honor system accessibility settings
Anti-patterns (enforced)
No arbitrary gradients - use only the liquid sunset tokens or data-driven gradients
No rounded-full - except true pills and status chips
No color without semantic meaning - decoration is noise
No animation > 400ms - for UI transitions (cinematic excepted)
How Claude uses it
Claude reads SOUL.md + the token system, applies light-mode defaults, and outputs shadcn/ui + Tailwind. The self-healing loop (CREATE → SCREENSHOT → ANALYZE → FIX → VERIFY, max 3 rounds) validates the result against the aesthetic.
Reskinning is how Mémoire transforms a neutral AgenticUI project into a branded case study. The structure stays, the skin changes. This is done entirely through token overrides - no component code changes.
What changes (token categories from DesignToken)
color tokensOverride --bg, --fg, --accent, --muted, --border, --card - auto-mapped to shadcn vars
typography tokensSwap --mono and --serif font stacks - brand typeface
spacing / radius4px base unit scale + border radius - --radius from 0 to 12px+
shadow tokensFlat to elevated - sm, md, lg elevation levels
Self-healing loopStill validates every canvas operation
RESKIN EXAMPLE
// Override tokens for a rose system case study
{
"color.bg": "var(--color-surface)",
"color.fg": "var(--color-foreground)",
"color.accent": "var(--color-accent)",
"color.muted": "var(--color-foreground-muted)",
"typography.family.mono": "'IBM Plex Mono', monospace",
"radius.md": "var(--radius-md)",
"shadow.md": "var(--shadow-md)"
}
CASE STUDIES
Presentable by default
Every Mémoire project generates a preview gallery automatically via memi preview. It runs on port 3030 and serves 6 pages in the AgenticUI aesthetic or the project's reskinned version.
Preview gallery pages
Index - project overview with component counts, token summary, Figma status
Specs - all component, page, and dataviz specs with validation status
Design System - live token table with swatches and export controls
Research - ingested data visualized as charts and insight cards
Changelog - version history with architectural decisions documented
Workflow
figma pull→token override→spec create→generate→preview=case study
DEVELOPMENTAL INTEGRITY
Guardrails that hold
Reskinning is surface-level by design. The development architecture underneath never bends. These constraints are enforced in code - not by convention, not by documentation, but by Zod schemas and validation at every step.
Enforced constraints
Atoms cannot compose
Zod rejects any atom spec with non-empty composesSpecs
Molecules must compose atoms
Spec validation checks that composed specs exist and are atoms
Templates have no content
Template specs define slots only - content comes from page specs
Tokens are semantic
Raw hex values in generated code trigger a self-healing correction
TypeScript strict
All generated code passes tsc --strict - no any, no implicit
Self-healing validates
Screenshot loop checks visual output against the spec intent, max 3 rounds
PHILOSOPHY
The skin is the variable. The skeleton is the constant. You can make it look like anything - but you cannot break the atomic hierarchy, skip validation, or bypass the self-healing loop. That is what developmental integrity means.
TERMINAL UI
mémoire TUI design system
The visual language of the memi CLI. Every command speaks through a shared format module - diamond marks, status sprites, dot leaders, bracket-titled boxes, and block progress bars. Monospace-native, ANSI-colored, designed for the terminal as a first-class surface.
Brand-consistent
Same diamond mark, same letter-spaced wordmark as the dashboard. One identity across surfaces.
Sprite vocabulary
Six status sprites cover every state. No icons, no Unicode variation - pure ASCII brackets.
Dot-leader alignment
Label-value pairs always align via dot leaders. Scannable at a glance.
ANSI-safe
All width calculations strip ANSI escape codes. Boxes and alignment work in any terminal.
memi init
♦ M E M O I R Ev0.3.0────────────────────────────────────────────────────────
Framework ········································· vite
Language ······································ typescript
Tailwind ········································yes
shadcn/ui ·······································yesSPECS──────────────────────────────────────────────────[+] MetricCard molecule[+] Dashboard page[+] ActivityChart dataviz────────────────────────────────────────────────────────♦ READY
BRAND MARK
The diamond wordmark
The brand header opens every major command. A bold diamond mark (♦), letter-spaced wordmark, and right-aligned version string sit above a dim horizontal rule. The width is fixed at 56 characters.
ui.brand()
♦ M E M O I R Ev0.3.0────────────────────────────────────────────────────────
♦Diamond mark - brand symbol, used in brand() and ready()
M E M O I R ELetter-spaced wordmark - monospace technical aesthetic
v0.3.0Version string - right-aligned, dim, from package.json
──────Horizontal rule - 56-char dim separator
SOURCE - src/tui/format.ts
brand(subtitle?: string): string {
const ver = chalk.dim("v" + getVersion());
const mark = chalk.bold("◆ M E M O I R E");
const gap = Math.max(1, RULE_W - vLen(mark) - vLen(ver));
const lines = [
"",
" " + mark + " ".repeat(gap) + ver,
" " + chalk.dim("─".repeat(RULE_W)),
];
if (subtitle) lines.push(" " + chalk.dim(subtitle));
lines.push("");
return lines.join("\n");
}
COLOR SYSTEM
Semantic ANSI colors
The TUI uses chalk for semantic coloring. Six colors map to six meanings. No decorative color - every hue communicates state. All colors degrade gracefully in non-TTY environments (piped output, CI logs).
green
Success, ready, confirmed
ui.ok()ui.ready()ui.green()
yellow
Warning, caution, attention
ui.warn()ui.yellow()
red
Error, failure, destructive
ui.fail()ui.red()
rose active
Active, running, interactive
ui.active()ui.promptPrefix()ui.rose()
dim
Secondary, muted, decorative
ui.skip()ui.pending()ui.dim()
bold (white)
Primary text, labels, emphasis
ui.bold()ui.section()
RULE
No color without semantic meaning - same principle as the dashboard. Green means success, red means failure, rose means active. Dim is for decoration and secondary information.
TYPOGRAPHY
Monospace only
The terminal is inherently monospace. All formatting relies on character-width calculations via the vLen() internal which strips ANSI codes to measure true visual length. Fixed-width characters make dot leaders, box drawing, and progress bars possible.
RULE_W = 56Fixed content width for all boxes, rules, and dot leaders
2-space indentAll output is indented 2 spaces from the left margin
UPPERCASESection labels, brand wordmark, status markers
// Strip ANSI codes for accurate width
const ANSI_RE = /\\x1b\\[[0-9;]*m/g;
function strip(text: string): string {
return text.replace(ANSI_RE, "");
}
function vLen(text: string): number {
return strip(text).length;
}
function padR(text: string, width: number): string {
const gap = width - vLen(text);
return gap > 0 ? text + " ".repeat(gap) : text;
}
STATUS SPRITES
Six states, six brackets
Status sprites are the TUI's primary feedback mechanism. Each is a three-character bracket glyph with a semantic color. They replace checkmarks, crosses, and other Unicode symbols with a consistent, scannable vocabulary.
status sprites
[+] MetricCard molecule - created[-] Starter specs already present[!] Daemon already running (PID 42091)
[x] Could not detect project context
[>] Detecting project...
[.] No generated files found
[+]
ok
Success, created, written
[-]
skip
Skipped, already exists
[!]
warn
Warning, non-blocking
[x]
fail
Error, failure, fatal
[>]
active
Running, in progress
[.]
pending
Waiting, queued, dry-run
DOT LEADERS
Label-value alignment
Dot leaders connect a label to its value across a fixed 56-character width. The dots are dim, the label is plain, the value is plain or semantically colored. This is the primary pattern for displaying key-value data.
ui.dots()
Framework ········································· vite
Language ······································ typescript
Tailwind ········································yes
Specs ····················· 3/3 ████████████ 100%
Boxes use Unicode box-drawing characters for bordered containers. The title sits inside brackets on the top rule. Content is padded 2 spaces from each wall. Width is fixed at RULE_W (56). An instruction variant uses dimmed borders for step lists.
ui.box(title, lines)
Primary container for grouped information. Title appears inset on the top border. Used for daemon status, connection info, and configuration summaries.
ui.box()
DAEMON - PID 42091
Preview: http://localhost:5173
Figma: port 9223
Stop with: memi daemon stop
titleBold, appears in [ brackets ] on the top border
linesArray of strings - each padded to inner width (54 chars)
widthOptional, defaults to RULE_W (56). Inner = width - 2
ui.instructions(lines)
Dimmed-border variant for step-by-step instructions. No title. All border characters are rendered in dim. Used for setup guides and next-step prompts.
ui.instructions()
1. Open figma.com/community/plugin/memoire
2. Click "Install"
3. Open any Figma file and run the plugin
IMPLEMENTATION
Box drawing uses padR() internally to right-pad each content line to the inner width. This guarantees the right border aligns perfectly regardless of content length. The vLen() function strips ANSI codes before measuring, so colored content aligns correctly.
PROGRESS BARS
Block-character indicators
Progress bars use filled (█) and empty (░) block characters. Green fill, dim empty. Percentage is appended. Used inline in dot-leader values for spec completion, task progress, and export counts.
Every command follows a consistent 6-layer structure. The brand opens, dot leaders provide context, sections divide content, sprites report per-item status, a rule closes, and a ready marker signals completion.
memi export --dry-run
♦ M E M O I R Ev0.3.0────────────────────────────────────────────────────────EXPORT
Files ··············································· 3
FILES──────────────────────────────────────────────────[.] MetricCard.tsx > src/components/molecules/[.] Dashboard.tsx > src/pages/[.] ActivityChart.tsx > src/components/dataviz/────────────────────────────────────────────────────────♦ DRY RUNwould export 3 files
Output structure
Every command follows this exact sequence. Skipping layers is allowed (not every command has sections or sprites), but the order never changes.
1
Brand header - ui.brand() opens every major command. Diamond + letter-spaced wordmark + right-aligned version + dim rule.
2
Metadata - ui.dots() key-value pairs. Framework, language, spec counts, options. Scannable at a glance via dot leaders.
3
Section divider - ui.section() bold uppercase label + dim dashes. Separates metadata from results.
4
Status lines - ui.ok/skip/warn/fail/active/pending() per-item results. Each line is a sprite + message.
5
Closing rule - ui.rule() dim horizontal separator signals "output complete."
6
Ready marker - ui.ready() green diamond + bold label. Final line of every successful command.
More command examples
memi compose "create a login page"
♦ M E M O I R Ev0.3.0────────────────────────────────────────────────────────COMPOSE
Intent ··········· "create a login page"
Category ········· page-layout
AI ···············enabled────────────────────────────────────────────────────────
Status ··································· completed
Tasks ·········· 3/3 ████████████ 100%
Mutations ································· 2
Time ······································ 2.1s
CHANGES────────────────────────────────────────────────
+ LoginPage: page spec created
+ LoginForm: molecule spec created
memi daemon status
♦ M E M O I R Ev0.3.0────────────────────────────────────────────────────────DAEMON[+] Running
PID ··············································· 42091
Uptime ······································· 1h 23m 4s
Preview ············· http://localhost:5173
Figma ····································· port 9223
Figma link ····························connected
memi connect
♦ M E M O I R Ev0.3.0────────────────────────────────────────────────────────[>] Scanning ports 9223-9232...
[+] Figma bridge on port 9223
FIGMA──────────────────────────────────────────────────
Port ·············································· 9223
File ······························ dashboard.fig
Tokens ·········································· 24
────────────────────────────────────────────────────────♦ READY
Guide pairs
Next-step suggestions use ui.guide() - a bold command name connected by dim dot leaders to a description. Shown at the end of init or after first-time setup.
ui.guide()
memi connect·······························Connect to Figmamemi generate·····························Generate code from specsmemi preview······························Start preview server
DESIGN RULES
Do and don't
Concrete examples of correct vs incorrect TUI usage. These rules apply to all command implementations that use the ui export.
✓ MetricCard created successfully!
✓ Dashboard created successfully!
- Starter specs already present
Data display
DO
Framework ·········· vite
Language ··········· typescript
Tailwind ···········yes
DON'T
Framework: vite
Language: typescript
Tailwind: yes
Color usage
DO
[+] Connected on port 9223[x] Could not detect project
─────────────────────────────
DON'T
INFO: Connected on port 9223ERROR:Could not detect project
========================
PRINCIPLE
Every color must carry semantic meaning. Green is success, red is failure, yellow is warning, rose is active, dim is decorative. Never use color for branding or aesthetics alone. If you remove all color, the output must still be readable and complete.
EVENT LOG
Timestamped stream
Long-running commands like daemon and watch output events as a timestamped log stream. Each event has a dim timestamp, a colored status symbol, a bold action name, and a dim detail string.
ui.event("+", ...)Green + symbol - success event (connected, synced, generated)
ui.event("x", ...)Red x symbol - failure event (disconnected, error, timeout)
ui.event("·", ...)Dim dot symbol - neutral event (in-progress, informational)
The timestamp comes from Date.toLocaleTimeString() with 2-digit hours, minutes, and seconds. The action name is always uppercase and bold. The detail string is always dim.
SPINNERS
Async feedback
The TUI uses ora (v8, ESM) for async operations. Spinners provide feedback during operations that take more than ~200ms - port scanning, Figma token extraction, code generation.
spinner lifecycle
[>] Scanning ports 9223-9232... (spinner)[+] Figma bridge on port 9223 (result)[>] Extracting design tokens... (spinner)
Tokens ·········································· 24 (result)
Libraryora v8 (ESM-only) - auto-detects TTY, falls back to plain text in CI
Colorrose - matches the [>] active sprite
Indent2 spaces - consistent with all other output
PatternStart spinner, await async work, stop spinner, log result via ui.dots() or ui.ok()
stdoutSpinners use process.stdout.write() - invisible to console.log test mocks
NOTE
The spinner replaces itself on completion. The final output is always a static line (dot-leader or sprite), never an animated element. This means piped output and test logs show only the result, not the spinner frames.
API REFERENCE
Complete ui export
All TUI formatting lives in src/tui/format.ts and is imported as ui across every command file.
ui.brand(subtitle?)Diamond wordmark header with version and optional subtitle
ui.box(title, lines, w?)Bracket-titled bordered box with padded content
ui.instructions(lines, w?)Dimmed-border instruction list
ui.section(label)Bold uppercase label + dim rule to 56 chars
chalk v5 (ESM-only) for ANSI colors. ora v8 (ESM-only) for spinners. Both auto-detect TTY - piped output and CI logs receive plain text. The format module has zero other dependencies.