From a76e20e91fa40d25fe13be9b3805c2ee7f240f30 Mon Sep 17 00:00:00 2001 From: Nicholai Date: Thu, 23 Oct 2025 05:11:03 -0600 Subject: [PATCH] Added Cursor Rules --- .cursor/rules/component-patterns.mdc | 159 +++++++++++++++++++++++++ .cursor/rules/data-content.mdc | 97 +++++++++++++++ .cursor/rules/deployment.mdc | 73 ++++++++++++ .cursor/rules/development-workflow.mdc | 74 ++++++++++++ .cursor/rules/forms-validation.mdc | 87 ++++++++++++++ .cursor/rules/images-assets.mdc | 75 ++++++++++++ .cursor/rules/project-structure.mdc | 60 ++++++++++ .cursor/rules/routing-layout.mdc | 67 +++++++++++ .cursor/rules/seo-metadata.mdc | 78 ++++++++++++ .cursor/rules/ui-system.mdc | 60 ++++++++++ .cursor/rules/vfx-specific.mdc | 99 +++++++++++++++ 11 files changed, 929 insertions(+) create mode 100644 .cursor/rules/component-patterns.mdc create mode 100644 .cursor/rules/data-content.mdc create mode 100644 .cursor/rules/deployment.mdc create mode 100644 .cursor/rules/development-workflow.mdc create mode 100644 .cursor/rules/forms-validation.mdc create mode 100644 .cursor/rules/images-assets.mdc create mode 100644 .cursor/rules/project-structure.mdc create mode 100644 .cursor/rules/routing-layout.mdc create mode 100644 .cursor/rules/seo-metadata.mdc create mode 100644 .cursor/rules/ui-system.mdc create mode 100644 .cursor/rules/vfx-specific.mdc diff --git a/.cursor/rules/component-patterns.mdc b/.cursor/rules/component-patterns.mdc new file mode 100644 index 0000000..540f28f --- /dev/null +++ b/.cursor/rules/component-patterns.mdc @@ -0,0 +1,159 @@ +--- +globs: src/components/**/*.tsx +--- + +# Component Patterns + +## Component Structure + +### File Organization +- Place reusable components in `src/components/` +- Use PascalCase for component files: `ComponentName.tsx` +- Group related components in subdirectories when needed + +### Component Template +```typescript +import { cn } from '@/lib/utils' + +interface ComponentProps { + className?: string + children?: React.ReactNode + // Other props +} + +export function ComponentName({ + className, + children, + ...props +}: ComponentProps) { + return ( +
+ {children} +
+ ) +} +``` + +## shadcn/ui Integration + +### Using shadcn/ui Components +```typescript +import { Button } from '@/components/ui/button' +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' +import { Badge } from '@/components/ui/badge' + +export function ProjectCard({ project }: { project: Project }) { + return ( + + + {project.title} + + + {project.category} + + + ) +} +``` + +### Extending shadcn/ui Components +```typescript +// Create wrapper components for common patterns +import { Button } from '@/components/ui/button' +import { cn } from '@/lib/utils' + +interface PrimaryButtonProps extends React.ComponentProps { + loading?: boolean +} + +export function PrimaryButton({ + loading, + className, + children, + ...props +}: PrimaryButtonProps) { + return ( + + ) +} +``` + +## Animation Patterns + +### Framer Motion Usage +```typescript +import { motion } from 'framer-motion' + +export function AnimatedCard({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ) +} +``` + +## Component Composition + +### Compound Components +```typescript +// Parent component +export function Accordion({ children }: { children: React.ReactNode }) { + return
{children}
+} + +// Child components +export function AccordionItem({ children }: { children: React.ReactNode }) { + return
{children}
+} + +export function AccordionTrigger({ children }: { children: React.ReactNode }) { + return +} + +// Usage + + + Title + Content + + +``` + +## Props and TypeScript + +### Interface Patterns +```typescript +// Use descriptive interface names +interface ProjectCardProps { + project: Project + variant?: 'default' | 'featured' + showDescription?: boolean + onSelect?: (project: Project) => void +} + +// Use React.ComponentProps for extending HTML elements +interface CustomButtonProps extends React.ComponentProps<'button'> { + variant?: 'primary' | 'secondary' + size?: 'sm' | 'md' | 'lg' +} +``` + +## Styling Guidelines + +1. **Tailwind First**: Use utility classes before custom CSS +2. **Conditional Classes**: Use `cn()` utility for conditional styling +3. **Responsive Design**: Mobile-first approach with responsive utilities +4. **Dark Theme**: Ensure all components work in dark mode +5. **Accessibility**: Include proper ARIA labels and semantic HTML \ No newline at end of file diff --git a/.cursor/rules/data-content.mdc b/.cursor/rules/data-content.mdc new file mode 100644 index 0000000..ab9190c --- /dev/null +++ b/.cursor/rules/data-content.mdc @@ -0,0 +1,97 @@ +--- +globs: src/data/**/*.ts,src/data/**/*.json +--- + +# Data and Content Management + +## Data Structure + +Non-secret content belongs in `src/data/` as TypeScript modules or JSON files. Keep data presentation-agnostic. + +## Current Data Files + +- [src/data/projects.ts](mdc:src/data/projects.ts) - Project portfolio data +- [src/data/services.ts](mdc:src/data/services.ts) - Service offerings data + +## Data Patterns + +### TypeScript Data Modules +```typescript +// src/data/projects.ts +export interface Project { + id: string + title: string + description: string + category: string + images: string[] + videoUrl?: string +} + +export const projects: Project[] = [ + { + id: 'project-1', + title: 'Project Title', + description: 'Project description', + category: 'commercial', + images: ['/image1.jpg', '/image2.jpg'] + } +] +``` + +### JSON Data Files +```json +{ + "services": [ + { + "id": "vfx", + "name": "Visual Effects", + "description": "High-end VFX services" + } + ] +} +``` + +## Data Usage Rules + +1. **Server Components**: Prefer server components for data fetching +2. **File Imports**: Use direct imports instead of client-side fetching for static data +3. **Type Safety**: Define TypeScript interfaces for all data structures +4. **Separation**: Keep data separate from presentation logic + +## Content Guidelines + +- Use descriptive, SEO-friendly content +- Include proper alt text for images +- Maintain consistent naming conventions +- Keep content up-to-date and accurate + +## Data Fetching Patterns + +```typescript +// ✅ Good: Server component with direct import +import { projects } from '@/data/projects' + +export default function PortfolioPage() { + return ( +
+ {projects.map(project => ( + + ))} +
+ ) +} + +// ❌ Avoid: Client-side fetching of static data +'use client' +import { useEffect, useState } from 'react' + +export function PortfolioPage() { + const [projects, setProjects] = useState([]) + + useEffect(() => { + fetch('/api/projects').then(res => res.json()) + }, []) + + // ... +} +``` \ No newline at end of file diff --git a/.cursor/rules/deployment.mdc b/.cursor/rules/deployment.mdc new file mode 100644 index 0000000..ab846e1 --- /dev/null +++ b/.cursor/rules/deployment.mdc @@ -0,0 +1,73 @@ +--- +alwaysApply: true +--- + +# Deployment and Build Process + +## Cloudflare Workers with OpenNext + +This project deploys to Cloudflare Workers using OpenNext for Next.js compatibility. + +### Build Process + +1. **Quality Gates** (run before build): + ```bash + npm run type-check # TypeScript validation + npm run lint # ESLint validation + ``` + +2. **Production Build**: + ```bash + npm run build # Next.js build + ``` + +3. **OpenNext Build**: + ```bash + npx open-next@latest build # Generate Cloudflare-compatible build + ``` + +4. **Deploy**: + ```bash + npx wrangler deploy .open-next/worker + ``` + +### Configuration Files + +- [wrangler.toml](mdc:wrangler.toml) - Cloudflare Workers configuration +- [open-next.config.ts](mdc:open-next.config.ts) - OpenNext build configuration +- [next.config.ts](mdc:next.config.ts) - Next.js configuration + +### Required wrangler.toml Settings + +```toml +name = "site-worker" +main = ".open-next/worker/index.mjs" +compatibility_date = "2024-09-23" +compatibility_flags = ["nodejs_compat"] +assets = { directory = ".open-next/assets" } +``` + +## Environment Variables + +Create `.env.sample` and keep it synchronized. Typical keys: +``` +NEXT_PUBLIC_SITE_URL= +RESEND_API_KEY= +CF_PAGES_URL= +``` + +**Security**: Never commit real secrets. Use `.env` locally and environment variables in production. + +## Build Configuration + +- ESLint and TypeScript errors are ignored during build for deployment speed +- CI still gates on `lint` and `type-check` before merge +- Always fix errors instead of bypassing checks + +## Deployment Checklist + +- [ ] Run `npm run type-check` and `npm run lint` +- [ ] Ensure `assets.directory` matches OpenNext output +- [ ] Keep compatibility date at or after 2024-09-23 +- [ ] Test build locally with `npm run build` +- [ ] Verify OpenNext build artifacts in `.open-next/` \ No newline at end of file diff --git a/.cursor/rules/development-workflow.mdc b/.cursor/rules/development-workflow.mdc new file mode 100644 index 0000000..e2cf8ba --- /dev/null +++ b/.cursor/rules/development-workflow.mdc @@ -0,0 +1,74 @@ +--- +alwaysApply: true +--- + +# Development Workflow + +## Git Workflow + +- **Default Branch**: `main` is protected +- **Workflow**: feature branches → PR → required checks → squash merge +- **Commit Format**: Conventional Commits + - `feat: add contact form schema` + - `fix: correct Image remote pattern` + - `chore: bump dependencies` + +## Required Checks + +Before any merge: +- `npm run lint` - ESLint validation +- `npm run type-check` - TypeScript validation +- `npm run build` - Production build (optional locally, required in CI) + +## Development Commands + +```bash +# Setup +npm ci # Install dependencies + +# Development +npm run dev # Dev server with Turbopack +npm run type-check # TypeScript validation +npm run lint # ESLint validation + +# Build & Deploy +npm run build # Production build +npm run start # Preview production build +npx open-next@latest build # OpenNext build +npx wrangler deploy .open-next/worker # Deploy to Cloudflare +``` + +## Code Quality + +### TypeScript +- Use strict mode (enabled in [tsconfig.json](mdc:tsconfig.json)) +- Prefer type inference over explicit types +- Use absolute imports with `@` alias + +### ESLint +- Follow Next.js ESLint config +- Fix all linting errors before committing +- Don't bypass checks in production builds + +## Testing Strategy + +- **Unit Tests**: Place close to sources, name with `.test.ts` or `.test.tsx` +- **E2E Tests**: Optional Playwright setup +- **Manual Testing**: Test all user flows before deployment + +## Pull Request Guidelines + +- Keep PRs small and reviewable +- Include screenshots for UI changes +- Update [AGENTS.md](mdc:AGENTS.md) if conventions change +- Justify new dependencies in PR description +- Never commit secrets or sensitive data + +## Common Pitfalls to Avoid + +1. Adding remote image domains without updating [next.config.ts](mdc:next.config.ts) +2. Introducing client components unnecessarily +3. Duplicating navigation in nested layouts +4. Bypassing Tailwind utilities for custom CSS +5. Forgetting to update middleware whitelist for new static assets +6. Committing secrets instead of using environment variables \ No newline at end of file diff --git a/.cursor/rules/forms-validation.mdc b/.cursor/rules/forms-validation.mdc new file mode 100644 index 0000000..fc86c86 --- /dev/null +++ b/.cursor/rules/forms-validation.mdc @@ -0,0 +1,87 @@ +--- +globs: **/*form*.tsx,**/*Form*.tsx +--- + +# Forms and Validation + +## Form Library Stack + +- **Forms**: react-hook-form for form state management +- **Validation**: Zod schemas for type-safe validation +- **Resolvers**: @hookform/resolvers for integration + +## Form Structure + +```typescript +import { useForm } from 'react-hook-form' +import { zodResolver } from '@hookform/resolvers/zod' +import { z } from 'zod' + +// Define schema +const formSchema = z.object({ + name: z.string().min(1, 'Name is required'), + email: z.string().email('Invalid email address'), + message: z.string().min(10, 'Message must be at least 10 characters') +}) + +type FormData = z.infer + +export function ContactForm() { + const form = useForm({ + resolver: zodResolver(formSchema), + defaultValues: { + name: '', + email: '', + message: '' + } + }) + + const onSubmit = (data: FormData) => { + // Handle form submission + } + + return ( +
+ {/* Form fields with error handling */} +
+ ) +} +``` + +## Error Handling Rules + +1. **Field-level errors**: Show validation errors under each field +2. **Generic submit error**: Display general submission errors +3. **Never swallow errors**: Always surface validation and submission errors +4. **Loading states**: Show loading indicators during submission + +## Form Components + +Use shadcn/ui form components from [src/components/ui/form.tsx](mdc:src/components/ui/form.tsx): + +```typescript +import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form' +import { Input } from '@/components/ui/input' +import { Button } from '@/components/ui/button' + + ( + + Email + + + + + + )} +/> +``` + +## Validation Patterns + +- Use Zod for all form validation +- Provide clear, user-friendly error messages +- Validate on both client and server side +- Handle async validation (e.g., email uniqueness) \ No newline at end of file diff --git a/.cursor/rules/images-assets.mdc b/.cursor/rules/images-assets.mdc new file mode 100644 index 0000000..bcbd27f --- /dev/null +++ b/.cursor/rules/images-assets.mdc @@ -0,0 +1,75 @@ +--- +globs: **/*.tsx,**/*.ts +--- + +# Images and Assets + +## Image Handling + +### Next.js Image Component +Always use Next.js Image component for remote images: + +```typescript +import Image from 'next/image' + +Descriptive alt text +``` + +### Remote Image Domains +Current allowed domains in [next.config.ts](mdc:next.config.ts): +- `images.unsplash.com` + +**When adding new external domains:** +1. Add to `remotePatterns` in [next.config.ts](mdc:next.config.ts) +2. Document the change in [AGENTS.md](mdc:AGENTS.md) + +## Static Assets + +### Public Directory +- Keep `public/` for truly static assets only +- Current assets: favicon files, images (OLIVER.jpeg, etc.), GIFs + +### Middleware Whitelist +**CRITICAL**: When adding new static assets to `public/`, update the middleware allowlist in [src/middleware.ts](mdc:src/middleware.ts) line 8: + +```typescript +// Add new asset paths here +if (pathname === '/' || + pathname.startsWith('/_next') || + pathname.startsWith('/favicon.') || + pathname === '/OLIVER.jpeg' || + pathname === '/new-asset.jpg' || // Add new assets here + pathname === '/reel.mp4') { + return NextResponse.next(); +} +``` + +**Common symptom**: If assets return "text/html" Content-Type error, the path isn't whitelisted. + +## Asset Optimization + +- Use appropriate image formats (WebP when possible) +- Provide proper alt text for accessibility +- Use responsive images with `sizes` prop +- Optimize file sizes for web delivery + +## Video Files + +Custom headers are configured in [next.config.ts](mdc:next.config.ts) for `.mp4` files: +```typescript +{ + source: "/:path*.mp4", + headers: [ + { + key: "Content-Type", + value: "video/mp4", + }, + ], +} +``` \ No newline at end of file diff --git a/.cursor/rules/project-structure.mdc b/.cursor/rules/project-structure.mdc new file mode 100644 index 0000000..1827ef7 --- /dev/null +++ b/.cursor/rules/project-structure.mdc @@ -0,0 +1,60 @@ +--- +alwaysApply: true +--- + +# Biohazard VFX Website - Project Structure + +This is a Next.js 15.5.4 VFX studio website built with React 19, TypeScript, Tailwind CSS 4, and shadcn/ui components. + +## Core Architecture + +- **Framework**: Next.js 15.5.4 with App Router +- **Styling**: Tailwind CSS 4 + shadcn/ui components +- **Animation**: Framer Motion for subtle transitions +- **Forms**: react-hook-form + Zod validation +- **Deployment**: Cloudflare Workers via OpenNext +- **Package Manager**: npm + +## Project Layout + +``` +src/ +├─ app/ # App Router pages and layouts +│ ├─ (marketing)/ # Route groups +│ ├─ api/ # Route handlers +│ └─ layout.tsx # Root layout with global providers +├─ components/ # Reusable UI components +│ └─ ui/ # shadcn/ui primitives +├─ data/ # JSON/TS data objects +├─ lib/ # Utilities, hooks, server actions +├─ styles/ # globals.css, Tailwind utilities +└─ types/ # Shared TypeScript types +``` + +## Key Files + +- [AGENTS.md](mdc:AGENTS.md) - Single source of truth for development guidelines +- [package.json](mdc:package.json) - Dependencies and scripts +- [next.config.ts](mdc:next.config.ts) - Next.js configuration +- [tsconfig.json](mdc:tsconfig.json) - TypeScript configuration with @ alias +- [src/middleware.ts](mdc:src/middleware.ts) - Route protection and redirects +- [src/app/layout.tsx](mdc:src/app/layout.tsx) - Root layout with fonts and metadata + +## Import Aliases + +Always use absolute imports with `@` mapped to `src/`: +```typescript +import { Component } from '@/components/Component' +import { data } from '@/data/projects' +``` + +## Development Commands + +```bash +npm ci # Install dependencies +npm run dev # Development server with Turbopack +npm run type-check # TypeScript validation +npm run lint # ESLint validation +npm run build # Production build +npx open-next@latest build # OpenNext build for Cloudflare +``` \ No newline at end of file diff --git a/.cursor/rules/routing-layout.mdc b/.cursor/rules/routing-layout.mdc new file mode 100644 index 0000000..ed06e1d --- /dev/null +++ b/.cursor/rules/routing-layout.mdc @@ -0,0 +1,67 @@ +--- +globs: src/app/**/*.tsx +--- + +# Routing and Layout Rules + +## App Router Structure + +- **Pages**: Live in `src/app/` directory +- **Server Components**: Default to server components, promote to client only when needed +- **Layout Hierarchy**: Root layout owns global providers, navigation, and footer +- **Route Groups**: Use `(marketing)` for grouped routes without affecting URL structure + +## Layout Rules + +### Root Layout ([src/app/layout.tsx](mdc:src/app/layout.tsx)) +- Owns global providers and theme class +- Contains `` and `