Dopplelganger logoDopplelganger
Comprar
Volver a la landing

Capitulos

Empezar

IntroduccionInstalacion local

Codebase

Estructura del proyecto

Configuracion

Variables de entornoBase de datos

Features

AutenticacionPagosEmailsInternacionalizacion

Producto

CustomizacionTesting

Produccion

DeployTroubleshooting

Documentacion

Dopplelganger para Next.js

Guia completa para instalar, configurar, customizar y publicar el boilerplate. Esta vista resume la documentacion que recibe el comprador dentro del repositorio.

Empezar

Introduccion

Dopplelganger es una base SaaS Next.js pensada para reemplazar la pantalla publica por tu producto y conservar infraestructura lista.

Que trae

El repositorio incluye una app funcional con autenticacion, dashboard protegido, billing, settings, emails, i18n, base de datos, tests y documentacion MDX.

La idea no es que uses la UI tal cual para siempre. La UI inicial existe para validar que la estructura funciona y para darte lugares claros donde reemplazar pantallas por tu producto real.

  • Landing reemplazable en app/[locale]/page.tsx.
  • Auth y dashboard separados por route groups.
  • Providers de pago aislados para Stripe y Lemon Squeezy.
  • Docs ES/EN incluidas para configurar y modificar el proyecto.

Cuando usarlo

Usalo cuando queres construir un SaaS con Next.js sin repetir setup de auth, pagos, emails e internacionalizacion.

No incluye multi-tenancy, analytics ni storage en v1. Eso mantiene la base mas simple y mas facil de adaptar.

Empezar

Instalacion local

El flujo local instala dependencias, crea el archivo de entorno, levanta PostgreSQL y genera Prisma Client.

Requisitos

Necesitas Node 22, pnpm 9 o superior y una base PostgreSQL. El repo trae docker-compose para levantar PostgreSQL local sin configurar un servicio externo.

  • Node.js >=22 <23
  • pnpm >=9
  • Docker o PostgreSQL propio

Comandos iniciales

Despues de comprar y acceder al repo, clona el proyecto, instala dependencias y crea tu .env desde el ejemplo.

git clone https://github.com/matills/doppelganger.git
cd doppelganger
pnpm install
cp .env.example .env
pnpm db:generate
pnpm run dev

Primer chequeo

Abri la app, crea una cuenta y confirma que podes entrar al dashboard. Si todavia no configuraste pagos, billing no debe romper: simplemente mostrara que no hay providers disponibles.

  • Crear cuenta en /es/register o /en/register.
  • Entrar al dashboard protegido.
  • Actualizar perfil desde settings.
  • Correr pnpm run typecheck antes de empezar cambios grandes.

Codebase

Estructura del proyecto

La app usa App Router, route groups para auth/dashboard y carpetas de dominio para auth, payments, billing, email y settings.

Mapa rapido

Las rutas publicas viven bajo app/[locale]. Auth y dashboard estan separados para que los layouts no se mezclen.

Ruta/carpetaResponsabilidad
app/[locale]/page.tsxLanding reemplazable
app/[locale]/(auth)Login, registro, reset password
app/[locale]/(dashboard)Dashboard, billing y settings protegidos
app/api/webhooksWebhooks de Stripe y Lemon Squeezy
lib/authServer actions, providers y validacion de auth
lib/paymentsInterfaz comun y providers de pago
lib/emailTemplates y envio de emails
messagesTraducciones ES/EN
docsDocumentacion MDX incluida

Patrones

La mayoria de paginas son Server Components. Las mutaciones importantes usan Server Actions. Las integraciones externas se activan por variables y degradan sin crashear cuando faltan.

  • Server Components por defecto.
  • Server Actions para auth, settings y checkout.
  • Provider pattern para pagos.
  • i18n con next-intl y rutas localizadas.

Configuracion

Variables de entorno

Las variables controlan que integraciones aparecen. El template evita mostrar providers que no esten configurados.

Core

Estas variables son la base para que la app arranque, genere URLs correctas y pueda conectarse a la base de datos.

VariableUsoRequerida
NEXT_PUBLIC_APP_URLURL publica para callbacks, emails y sitemapSi
AUTH_SECRETFirma de sesiones y tokensSi
DATABASE_URLConexion principal PrismaSi
DIRECT_URLConexion directa para migracionesSi

Integraciones opcionales

OAuth, pagos, emails y rate limiting pueden activarse por partes. Si no completas una familia de variables, esa feature se oculta o se salta en desarrollo.

FeatureVariables
OAuthGOOGLE_CLIENT_ID, GITHUB_CLIENT_ID, DISCORD_CLIENT_ID
StripeSTRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, STRIPE_*_PRICE_IDS
Lemon SqueezyLEMON_SQUEEZY_API_KEY, STORE_ID, WEBHOOK_SECRET, VARIANT_IDS
EmailRESEND_API_KEY, EMAIL_FROM
Rate limitUPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_TOKEN

Configuracion

Base de datos

Prisma modela usuarios, cuentas OAuth, sesiones, tokens, suscripciones y compras.

Modelos incluidos

El schema Prisma cubre los modelos necesarios para Auth.js y billing. Subscription y Purchase estan separados porque tienen ciclos de vida diferentes.

  • User, Account, Session y VerificationToken para auth.
  • Subscription para pagos recurrentes.
  • Purchase para pagos unicos.
  • Campos de provider para poder soportar Stripe y Lemon Squeezy.

Migraciones

En local podes usar migrate dev. Para demos rapidas tambien podes usar db push, pero para entregar un producto conviene versionar migraciones.

pnpm db:generate
pnpm db:migrate --name init
pnpm db:studio

