npm install && npm run devVisit: http://localhost:3000
| Task | File Location |
|---|---|
| Add form field | src/components/sections/[section]-section.tsx |
| Add validation | src/lib/validations.ts |
| Modify markdown output | src/lib/markdown-generator.ts |
| Add new section | Create in src/components/sections/ + add to src/app/page.tsx |
| Create form component | src/components/forms/ |
| Add skill | src/constants/skills.ts |
| Storage logic | src/lib/storage.ts |
| Theme colors | src/styles/globals.css |
| Header/Footer | src/components/layout/ |
// Backgrounds
bg-background // Main background
bg-card // Card background
bg-accent // Accent background
bg-muted // Muted background
bg-primary // Primary action background
// Text
text-foreground // Main text
text-muted-foreground // Secondary text
text-primary-foreground // Text on primary bg
text-destructive // Error text
// Borders & Effects
border-border // Border color
border-input // Input border
ring-ring // Focus ring❌ Never hardcode: bg-white, text-black, border-gray-300
'use client';
import { forwardRef } from 'react';
import type { InputHTMLAttributes } from 'react';
export interface MyInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {
label?: string;
error?: string;
}
export const MyInput = forwardRef<HTMLInputElement, MyInputProps>(
({ label, error, className = '', ...props }, ref) => {
return (
<div className="w-full space-y-1">
{label && <label htmlFor={props.id} className="text-foreground text-sm font-medium">{label}</label>}
<input
ref={ref}
className={`border-input bg-background text-foreground focus:ring-ring w-full rounded-lg border px-4 py-2 transition-colors focus:outline-none focus:ring-2 disabled:cursor-not-allowed disabled:opacity-50 ${error ? 'border-destructive' : ''} ${className}`}
aria-invalid={!!error}
{...props}
/>
{error && <p className="text-destructive text-sm" role="alert">{error}</p>}
</div>
);
}
);
MyInput.displayName = 'MyInput';'use client';
import { UseFormRegister, FieldErrors } from 'react-hook-form';
import { FormInput } from '@/components/forms/form-input';
import type { MyFormData } from '@/lib/validations';
interface MySectionProps {
register: UseFormRegister<MyFormData>;
errors: FieldErrors<MyFormData>;
}
export function MySection({ register, errors }: MySectionProps) {
return (
<div className="space-y-6">
<div className="border-b border-border pb-4">
<h2 className="text-2xl font-bold">Section Title</h2>
<p className="text-muted-foreground mt-1 text-sm">Description</p>
</div>
<div className="grid gap-4 md:grid-cols-2">
<FormInput
{...register('fieldName')}
id="fieldName"
label="Label"
error={errors.fieldName?.message}
/>
</div>
</div>
);
}// Component Props
interface ComponentProps {
title: string; // Required
count?: number; // Optional
onAction: () => void; // Required function
onChange?: (val: string) => void; // Optional function
}
// Zod Schema
const schema = z.object({
email: z.string().email(),
age: z.number().min(0).max(120),
url: z.string().url().optional(),
isActive: z.boolean().default(false),
});
type FormData = z.infer<typeof schema>;
// Form Hook
const { register, watch, setValue, formState: { errors } } = useForm<FormData>({
resolver: zodResolver(schema),
defaultValues: { isActive: false }
});// ✅ Keyboard Navigation
<button
onClick={handleClick}
onKeyDown={(e) => e.key === 'Enter' && handleClick()}
className="focus:ring-2 focus:ring-primary"
>
// ✅ ARIA Labels
<nav aria-label="Main navigation">
<button aria-label="Close dialog">
<input aria-describedby="help-text" aria-invalid={!!error} />
// ✅ Form Labels
<label htmlFor="email">Email</label>
<input id="email" />
// ✅ Error Messages
<p id="email-error" role="alert" className="text-destructive">
{error}
</p>
// ✅ Active States
<Link href="/" aria-current={isActive ? 'page' : undefined}>
// ✅ Alt Text
<img src={url} alt="Descriptive text" loading="lazy" />// Mobile First
className="text-sm md:text-base lg:text-lg"
// Grid Layouts
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"
// Visibility
className="hidden md:block" // Desktop only
className="block md:hidden" // Mobile only
// Spacing
className="gap-2 md:gap-4 lg:gap-6"
className="px-4 md:px-6 lg:px-8"
// Breakpoints
// base: 0-639px
// sm: 640px+
// md: 768px+
// lg: 1024px+
// xl: 1280px+// 1. React & Next.js
import { useState, useEffect } from 'react';
import Link from 'next/link';
// 2. Third-party
import { useForm } from 'react-hook-form';
import { z } from 'zod';
// 3. Internal utils
import { saveFormData } from '@/lib/storage';
import type { ProfileFormData } from '@/lib/validations';
// 4. Components
import { FormInput } from '@/components/forms/form-input';
// 5. Constants
import { skills } from '@/constants/skills';// Memoize calculations
const count = useMemo(() =>
expensiveCalculation(data),
[data]
);
// Memoize callbacks
const handleClick = useCallback(() => {
doSomething();
}, []);
// Memoize components
const MemoizedComponent = React.memo(Component);
// Debounce auto-save
useEffect(() => {
const timer = setTimeout(() => {
saveData();
}, 1000);
return () => clearTimeout(timer);
}, [data]);
// Lazy load images
<img src={url} alt="..." loading="lazy" />// Save
import { saveFormData } from '@/lib/storage';
saveFormData({
profile: getProfileValues(),
social: getSocialValues(),
// ...
skills: selectedSkills,
lastSaved: new Date().toISOString(),
});
// Load
import { loadFormData } from '@/lib/storage';
useEffect(() => {
const saved = loadFormData();
if (saved) {
// Restore data
setValue('title', saved.profile.title);
}
}, []);
// Clear
import { clearFormData } from '@/lib/storage';
clearFormData();| Error | Fix |
|---|---|
| "Type 'any' is not assignable" | Add explicit types, avoid any |
| "Property does not exist" | Add to interface, check spelling |
| "Cannot find module '@/...'" | Check path, restart TS server |
| "localStorage is not defined" | Wrap in useEffect, check 'use client' |
| "Hydration mismatch" | Ensure same HTML on server/client |
| TypeScript errors after install | Run npm run type-check |
Layout → Size → Spacing → Typography → Colors → Borders → Effects → States → Responsive
Example:
className="flex items-center gap-2 w-full px-4 py-2 text-sm font-medium text-foreground bg-accent rounded-lg border border-border shadow-sm transition-colors hover:bg-accent/80 focus:ring-2 focus:ring-primary disabled:opacity-50 md:px-6 lg:text-base"# Development
npm run dev # Start dev server (Turbopack)
npm run build # Production build
npm run start # Start production server
npm run type-check # Check TypeScript
npm run lint # Run ESLint
# Git
git status # Check changes
git add . # Stage all changes
git commit -m "feat: add feature" # Commit
git push # Push to remotefeat(scope): # New feature
fix(scope): # Bug fix
refactor(scope): # Code restructure
style(scope): # Formatting
a11y(scope): # Accessibility
perf(scope): # Performance
docs(scope): # Documentation
test(scope): # Tests
chore(scope): # Maintenance
- REVAMP_SUMMARY.md - Full architecture
- .cursorrules - Code conventions
- .cursorrules-quick - Quick patterns
- DX_GUIDE.md - Developer guide
- src/app/page.tsx - Main wizard implementation
# Include file in context
@filename
# Include folder
@folder
# Create component
@.cursorrules Create a form component for [x]
# Fix code
@.cursorrules Fix accessibility issues in [component]
# Review
@.cursorrules Review this code for [standards]
- Always use 'use client' for components with state/events
- Never hardcode colors - use CSS variables
- Type everything - avoid
any - Think accessibility first - keyboard + ARIA
- Mobile first - base styles for mobile
- Test dark mode - both themes
- Debounce saves - 1 second delay
- Memoize when needed - useMemo/useCallback
- Clean up effects - return cleanup function
- Follow patterns - check existing code first
- No TypeScript errors
- No ESLint warnings
- Works on mobile (375px)
- Works on desktop (1440px)
- Keyboard navigable
- Focus indicators visible
- Dark mode tested
- Auto-save works (if form)
- No console errors
- Follows .cursorrules patterns
- Internal: REVAMP_SUMMARY.md, .cursorrules, DX_GUIDE.md
- Next.js: https://nextjs.org/docs
- React: https://react.dev
- Tailwind: https://tailwindcss.com/docs
- React Hook Form: https://react-hook-form.com
- Zod: https://zod.dev
- WCAG: https://www.w3.org/WAI/WCAG21/quickref/
Print this and keep it handy! 📋