prototype-system

Installation
SKILL.md

Prototype System Skill

The unified reference for building prototypes that look and behave like they already belong in the AskElephant app.

When to Use

  • Building new prototypes (/proto)
  • Iterating on existing prototypes (/iterate)
  • Reviewing prototype quality (/proto-audit)
  • Deciding where a feature should live in the app (placement analysis)
  • Checking design token compliance
  • Understanding available production components

Supporting Documents

This skill references two companion documents — load them when building:

  • Component Registry: .cursor/skills/prototype-system/component-registry.md — Catalog of all production components available for prototype reuse
  • Interactive Patterns: .cursor/skills/prototype-system/interactive-patterns.md — Patterns for making prototypes fully functional

1. Component-First Approach

The #1 reason prototypes look wrong is they don't use production components.

Before Creating ANY Component

Always scan the live codebase first. The component registry (component-registry.md) documents import patterns and usage notes, but the codebase is the source of truth — it ships faster than any doc.

  1. Scan the live codebase at the start of every prototype build:
    # What primitives exist right now?
    ls elephant-ai/apps/web/src/components/primitives/
    
    # What UI components exist right now?
    ls elephant-ai/apps/web/src/components/ui/
    
    # What domain component directories exist?
    ls -d elephant-ai/apps/web/src/components/*/
    
    # What AI elements exist?
    ls elephant-ai/apps/web/src/components/ai-elements/
    
    # What prototype infrastructure exists?
    ls elephant-ai/apps/web/src/components/prototypes/_shared/
    
    # Search for a specific component by name
    rg -l "export.*ComponentName" elephant-ai/apps/web/src/components/ --type tsx
    
  2. If found — Import and use directly, or create a thin wrapper in the prototype's components/ directory
  3. If similar — Read the actual file to understand its props and patterns before building
  4. If not found — Build from production primitives, matching production patterns exactly

component-registry.md is a patterns reference (import paths, key props, usage notes). Use it after the live scan to understand how to use what you found — not to discover what exists.

Import Priority Order

// 1. Primitives buffer layer (preferred — themed, wrapped)
import { Button } from '@/components/primitives/button';
import { Card, CardHeader, CardContent } from '@/components/primitives/card';

// 2. UI layer (fallback when no primitive wrapper exists)
import { Calendar } from '@/components/ui/calendar';
import { Chart } from '@/components/ui/chart';

// 3. Domain components (for feature-specific reuse)
import { EngagementStateBadge } from '@/components/engagements/engagement-state-badge';
import { CompanyLogo } from '@/components/company/company-logo';

// 4. AI elements (for AI feature prototypes)
import { ChainOfThought } from '@/components/ai-elements/chain-of-thought';
import { Suggestion } from '@/components/ai-elements/suggestion';

// ❌ NEVER — prototype-specific base components
import { Button } from './ui/button';
import { Card } from '../shared/card';

When You Must Create New Components

Place them in the prototype's components/ directory. Build from production primitives:

// ✅ New component built from production primitives
import { Card, CardHeader, CardContent } from '@/components/primitives/card';
import { Badge } from '@/components/primitives/badge';
import { Progress } from '@/components/ui/progress';

export function HealthScoreGauge({ score, label }: HealthScoreGaugeProps) {
  return (
    <Card>
      <CardHeader className="pb-2">
        <CardTitle className="text-sm">{label}</CardTitle>
      </CardHeader>
      <CardContent className="pt-0">
        <Progress value={score} className="h-2" />
        <Badge variant="outline" className="mt-2">
          {score}% healthy
        </Badge>
      </CardContent>
    </Card>
  );
}

2. App Shell Integration

Every prototype renders inside the real app navigation. No exceptions.

The App Shell Provides

  • Top-level navigation — Horizontal nav bar with app sections (Search, My meetings, Customers, Chats, Workflows)
  • Global chat access — Pull-out drawer via Cmd/Ctrl+K or nav chat button
  • Content header — Page title and actions area
  • User/workspace context — Profile menu, workspace switcher

How to Use

For views/ and demo/ stories (any full-page view), wrap in the AppShell decorator:

import { withAppShell } from '@/components/prototypes/_shared';

const meta: Meta = {
  title: 'Prototypes/CustomerHealth/v1/Views/Dashboard',
  parameters: { layout: 'fullscreen' },
  decorators: [
    withAppShell({
      workspaceId: 'demo-workspace',
      route: '/workspaces/demo-workspace/customers/health',
    }),
  ],
};

The withAppShell decorator is implemented at elephant-ai/apps/web/src/components/prototypes/_shared/AppShell.tsx. It wraps stories in the real TopNav, GlobalCommand, and GlobalChat context. Use the barrel import from @/components/prototypes/_shared.

Feature flags — pass them as story parameters (handled by the existing PostHog mock):

parameters: {
  featureFlags: { 'customers-page': true, 'new-home-page': true },
}

When NOT to Use the App Shell

  • components/ stories (isolated component testing) — Use layout: 'centered' or layout: 'padded'
  • Testing a component in multiple contexts — Create both isolated and in-shell stories

3. Prototype Structure

Canonical Directory Layout

elephant-ai/apps/web/src/components/prototypes/[InitiativeName]/
├── index.ts                           # Re-exports latest version
├── v1/
│   ├── components/                    # Feature-specific components
│   │   ├── [Component].tsx
│   │   ├── [Component].stories.tsx
│   │   └── ...
│   ├── views/                         # Full page/panel views (AppShell required)
│   │   ├── [FeaturePage].tsx
│   │   ├── [FeaturePage].stories.tsx
│   │   └── ...
│   ├── flows/                         # Interactive journey stories
│   │   ├── Discovery.tsx
│   │   ├── Onboarding.tsx
│   │   ├── HappyPath.tsx
│   │   ├── ErrorRecovery.tsx
│   │   ├── DayTwo.tsx
│   │   └── Flows.stories.tsx
│   ├── demo/                          # Fully functional prototype
│   │   ├── Demo.tsx
│   │   ├── Demo.stories.tsx
│   │   ├── Walkthrough.tsx
│   │   └── Walkthrough.stories.tsx
│   ├── types.ts
│   └── mock-data.ts

What Goes Where

Directory Purpose AppShell? Layout
components/ Isolated building blocks No centered or padded
views/ Full page as it appears in app Yes fullscreen
flows/ Multi-step user journeys Yes fullscreen
demo/ Stakeholder-ready click-through Yes fullscreen

Storybook Titles

Prototypes / [InitiativeName] / v1 / Components / [Name]
Prototypes / [InitiativeName] / v1 / Views / [Name]
Prototypes / [InitiativeName] / v1 / Flows
Prototypes / [InitiativeName] / v1 / Demo
Prototypes / [InitiativeName] / v1 / Walkthrough

4. Placement Analysis

Before building, determine where the feature lives. This information configures the app shell and drives the discovery flow.

Questions to Answer

Question Determines
What type of feature? Container type (page, panel, modal, section)
Where do similar features live? Domain folder, layout pattern
How do users discover it? Nav item, command palette, deep link, button
What's adjacent? What users do before/after
What role/permissions needed? Feature flag, role check

Feature Type → Container Decision

Feature Type Container Navigation Example
Primary workflow Full page Top nav item Customers dashboard
Detail view Side panel / Sheet Click from list Company detail panel
Quick action Modal / Dialog Button trigger Send notetaker dialog
Configuration Settings page Settings > Section Integration config
Inline enhancement Embedded section Already visible AI suggestions on meeting page
Global utility Drawer / Overlay Keyboard shortcut Global chat (Cmd+K)

Record Placement Decision

Save to pm-workspace-docs/initiatives/active/[name]/placement-research.md:

## Placement: [Feature Name]

**Type:** Full page
**Route:** `/workspaces/:workspaceId/customer-health`
**Nav Entry:** Top nav > Customers (sub-item or replaces)
**Discovery:** Top nav click + command palette search
**Adjacent Features:** Company detail, engagement list
**Feature Flags:** `customer-health-dashboard`
**Rationale:** [2-3 sentences]

5. Design Token Compliance

Colors — Theme V2 Semantic Tokens

Always use semantic tokens. Never use raw Tailwind color names for semantic purposes.

Purpose Use NOT
Success/positive text-success-foreground, bg-success-50 text-emerald-500, bg-emerald-50
Error/destructive text-destruction-foreground, bg-destruction-50 text-red-500, bg-rose-50
Warning text-warning-foreground, bg-warning-50 text-amber-500, bg-amber-50
Primary actions bg-primary, text-primary-foreground bg-blue-500
Muted text text-muted-foreground text-gray-500, text-slate-500
Borders border-border border-gray-200
Card surfaces bg-card bg-white
Page background bg-background bg-gray-50, bg-slate-50

When the .theme-v2 CSS class is needed: Add it to the root wrapper. Check apps/web/src/index.css for the latest token definitions.

When the audit source says emerald/amber/rose: The storybook-components-audit was written before V2 tokens. Map these to semantic tokens.

Spacing — 4px Grid

Token Value Tailwind Usage
xs 4px p-1, gap-1 Icon padding, tight gaps
sm 8px p-2, gap-2 Inline gaps
md 12px p-3, gap-3 Component internal padding
lg 16px p-4, gap-4 Card padding, section gaps
xl 24px p-6, gap-6 Page sections
2xl 32px p-8, gap-8 Page margins

Card pattern: p-6 outer, CardContent p-6 pt-0, CardHeader pb-2

No arbitrary values. p-[13px] is always wrong. Use the grid.

Typography

Level Classes Usage
Page title text-2xl font-semibold tracking-tight One per page
Section header text-lg font-semibold Section dividers
Card title text-sm font-medium Card headers
Body text-sm Primary content
Secondary text-xs text-muted-foreground Timestamps, metadata
Label text-sm font-medium Form labels

Icons

Lucide React only. Never inline SVGs.

import { Search, MessageSquare, Upload, Settings, ChevronRight } from 'lucide-react';

// Inline with text: h-4 w-4
<Search className="h-4 w-4" />

// Standalone / buttons: h-5 w-5
<Settings className="h-5 w-5" />

6. Flow Requirements

Full Mode — Required Flows

Flow What It Shows Starts From Key Question Answered
Discovery How users learn this exists Dashboard, notification, nav "How would I even know about this?"
Onboarding First-time setup/activation Feature entry point "What do I do the first time?"
HappyPath Core usage scenario Feature main view "How does it work when things go right?"
ErrorRecovery Failure handling Mid-flow error "What happens when things go wrong?"
DayTwo Returning user value App home → feature "Why would I come back to this?"

Lofi Mode — Minimum Required

Flow What It Shows
HappyPath Core usage scenario

Flow Implementation

Each flow is a state machine that walks the user through a multi-step journey:

function DiscoveryFlow() {
  const { state, advance } = useFlowState('browsing');
  
  switch (state) {
    case 'browsing':
      return <AppDashboard onNoticeFeature={() => advance('noticed')} />;
    case 'noticed':
      return <FeatureTeaser onExplore={() => advance('exploring')} />;
    case 'exploring':
      return <FeatureLanding onActivate={() => advance('activated')} />;
    case 'activated':
      return <ActivationSuccess />;
  }
}

7. Quality Checklist

Run this before considering a prototype "done":

Structure

  • Follows canonical directory layout (components/ views/ flows/ demo/)
  • Storybook titles follow convention
  • index.ts re-exports latest version
  • mock-data.ts uses realistic AskElephant data (no lorem ipsum)

Component Reuse

  • No prototype-specific ui/ directory
  • All base components from @/components/primitives/ or @/components/ui/
  • Icons from Lucide React (no inline SVGs)
  • Report lists reused vs. created components

App Shell

  • All views/ stories wrap in AppShell decorator
  • All demo/ stories wrap in AppShell decorator
  • Correct nav item highlighted
  • Global chat accessible (not in-page chat)

Design Tokens

  • Semantic color tokens only (no raw Tailwind colors for semantic use)
  • Spacing on 4px grid (no arbitrary values)
  • Typography matches production scale
  • .theme-v2 applied where needed

Interactivity

  • Every button triggers a state change or action
  • Forms validate and submit to mock handlers
  • Navigation within prototype works
  • Loading states resolve after realistic delay
  • Error states show recovery actions

Flows

  • Discovery flow: how users find the feature
  • Onboarding flow: first-time experience
  • HappyPath flow: core usage
  • ErrorRecovery flow: failure handling
  • DayTwo flow: returning user value
  • (Lofi: HappyPath only is acceptable)

AI States (for AI features)

  • Loading (short)
  • Loading (long — 3+ seconds)
  • Success
  • Error
  • Low Confidence
  • Empty

Demo

  • Fully functional click-through
  • Every interaction works
  • Walkthrough with step-by-step narration
  • Suitable for sharing with stakeholders on Chromatic

8. Anti-Patterns — What Makes Prototypes Look Wrong

Anti-Pattern Why It's Wrong Do This Instead
Prototype-specific ui/ components Diverges from production look Import from @/components/primitives/
Standalone page without app shell Doesn't show real app context Use AppShell decorator
In-page chat interface App uses global chat drawer Show global chat opening via Cmd+K
Sidebar navigation App switched to top-level nav Use TopNav via AppShell
Raw Tailwind colors (emerald-500) Breaks in theme switching Use semantic tokens (success-*)
Non-functional buttons Feels like a mockup, not a prototype Use onClick handlers with state changes
Lorem ipsum data Doesn't feel real Use realistic AskElephant data
Starting at the feature Skips discovery context Start at the user's natural entry point
Inline SVG icons Inconsistent with production Use Lucide React
bg-white / bg-gray-50 Breaks dark mode Use bg-card / bg-background
Missing loading states Feels static, unrealistic Add simulated loading with delays
Single creative direction Not enough exploration Show 2+ options (full mode)
p-[13px] arbitrary spacing Off the design grid Use 4px grid values

9. Global Chat Pattern

AskElephant's global chat is a pull-out drawer, NOT an in-page component.

How It Works in Production

  1. User presses Cmd/Ctrl+K or clicks the Chat nav button
  2. Chat panel slides in from the right side
  3. Chat is contextual — it knows what page/entity the user is on
  4. User can keep chat open while navigating
  5. Chat thread persists across navigation

How to Prototype Chat Features

  • Show the global chat drawer opening (use Sheet component from right side)
  • Pre-populate with contextual suggestions based on the current page
  • Use the useMockChat() hook for simulated AI responses
  • Show ContextIndicator with the current entity
  • NEVER create a chat input embedded in the page content area

Exception: Specialized Chat Surfaces

Some features use chat as their primary interface (e.g., the Chats page itself). In these cases:

  • The chat IS the page content
  • It still lives within the app shell
  • It's accessed via the "Chats" top nav item
  • This is different from creating ad-hoc chat panels inside other features
Related skills
Installs
1
First Seen
Mar 30, 2026