Casper Studios internal design system for generating consistent, production-grade SaaS UI. Use this skill whenever generating UI code for internal tools, client apps, dashboards, POCs, prototypes, or any visual interface — even quick mockups or artifacts. Apply it any time the output is a React component, page, or layout. If the user mentions "our design system", "Casper style", "match our look", or asks you to build any kind of app or interface, use this skill. Also trigger when restyling or theming existing UI to match Casper's visual language. This skill takes priority over generic frontend-design guidance.
Instalación
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Casper Studios internal design system for generating consistent, production-grade SaaS UI. Use this skill whenever generating UI code for internal tools, client apps, dashboards, POCs, prototypes, or any visual interface — even quick mockups or artifacts. Apply it any time the output is a React component, page, or layout. If the user mentions "our design system", "Casper style", "match our look", or asks you to build any kind of app or interface, use this skill. Also trigger when restyling or theming existing UI to match Casper's visual language. This skill takes priority over generic frontend-design guidance.
Casper Studios Design System
A clean, elevated SaaS design system built on shadcn/ui, Tailwind CSS v4, and React (Vite). Every interface generated for Casper Studios — whether a client demo, internal tool, or quick prototype — must follow these rules to maintain a consistent, professional visual identity across the team.
Before generating any UI code, read this file completely and the reference files listed below. You MUST read the reference files — they contain rules and code examples that are required for correct output. Skipping them will produce incorrect, off-brand UI.
Required for EVERY project:
references/components.md — ALWAYS read. Reusable pieces: stat cards, list items, filter bars, kanban boards, profile cards, product cards, activity feeds, toast notifications, form validation states. Required whenever building UI elements inside a layout.
references/theme.css — ALWAYS read. Tailwind CSS v4 theme tokens. Copy this file into your project as-is.
assets/ — Contains Casper Studios logo SVGs in 4 variants (default, variant, mono-black, mono-white). Use the correct variant based on background color — see the Logo section below.
Required based on platform:
references/web-layouts.md — MUST read when the project is a web application. Web-specific responsive rules + code examples: app shell, sidebar nav, dashboard grid, data table page, page header.
references/mobile.md — MUST read when the project is a mobile application. Mobile-specific rules + code examples: device frame, top bar, bottom tab navigation, form patterns, pinned-button layout, list views, card stacks, full screen compositions, contextual actions (menus + bottom sheets).
Non-negotiable: Do not generate UI without reading the platform reference file first. If you are unsure whether the project is web or mobile, ask the user before proceeding.
Before You Generate: Required Context
Before producing any UI code, confirm the following with the user. If their prompt already answers these clearly, proceed without asking. If not, ask before generating anything.
Platform — Is this a web application or a mobile application? (Determines which reference file to follow.)
Dark mode — Should the interface support dark mode, or is it light mode only? (Determines whether to implement .dark class overrides, use bg-neutral-0 for surfaces, and include the mono-white logo variant.)
Do NOT assume defaults for these. If the user says "build me a dashboard," you don't know if it's web or mobile, or if it needs dark mode. Ask.
Summary
The Casper aesthetic is clean authority — a professional SaaS style that feels premium without trying too hard. It uses generous whitespace, a restrained purple accent, and soft rounded surfaces to create interfaces that feel trustworthy and modern. Think Linear meets Notion: structured, breathable, quietly confident.
Core Principles
Whitespace is a feature. Generous padding, breathing room between sections. Never cram.
One accent, used sparingly. Brand purple (#5900FF) appears on active states, primary buttons, and key CTAs — nowhere else. If everything is purple, nothing is.
Rounded but not bubbly. 10px default radius for cards (shadcn default). Buttons and inputs use 8px. Feels modern without feeling like a toy.
Flat with depth hints. No heavy shadows. Use shadow-sm for cards, shadow-md for popovers. Never use shadow-lg on in-page elements.
Content over chrome. The UI should disappear. Users notice the data, not the design.
Tech Stack
React (Vite) with TypeScript
Tailwind CSS v4 — Use the theme file at references/theme.css as Casper brand overrides
shadcn/ui — Initialize a standard shadcn/ui project first (shadcn init), then layer Casper brand tokens from references/theme.css on top. The shadcn semantic layer (bg-background, text-foreground, bg-primary, border-border, etc.) is the base — Casper's theme.css adds brand colors, typography, shadows, and spacing on top of it, not as a replacement. Use shadcn components directly. Do NOT create custom base components that duplicate shadcn functionality
Lucide React — Icon library. Always use Lucide, never Heroicons or FontAwesome
Fonts — DM Sans with sans-serif as fallback for all UI text. Load via Google Fonts or bundle
Color System
The palette is intentionally restrained. Most of the UI is neutral gray + white, with purple as a sharp accent.
Usage Rules
Role
Token
Hex
When to use
Brand accent
brand-500
#5900FF
Active nav items, primary buttons, links, focus rings
Brand subtle
brand-50
#EEE5FF
Active nav background, selected row highlight, hover tints
Brand light
brand-100
#DECCFF
Icon circle backgrounds, soft tag fills
Default text
neutral-950
#0A0A0A
Page titles, headings
Body text
neutral-900
#171717
Primary body text
Subtext
neutral-500
#737373
Metadata, timestamps, secondary labels
Borders
neutral-200
#E5E5E5
Card borders, dividers, table lines
Surface
neutral-50
#FAFAFA
Page background behind cards
Card surface
neutral-0
#FFFFFF
Card backgrounds, panels (use bg-neutral-0 for dark mode compatibility — see Dark Mode section)
Semantic Colors
Use these ONLY for status indicators, badges, and contextual feedback — never as decorative accents.
Success — success-500 (#22C55E) for badges/icons, success-50 for pill backgrounds
Error — error-500 (#EF4444) for badges/icons, error-50 for pill backgrounds
Warning — warning-500 (#F59E0B) for badges/icons, warning-50 for pill backgrounds
What NOT to do
Do NOT use brand purple for backgrounds on large surfaces
Do NOT use semantic colors decoratively
Do NOT introduce new colors. If you need a new shade, use the neutral scale
Do NOT use opacity-based colors when a token exists (e.g., don't do text-black/50, use neutral-500)
Typography
All text is set in DM Sans with sans-serif as fallback (font-family: 'DM Sans', sans-serif). Monospace (font-mono) is acceptable for code blocks, data labels, and IDs only.
Scale
Style
Size
Weight
Line Height
Use
Heading 1
30px
500
36px
Page titles only. One per view.
Heading 2
20px
500
24px
Section titles within a page
Heading 3
16px
500
20px
Card titles, subsection labels
Body
14px
400
20px
Default paragraph and UI text
Body Bold
14px
500
20px
Emphasis within body text, table headers
Caption
12px
400
16px
Timestamps, helper text, metadata
Caption Bold
12px
500
16px
Badge labels, small category tags
Rules
Headings are always medium weight (500), never bold (700)
NEVER use all-caps except for tiny metadata labels (e.g., "STATUS", "OWNER" in table column headers) set at caption size
Links use brand-500 color with no underline by default, underline on hover
Do NOT vary font size beyond this scale. If something feels wrong, adjust spacing not font size
Spacing & Layout
Spacing Scale
Use Tailwind's default spacing scale. Key values:
4px (p-1) — icon padding, tight gaps
8px (p-2) — badge padding, small gaps
12px (p-3) — input padding, card internal gaps
16px (p-4) — card padding, section gaps
24px (p-6) — between cards, content sections
32px (p-8) — major section separation
48px (p-12) — page-level padding on large screens
Layout Rules
Page background: neutral-50 (#FAFAFA)
Content is always organized inside Cards (white background, border, rounded)
Maximum content width: 1280px centered
On pages with a sidebar, sidebar is 240px fixed width
Main content area uses remaining space with 24px padding
Shadows & Elevation
The design is predominantly flat. Shadows are used to indicate layers, not to add decoration.
Token
Use
shadow-sm
Cards, inputs at rest
shadow-md
Dropdown menus, popovers, tooltips
shadow-lg
Modals, command palettes, overlays ONLY
shadow-overlay
Semantic alias for shadow-lg — identical value. Use on modals/sheets so the intent reads clearly in code
NEVER apply shadow-lg (or its alias shadow-overlay) to cards or in-page elements. These are reserved for floating layers only.
Border Radius
The theme file (references/theme.css) uses the shadcn/ui radius system — a single --radius base variable in :root that controls the entire scale via calc(). This is mapped into Tailwind classes via @theme inline. No Tailwind v4 defaults are overridden.
The base value --radius: 0.625rem (10px) is the shadcn default. To make the entire UI sharper or rounder, change this single value — all tokens recalculate automatically.
Cards always use rounded-lg (10px). Buttons and inputs always use rounded-md (8px). Nested elements inside cards should use rounded-sm (6px) for non-interactive elements to maintain visual hierarchy — the inner radius should always be smaller than the outer.
Iconography
Use Lucide React exclusively. Import as: import { IconName } from "lucide-react"
Default icon size: 16px for inline, 20px for standalone
Icon color follows its text context (e.g., neutral-500 for subtext, brand-500 for active)
For icons inside circular backgrounds (common in lists and dashboards):
Circle: 40px diameter, brand-50 or brand-100 background, rounded-full
Icon: 20px, brand-500 color
For semantic contexts, swap to the matching semantic color pair (e.g., error-50 bg + error-500 icon)
Casper Studios Logo
The Casper Studios logo has four variants stored in assets/. Use the correct variant based on the background it sits on:
Variant
File
When to use
Default (full color)
assets/logo-on-white-default.svg
Light/white backgrounds. Gradient icon + purple "CASPER" + dark "STUDIOS". This is the primary logo — use it whenever possible.
Variant (full color)
assets/logo-on-white-variant.svg
Light/white backgrounds when you want all-black text instead of purple + dark gray. Same gradient icon.
Mono Black
assets/logo-mono-black.svg
Light backgrounds where color is unavailable (e.g., print, grayscale contexts). Grayscale icon + near-black text.
Mono White
assets/logo-mono-white.svg
Dark backgrounds only. Gray icon + white text. Use this whenever the logo sits on a dark surface (dark nav bars, dark hero sections, overlays, dark mode).
Rules
Light mode (default): Use logo-on-white-default.svg or logo-on-white-variant.svg
Dark mode or dark surfaces: Use logo-mono-white.svg — never place the default or black logo on a dark background
The logo should appear in the sidebar header (web) or top bar (mobile) at the sizes defined in those patterns
Do NOT resize the logo disproportionately — maintain the original aspect ratio
Do NOT place the logo on busy backgrounds or low-contrast surfaces. If contrast is insufficient, use the mono variant that provides the best visibility
Minimum clear space around the logo: 8px on all sides
shadcn/ui Component Theming
Use shadcn/ui components as your base layer. Theme them using the CSS variables in references/theme.css. Here is how specific components should be configured:
Button
Primary: brand-500 bg, text-white (literal white, not a token), rounded-md. Hover: brand-600.
Default height: 48px (h-12). Use this on standalone pages, forms, modals, and any top-level content area.
Compact height: 36px (h-9). Use when the button lives inside a smaller container — cards, panels, table rows, sidebar nav, filter bars, inline actions. The tighter context calls for a tighter control.
Badge
rounded-full (pill shape). Height 22px. Caption-bold text (12px, 500 weight).
Row height: 48-56px. Rows separated by 1pxneutral-200 bottom border.
Row hover: neutral-50 background.
No alternating row colors.
Input / Textarea
rounded-md (8px). 1pxneutral-200 border. neutral-50 bg or white bg.
Focus: 2pxbrand-500 ring (use Tailwind ring-2 ring-brand-500).
Labels MUST be visible and external — render a <label> element above every input, never inside it. Labels use 14px/400 in neutral-900. The gap between label and input is 6px (space-y-1.5).
Placeholder text MUST be de-emphasized — neutral-400 color, normal weight (400), short hint text (e.g., "e.g. john@email.com"). Placeholders are supplementary hints, not labels.
Select inputs follow the same pattern: visible label above, de-emphasized placeholder inside.
Spacing between fields: 16px (space-y-4 or gap-4).
Default height: 48px (h-12). Use for inputs on standalone pages, forms, modals, and any top-level content area.
Compact height: 36px (h-9). Use when the input lives inside a smaller container — cards, panels, table rows, filter bars, inline search fields. Same logic as compact buttons.
Sidebar (App Shell)
See references/web-layouts.md for the full sidebar code pattern. Key specs:
Width: 240px. White background. Right border: 1pxneutral-200.
Nav items: 36px height (compact — inside sidebar panel), rounded-sm (6px), 12px left padding.
references/components.md — Stat Card, List Item Row, Filter Bar, Kanban Board, Profile/Discovery Card, Product Card, Activity Feed Item, Toast Notifications, Form Validation States
references/mobile.md — Mobile rules, Device Frame Shell, Mobile Top Bar, Bottom Tab Navigation, Mobile Form Layout, Pinned Bottom Button, Mobile List View, Mobile Card Stack, Full Screen Composition, Contextual Actions
Web vs Mobile Context
Every project is either a web application or a mobile application — the layout approach is fundamentally different. You MUST have already read the appropriate platform reference file (as instructed at the top of this document) before reaching this point. If you haven't, stop and read it now:
Web application → references/web-layouts.md (responsive breakpoints, sidebar behavior, layout patterns)
Do NOT treat a mobile app as a responsive web page. Mobile apps render inside a device frame and follow entirely different navigation, spacing, and interaction patterns.
Image Placeholders
When no real image is available, use soft gradient mesh backgrounds — NOT gray boxes. These should feel like abstract art, not loading states.
Gradient recipes (CSS linear-gradient or radial-gradient combos):
Apply rounded-lg to image containers. These are placeholders — they should look intentional and beautiful.
Transitions & Animations
Every state change should feel smooth and intentional — no hard cuts. This applies across both web and mobile:
Interactive elements (buttons, inputs, cards): Use transition-colors or transition-all with Tailwind's default duration (~150ms). State changes like hover, focus, and active should never feel instantaneous.
Page transitions: When navigating between views, apply a subtle slide or fade. A 150–300ms ease-out transition keeps things feeling responsive without sluggish.
Modals, Dialogs, Sheets: Always animate in and out. Sheets slide from their edge (left, right, bottom), dialogs/modals fade + scale up slightly from ~95% to 100%. The overlay backdrop should fade in (opacity 0→50%), not appear instantly.
Lists and content loading: When new items appear (e.g., after a fetch), a subtle fade-in or stagger is preferred over a hard pop-in.
Nothing on screen should ever just "appear" or "disappear" — every visual change gets a brief, smooth transition.
Empty, Error & Loading States
Every screen has at least three faces: populated, empty, and broken. AI-generated interfaces almost always show only the happy path with fake data. A polished interface acknowledges the other two.
Empty State
When a list, table, or content area has no data yet (first-time use, zero results, cleared filters):
Center a Lucide icon (48px, neutral-300) + a short heading (Heading 3) + one line of body text (neutral-500) vertically in the content area
Optionally include a primary action button below the text (e.g., "Create your first project")
Do NOT show an empty table with headers and no rows — that looks like a bug, not a feature
Do NOT use illustrations or complex graphics. Keep it text + icon. Minimal.
Error State
When something goes wrong (network failure, permission denied, server error):
Same centered layout as empty state, but use error-500 for the icon color
Icon: contextual — WifiOff for network errors, ShieldX for permission, AlertTriangle as a generic fallback
Heading: brief, human-readable ("Something went wrong", "Couldn't load projects")
Body: one sentence explaining what to do ("Check your connection and try again")
Include a "Retry" button (secondary variant) when the action is retryable
Loading State
When content is being fetched:
For initial page loads: Show a single centered spinner (Loader2 icon with animate-spin, 24px, neutral-400). No skeleton screens unless explicitly requested — they add complexity without clarifying the design
For inline updates (e.g., submitting a form, loading more items): Swap the trigger button's label to a spinner + "Loading…" and disable the button
For pull-to-refresh or lazy loading: A small spinner at the top or bottom of the list, neutral-400
The anti-pattern rule "No animated skeletons or shimmer effects in static mockups" still stands — but a simple animate-spin on a loader icon is fine for interactive interfaces.
Form Validation & Error Feedback
Inputs need to clearly communicate when something is wrong. This applies to both web and mobile. For code examples, see the Form Validation States section in references/components.md.
Behavioral Rules
Validate on blur (when the user leaves the field), not on every keystroke — keystroke validation feels aggressive
Show errors inline, directly below the relevant field. Never collect errors at the top of the form — users shouldn't have to hunt
When the user corrects the input and the field is valid, remove the error state immediately (on change, not on blur)
If the form is submitted with errors, scroll to the first invalid field and focus it
Success Confirmation (Post-Submit)
After a successful form submission, provide clear feedback. Don't just silently navigate away:
Option A: Toast notification confirming the action + navigate to the next logical screen
Option B: Inline success message replacing the form content (useful for single-purpose screens like "Reset password")
Toast Notifications
Transient feedback messages that confirm actions, surface errors, or provide information. Use shadcn's Sonner toast component. For code examples and the full variant table, see the Toast Notification section in references/components.md.
Positioning & Behavior
Web: Bottom-right corner, 16px from the edge
Mobile: Top-center, below the status bar / top bar area
Duration: 4000ms default, 6000ms for messages with an action link. Error toasts should persist until dismissed
Stacking: Max 3 visible at once. New toasts push older ones up (web) or down (mobile)
Animation: Slide in from the edge + fade. Slide out + fade on dismiss. Should feel like the Transitions & Animations section — smooth, never instant
Data Visualization Palette
When rendering charts (Recharts, Chart.js, etc.), use this ordered color sequence so data visualizations feel native to the brand. The palette starts with the brand purple and fans out through distinguishable hues:
Order
Name
Hex
Use
1
Brand
#5900FF
Primary data series, single-metric charts
2
Teal
#14B8A6
Secondary series
3
Amber
#F59E0B
Tertiary series
4
Rose
#F43F5E
Fourth series, or "negative" in comparisons
5
Sky
#0EA5E9
Fifth series
6
Lime
#84CC16
Sixth series
Rules
For single-metric charts (one bar, one line, one donut), always use Brand (#5900FF)
For two-series comparisons, use Brand + Teal
Apply colors in order — don't skip or shuffle. Consistency across charts makes dashboards feel cohesive
Use 10% opacity fills for area charts (e.g., #5900FF1A for brand area fill)
Tooltips: White bg, shadow-md, rounded-md, neutral-200 border — same treatment as popovers
Never use brand purple for "negative" or "declining" values — use Rose for that. Purple is always neutral-to-positive
Dark Mode
Dark mode is off by default. Only implement it when explicitly requested by the user or client. When dark mode is requested, follow these rules — do NOT improvise an inverted palette.
How It Works
The theme file (references/theme.css) includes a .dark class block that overrides CSS custom properties. Adding class="dark" to <html> or a wrapper element flips the entire color system without changing any component code. The neutral scale inverts so existing utilities (text-neutral-900, bg-neutral-50, border-neutral-200) automatically produce the correct dark-mode values.
Token Behavior in Dark Mode
You don't change token names in your code — the .dark override changes the values behind them. Here's what each token resolves to:
Token (unchanged in code)
Light Mode Value
Dark Mode Value
Notes
bg-neutral-50
#FAFAFA (light gray)
#171717 (near-black)
Page background
bg-neutral-0
#FFFFFF (white)
#0A0A0A (near-black)
Card surfaces
border-neutral-200
#E5E5E5 (light gray)
#404040 (dark gray)
Borders / dividers
text-neutral-950
#0A0A0A (near-black)
#FFFFFF (white)
Page titles
text-neutral-900
#171717 (near-black)
#FAFAFA (near-white)
Body text
text-neutral-500
#737373 (mid-gray)
#737373 (mid-gray)
Stays the same — mid-range
text-neutral-400
#A3A3A3 (light gray)
#A3A3A3 (stays same)
Subtext — readable on dark
bg-brand-500
#5900FF
#7A33FF (lighter)
Brighter for contrast on dark bg
bg-brand-50
#EEE5FF (light purple)
#120033 (very dark purple)
Tinted backgrounds invert
bg-white vs bg-neutral-0 — Critical Distinction
Tailwind's built-in white and black are NOT overridden in dark mode. They always resolve to literal #FFFFFF and #000000.
Use text-white when you mean actual white — e.g., button text on a brand-500 background. This stays white in both modes. ✅
Use bg-neutral-0 (not bg-white) for surfaces that should invert in dark mode — e.g., card backgrounds, sidebars, top bars. bg-neutral-0 maps to #FFFFFF in light and #0A0A0A in dark. ✅
Use bg-neutral-50 for page backgrounds. Maps to #FAFAFA in light, #171717 in dark. ✅
If you use bg-white on a card, it will stay bright white in dark mode — blinding. Use bg-neutral-0 instead.
Shadows in Dark Mode
Shadows are nearly invisible on dark surfaces. The .dark block increases shadow opacity so elevation is still perceptible, but cards should primarily rely on their neutral-200 border (which maps to a subtle dark gray divider in dark mode) for definition.
Logo
Use assets/logo-mono-white.svg — the only variant approved for dark surfaces.
What NOT to Do in Dark Mode
Do NOT manually set dark colors in component code — rely on the .dark class override
Do NOT use bg-white for surfaces — use bg-neutral-0 so they invert properly
Do NOT use brand-500 for large tinted surfaces — use brand-50 (which maps to a dark purple in dark mode)
Do NOT change spacing, radius, or typography — the spatial system is mode-independent
Anti-Patterns (Do NOT)
No gradients on buttons. Flat solid colors only.
No colored page backgrounds. Background is always neutral-50 or neutral-0.
No heavy borders. Max 1px for structural borders. Never 2px+.
No rounded-full on cards. Cards are rounded-lg (10px), never circles.
No custom fonts. DM Sans / sans-serif only. Monospace for code.
Prefer icon + label navigation on desktop. Icon-only sidebars are acceptable if a tooltip with the label appears on hover or focus.
No dark mode unless explicitly requested. Default is always light.
No animated skeletons or shimmer effects in static mockups.
No drop shadows on text. Ever.
No border-radius mixing. Don't use the same radius token at different hierarchy levels — e.g., rounded-lg cards should contain rounded-sm children, not rounded-lg children. The inner radius should always be smaller than the outer.
No floating labels or placeholder-as-label. Labels must always be visible above inputs. Placeholders are hints, not labels — they vanish on focus and users lose context.
No emojis in the UI. Icons only. The only exception is user-generated content — if a user typed an emoji, display it. But never add emojis to labels, headings, buttons, nav items, placeholders, or any system-generated text.
Checklist Before Output
Before delivering any UI code, verify:
Uses DM Sans font family (with sans-serif fallback)
Brand purple only on interactive/active elements
Cards have bg-neutral-0 + neutral-200 border + rounded-lg + shadow-sm
No unauthorized colors, fonts, or shadows
All icons from Lucide React
shadcn components used where available (not custom recreations)
Spacing feels generous — nothing cramped
Page background is neutral-50, not white
Empty states are handled (not just the happy path with fake data)
Form inputs show error styling on validation failure (red border + message below)
Actions provide feedback via toast or inline confirmation
Charts (if present) use the data visualization palette in order
All form inputs have visible external labels (not inside the input)
Placeholder text is de-emphasized (neutral-400, normal weight)
Casper Studios logo uses the correct variant for the background (default on light, mono-white on dark)
If dark mode was requested: .dark class applied, logo uses mono-white variant, surfaces use bg-neutral-0 (not bg-white)
Border-radius: buttons/inputs use rounded-md (8px), cards use rounded-lg (10px), nav items/inner elements use rounded-sm (6px)
Button/input heights: 48px (h-12) by default, 36px (h-9) when inside cards, panels, tables, or other compact containers
Additional checks for Web Applications:
Sidebar follows the 240px / grouped nav / active state pattern