Files
fast-next-template/frontend/docs/design-system/08-ai-guidelines.md
Felipe Cardoso 30cbaf8ad5 Add documentation for component creation and design system structure
- **Component Creation Guide:** Document best practices for creating reusable, accessible components using CVA patterns. Includes guidance on when to compose vs create, decision trees, templates, prop design, testing checklists, and real-world examples.
- **Design System README:** Introduce an organized structure for the design system documentation with quick navigation, learning paths, and reference links to key topics. Includes paths for quick starts, layouts, components, forms, and AI setup.
2025-11-02 12:32:01 +01:00

13 KiB

AI Code Generation Guidelines

For AI Assistants: This document contains strict rules for generating code in the FastNext Template project. Follow these rules to ensure generated code matches the design system perfectly.


🎯 Core Rules

ALWAYS Do

  1. Import from @/components/ui/*

    import { Button } from '@/components/ui/button';
    import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
    
  2. Use semantic color tokens

    className="bg-primary text-primary-foreground"
    className="text-destructive"
    className="bg-muted text-muted-foreground"
    
  3. Use cn() utility for className merging

    import { cn } from '@/lib/utils';
    
    className={cn("base-classes", conditional && "conditional-classes", className)}
    
  4. Follow spacing scale (multiples of 4: 0, 1, 2, 3, 4, 6, 8, 12, 16)

    className="p-4 space-y-6 mb-8"
    
  5. Add accessibility attributes

    <Label htmlFor="email">Email</Label>
    <Input
      id="email"
      aria-invalid={!!errors.email}
      aria-describedby={errors.email ? 'email-error' : undefined}
    />
    
  6. Use component variants

    <Button variant="destructive">Delete</Button>
    <Alert variant="destructive">Error message</Alert>
    
  7. Compose from shadcn/ui primitives

    // Don't create custom card components
    // Use Card + CardHeader + CardTitle + CardContent
    
  8. Use mobile-first responsive design

    className="text-2xl sm:text-3xl lg:text-4xl"
    className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
    

NEVER Do

  1. NO arbitrary colors

    // ❌ WRONG
    className="bg-blue-500 text-white"
    
    // ✅ CORRECT
    className="bg-primary text-primary-foreground"
    
  2. NO arbitrary spacing values

    // ❌ WRONG
    className="p-[13px] mb-[17px]"
    
    // ✅ CORRECT
    className="p-4 mb-4"
    
  3. NO inline styles

    // ❌ WRONG
    style={{ margin: '10px', color: '#3b82f6' }}
    
    // ✅ CORRECT
    className="m-4 text-primary"
    
  4. NO custom CSS classes (use Tailwind utilities)

    // ❌ WRONG
    <div className="my-custom-class">
    
    // ✅ CORRECT
    <div className="flex items-center justify-between p-4">
    
  5. NO mixing component libraries

    // ❌ WRONG - Don't use Material-UI, Ant Design, etc.
    import { Button } from '@mui/material';
    
    // ✅ CORRECT - Only shadcn/ui
    import { Button } from '@/components/ui/button';
    
  6. NO skipping accessibility

    // ❌ WRONG
    <button><X /></button>
    
    // ✅ CORRECT
    <Button size="icon" aria-label="Close">
      <X className="h-4 w-4" />
    </Button>
    
  7. NO creating custom variants without CVA

    // ❌ WRONG
    <Button className={type === 'danger' ? 'bg-red-500' : 'bg-blue-500'}>
    
    // ✅ CORRECT
    <Button variant="destructive">Delete</Button>
    

📐 Layout Patterns

Page Container

<div className="container mx-auto px-4 py-8">
  <div className="max-w-4xl mx-auto space-y-6">
    {/* Content */}
  </div>
</div>

Dashboard Grid

<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
  {items.map(item => <Card key={item.id}>...</Card>)}
</div>

Form Layout

<Card className="max-w-md mx-auto">
  <CardHeader>
    <CardTitle>Form Title</CardTitle>
  </CardHeader>
  <CardContent>
    <form className="space-y-4">
      {/* Form fields */}
    </form>
  </CardContent>
</Card>

Centered Content

