Aller au contenu principal

Vibe Coding Guide — 17 Ready-to-Paste Prompts

17 battle-tested prompts for Claude Code & Cursor. Copy a prompt, paste it into your AI chat, and ship features in minutes. Every prompt references real files from this codebase — no generic boilerplate.


How to Use This Guide

With Claude Code (CLI)

cd /path/to/heartco
claude
# Paste any prompt below into the chat

With Cursor

  1. Open this project in Cursor
  2. Press Cmd+L (Mac) or Ctrl+L (Windows) to open AI chat
  3. Copy-paste any prompt below
  4. Reference files with @filename when indicated
  5. Let it cook

🏗️ Modules & Features

1. Add a new module (full scaffold)

Prompt:

I need to create a new module called "{{module_name}}" in this HeartCo codebase.
Follow the module template structure in @src/modules/_template/.

Steps:
1. Copy src/modules/_template to src/modules/{{module_name}}
2. Create a Prisma model fragment (add to prisma/schema.prisma):
   - Must include organizationId for multi-tenant isolation
   - Add @@index([organizationId]) for query performance
   - Add the model to ORG_SCOPED_MODELS in src/lib/prisma-org-scope.ts
3. Create a tRPC router at src/server/api/routers/{{module_name}}.ts:
   - Implement CRUD operations (create, read, list, update, delete)
   - Use staffProcedure for internal routes, protectedProcedure for client portal
   - Validate all inputs with Zod
   - Ensure organizationId filtering on all writes (update/delete)
4. Register the router in @src/server/api/root.ts:
   - Import the new router
   - Add it to the createTRPCRouter object
5. Create a page at src/app/dashboard/{{module_name}}/page.tsx:
   - Use the DataTable and ItemDialog components from the template
   - Fetch data via tRPC hook (api.{{module_name}}.list.useQuery())
6. Update navigation in src/components/layout/sidebar.tsx:
   - Add a menu item pointing to /dashboard/{{module_name}}
7. Create unit tests in src/server/api/routers/__tests__/{{module_name}}.test.ts:
   - Mock Prisma client
   - Test all CRUD operations
   - Test security (organizationId filtering)

After setup, run:
- pnpm prisma generate
- pnpm typecheck
- pnpm test
- pnpm lint:fix

Output: Full working CRUD module with page, router, components, and tests.

Context files: @src/modules/_template/ @src/server/api/root.ts @prisma/schema.prisma @src/lib/prisma-org-scope.ts

Expected result: A complete, production-ready module with page, tRPC router, Prisma model, components, and tests.

Verify it works:

pnpm typecheck
pnpm dev
# Navigate to http://localhost:3000/dashboard/{{module_name}}
# Try creating, reading, updating, and deleting items
pnpm test -- {{module_name}}

2. Add a field to an existing model

Prompt:

I need to add a field to the "{{ModelName}}" Prisma model.

Field details:
- Name: {{fieldName}}
- Type: {{fieldType}} (e.g., String, Int, Boolean, DateTime)
- Required/Optional: {{required}}
- Default value: {{defaultValue}} (if any)
- Indexed: {{isIndexed}} (true/false)

Steps:
1. Add the field to prisma/schema.prisma in the {{ModelName}} model
2. If the model has organizationId, NO need to add it again
3. Create a Prisma migration:
   - npx prisma migrate dev --name add_{{fieldName}}_to_{{model_name}}
4. Update the tRPC router in src/server/api/routers/{{router_name}}.ts:
   - Update Zod schemas (input validation)
   - Update the router procedures to include the new field in queries/mutations
5. Update the React component:
   - If it's a form, add a form field using react-hook-form
   - If it's a table, add a new column to DataTable
6. Run the full pipeline:
   - pnpm prisma generate
   - pnpm typecheck
   - pnpm test
   - pnpm lint:fix

Do NOT forget the migration step — migrations are committed to git.

Context files: @prisma/schema.prisma @src/server/api/routers/ (the relevant router)

Expected result: A new field added to the model, Prisma migration created, router and UI updated.

Verify it works:

npx prisma migrate status
pnpm typecheck
pnpm test -- {{router_name}}
pnpm dev
# Check that the field appears in forms/tables

3. Create a KPI dashboard for

Prompt:

Create a KPI dashboard page for {{module_name}} at src/app/dashboard/{{module_name}}/analytics/page.tsx.

Requirements:
1. Show 4 key metrics in a metric card grid:
   - {{metric1_name}} (value, trend, unit)
   - {{metric2_name}} (value, trend, unit)
   - {{metric3_name}} (value, trend, unit)
   - {{metric4_name}} (value, trend, unit)
