Rules & Markdown
Source of truth for AI rules and markdown guidelines.
Cursor Rules
Loaded from the local airy-ui workspace.
AIRY_RULES
AIRY_RULES.mdAiry 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:
- Create a wrapper component in
components/blocks/(orregistry/blocks/in the Airy registry repo) - Add styling through className props or semantic tokens
- Use descendant selectors or data-slot attributes to override styles from the wrapper
- 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:
- Explain what change you want to make and why
- Suggest consulting with Product Design before proceeding
- Wait for explicit approval from the user
- Only then proceed with the modification
This includes:
src/styles/airy.css- semantic color tokenssrc/styles/primitives.css- base design tokenssrc/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-logocomponent 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
currentColorso it inherits text color automatically
Theming
- Use semantic tokens:
background,foreground,primary,muted, etc. - Never use raw hex/rgb values like
#ff0000orrgb(255,0,0) - Never use raw Tailwind colors like
bg-orange-500- use semantic tokens - Respect the dual theme structure:
- App:
:rootand.dark - Marketing:
.theme-marketingand.theme-marketing.dark
- App:
Forms
- Use the provided Form components
- Inputs must have labels and error messages
- Use
react-hook-formfor 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.mdAiry 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:
:rootand.dark - Marketing theme:
.theme-marketingand.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.mdCode 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, andFormMessage. - 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-onlyfor visual hiding, notdisplay: none.
Naming Conventions
- Component names:
PascalCase - Props:
camelCase - Variants:
kebab-caseor semantic words (default,secondary,ghost)
Feedback and Errors
- Use
sonnerfor toasts when a top-level action succeeds or fails. - Inline errors should use
FormMessage.
Copy
copy.mdCopy 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.mdVisual Design Rules
This guide documents the visual system behind Airy.
Theme Architecture
Airy supports two themes with light and dark variants:
- App theme:
:rootand.dark - Marketing theme:
.theme-marketingand.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-xsthrough--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-0through--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-logoregistry 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-xswithsize-3.5text-smwithsize-4text-basewithsize-5text-lgortext-xlwithsize-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— infoCircleAlert— warningTriangleAlert— errorCircleCheck— success
Universal system actions:
CircleHelp— helpSearch— searchShare2— shareSettings— settingsMoreHorizontal— moreRefreshCw— refresh
File manipulations:
Save— saveTrash2— deleteUpload— uploadDownload— downloadCopy— copy / duplicate
Editing:
Pencil— editLink— linkUndo2— undoRedo2— redo
Dark Mode
- Maintain contrast ratios for all text and controls.
- Avoid hard-coded colors in components.
- Verify
hover,focus, anddisabledstates 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.