Copy this file into the root of your project as AGENTS.md.
AGENTS.md
Project
A multi-tenant SaaS built on Next.js 15 (App Router) with Supabase for auth, database, and storage. Stripe handles subscriptions. shadcn/ui + Tailwind for the UI layer.
Commands
pnpm install— install dependenciespnpm dev— start dev server on http://localhost:3000pnpm build— production buildpnpm typecheck—tsc --noEmitpnpm lint— ESLintpnpm test— Vitest unit testspnpm e2e— Playwright end-to-end testspnpm db:push— push schema changes to Supabasepnpm db:types— regenerate TypeScript types from Supabase
After making a change, always run pnpm typecheck and pnpm lint. Do not commit if either fails.
Code style
- TypeScript strict mode. No
any— useunknownif the type is truly unknown. - Server Components by default. Add
"use client"only when you need state, effects, or browser APIs. - Prefer Server Actions for mutations over API routes.
- Use the
cn()helper fromsrc/lib/utils.tsfor conditional classnames. - Tailwind only. No CSS modules. No styled-components. Component variants via
class-variance-authority. - File names: kebab-case for utilities, PascalCase for components.
- Imports: use
@/alias for absolute imports.
Stack rules
Supabase
- All tables use Row Level Security (RLS). Every new table needs an RLS policy.
- Never bypass RLS with the service role key from the client.
- Use the typed client from
src/lib/supabase/server.ts(server) orsrc/lib/supabase/client.ts(client). - Schema lives in
supabase/migrations/. Usepnpm db:pushafter edits. - After schema changes run
pnpm db:typesto update TypeScript types.
Stripe
- Subscription state is mirrored to a
subscriptionstable via webhook (/api/webhooks/stripe). - Never trust
session.subscriptionfrom the client — always re-read from Stripe in webhook handlers. - Use idempotency keys for write operations.
Auth
- Auth happens via Supabase Auth helpers. Sessions are set in middleware.
- Server Components must use
createServerClient()and pass cookies. - Protected routes go under
app/(protected)/with a layout that redirects unauthenticated users.
Before editing
- Read the relevant migration in
supabase/migrations/to understand the schema. - Check existing patterns in
src/lib/andsrc/components/. - If adding a new dependency, check
package.jsonfor an existing alternative first. - For UI changes, look at
src/components/ui/(shadcn) before creating a new primitive.
Constraints
- Do not introduce new state management libraries. Use React state, URL state, or Server Actions.
- Do not add a backend service. Everything goes through Supabase or Next.js Server Actions.
- Avoid
useEffectfor data fetching — use Server Components or Server Actions instead. - Don't write tests for trivial getters/setters. Focus on business logic and integration paths.
- Do not commit
.env.local. Use.env.exampleto document new env vars.