2. Add a date range picker (use shadcn DatePicker, optional)
3. Use Recharts for visualization:
   - Line chart for time-series data
   - Bar chart for comparison
4. Fetch data from a tRPC query (create if missing):
   - src/server/api/routers/{{module_name}}.ts → analytics procedure
   - Query returns: { metrics: {...}, chartData: [...] }
5. Styling:
   - Use shadcn Card component
   - Apply Tailwind for layout (grid-cols-4 on desktop, grid-cols-1 on mobile)
   - Dark mode support (use tokens from design.md)
   - Add subtle animations (Framer Motion on scroll)
6. Error handling:
   - Show a loading skeleton while fetching
   - Display error message if query fails
   - Graceful fallback if no data

Use @src/components/landing/ for animation patterns and @src/lib/utils.ts for the cn() utility.

Context files: @src/components/ui/card.tsx @src/lib/utils.ts ./.claude/rules/design.md

Expected result: A polished analytics page with KPI cards, charts, and date filtering.

Verify it works:

pnpm dev
# Navigate to /dashboard/{{module_name}}/analytics
# Verify metrics load and charts render
# Check responsive design on mobile

4. Add a page with a form (Create/Edit)

Prompt:

Create a form page for {{resource_name}} at src/app/dashboard/{{module_name}}/[id]/page.tsx (edit) and a create modal at src/components/{{module_name}}/{{resource_name}}Form.tsx.

Form details:
- Resource: {{resource_name}}
- Fields: {{field1_name}} (type: {{type1}}), {{field2_name}} (type: {{type2}}), ...
- Create endpoint: api.{{module_name}}.create.useMutation()
- Update endpoint: api.{{module_name}}.update.useMutation()
- Delete endpoint: api.{{module_name}}.delete.useMutation() (optional)

Implementation:
1. Create Zod schema in src/server/api/routers/{{module_name}}.ts:
   - Define createInput and updateInput with proper validation
   - Add custom refinements if needed (e.g., date validations)
2. Create tRPC procedures:
   - create: staffProcedure + input validation → save to DB
   - update: staffProcedure + input validation + organizationId check
   - delete: staffProcedure + soft delete or hard delete (decide)
3. Create form component at src/components/{{module_name}}/{{resource_name}}Form.tsx:
   - Use react-hook-form + react-hook-form/resolvers
   - Connect form fields to Zod schema (zodResolver)
   - Add submit handler: call mutation → navigate on success
   - Show loading state during mutation
   - Show error toast if mutation fails
4. Create page at src/app/dashboard/{{module_name}}/[id]/page.tsx:
   - Fetch existing resource data if editing
   - Pass data to form component
   - Show 404 if resource not found (IDOR protection)
5. Add form fields:
   - Text inputs: <Input /> from shadcn
   - Select: <Select /> from shadcn
   - Checkboxes: <Checkbox /> from shadcn
   - Date/Time: <DatePicker /> from shadcn
   - Rich text: Consider @tiptap/react if needed
6. Style the form:
   - Use Tailwind for layout (flex, grid)
   - Add proper spacing and typography
   - Highlight required fields with asterisk
   - Show validation errors inline

Use @src/modules/_template/components/ItemForm.tsx as the structural reference.

Context files: @src/modules/_template/components/ItemForm.tsx @src/components/ui/ @src/lib/utils.ts

Expected result: A fully functional create/edit form with validation, error handling, and type safety.

Verify it works:

pnpm typecheck
pnpm dev
# Navigate to create form
# Fill in fields and submit → verify data saved in DB
# Edit an existing resource → verify data loads and updates
# Trigger validation errors → verify error messages show

5. Create a Kanban board for

Prompt:

Create a Kanban board (drag-and-drop) for {{resource_name}} at src/app/dashboard/{{module_name}}/kanban/page.tsx.

Requirements:
1. Status columns: {{status1}}, {{status2}}, {{status3}}, {{status4}} (from your domain)
2. Cards:
   - Display {{field1}}, {{field2}}, {{field3}} on each card
   - Color coding based on priority/category (optional)
   - Click to open detail modal (ItemDialog pattern)
3. Drag-and-drop:
   - Use dnd-kit library (already in project)
   - Dragging card from one column to another updates status
   - Optimistic UI update + server mutation
   - Rollback if mutation fails
4. Data fetching:
   - Fetch all items grouped by status
   - Or fetch all items and group in React (simpler for small datasets)
5. Styling:
   - Column containers with border and background
   - Cards with shadow on hover
   - Smooth drag animations
   - Mobile: convert to vertical scrolling (not drag-drop on touch)

Reference the CRM kanban pattern in src/app/dashboard/crm/[id]/kanban/page.tsx.

