Rules & Markdown

Source of truth for AI rules and markdown guidelines.

Cursor Rules

Loaded from the local airy-ui workspace.

AIRY_RULES

AIRY_RULES.md

Airy Design System - AI Agent Rules

These rules apply to projects using the Airy design system. This file is managed by the Airy registry and may be updated when you reinstall airy-rules.

Protected Files - DO NOT MODIFY

Never modify files in components/ui/ (or registry/ui/ in the Airy registry repo)

These are Airy/shadcn primitives installed from the registry. Modifications will be lost on updates.

If you need custom behavior:

  1. Create a wrapper component in components/blocks/ (or registry/blocks/ in the Airy registry repo)
  2. Add styling through className props or semantic tokens
  3. Use descendant selectors or data-slot attributes to override styles from the wrapper
  4. Document any customizations
// ❌ BAD: Modifying components/ui/button.tsx directly

// ✅ GOOD: Create components/custom-button.tsx
import { Button } from "@/components/ui/button"

export function CustomButton(props) {
  return <Button className="..." {...props} />
}

// ✅ GOOD: Override child component styles from a wrapper using data-slot selectors
<SidebarProvider className="[&_[data-slot=sidebar-gap]]:duration-300">

Sensitive Files - ASK BEFORE MODIFYING

Always ask for permission before modifying theme files in src/styles/

Theme files affect the entire application's visual design. Before making any changes:

  1. Explain what change you want to make and why
  2. Suggest consulting with Product Design before proceeding
  3. Wait for explicit approval from the user
  4. Only then proceed with the modification

This includes:

  • src/styles/airy.css - semantic color tokens
  • src/styles/primitives.css - base design tokens
  • src/styles/fonts.css - typography

