Added Cursor Rules
This commit is contained in:
parent
a2c67c3fb9
commit
a76e20e91f
159
.cursor/rules/component-patterns.mdc
Normal file
159
.cursor/rules/component-patterns.mdc
Normal file
@ -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 (
|
||||
<div className={cn("base-styles", className)} {...props}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## 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 (
|
||||
<Card className="bg-black border-gray-800">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-white">{project.title}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Badge variant="outline">{project.category}</Badge>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 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<typeof Button> {
|
||||
loading?: boolean
|
||||
}
|
||||
|
||||
export function PrimaryButton({
|
||||
loading,
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: PrimaryButtonProps) {
|
||||
return (
|
||||
<Button
|
||||
className={cn("bg-primary hover:bg-primary/90", className)}
|
||||
disabled={loading}
|
||||
{...props}
|
||||
>
|
||||
{loading ? "Loading..." : children}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Animation Patterns
|
||||
|
||||
### Framer Motion Usage
|
||||
```typescript
|
||||
import { motion } from 'framer-motion'
|
||||
|
||||
export function AnimatedCard({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
className="card-styles"
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Component Composition
|
||||
|
||||
### Compound Components
|
||||
```typescript
|
||||
// Parent component
|
||||
export function Accordion({ children }: { children: React.ReactNode }) {
|
||||
return <div className="accordion-container">{children}</div>
|
||||
}
|
||||
|
||||
// Child components
|
||||
export function AccordionItem({ children }: { children: React.ReactNode }) {
|
||||
return <div className="accordion-item">{children}</div>
|
||||
}
|
||||
|
||||
export function AccordionTrigger({ children }: { children: React.ReactNode }) {
|
||||
return <button className="accordion-trigger">{children}</button>
|
||||
}
|
||||
|
||||
// Usage
|
||||
<Accordion>
|
||||
<AccordionItem>
|
||||
<AccordionTrigger>Title</AccordionTrigger>
|
||||
<AccordionContent>Content</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
```
|
||||
|
||||
## 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
|
||||
97
.cursor/rules/data-content.mdc
Normal file
97
.cursor/rules/data-content.mdc
Normal file
@ -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 (
|
||||
<div>
|
||||
{projects.map(project => (
|
||||
<ProjectCard key={project.id} project={project} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// ❌ 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())
|
||||
}, [])
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
73
.cursor/rules/deployment.mdc
Normal file
73
.cursor/rules/deployment.mdc
Normal file
@ -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/`
|
||||
74
.cursor/rules/development-workflow.mdc
Normal file
74
.cursor/rules/development-workflow.mdc
Normal file
@ -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
|
||||
87
.cursor/rules/forms-validation.mdc
Normal file
87
.cursor/rules/forms-validation.mdc
Normal file
@ -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<typeof formSchema>
|
||||
|
||||
export function ContactForm() {
|
||||
const form = useForm<FormData>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
name: '',
|
||||
email: '',
|
||||
message: ''
|
||||
}
|
||||
})
|
||||
|
||||
const onSubmit = (data: FormData) => {
|
||||
// Handle form submission
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={form.handleSubmit(onSubmit)}>
|
||||
{/* Form fields with error handling */}
|
||||
</form>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## 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'
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="email"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Email</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="your@email.com" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
```
|
||||
|
||||
## 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)
|
||||
75
.cursor/rules/images-assets.mdc
Normal file
75
.cursor/rules/images-assets.mdc
Normal file
@ -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'
|
||||
|
||||
<Image
|
||||
src="https://images.unsplash.com/photo-123"
|
||||
alt="Descriptive alt text"
|
||||
width={800}
|
||||
height={600}
|
||||
className="rounded-lg"
|
||||
/>
|
||||
```
|
||||
|
||||
### 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",
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
60
.cursor/rules/project-structure.mdc
Normal file
60
.cursor/rules/project-structure.mdc
Normal file
@ -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
|
||||
```
|
||||
67
.cursor/rules/routing-layout.mdc
Normal file
67
.cursor/rules/routing-layout.mdc
Normal file
@ -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 `<Navigation />` and `<Footer />` components
|
||||
- Sets up font variables and metadata
|
||||
- **DO NOT** duplicate these in child layouts
|
||||
|
||||
### Page Layouts
|
||||
- Keep server components as default
|
||||
- Add `"use client"` only when necessary for interactivity
|
||||
- Define unique metadata for each route
|
||||
|
||||
## Metadata Requirements
|
||||
|
||||
Every page must have:
|
||||
```typescript
|
||||
export const metadata: Metadata = {
|
||||
title: "Unique Page Title",
|
||||
description: "Unique description for SEO",
|
||||
// Include Open Graph and Twitter cards
|
||||
}
|
||||
```
|
||||
|
||||
## Route Protection
|
||||
|
||||
The [src/middleware.ts](mdc:src/middleware.ts) currently redirects all routes to `/` except:
|
||||
- Home page (`/`)
|
||||
- Next.js internal routes (`/_next/*`)
|
||||
- Favicon files
|
||||
- Specific static assets (OLIVER.jpeg, OLIVER_depth.jpeg, etc.)
|
||||
|
||||
## Static Assets
|
||||
|
||||
When adding new files to `public/`, update the middleware allowlist in [src/middleware.ts](mdc:src/middleware.ts) line 8 to prevent 307 redirects.
|
||||
|
||||
## Common Patterns
|
||||
|
||||
```typescript
|
||||
// Page component
|
||||
export default function PageName() {
|
||||
return (
|
||||
<div className="container mx-auto px-4">
|
||||
{/* Page content */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// With metadata
|
||||
export const metadata: Metadata = {
|
||||
title: "Page Title",
|
||||
description: "Page description"
|
||||
}
|
||||
```
|
||||
78
.cursor/rules/seo-metadata.mdc
Normal file
78
.cursor/rules/seo-metadata.mdc
Normal file
@ -0,0 +1,78 @@
|
||||
---
|
||||
globs: src/app/**/page.tsx,src/app/**/layout.tsx
|
||||
---
|
||||
|
||||
# SEO and Metadata
|
||||
|
||||
## Metadata API Requirements
|
||||
|
||||
Every page must define unique metadata using the Next.js Metadata API:
|
||||
|
||||
```typescript
|
||||
import type { Metadata } from "next"
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Unique Page Title | Biohazard VFX",
|
||||
description: "Unique, descriptive page description for SEO",
|
||||
metadataBase: new URL("https://biohazardvfx.com"),
|
||||
openGraph: {
|
||||
title: "Page Title",
|
||||
description: "Page description",
|
||||
type: "website",
|
||||
locale: "en_US",
|
||||
siteName: "Biohazard VFX",
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title: "Page Title",
|
||||
description: "Page description",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Root Layout Metadata
|
||||
|
||||
The root layout in [src/app/layout.tsx](mdc:src/app/layout.tsx) includes:
|
||||
- Global site metadata
|
||||
- Open Graph configuration
|
||||
- Twitter card setup
|
||||
- JSON-LD structured data
|
||||
- Canonical URLs
|
||||
|
||||
## SEO Best Practices
|
||||
|
||||
1. **Unique Titles**: Each page must have a unique, descriptive title
|
||||
2. **Descriptions**: Write compelling meta descriptions (150-160 characters)
|
||||
3. **Structured Data**: Use JSON-LD for rich snippets
|
||||
4. **Canonical URLs**: Set canonical URLs to prevent duplicate content
|
||||
5. **Open Graph**: Include OG tags for social media sharing
|
||||
6. **Twitter Cards**: Configure Twitter card metadata
|
||||
|
||||
## Structured Data Example
|
||||
|
||||
```typescript
|
||||
const jsonLd = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Organization",
|
||||
name: "Biohazard VFX",
|
||||
description: "Visual effects studio",
|
||||
url: "https://biohazardvfx.com",
|
||||
logo: "https://biohazardvfx.com/logo.png",
|
||||
sameAs: ["https://instagram.com/biohazardvfx"],
|
||||
}
|
||||
```
|
||||
|
||||
## Page-Specific Metadata
|
||||
|
||||
- **Home**: Focus on main services and value proposition
|
||||
- **Portfolio**: Highlight featured projects and capabilities
|
||||
- **Services**: Target specific service keywords
|
||||
- **About**: Include company information and team details
|
||||
- **Contact**: Include location and contact information
|
||||
|
||||
## Image SEO
|
||||
|
||||
- Use descriptive alt text for all images
|
||||
- Optimize image file names
|
||||
- Include image dimensions
|
||||
- Use appropriate image formats (WebP when possible)
|
||||
60
.cursor/rules/ui-system.mdc
Normal file
60
.cursor/rules/ui-system.mdc
Normal file
@ -0,0 +1,60 @@
|
||||
---
|
||||
globs: *.tsx,*.ts,*.css
|
||||
---
|
||||
|
||||
# UI System Guidelines
|
||||
|
||||
## Theme & Design System
|
||||
|
||||
- **Default Theme**: Dark mode only - do not introduce light-first designs
|
||||
- **Typography**: Use CSS variables for fonts (Geist, Geist Mono, Bebas Neue, Orbitron, etc.)
|
||||
- **Components**: Use shadcn/ui primitives from [src/components/ui/](mdc:src/components/ui/)
|
||||
- **Spacing**: Follow Tailwind 4 defaults, prefer utility classes over custom CSS
|
||||
- **Animation**: Keep Framer Motion subtle and meaningful only
|
||||
|
||||
## Component Structure
|
||||
|
||||
```typescript
|
||||
// Use shadcn/ui primitives as base
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card } from '@/components/ui/card'
|
||||
|
||||
// Extend with local wrappers when needed
|
||||
export function CustomComponent() {
|
||||
return (
|
||||
<Card className="bg-black border-gray-800">
|
||||
<Button variant="outline" className="text-white">
|
||||
Action
|
||||
</Button>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Styling Rules
|
||||
|
||||
1. **Dark Theme**: All components must work in dark mode
|
||||
2. **Tailwind First**: Use utility classes before custom CSS
|
||||
3. **Component Variants**: Use class-variance-authority for component variants
|
||||
4. **Responsive**: Mobile-first responsive design
|
||||
5. **Accessibility**: Include proper ARIA labels and semantic HTML
|
||||
|
||||
## Font Usage
|
||||
|
||||
Available font variables from [src/app/layout.tsx](mdc:src/app/layout.tsx):
|
||||
- `--font-geist-sans` (default)
|
||||
- `--font-geist-mono`
|
||||
- `--font-bebas`
|
||||
- `--font-orbitron`
|
||||
- `--font-inter`
|
||||
- `--font-jetbrains-mono`
|
||||
- `--font-space-mono`
|
||||
- `--font-rajdhani`
|
||||
- `--font-exo-2`
|
||||
|
||||
## Animation Guidelines
|
||||
|
||||
- Use Framer Motion sparingly for meaningful transitions
|
||||
- Prefer CSS transitions for simple hover effects
|
||||
- Keep animations under 300ms for UI feedback
|
||||
- Respect `prefers-reduced-motion` for accessibility
|
||||
99
.cursor/rules/vfx-specific.mdc
Normal file
99
.cursor/rules/vfx-specific.mdc
Normal file
@ -0,0 +1,99 @@
|
||||
---
|
||||
description: VFX studio specific patterns and requirements
|
||||
---
|
||||
|
||||
# VFX Studio Specific Guidelines
|
||||
|
||||
## Media Handling
|
||||
|
||||
### Video Components
|
||||
- Use [src/components/VideoPlayer.tsx](mdc:src/components/VideoPlayer.tsx) for video playback
|
||||
- Use [src/components/ReelPlayer.tsx](mdc:src/components/ReelPlayer.tsx) for demo reels
|
||||
- Support multiple video formats (MP4, WebM)
|
||||
- Include proper video metadata and thumbnails
|
||||
|
||||
### Image Components
|
||||
- Use [src/components/DepthMap.tsx](mdc:src/components/DepthMap.tsx) for depth map visualizations
|
||||
- Implement lazy loading for portfolio images
|
||||
- Use Next.js Image optimization for all media
|
||||
|
||||
## Portfolio Patterns
|
||||
|
||||
### Project Showcase
|
||||
```typescript
|
||||
// Use ProjectCard component for consistent project display
|
||||
import { ProjectCard } from '@/components/ProjectCard'
|
||||
import { ProjectShowcase } from '@/components/ProjectShowcase'
|
||||
|
||||
// Project data structure from src/data/projects.ts
|
||||
interface Project {
|
||||
id: string
|
||||
title: string
|
||||
description: string
|
||||
category: 'commercial' | 'music-video' | 'film' | 'animation'
|
||||
client?: string
|
||||
year: number
|
||||
images: string[]
|
||||
videoUrl?: string
|
||||
tags: string[]
|
||||
}
|
||||
```
|
||||
|
||||
### Service Categories
|
||||
- Visual Effects (VFX)
|
||||
- Motion Graphics
|
||||
- 3D Animation
|
||||
- Compositing
|
||||
- Color Grading
|
||||
- Post-Production
|
||||
|
||||
## Client Work Patterns
|
||||
|
||||
### Client Logo Grid
|
||||
- Use [src/components/ClientLogoGrid.tsx](mdc:src/components/ClientLogoGrid.tsx)
|
||||
- Display client logos with proper attribution
|
||||
- Ensure logos are high-quality and properly sized
|
||||
|
||||
### Project Filtering
|
||||
- Implement category-based filtering
|
||||
- Support tag-based search
|
||||
- Include year-based sorting
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### Media Optimization
|
||||
- Compress images and videos for web delivery
|
||||
- Use appropriate formats (WebP for images, MP4 for videos)
|
||||
- Implement progressive loading for large media files
|
||||
- Use CDN for media delivery
|
||||
|
||||
### Loading States
|
||||
- Show skeleton loaders for media content
|
||||
- Implement progressive image loading
|
||||
- Use intersection observer for lazy loading
|
||||
|
||||
## VFX-Specific UI Elements
|
||||
|
||||
### Before/After Comparisons
|
||||
- Implement split-screen comparisons
|
||||
- Use slider controls for reveal effects
|
||||
- Include toggle for before/after views
|
||||
|
||||
### Process Showcases
|
||||
- Show breakdowns of VFX work
|
||||
- Include wireframe and final render comparisons
|
||||
- Display technical specifications
|
||||
|
||||
## Content Guidelines
|
||||
|
||||
### Project Descriptions
|
||||
- Include technical details (software used, techniques)
|
||||
- Mention client and project scope
|
||||
- Highlight challenges and solutions
|
||||
- Use industry-standard terminology
|
||||
|
||||
### Service Descriptions
|
||||
- Be specific about capabilities
|
||||
- Include typical project timelines
|
||||
- Mention software and hardware capabilities
|
||||
- Provide clear pricing structure (if applicable)
|
||||
Loading…
x
Reference in New Issue
Block a user