Steps:
1. Create tRPC procedures in src/server/api/routers/{{module_name}}.ts:
   - listByStatus: return items grouped by status
   - updateStatus: change item status (mutation)
2. Create Kanban component at src/components/{{module_name}}/KanbanBoard.tsx:
   - Use dnd-kit for drag-and-drop
   - Render status columns in a horizontal grid
3. Create page at src/app/dashboard/{{module_name}}/kanban/page.tsx
4. Add to sidebar navigation

Context files: @src/app/dashboard/crm/ (for CRM kanban reference), @src/lib/utils.ts

Expected result: A fully functional Kanban board with drag-and-drop status updates.

Verify it works:

pnpm dev
# Navigate to /dashboard/{{module_name}}/kanban
# Drag cards between columns → verify status updates in DB
# Refresh page → verify persisted changes
# Mobile view → verify no drag-drop, but card details still clickable

🔌 Integrations

6. Integrate an external API (with caching)

Prompt:

Integrate the {{api_name}} API into HeartCo.

API Details:
- Base URL: {{api_url}}
- Authentication: {{auth_type}} (Bearer, API Key, OAuth)
- Rate limit: {{rate_limit}}
- Key endpoints: {{endpoints}}
- Example response: {{example_response}}

Implementation:
1. Create a service layer at src/lib/api/{{api_name}}-client.ts:
   - Authenticate with the API (use env variables for secrets)
   - Implement typed functions for each endpoint
   - Add error handling and retry logic (exponential backoff)
   - Type responses with TypeScript interfaces
2. Add Redis caching layer:
   - Cache GET requests for 5-60 min (based on endpoint)
   - Invalidate cache on mutations
   - Pattern: check Redis first → call API → store in Redis
   - Use Redis key format: "{{api_name}}:{{resource_id}}"
3. Create tRPC procedures in src/server/api/routers/{{module_name}}.ts:
   - Call the service → add to context response
   - Add requirePermission() guards if needed
   - Validate organizationId for multi-tenant isolation
4. Handle rate limits gracefully:
   - If rate limited, return cached data (if available)
   - Log rate limit warnings
   - Implement backoff strategy
5. Add environment variables to src/env.js:
   - {{API_NAME}}_API_KEY
   - {{API_NAME}}_BASE_URL
   - Validate on app startup
6. Create tests:
   - Mock the API client in src/server/api/routers/__tests__/
   - Test cache hits/misses
   - Test error scenarios

Use @src/modules/bridge/bridge-client.ts as a reference for API integration patterns.

Context files: @src/modules/bridge/bridge-client.ts @src/env.js @src/lib/redis.ts (if Redis is set up)

Expected result: A production-grade API integration with caching, error handling, and type safety.

Verify it works:

pnpm typecheck
pnpm test -- {{module_name}}
pnpm dev
# Call the tRPC procedure → verify API response
# Call again → verify caching (check redis)
# Stop the API → verify graceful fallback

7. Add incoming webhooks (with HMAC verification)

Prompt:

Add webhook support for {{webhook_provider}} (e.g., Stripe, Bridge, Mistral).

Webhook details:
- Provider: {{webhook_provider}}
- Event types: {{event_types}}
- Signature header: {{signature_header}} (e.g., "x-webhook-signature")
- Secret: stored in env as {{SECRET_ENV_VAR}}
- Expected payload: {{payload_structure}}

Implementation:
1. Create webhook handler at src/app/api/webhooks/{{webhook_provider}}/route.ts:
   - Accept POST requests
   - Extract the raw request body (required for HMAC verification)
   - Verify HMAC signature with crypto.timingSafeEqual (never use ===)
   - Parse and validate payload with Zod
   - Respond 200 immediately (async processing)
2. Create webhook processor at src/server/webhooks/{{webhook_provider}}-processor.ts:
   - Handle each event type (if/switch on event.type)
   - Update database based on event
   - Use organizationId from payload or event context
   - Add error logging (log unparseable events)
3. Database updates:
   - Example: on "payment.success" → update Invoice status
   - Example: on "user.created" → sync to CRM
   - Always wrap in try/catch, always log failures
4. Add tests in src/server/webhooks/__tests__/:
   - Test valid signature passes, invalid signature rejected
   - Test each event type processed correctly
   - Test HMAC verification (crypto.timingSafeEqual)
5. Environment setup:
   - Add {{SECRET_ENV_VAR}} to .env.example
   - Validate in src/env.js