<div className="max-w-2xl mx-auto px-4">
  {/* Readable content width */}
</div>

🧩 Component Templates

Custom Component Template

import { cn } from '@/lib/utils';
import { Card } from '@/components/ui/card';

interface MyComponentProps {
  variant?: 'default' | 'compact';
  className?: string;
  children: React.ReactNode;
}

export function MyComponent({
  variant = 'default',
  className,
  children
}: MyComponentProps) {
  return (
    <Card className={cn(
      "p-4", // base styles
      variant === 'compact' && "p-2",
      className // allow overrides
    )}>
      {children}
    </Card>
  );
}

Component with CVA (class-variance-authority)

import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@/lib/utils';

const componentVariants = cva(
  "base-classes-here", // base
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground",
        destructive: "bg-destructive text-destructive-foreground",
      },
      size: {
        sm: "h-8 px-3 text-xs",
        default: "h-10 px-4 text-sm",
        lg: "h-12 px-6 text-base",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  }
);

interface ComponentProps
  extends React.HTMLAttributes<HTMLDivElement>,
    VariantProps<typeof componentVariants> {}

export function Component({ variant, size, className, ...props }: ComponentProps) {
  return (
    <div className={cn(componentVariants({ variant, size, className }))} {...props} />
  );
}

📝 Form Pattern Template

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Alert } from '@/components/ui/alert';

const formSchema = z.object({
  email: z.string().email('Invalid email address'),
  password: z.string().min(8, 'Password must be at least 8 characters'),
});

type FormData = z.infer<typeof formSchema>;

export function MyForm() {
  const form = useForm<FormData>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      email: '',
      password: '',
    },
  });

  const onSubmit = async (data: FormData) => {
    // Handle submission
  };

  return (
    <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
      {/* Email Field */}
      <div className="space-y-2">
        <Label htmlFor="email">Email</Label>
        <Input
          id="email"
          type="email"
          {...form.register('email')}
          aria-invalid={!!form.formState.errors.email}
          aria-describedby={form.formState.errors.email ? 'email-error' : undefined}
        />
        {form.formState.errors.email && (
          <p id="email-error" className="text-sm text-destructive">
            {form.formState.errors.email.message}
          </p>
        )}
      </div>

      {/* Submit Button */}
      <Button type="submit" disabled={form.formState.isSubmitting}>
        {form.formState.isSubmitting ? 'Submitting...' : 'Submit'}
      </Button>
    </form>
  );
}

🎨 Color Token Reference

Always use these semantic tokens:

Token Usage
bg-primary text-primary-foreground Primary buttons, CTAs
bg-secondary text-secondary-foreground Secondary actions
bg-destructive text-destructive-foreground Delete, errors
bg-muted text-muted-foreground Disabled states
bg-accent text-accent-foreground Hover states
bg-card text-card-foreground Card backgrounds
text-foreground Body text
text-muted-foreground Secondary text
border-border Borders
ring-ring Focus rings

📏 Spacing Reference

Use these spacing values (multiples of 4px):

Class Value Pixels Usage
2 0.5rem 8px Tight spacing
4 1rem 16px Standard spacing
6 1.5rem 24px Section spacing
8 2rem 32px Large gaps
12 3rem 48px Section dividers
16 4rem 64px Page sections

🔑 Decision Trees

When to use Grid vs Flex?

Need equal-width columns? → Use Grid
  className="grid grid-cols-3 gap-6"

Need flexible item sizes? → Use Flex
  className="flex gap-4"

Need 2D layout (rows + columns)? → Use Grid
  className="grid grid-cols-2 grid-rows-3 gap-4"

Need 1D layout (single row OR column)? → Use Flex
  className="flex flex-col gap-4"

When to use Margin vs Padding?

Spacing between sibling elements? → Use gap or space-y
  className="flex gap-4"
  className="space-y-4"

Internal element spacing? → Use padding
  className="p-4"

External element spacing? → Avoid margins, use parent gap
  // ❌ Child with margin
  <div className="mb-4">

  // ✅ Parent with gap
  <div className="space-y-4">

🚨 Common Mistakes to Avoid

Mistake 1: Hardcoding colors