Component Usage

  • Always use Airy components from @/components/ui/*
  • Do not recreate primitives (Button, Card, Dialog, etc.)
  • Prefer component variants and props over custom class overrides

Brand Assets

  • Always use the lev-logo component for Lev brand marks — never recreate or approximate the logo
  • Install: npx shadcn@latest add @airy/lev-logo -y -o
  • Import: import { LevLogo } from "@/components/lev-assets/lev-logo"
  • Variants: icon (mark only), logo (wordmark only), lockup (wordmark + icon)
  • Uses currentColor so it inherits text color automatically

Theming

  • Use semantic tokens: background, foreground, primary, muted, etc.
  • Never use raw hex/rgb values like #ff0000 or rgb(255,0,0)
  • Never use raw Tailwind colors like bg-orange-500 - use semantic tokens
  • Respect the dual theme structure:
    • App: :root and .dark
    • Marketing: .theme-marketing and .theme-marketing.dark

Forms

  • Use the provided Form components
  • Inputs must have labels and error messages
  • Use react-hook-form for controlled forms

Accessibility

  • Maintain keyboard navigation and focus states
  • Use appropriate aria-* attributes
  • Never remove focus outlines unless replaced with accessible alternatives

Component Classification

Airy has two types of components:

  • Primitives (components/ui/) — shadcn components installed from the registry. Protected, do not modify. These are low-level building blocks: Button, Card, Dialog, Sidebar, etc.
  • Blocks (components/blocks/) — Everything Airy ships on top of primitives. Any composed component — sidebars, nav groups, page shells, cards, charts, data tables — is a block. If it isn't a shadcn primitive, it's a block.

File Structure

components/
├── ui/          # ⛔ PROTECTED - Airy primitives, do not modify
├── blocks/      # ✅ Blocks — all composed components go here
└── ...          # ✅ Your app-specific components

src/styles/
├── airy.css       # ⚠️ SENSITIVE - ask before modifying
├── primitives.css # ⚠️ SENSITIVE - ask before modifying
└── fonts.css      # ⚠️ SENSITIVE - ask before modifying

In the Airy registry repo, the equivalent paths are:

registry/
├── ui/       # ⛔ PROTECTED - do not modify
├── blocks/   # ✅ Blocks — all composed components go here
└── theme/    # ⚠️ SENSITIVE - ask before modifying

Guidelines Markdown

Airy-ui markdown guidelines rendered from source.

Overview

index.md

Airy Design System

Airy is Levco's design system built on shadcn/ui. It provides a consistent UI foundation across product apps and marketing surfaces, plus AI guidance for creating new assets.

Quick Start

Install from the registry:

npx shadcn@latest registry add @airy=https://airy.lev.com/r/{name}.json
npx shadcn@latest add @airy/airy-theme @airy/airy-rules
npx shadcn@latest add @airy/button @airy/card

Import components and styles:

import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { ThemeProvider } from "@/components/ui/theme-provider";
@import "./styles/primitives.css";
@import "./styles/airy.css";

Theme Provider

Wrap your app with the theme provider:

import { ThemeProvider } from "@/components/ui/theme-provider";

export function AppShell({ children }) {
  return (
    <ThemeProvider attribute="class" defaultTheme="light" enableSystem>
      {children}
    </ThemeProvider>
  );
}

Design Themes

Airy supports two design themes, each with light and dark modes:

  • App theme: :root and .dark
  • Marketing theme: .theme-marketing and .theme-marketing.dark

Use the ThemeSwitcher component or useDesignTheme hook to toggle between App and Marketing.

Rules of Use

  • Always prefer Airy components over custom primitives.
  • Use semantic colors (background, foreground, primary, etc).
  • Use the theme tokens defined in src/styles/airy.css.

Code Patterns

code-patterns.md

Code Patterns

This guide documents how to use Airy components consistently.

Component Usage

  • Use composition over custom styling.
  • Prefer variants and size props over adding new classes.
  • Only add custom classes for layout or spacing.

Example button usage:

import { Button } from "@/components/ui/button";

<Button variant="default" size="lg">Continue</Button>

For icon usage, sizing, and reserved icon mappings, see the Iconography section in the visual-design guideline.

Forms (react-hook-form)

  • Use Form, FormField, FormItem, FormLabel, and FormMessage.
  • Validate with a schema library (zod is recommended).
  • Keep labels and descriptions accessible.

Example structure:

<Form {...form}>
  <form onSubmit={form.handleSubmit(onSubmit)}>
    <FormField
      control={form.control}
      name="email"
      render={({ field }) => (
        <FormItem>
          <FormLabel>Email</FormLabel>
          <FormControl>
            <Input placeholder="name@company.com" {...field} />
          </FormControl>
          <FormMessage />
        </FormItem>
      )}
    />
  </form>
</Form>

Accessibility

  • Every input must have a label.
  • All interactive elements must be keyboard accessible.
  • Preserve focus rings and aria-* attributes.
  • Use sr-only for visual hiding, not display: none.

Naming Conventions

  • Component names: PascalCase
  • Props: camelCase
  • Variants: kebab-case or semantic words (default, secondary, ghost)

Feedback and Errors

  • Use sonner for toasts when a top-level action succeeds or fails.
  • Inline errors should use FormMessage.

Copy

copy.md

Copy Guidelines

These guidelines ensure consistent brand voice and messaging across all platforms. Adhering to them strengthens brand recognition and builds trust with our audience.

Capitalization

  • Utilize sentence case for all text, buttons, field names, and descriptions.
  • Use Title Case for all proper nouns (e.g. product names, client names, feature names)
  • Use all caps sparingly – only for emphasis or established acronyms

CTA Words

Use these standard action words consistently across the product:

  • New: Creates a new item from scratch (e.g. New deal, New slide, New message)
  • Add: Includes an existing item in a given context (e.g. "Add a placement to a deal")
  • Save: Commits unsaved changes
    • Use Update when the distinction between saving and updating matters
  • Delete: Permanently removes something
    • Remove: Removes item from the collection but does not destroy it
  • View: To look at something (e.g. View contacts)
    • Open: "View", specifically for documents, modals, and files
  • Cancel: Exits without saving changes
  • Dismiss: Closes a notification or message without taking action

Commas

Always use Oxford commas (serial commas) in lists of three or more items.

✓ "deals, placements, and messages"

✗ "deals, placements and messages"

Punctuation Standards

  • No periods in headlines, buttons, or labels unless they contain multiple sentences or they are used for effect
  • Use em dashes (—) for breaks in thought, not hyphens or double dashes
  • Use double quotes ("") for primary quotations and quoted speech
  • Use single quotes ('') for quotes within quotes
  • Semicolons (;) only when joining related independent clauses; prefer periods or separate sentences

Numbers and Metrics

General Number Formatting

  • Spell out one (1) through nine (9) in body text
  • Use numerals for 10 and above
  • Exception: Always use numerals with units (5 days, 3 deals)
  • Large numbers: Use commas for thousands (10,000+)

Currency

  • Format: $1,234,567 (with commas for thousands)
  • Decimals: Show cents only when necessary ($50 not $50.00)
  • Large numbers: Use K, M, B notation when space is limited
    • $1.2M (not $1,200,000)
    • $850K (not $850,000)

Percentages

  • Format: 15.5% (no space between number and %)
  • Decimals: One decimal place for precision, whole numbers when possible
  • Ranges: 10%–15% (use en dash, no spaces)

Units of Measure

Area

  • Square feet: 1200 sq ft
  • Square miles: 5.2 sq mi
  • Acres: 2.5 acres (spelled out)

Distance

  • Miles: 15 miles, 2.3 mi (spell out in body text, abbreviate in tight spaces)
  • Feet: 500 feet, 500 ft
  • Kilometers: 10 kilometers, 10 km (when relevant)

Weight

  • Pounds: 150 pounds, 150 lbs
  • Tons: 2.5 tons (spell out)

Volume

  • Gallons: 500 gallons, 500 gal
  • Cubic feet: 1,000 cu ft

Date and Time

Date Formats

  • Default format: Aug 27, 2025 (abbreviated month, no leading zeros)
  • Short format: 8/27/25 (when space is very limited)
  • ISO format: 2025-08-27 (for technical contexts only)
  • Ranges: Aug 27–30, 2025 (en dash, no spaces)

Time Formats

  • 12-hour format: 2:30 PM (no leading zeros, space before AM/PM)
  • Time ranges: 2:30–4:00 PM (en dash, repeat AM/PM only when crossing)
  • Duration: 1h 30m (no spaces around units)

Relative Time

  • Recent: "2 minutes ago", "1 hour ago", "yesterday"
  • Future: "in 5 minutes", "tomorrow", "next week"
  • Always spell out time units in relative formats

Days of the Week

  • Full names: Monday, Tuesday, Wednesday (in body text and formal contexts)
  • Abbreviations: Mon, Tue, Wed, Thu, Fri, Sat, Sun (in calendars, tables, tight spaces)
  • Ranges: Monday–Friday (en dash, no spaces), Mon–Fri (abbreviated)
  • Today/Tomorrow: Use "today" and "tomorrow" instead of day names when referring to current/next day
  • Capitalization: Always capitalize day names and abbreviations

Visual Design

visual-design.md

Visual Design Rules

This guide documents the visual system behind Airy.

Theme Architecture

Airy supports two themes with light and dark variants:

  • App theme: :root and .dark
  • Marketing theme: .theme-marketing and .theme-marketing.dark

All tokens currently use identical defaults so you can customize later without changing component code.

Color System

Use semantic tokens, not raw hex values:

  • --background, --foreground
  • --primary, --secondary, --accent
  • --muted, --destructive, --border
  • --card, --popover, --ring

Charts and sidebar tokens exist for dashboards and admin surfaces.

Typography

Use the tokenized scale in styles.css:

  • --text-xs through --text-3xl
  • --line-height-tight, --line-height-normal, --line-height-relaxed
  • --font-weight-regular, --font-weight-medium, --font-weight-semibold, --font-weight-bold

Spacing

Use the spacing tokens:

  • --space-0 through --space-24

Prefer layout utilities for spacing. Use tokens when defining new CSS rules.

Radius

Use --radius and derived tokens (--radius-md, --radius-lg, etc).

Brand

  • Use the lev-logo registry component for all logo placements
  • Three variants: icon, logo (wordmark), lockup (wordmark + icon)
  • The logo uses currentColor — set text color on the parent to control it
  • Never recreate the logo as raw SVG or an image tag

Iconography

Airy uses the Lucide icon set. Browse the full library at lucide.dev.

Sizing and alignment

  • Icons are drawn on a 24x24 grid but can be scaled up or down as needed
  • Icon size should be roughly 2px larger than the accompanying text size
  • Maintain 16-24px clear padding from surrounding UI elements
  • Align icons optically to the text's x-height for visual balance
  • Single-line text: center-align the icon vertically
  • Multiline text: align the icon to the top edge of the text
  • Never use emojis as icon substitutes

If you need an icon not in the Lucide standard set, contact Product Design before introducing a new one.

Code implementation

In React, import from lucide-react:

import { Mail, Search, Settings } from "lucide-react"

Size pairings (icon should be ~2px larger than the text):

  • text-xs with size-3.5
  • text-sm with size-4
  • text-base with size-5
  • text-lg or text-xl with size-6

Use text-muted-foreground for secondary/decorative icons and text-foreground for primary action icons.

Example:

<Button><Mail className="size-4" /> Send email</Button>

When lucide-react cannot be imported (static HTML, emails, sandboxed environments): use inline SVGs from lucide.dev. Never use emojis or image tags as substitutes.

Reserved icons

These icons are reserved to ensure consistency across Lev products. They represent core actions and concepts that should not be replaced, restyled, or repurposed. Always reference the reserved set first and only introduce new icons when a concept is not already represented.

Status and feedback:

  • Info — info
  • CircleAlert — warning
  • TriangleAlert — error
  • CircleCheck — success

Universal system actions:

  • CircleHelp — help
  • Search — search
  • Share2 — share
  • Settings — settings
  • MoreHorizontal — more
  • RefreshCw — refresh

File manipulations:

  • Save — save
  • Trash2 — delete
  • Upload — upload
  • Download — download
  • Copy — copy / duplicate

Editing:

  • Pencil — edit
  • Link — link
  • Undo2 — undo
  • Redo2 — redo

Dark Mode

  • Maintain contrast ratios for all text and controls.
  • Avoid hard-coded colors in components.
  • Verify hover, focus, and disabled states in both themes.

Marketing Assets

Marketing materials — brochures, one-pagers, landing pages, pitch decks — use the marketing dark theme (.theme-marketing.dark). All colors must come from the semantic tokens defined in that theme context, not from primitives or hardcoded values.

The marketing dark theme provides a dark background with green accent palette. Use the same semantic token names as the app theme (--background, --foreground, --card, --primary, --border, etc.) — they resolve to the correct marketing values automatically.

When generating output that cannot reference CSS variables (PDFs, static HTML, sandboxed artifacts), resolve the marketing dark theme tokens from airy.css under the .theme-marketing.dark selector and use those values directly. Never extract colors from Figma mockups or approximate values.