Features

Autenticacion

Auth.js v5 con Prisma Adapter, credenciales, OAuth opcional y recuperacion de password.

Flujos incluidos

El comprador recibe pantallas de login, registro, forgot password y reset password. Los providers OAuth solo se muestran si existen variables configuradas.

  • Credentials con bcryptjs.
  • OAuth Google, GitHub y Discord opcionales.
  • Password reset con tokens en base de datos.
  • Proteccion de dashboard, billing y settings desde proxy.

Archivos clave

La configuracion principal vive en auth.ts. Las validaciones y acciones estan separadas para que puedas cambiar UI sin mezclar reglas de negocio.

ArchivoUso
auth.tsConfig de Auth.js y providers
lib/auth/actions.tsServer actions de login/register/reset
lib/auth/providers.tsDeteccion de OAuth configurado
components/auth/auth-card.tsxUI base de formularios

Features

Pagos

Stripe y Lemon Squeezy implementan una interfaz comun para checkout, portal, webhooks y catalogo.

Como decide que mostrar

Billing lee los providers disponibles por variables. Si Stripe no esta configurado, no muestra productos Stripe. Lo mismo aplica para Lemon Squeezy.

  • Suscripciones y pagos unicos se agrupan por seccion.
  • El guard evita compras duplicadas si ya hay acceso activo.
  • Los webhooks sincronizan status, renovacion y acceso.

Lemon Squeezy

Para usar Lemon Squeezy crea un store, producto, variantes y webhook. Luego completa API key, store ID, webhook secret y variant IDs.

LEMON_SQUEEZY_API_KEY=
LEMON_SQUEEZY_STORE_ID=
LEMON_SQUEEZY_WEBHOOK_SECRET=
LEMON_SQUEEZY_PAYMENT_VARIANT_IDS=345678

Stripe

Para Stripe crea productos y price IDs, configura webhook secret y agrega los price IDs segun sean suscripciones o pagos unicos.

STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_SUBSCRIPTION_PRICE_IDS=price_abc123
STRIPE_PAYMENT_PRICE_IDS=price_def456

Features

Emails

Templates con React Email y envio con Resend cuando RESEND_API_KEY esta configurada.

Comportamiento

En desarrollo o sin API key, el envio se salta de forma segura. Esto evita errores por no tener proveedor de email el primer dia.

  • Welcome email como template base.
  • Password reset con URL generada desde NEXT_PUBLIC_APP_URL.
  • Templates en lib/email/templates.tsx.

Features

Internacionalizacion

La app incluye rutas localizadas, mensajes separados y selector de idioma.

Estructura

Los locales disponibles estan en i18n/config.ts y los mensajes en messages/en.json y messages/es.json.

  • Locale por defecto: es.
  • Rutas bajo /es y /en.
  • Metadata localizada desde app/[locale]/layout.tsx.

Producto

Customizacion

Los primeros cambios deberian enfocarse en marca, landing, copy, modelos propios y pantallas de producto.

Que cambiar primero

El template esta pensado para que reemplaces lo publico y conserves lo funcional. No arranques refactorizando auth o billing si todavia no definiste el producto.

  • Reemplaza app/[locale]/page.tsx por tu landing.
  • Actualiza app/layout.tsx con metadata real.
  • Cambia messages/en.json y messages/es.json.
  • Agrega modelos propios en prisma/schema.prisma.
  • Crea rutas protegidas dentro de app/[locale]/(dashboard).

Agregar una pagina protegida

Las rutas dentro del grupo dashboard heredan sidebar, topbar y proteccion de sesion.

app/[locale]/(dashboard)/projects/page.tsx
components/dashboard/sidebar.tsx
messages/es.json
messages/en.json

Producto

Testing

Vitest cubre helpers, validaciones, providers, emails, payments y rutas criticas.

Comandos

Antes de publicar o tocar integraciones, corre typecheck, tests y build.

pnpm run typecheck
pnpm run test
pnpm run build

Patron de tests

Las rutas API y Server Actions se testean importando handlers y mockeando dependencias externas.

  • vi.hoisted para mocks compartidos.
  • Testing Library para componentes interactivos.
  • jsdom configurado para tests de React.

Produccion

Deploy

El deploy requiere variables completas, base productiva, webhooks publicos y dominio final.

Checklist

La mayor fuente de errores en produccion son URLs publicas y webhook secrets mal configurados.

  • Setear NEXT_PUBLIC_APP_URL con el dominio real.
  • Cargar DATABASE_URL y DIRECT_URL del proveedor productivo.
  • Registrar webhooks de Stripe o Lemon Squeezy contra /api/webhooks.
  • Verificar EMAIL_FROM con dominio validado en Resend.
  • Correr build en el mismo entorno donde vas a publicar.

Produccion

Troubleshooting

Errores comunes y donde mirar cuando algo no aparece o no sincroniza.

Providers no aparecen

Si OAuth o pagos no aparecen, casi siempre falta una variable de entorno o el servidor sigue usando variables viejas.

  • Reinicia el dev server despues de cambiar .env.
  • Confirma que los IDs no tengan espacios o comillas extra.
  • Revisa logs del server para errores de provider.

Webhook no sincroniza

El webhook secret debe ser el secret del endpoint, no la API key del proveedor.

  • Comprueba que la URL publica coincide exactamente.
  • Selecciona los eventos documentados.
  • Usa Stripe CLI o ngrok para pruebas locales.

En esta pagina

IntroduccionInstalacion localEstructura del proyectoVariables de entornoBase de datosAutenticacionPagosEmailsInternacionalizacionCustomizacionTestingDeployTroubleshooting