Critical security rules:
- ALWAYS use crypto.timingSafeEqual for HMAC verification
- NEVER use === to compare signatures (timing attack vulnerability)
- Verify signature before processing payload
- Log all signature failures (potential attacks)
- Respond 200 even if processing fails (don't retry forever)
- Use organizationId filtering on all DB updates

Use @src/modules/bridge/webhooks/ as reference for webhook patterns.

Context files: @src/modules/bridge/webhooks/ @src/env.js @src/app/api/webhooks/ (if other webhooks exist)

Expected result: A secure, production-grade webhook handler with HMAC verification and error logging.

Verify it works:

pnpm typecheck
pnpm test -- webhooks
# Use ngrok or Webhook.cool to tunnel localhost
# Send test webhook from provider
# Verify payload processed and DB updated
# Send invalid signature → verify rejected

8. Add realtime events with Pusher

Prompt:

Add realtime notification support using Pusher.

Scenarios:
- {{scenario1}} (e.g., "When a new invoice is created, notify all managers")
- {{scenario2}} (e.g., "When a chat message is sent, notify recipient in real-time")

Implementation:
1. Set up Pusher client:
   - Add NEXT_PUBLIC_PUSHER_KEY, PUSHER_SECRET, PUSHER_CLUSTER to .env
   - Validate in src/env.js
   - Create Pusher instance at src/lib/pusher.ts (if not exists)
2. Create server-side trigger in tRPC router:
   - After creating a {{resource}} (e.g., Invoice), call pusher.trigger()
   - Channel name: "org_{{organizationId}}_{{resource_type}}"
   - Event name: "{{resource_type}}.created"
   - Data: JSON payload (avoid sensitive data)
3. Create client-side subscription:
   - Use useEffect to subscribe to Pusher channel
   - Call pusher.subscribe("org_..." + organizationId)
   - Listen for event: channel.bind("{{event_name}}", callback)
   - Update React state on event
   - Cleanup: unsubscribe on unmount
4. UI updates:
   - Show toast notification when event received
   - Optionally update list in real-time (re-fetch or add to state)
   - Optimistic updates for better UX
5. Security:
   - Only subscribe to channels for your organization (use organizationId)
   - Verify Pusher signature on private channels (if using)
   - Don't send sensitive data through Pusher events
6. Tests:
   - Mock Pusher in unit tests (vi.mock() at test start)
   - Test trigger called with correct channel/event
   - Test subscription and callback

Use @src/lib/pusher.ts and look for existing Pusher usage in the codebase.

Context files: @src/lib/pusher.ts (if exists), @src/env.js, any existing Pusher usage

Expected result: Realtime notifications working across multiple browser tabs and users.

Verify it works:

pnpm dev
# Open 2 browser windows, same organization
# Create a {{resource}} in one window
# Verify notification appears in second window immediately
# Check browser console for Pusher debug logs

9. Add an AI provider (Mistral, OpenAI, or Fal.ai)

Prompt:

Integrate {{ai_provider}} (Mistral/OpenAI/Fal.ai) for {{use_case}}.

Integration details:
- Provider: {{ai_provider}}
- API Key env var: {{API_KEY_VAR}}
- Model: {{model_name}}
- Use case: {{use_case}} (e.g., "generate invoice summaries", "analyze images")
- Input: {{input_structure}}
- Expected output: {{output_structure}}
- Rate limit/quota: {{quota_info}}

Implementation:
1. Create AI client at src/lib/ai/{{provider_name}}-client.ts:
   - Initialize client with API key from env
   - Implement function for your use case (e.g., generateSummary())
   - Handle streaming if applicable (for longer responses)
   - Add timeout (e.g., 30s) and retry logic
   - Return typed response (TypeScript interface)
   - Log API usage (tokens, latency) for freemium quota tracking
2. Add to freemium quota system (if applicable):
   - Add {{ai_use_case}}PerMonth to src/lib/freemium/freemium-limits.ts
   - Call checkFreemiumLimit() in tRPC router before API call
   - Increment usage counter after successful API call
   - Reference: ./.claude/rules/freemium.md
3. Create tRPC procedure in src/server/api/routers/{{module_name}}.ts:
   - Input: {{input_fields}} (Zod validated)
   - Check freemium quota
   - Call AI client
   - Store result in DB (if needed)
   - Return typed response
4. Optional: Add to prompt context:
   - If multi-turn: maintain conversation history in DB
   - Store system prompt in config or database
5. Error handling:
   - Rate limit errors → suggest retry later
   - Invalid input → return BAD_REQUEST
   - API errors → log and return generic error (don't expose API details)
6. Tests:
   - Mock {{ai_provider}} API responses
   - Test quota enforcement
   - Test error scenarios

Use @src/lib/ai/ as reference for AI integration patterns (Mistral, OpenAI examples).

Context files: @src/lib/ai/ @src/env.js @src/lib/freemium/ ./.claude/rules/freemium.md

Expected result: A fully integrated AI feature with quota management and error handling.

Verify it works:

pnpm typecheck
pnpm dev
# Call the AI tRPC procedure
# Verify response returned and stored (if applicable)
# Check quota usage incremented
# Exceed quota → verify graceful error message

🔐 Auth & Security

10. Add a new user role to RBAC

Prompt:

Add a new role "{{role_name}}" (e.g., "FINANCE_MANAGER") to the RBAC system.

Role details:
- Role name: {{role_name}} (must be UPPERCASE)
- Permissions: {{permission_list}} (e.g., "facturation:read", "comptabilite:export_fec")
- Can manage: {{manages_resources}} (optional)
- Parent role hierarchy: {{inherits_from}} (optional, e.g., inherits from MANAGER)

Implementation:
1. Add role to Type union in src/lib/permissions/matrix.ts:
   - Add "{{role_name}}" to the Role type definition
2. Add to permissions matrix (same file):
   - Define permissions object for {{role_name}}
   - Assign array of permission strings
   - Follow naming pattern: "resource:action"
   - Reference existing permissions (don't create duplicates)
3. Update Prisma schema in prisma/schema.prisma:
   - If role determines field defaults, add migration
   - Example: "role: {{role_name}}" → read-only access to certain tables
4. Update role selection UI:
   - Verify src/app/dashboard/organization/members/page.tsx shows new role in dropdown
   - Ensure only ADMIN can assign this role
5. Create role seeding (if applicable):
   - Add to database seeders if using Prisma seed
6. Add tests in src/__tests__/security/:
   - Test that role has correct permissions
   - Test that role cannot access denied resources
   - Test role hierarchy if applicable

Follow RBAC matrix structure in @src/lib/permissions/matrix.ts — it's the source of truth.

Context files: @src/lib/permissions/matrix.ts @prisma/schema.prisma @src/__tests__/security/

Expected result: New role available in member management UI with correct permission restrictions.

Verify it works:

pnpm test:security
pnpm typecheck
pnpm dev
# Go to /dashboard/organization/members
# Verify new role appears in dropdown
# Assign role to test user
# Log in as that user → verify correct resources accessible
# Try accessing denied resource → verify 403 error

11. Add a granular permission to RBAC matrix

Prompt:

Add a new granular permission "{{permission_string}}" (e.g., "invoices:void").

Permission details:
- Permission string: {{permission_string}} (format: "resource:action")
- Description: {{description}}
- Which roles can use it: {{role_list}} (e.g., ADMIN, DIRECTION, MANAGER)
- Replaces/adds to: {{existing_permission}} (if refactoring)

Implementation:
1. Add permission string to Permission type union in @src/lib/permissions/matrix.ts:
   - Line 22, add: | "{{permission_string}}"
   - Keep alphabetical within resource group
2. Update role permission assignments (in same file):
   - For each role that should have this permission, add the string to their permissions array
3. Update tRPC router guard:
   - Find the tRPC procedure that needs this permission
   - Replace staffProcedure or other guards with: requirePermission("{{permission_string}}")
   - Example: export const {{procName}} = {{procedure}}.use(requirePermission("{{permission_string}}"))
4. Update permission checks:
   - If checking dynamically, use hasPermission(ctx.session, "{{permission_string}}")
5. Add to UI (role assignment dropdown):
   - Verify new permission shows in organization settings (if you have a permission UI)
   - Most projects manage this via matrix.ts only
6. Add test:
   - src/__tests__/security/rbac.test.ts → test role has permission

Reference: @src/lib/permissions/matrix.ts (source of truth), @src/server/api/trpc.ts (requirePermission helper).

Context files: @src/lib/permissions/matrix.ts @src/server/api/trpc.ts @src/__tests__/security/

Expected result: New permission enforced in tRPC routers, only accessible to authorized roles.

Verify it works:

pnpm test:security
pnpm typecheck
pnpm dev
# As authorized role, call protected procedure → succeeds
# As unauthorized role, call procedure → fails with FORBIDDEN
# Check procedure uses requirePermission() guard

12. Add an OAuth provider (GitHub, Google, etc.)

Prompt:

Add OAuth login via {{oauth_provider}} (e.g., GitHub, Google, Azure AD).

Provider details:
- Provider: {{oauth_provider}}
- Client ID: {{client_id_env_var}}
- Client Secret: {{client_secret_env_var}}
- Scopes: {{scopes}} (e.g., "user:email", "profile")
- Callback URL: https://{{domain}}/api/auth/callback/{{provider_slug}}

Implementation:
1. Set up provider credentials:
   - Go to {{provider}} developer console
   - Create OAuth app with callback URL above
   - Copy Client ID and Secret
   - Add to .env: {{CLIENT_ID_ENV_VAR}}={{id}}, {{CLIENT_SECRET_ENV_VAR}}={{secret}}
   - Add to .env.example (WITHOUT secret)
2. Update NextAuth config at src/app/api/auth/[...nextauth]/route.ts:
   - Import {{Provider}}Provider from next-auth/providers/{{provider_slug}}
   - Add to providers array:
     {{Provider}}Provider({
       clientId: env.{{CLIENT_ID_ENV_VAR}},
       clientSecret: env.{{CLIENT_SECRET_ENV_VAR}},
       allowDangerousEmailAccountLinking: false,
     })
3. Add env vars to src/env.js:
   - {{CLIENT_ID_ENV_VAR}}: z.string(),
   - {{CLIENT_SECRET_ENV_VAR}}: z.string(),
4. Test OAuth flow:
   - Run pnpm dev
   - Go to /api/auth/signin
   - Click "{{OAuth Provider}}"
   - Authorize app
   - Verify redirected to dashboard
5. Handle new users:
   - Existing logic in NextAuth callbacks should auto-create user
   - Verify user.organizationId is set (may need custom callback)
6. Security:
   - Store secrets in env (never commit)
   - Use secure callback validation
   - Validate tokens from provider

Reference: src/app/api/auth/[...nextauth]/route.ts for existing OAuth examples.

Context files: @src/app/api/auth/[...nextauth]/route.ts @src/env.js .env.example

Expected result: OAuth login working with automatic user provisioning.

Verify it works:

pnpm dev
# Go to /api/auth/signin
# Click {{OAuth Provider}}
# Authorize and verify logged in
# Check user created in database
# Log out and log back in → verify existing user found

🎨 UI & Design

13. Customize the design system (theming)

Prompt:

Customize the HeartCo design system colors, fonts, and tokens.

Customizations:
- Brand color: {{hex_color}} (e.g., #6366f1)
- Accent color: {{accent_color}}
- Font family (headings): {{heading_font}} (e.g., "Plus Jakarta Sans")
- Font family (body): {{body_font}} (e.g., "Geist")
- Dark mode: enabled/disabled
- Additional tokens: {{custom_tokens}}

Implementation:
1. Update Tailwind config at tailwind.config.ts:
   - colors.brand: update to {{brand_color}}
   - colors.accent: update to {{accent_color}}
   - fonts: update heading and body fonts
   - Add custom color tokens if needed
2. Update CSS variables in src/styles/globals.css:
   - --color-brand: {{hex_color}}
   - --color-accent: {{accent_color}}
   - --color-dark: {{dark_bg}}
   - --color-light: {{light_bg}}
3. Update shadcn/ui theme (if using dark mode toggle):
   - src/components/ui/theme-provider.tsx
   - Adjust default scheme (light/dark/system)
4. Update marketing design tokens:
   - Reference: @./.claude/rules/design.md
   - Ensure no hardcoded colors in components
   - Use token-based colors: bg-brand, text-brand, etc.
5. Test theme across pages:
   - Dashboard pages
   - Landing page sections
   - Dark mode toggle
   - Mobile responsiveness
6. Commit changes:
   - Update tailwind.config.ts
   - Update globals.css
   - Commit as: chore: customize design system colors

Run:
- pnpm lint:fix (Tailwind class linting)
- pnpm format:write

Context files: @tailwind.config.ts @src/styles/globals.css @./.claude/rules/design.md

Expected result: Consistent theming across the entire app with updated brand colors.

Verify it works:

pnpm dev
# Check /dashboard and / pages for new colors
# Toggle dark mode → verify both themes use new colors
# No hardcoded colors should appear (use tokens)
# Mobile view → verify responsive

14. Create a reusable component library

Prompt:

Create a reusable component {{component_name}} at src/components/{{component_name}}.tsx.

Component details:
- Name: {{component_name}} (e.g., "CardWithBadge")
- Props: {{prop_list}} (e.g., "title: string, badge: string, onClick?: () => void")
- Variants: {{variants}} (e.g., "primary, secondary, outline")
- Use case: {{use_case}}
- Where it's used: {{usage_locations}} (current/future)

Implementation:
1. Create component file at src/components/{{component_name}}.tsx:
   - Accept props as TypeScript interface
   - Use forwardRef if component should accept ref
   - Implement multiple variants with cn() utility
   - Add JSDoc comments (explain props and variants)
2. Styling:
   - Use Tailwind classes (cn() for merging)
   - Support dark mode (use color tokens, not hardcoded)
   - Add hover/active/focus states
   - Responsive design if applicable
3. Accessibility:
   - Proper semantic HTML (button, div, section, etc.)
   - ARIA labels where needed
   - Keyboard navigation if interactive
   - Focus visible states
4. Documentation:
   - JSDoc on component and props
   - Example usage comment
5. Export:
   - Add export to src/components/index.ts (if centralized)
   - Or export directly from the file
6. Create story (optional, if using Storybook):
   - src/components/{{component_name}}.stories.tsx
   - Show all variants
   - Show with different content

Reference shadcn/ui components for patterns: @src/components/ui/

Context files: @src/components/ui/ @src/lib/utils.ts @./.claude/rules/design.md

Expected result: A well-documented, reusable component with multiple variants.

Verify it works:

pnpm typecheck
# Import and use {{component_name}} in a test page
pnpm dev
# Verify component renders correctly
# Test all variants
# Test dark mode
# Test responsive design on mobile

🚀 DevOps & Deployment

15. Deploy to production (Vercel + Supabase)

Prompt:

Set up production deployment for HeartCo on Vercel with Supabase PostgreSQL.

Prerequisites:
- Vercel account created
- Supabase project created
- GitHub repo connected to Vercel

Steps:
1. Supabase setup:
   - Create PostgreSQL project in Supabase
   - Copy DATABASE_URL (environment variable)
   - Run migrations: npx prisma migrate deploy
   - Create backups in Supabase dashboard
2. Vercel environment variables:
   - Set all .env variables in Vercel project settings:
     - DATABASE_URL (from Supabase)
     - NEXTAUTH_SECRET (generate: openssl rand -base64 32)
     - NEXTAUTH_URL (https://yourdomain.com)
     - OAuth provider secrets (GitHub, Google, etc.)
     - Stripe keys, Pusher keys, Mistral API keys
     - All variables from .env.example
   - Do NOT commit .env to git
3. Prisma migrations:
   - Ensure all migrations committed to git
   - Vercel runs "pnpm install && pnpm build" automatically
   - Build script should include: npx prisma generate && npx prisma migrate deploy
   - Verify next.config.js has prisma build step (if needed)
4. Database backups:
   - Enable automated daily backups in Supabase
   - Store backup credentials securely
5. Monitoring:
   - Set up error logging (Sentry recommended)
   - Monitor Vercel logs in dashboard
   - Set up database query monitoring in Supabase
6. Custom domain:
   - Point DNS to Vercel
   - Set CNAME in Vercel project settings
   - Update NEXTAUTH_URL and OAuth callback URLs
7. SSL/TLS:
   - Vercel auto-enables HTTPS
   - Monitor SSL certificate status
8. Verify deployment:
   - Trigger deploy from git push
   - Check Vercel build logs (no errors)
   - Open live app and test key features
   - Verify database writes persisted

Use environment variable checklists from .env.example.

Context files: .env.example @next.config.js @prisma/schema.prisma @package.json

Expected result: App live on Vercel with auto-deployment on git push.

Verify it works:

# Push to main branch
# Check Vercel dashboard → build completes
# Visit live URL → verify all features work
# Check database → new data persists
# Monitor Vercel logs → no errors

16. Add tests for a module (Vitest + Testing Library)

Prompt:

Create comprehensive tests for {{module_name}} module.

Test scope:
- Unit tests for router procedures (CRUD)
- Security tests (IDOR, permission checks)
- Integration tests (DB interactions)
- Optional: E2E tests with Playwright

Implementation:
1. Create test file at src/server/api/routers/__tests__/{{module_name}}.test.ts:
   - Use Vitest (describe, it, expect)
   - Mock Prisma client
   - Mock tRPC context (user, session, permissions)
2. Test structure:
   describe("{{module_name}} router", () => {
     describe("create", () => {
       it("should create item with valid input", async () => { ... })
       it("should reject invalid input", async () => { ... })
       it("should enforce organizationId isolation", async () => { ... })
     })
     describe("read/list", () => {
       it("should return items filtered by organizationId", async () => { ... })
       it("should paginate results", async () => { ... })
     })
     describe("update", () => {
       it("should update own item", async () => { ... })
       it("should reject update to other org items (IDOR)", async () => { ... })
     })
     describe("delete", () => {
       it("should delete item with permission", async () => { ... })
       it("should reject delete without permission", async () => { ... })
     })
   })
3. Security test cases:
   - IDOR: Try to read/edit/delete item from different organization → expect NOT_FOUND
   - Permissions: Try procedure without required permission → expect FORBIDDEN
   - RBAC: Different roles should have different access
   - Input validation: Invalid Zod input → expect BAD_REQUEST
4. Mock patterns:
   - vi.mock("~/server/db") for Prisma
   - createMockContext() helper for tRPC context
   - Use faker.js for fake data
5. Database mocking:
   - Never use real database in tests
   - Mock Prisma methods with vi.spyOn()
   - Return mock data from spies
6. Run tests:
   - pnpm test -- {{module_name}}
   - Check coverage: pnpm test -- --coverage
7. E2E (optional):
   - Create e2e/{{module_name}}.spec.ts with Playwright
   - Test full user flow (create form → submit → verify in list)

Reference: @src/server/api/routers/__tests__/ for existing test patterns.

Context files: @src/server/api/routers/__tests__/ @src/lib/test-utils.ts (if exists) @./.claude/rules/testing.md

Expected result: Comprehensive test suite with unit, security, and E2E tests.

Verify it works:

pnpm test -- {{module_name}}
# All tests pass
# All module tests pass
pnpm test:security
# Security tests pass (IDOR, permission checks)

17. Debug a tRPC error (diagnostic guide)

Prompt:

I'm getting an error with tRPC procedure {{procedure_name}}.

Error details:
- Error message: {{error_message}}
- Procedure: {{procedure_path}} (e.g., "api.invoices.list")
- Context: {{context}} (what triggers the error)
- Stack trace: {{stack_trace}} (if available)

Diagnostic steps:
1. Check tRPC procedure exists:
   - Verify src/server/api/routers/{{router}}.ts has export const {{procName}}
   - Verify registered in src/server/api/root.ts: {{routerName}}: {{routerName}}Router
   - Restart dev server if procedure just added
2. Check input validation:
   - Verify Zod schema matches expected input
   - Use Zod .parse() in tests to debug validation errors
   - Check frontend sends correct input format (client-side console.log the input)
3. Check context and permissions:
   - If error is UNAUTHORIZED → verify user logged in (check NextAuth session)
   - If error is FORBIDDEN → verify user has permission (check RBAC matrix)
   - If error is NOT_FOUND → verify organizationId filtering correct
4. Check database queries:
   - Add console.log(input) inside procedure for debugging
   - Verify Prisma query is correct (check prisma/schema.prisma)
   - If multi-tenant: verify organizationId in WHERE clause
   - Use findFirst (never findUnique for org-scoped resources)
5. Check error response format:
   - tRPC errors should be TRPCError (not Error)
   - Error codes: "UNAUTHORIZED" | "FORBIDDEN" | "NOT_FOUND" | "BAD_REQUEST" | etc.
   - Don't expose sensitive data in error messages
6. Check frontend error handling:
   - Verify mutation/query has .useQuery()/.useMutation()
   - Check error object: error.data.code and error.data.message
   - Log error in browser console for details
7. Check logs:
   - Run pnpm dev → check terminal for server-side logs
   - Check browser console (F12) for client-side errors
   - Add console.log() at each step to trace execution
8. Restart and rebuild:
   - Kill dev server
   - Delete .next and generated/prisma/
   - Run pnpm install
   - Run pnpm prisma generate
   - Run pnpm dev

If still stuck:
- Share full stack trace
- Share tRPC error code (UNAUTHORIZED, FORBIDDEN, etc.)
- Share the procedure code (redact secrets)
- Share frontend code that calls procedure

Context files: @src/server/api/routers/ (the relevant router) @src/server/api/trpc.ts @src/lib/permissions/matrix.ts

Expected result: Error diagnosed and fixed with root cause identified.

Verify it works:

pnpm dev
# Trigger the procedure again
# Verify it succeeds without error
# Check browser/server logs are clean
# If persists, check error code and trace from step above

💡 Pro Tips

  • Always reference @CLAUDE.md at the start of your session — it contains your project's exact conventions
  • Use @src/lib/permissions/matrix.ts when working on auth/security features — it's the source of truth
  • Use @src/modules/_template/ as your starting point for any new module — saves 30 min
  • Run pnpm typecheck after every AI-generated change — catches type errors early
  • Keep commits atomic: one feature = one commit — makes git history clean and reviewable
  • When in doubt about multi-tenant isolation, add organizationId to the WHERE clause — better safe than sorry
  • Test IDOR vulnerabilities by trying to access/edit resources from a different organization — critical security
  • Use the freemium quota system before calling expensive APIs — prevents runaway costs
  • Dark mode is mandatory — use CSS tokens, never hardcoded colors
  • Use ctx.orgDb for reads (auto-filters organizationId), but add organizationId manually for writes

🎯 Workflow Checklist

After pasting a prompt and AI generates code:

  1. Typecheck: pnpm typecheck — must pass
  2. Tests: pnpm test — no new failures
  3. Lint: pnpm lint:fix && pnpm format:write
  4. Commit: git add -A && git commit -m "type: message"
  5. Dev: pnpm dev → verify feature works in browser

If Prisma schema was modified:

  • npx prisma generatenpx prisma migrate dev --name <descriptive>

That's it. You're shipping.


Good luck, vibecoder. Ship fast, break nothing. 🚀