{
  "id": "nextjs-saas-starter",
  "type": "context-packs",
  "category": "context",
  "locale": "es",
  "url": "/es/context/nextjs-saas-starter",
  "title": "Next.js SaaS Starter — Paquete de contexto",
  "description": "Paquete de contexto copiable para una aplicación SaaS de Next.js con App Router, Better Auth, facturación de Stripe y Postgres para que tu agente de IA funcione correctamente desde el primer mensaje.",
  "tools": [
    "Cursor",
    "Claude Code",
    "Codex",
    "Windsurf"
  ],
  "stack": [
    "Next.js",
    "PostgreSQL",
    "TypeScript",
    "Tailwind"
  ],
  "tags": [
    "nextjs",
    "saas",
    "postgres",
    "auth",
    "context-pack",
    "typescript"
  ],
  "difficulty": null,
  "updated": "2026-06-08",
  "markdown": "Pega esto al inicio de una nueva tarea para que el agente entienda la estructura, convenciones y límites del proyecto SaaS antes de escribir una sola línea de código.\n\n## Antecedentes del proyecto\n\n```txt\nA multi-tenant SaaS application built with Next.js 15 App Router.\nAuthentication is handled by Better Auth with email/password and OAuth providers.\nBilling uses Stripe Checkout + webhooks. All persistent data lives in PostgreSQL\naccessed via Drizzle ORM. The app is deployed to Vercel with a Neon Postgres\ndatabase.\n```\n\n## Stack\n\n```txt\nNext.js 15 (App Router, React Server Components)\nTypeScript (strict mode, no implicit any)\nTailwind CSS v4\nBetter Auth v1 (session cookies, OAuth: Google + GitHub)\nDrizzle ORM + drizzle-kit migrations\nNeon PostgreSQL (serverless driver @neondatabase/serverless)\nStripe (Checkout sessions, Customer Portal, webhooks)\nResend for transactional email\nZod for all input validation\n```\n\n## Estructura de directorios\n\n```txt\nsrc/\n  app/                    # App Router — every folder is a route segment\n    (auth)/               # Sign-in / sign-up pages (unauthenticated layout)\n    (dashboard)/          # Protected routes (authenticated layout)\n      billing/\n      settings/\n    api/\n      auth/[...all]/      # Better Auth catch-all handler\n      webhooks/stripe/    # Stripe webhook endpoint\n  components/\n    ui/                   # shadcn/ui primitives (do not edit generated files)\n    app/                  # Application-level components\n  lib/\n    auth.ts               # Better Auth server instance + config\n    auth-client.ts        # Better Auth browser client\n    db/\n      schema.ts           # Drizzle table definitions (single source of truth)\n      index.ts            # db client (Neon serverless)\n    stripe.ts             # Stripe SDK singleton\n    validations/          # Zod schemas, one file per domain\n  middleware.ts           # Auth session check + route protection\ndrizzle/\n  migrations/             # Auto-generated SQL — never hand-edit\ndrizzle.config.ts\n```\n\n## Convenciones de código\n\n```txt\n- Server Components by default. Add \"use client\" only when you need browser\n  APIs, event handlers, or React hooks.\n- Data fetching happens in Server Components or Route Handlers — never\n  fetch from a Client Component via useEffect.\n- Database access only inside lib/db or server actions; never import the db\n  client into a Client Component.\n- All user input is validated with Zod before hitting the database.\n- Drizzle schema changes require a migration: `npx drizzle-kit generate` then\n  `npx drizzle-kit migrate`. Never hand-edit files in drizzle/migrations/.\n- API routes live under app/api/ and export named HTTP-method handlers\n  (GET, POST, etc.). Use NextResponse.json() for responses.\n- Environment variables accessed via process.env must also be declared in\n  .env.example (no secrets in that file).\n- Stripe amounts are always in the smallest currency unit (cents).\n```\n\n## Límites de las tareas de IA\n\n```txt\n- Do not switch the ORM, auth library, or email provider without explicit\n  instruction.\n- Do not edit files under src/components/ui/ — they are shadcn/ui generated\n  and will be overwritten.\n- Do not hard-code secrets. Use process.env and add the key to .env.example.\n- Do not add a Pages Router file (pages/ directory). This is App Router only.\n- All schema changes must go through Drizzle migrations, not raw SQL ALTER.\n- Middleware (middleware.ts) must remain at the project root, not inside src/app.\n- Stripe webhook handler must verify the signature with\n  stripe.webhooks.constructEvent before processing any event.\n```\n\n## llms.txt\n\nEl repositorio expone un `/llms.txt` en la raíz del proyecto que enumera las convenciones clave y los propósitos de los archivos para que los agentes puedan orientarse sin leer cada archivo.\n\n```txt\n# Next.js SaaS Starter\nFramework: Next.js 15 App Router\nAuth: Better Auth (src/lib/auth.ts)\nDB: Drizzle ORM + Neon Postgres (src/lib/db/schema.ts)\nBilling: Stripe (src/lib/stripe.ts)\nEmail: Resend\nValidation: Zod (src/lib/validations/)\nProtected routes: everything under src/app/(dashboard)/\nPublic routes: src/app/(auth)/ and landing page\n```"
}