// ❌ WRONG
<div className="bg-red-500 text-white">Error</div>

// ✅ CORRECT
<Alert variant="destructive">Error message</Alert>

Mistake 2: Arbitrary spacing

// ❌ WRONG
<div className="p-[15px] mb-[23px]">

// ✅ CORRECT
<div className="p-4 mb-6">

Mistake 3: Missing accessibility

// ❌ WRONG
<input type="email" />

// ✅ CORRECT
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" />

Mistake 4: Creating custom components unnecessarily

// ❌ WRONG - Custom component for simple composition
function MyCard({ title, children }) {
  return <div className="card">{children}</div>;
}

// ✅ CORRECT - Use shadcn/ui primitives
<Card>
  <CardHeader>
    <CardTitle>{title}</CardTitle>
  </CardHeader>
  <CardContent>{children}</CardContent>
</Card>

Mistake 5: Not using cn() utility

// ❌ WRONG
<div className={`base-class ${isActive ? 'active-class' : ''} ${className}`}>

// ✅ CORRECT
<div className={cn("base-class", isActive && "active-class", className)}>

📚 Reference Documentation

Before generating code, check these resources:

  1. Quick Start - Essential patterns
  2. Components - All shadcn/ui components
  3. Layouts - Layout patterns
  4. Spacing - Spacing rules
  5. Forms - Form patterns
  6. Reference - Quick lookup tables

Code Generation Checklist

Before outputting code, verify:

  • All imports from @/components/ui/*
  • Using semantic color tokens (no bg-blue-500)
  • Using spacing scale (multiples of 4)
  • Using cn() for className merging
  • Accessibility attributes included
  • Mobile-first responsive design
  • Composing from shadcn/ui primitives
  • Following established patterns from docs
  • No inline styles
  • No arbitrary values

🤖 AI Assistant Configuration

For Claude Code / Cursor

Add this to your project context:

When generating React/Next.js components:
1. Always import from @/components/ui/*
2. Use semantic tokens (bg-primary, text-destructive)
3. Use cn() utility for classNames
4. Follow spacing scale (4, 8, 12, 16, 24, 32)
5. Add accessibility (labels, ARIA)
6. Use component variants (variant="destructive")
7. Reference: /docs/design-system/08-ai-guidelines.md

For GitHub Copilot

Add to .github/copilot-instructions.md:

# Component Guidelines

- Import from @/components/ui/*
- Use semantic colors: bg-primary, text-destructive
- Spacing: multiples of 4 (p-4, mb-6, gap-8)
- Use cn() for className merging
- Add accessibility attributes
- See /docs/design-system/08-ai-guidelines.md

📊 Examples

Good Component (AI Generated)

import { cn } from '@/lib/utils';
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
import { Button } from '@/components/ui/button';

interface DashboardCardProps {
  title: string;
  value: string;
  trend?: 'up' | 'down';
  className?: string;
}

export function DashboardCard({ title, value, trend, className }: DashboardCardProps) {
  return (
    <Card className={cn("p-6", className)}>
      <CardHeader>
        <CardTitle className="text-sm font-medium text-muted-foreground">
          {title}
        </CardTitle>
      </CardHeader>
      <CardContent>
        <div className="text-2xl font-bold">{value}</div>
        {trend && (
          <p className={cn(
            "text-xs",
            trend === 'up' && "text-green-600",
            trend === 'down' && "text-destructive"
          )}>
            {trend === 'up' ? '↑' : '↓'} Trend
          </p>
        )}
      </CardContent>
    </Card>
  );
}

Why it's good:

  • Imports from @/components/ui/*
  • Uses semantic tokens
  • Uses cn() utility
  • Follows spacing scale
  • Composes from shadcn/ui primitives
  • TypeScript interfaces
  • Allows className override

🎓 Learning Path for AI

  1. Read Quick Start - Essential patterns
  2. Read this document - Rules and templates
  3. Reference Component Guide - All components
  4. Check Reference Tables - Token lookups

With these guidelines, you can generate code that perfectly matches the design system. Always prioritize consistency over creativity.


Last Updated: November 2, 2025 For AI Assistants: Follow these rules strictly for optimal code generation.