Una plantilla robusta y moderna para proyectos empresariales con Next.js 14, TypeScript, autenticación completa y componentes UI profesionales.
- Características
- Requisitos Previos
- Instalación
- Scripts Disponibles
- Estructura del Proyecto
- Tecnologías Utilizadas
- Seguridad
- Solución de Problemas
- ✅ Sistema de login con NextAuth.js
- ✅ Autenticación con credenciales (email/password)
- ✅ Hashing de contraseñas con bcryptjs
- ✅ Protección de rutas con middleware
- ✅ Rate limiting para prevenir ataques de fuerza bruta
- ✅ Bloqueo temporal de cuenta tras intentos fallidos
- ✅ Sistema de logout con limpieza de sesión
- ✅ Seed automático con usuario administrador
- ✅ Sistema de pruebas de seguridad integrado (desarrollo)
- ✅ Componentes de shadcn/ui
- ✅ Dashboard profesional con sidebar colapsable
- ✅ Tema claro/oscuro
- ✅ Diseño totalmente responsive
- ✅ Animaciones y transiciones suaves
- ✅ Iconos con Lucide React
- ✅ PostgreSQL con Prisma ORM
- ✅ Migraciones automáticas
- ✅ Modelo de usuarios con roles
- ✅ Seed automático para datos iniciales
Antes de comenzar, asegúrate de tener instalado:
git clone [URL-DE-TU-REPOSITORIO]
cd [NOMBRE-DEL-PROYECTO]npm installCrear el archivo .env en la raíz del proyecto con el siguiente contenido:
# Conexión Base de Datos - Supabase + PostgreSQL
# Reemplazar [DATABASE-PASSWORD] y [DATABASE-NAME] con los valores reales de tu proyecto Supabase
DATABASE_URL="postgresql://postgres:[DATABASE-PASSWORD]@db.[DATABASE-NAME].supabase.co:5432/postgres"
# Configuración de NextJS
NEXTAUTH_URL="http://localhost:3000" # Cambiar a la URL de producción en despliegue
NEXTAUTH_SECRET="GENERATED-SECRET-HERE" # Generar con `openssl rand -base64 32`
# Variables de Seguridad
SECURITY_RATE_LIMIT_ENABLED=true # Habilitar limitación de tasa
SECURITY_HEADERS_ENABLED=true # Habilitar headers de seguridad
# Usuario Admin
ADMIN_EMAIL=admin@basetemplate.com # Cambiar email por defecto en producción
ADMIN_PASSWORD=Admin123 # Cambiar password por defecto en producciónSi usas Supabase, utiliza la URL de Connection Pooling o Transaction Pooler para mejor rendimiento:
# En Vercel usar Transaction Pooler (puerto 6543) o el puerto asignado de Supabase
DATABASE_URL="postgresql://postgres.[tu-proyecto]:[password]@aws-[region].pooler.supabase.com:6543/postgres?pgbouncer=true"En Terminal Git Bash:
openssl rand -base64 32
⚠️ Importante: Copia el resultado y pégalo enNEXTAUTH_SECRETen tu archivo.env.local
# Crear las tablas en la base de datos
npx prisma migrate dev --name init
# Generar el cliente de Prisma
npx prisma generate# Solo generar el cliente de Prisma
npx prisma generate
# Sincronizar el esquema si es necesario
npx prisma db pushEl proyecto ya incluye un archivo prisma/admin-user/seed.js con un usuario administrador predefinido:
# Ejecutar el seed
npm run seed✅ Esto creará automáticamente:
- Email:
admin@example.com - Contraseña:
admin123 - Rol: ADMIN
💡 Nota: El seed usa
upsert, por lo que si el usuario ya existe, no lo duplicará.
npx prisma studio- Abre automáticamente en
http://localhost:5555 - Verifica que el usuario admin esté creado en la tabla
User
npm run dev- Abre
http://localhost:3000 - Prueba el login con las credenciales del admin
| Comando | Descripción |
|---|---|
npm run dev |
Iniciar servidor de desarrollo |
npm run build |
Compilar para producción |
npm run start |
Iniciar servidor de producción |
npm run lint |
Ejecutar linter |
npm run seed |
Ejecutar seed (crear usuario admin) |
npx prisma studio |
Abrir GUI de base de datos |
npx prisma migrate dev |
Crear/aplicar migraciones |
npx prisma generate |
Regenerar cliente Prisma |
basetemplate/
├── .env.example
├── .gitignore
├── README.md
├── components.json
├── eslint.config.mjs
├── next.config.ts
├── package-lock.json
├── package.json
├── postcss.config.mjs
├── prisma/
│ ├── admin-user/
│ │ └── seed.js
│ ├── migrations/
│ │ └── 20250908041523_init/
│ └── schema.prisma
├── public/
│ ├── avatars/
│ │ └── shadcn.jpg
│ ├── file.svg
│ ├── globe.svg
│ ├── next.svg
│ ├── vercel.svg
│ └── window.svg
├── src/
│ ├── app/
│ │ ├── api/
│ │ │ ├── auth/
│ │ │ │ └── [...nextauth]/
│ │ │ │ └── route.ts
│ │ │ ├── clear-rate-limit/
│ │ │ │ └── route.ts
│ │ │ ├── test-db/
│ │ │ │ └── route.ts
│ │ │ ├── test-rate-limit/
│ │ │ │ └── route.ts
│ │ │ └── test-roles/
│ │ │ └── route.ts
│ │ ├── auth/
│ │ │ └── login/
│ │ │ └── page.tsx
│ │ ├── dashboard/
│ │ │ └── page.tsx
│ │ ├── favicon.ico
│ │ ├── globals.css
│ │ ├── layout.tsx
│ │ ├── page.tsx
│ │ └── test-security/
│ │ └── page.tsx
│ ├── components/
│ │ ├── blocks/
│ │ │ ├── app-loader.tsx
│ │ │ ├── app-sidebar.tsx
│ │ │ ├── login-form.tsx
│ │ │ ├── nav-main.tsx
│ │ │ ├── nav-projects.tsx
│ │ │ ├── nav-user.tsx
│ │ │ ├── security-test-sidebar.tsx
│ │ │ ├── session-wrapper.tsx
│ │ │ └── team-switcher.tsx
│ │ └── ui/
│ │ ├── alert-dialog.tsx
│ │ ├── alert.tsx
│ │ ├── avatar.tsx
│ │ ├── badge.tsx
│ │ ├── breadcrumb.tsx
│ │ ├── button.tsx
│ │ ├── calendar.tsx
│ │ ├── card.tsx
│ │ ├── checkbox.tsx
│ │ ├── collapsible.tsx
│ │ ├── command.tsx
│ │ ├── dialog.tsx
│ │ ├── dropdown-menu.tsx
│ │ ├── form.tsx
│ │ ├── input.tsx
│ │ ├── label.tsx
│ │ ├── popover.tsx
│ │ ├── radio-group.tsx
│ │ ├── select.tsx
│ │ ├── separator.tsx
│ │ ├── sheet.tsx
│ │ ├── sidebar.tsx
│ │ ├── skeleton.tsx
│ │ ├── switch.tsx
│ │ ├── table.tsx
│ │ ├── tabs.tsx
│ │ ├── textarea.tsx
│ │ └── tooltip.tsx
│ ├── config/
│ │ └── app.ts
│ ├── hooks/
│ │ └── use-mobile.ts
│ ├── lib/
│ │ ├── auth.ts
│ │ ├── csrf-protection.ts
│ │ ├── prisma.ts
│ │ ├── rate-limiter.ts
│ │ ├── role-validator.ts
│ │ └── utils.ts
│ └── middleware.ts
└── tsconfig.json
- Next.js 14 - Framework React con App Router
- TypeScript - Type safety
- NextAuth.js - Autenticación
- Prisma - ORM para PostgreSQL
- PostgreSQL - Base de datos
- shadcn/ui - Componentes UI
- Tailwind CSS - Estilos
- Lucide React - Iconos
- ✅ Rate Limiting: 5 intentos por IP cada 15 minutos
- ✅ Bloqueo de cuenta: 3 minutos tras 5 intentos fallidos
- ✅ Hashing seguro: bcrypt con salt rounds configurables
- ✅ Validación de entrada: Zod schemas en todas las entradas
- ✅ CSRF Protection: Integrado con NextAuth
- ✅ Secure Cookies: httpOnly, secure, sameSite
- ✅ Middleware de autenticación: Protección de rutas
- Verifica que el archivo
.env.localesté creado en la raíz del proyecto - Asegúrate de que la variable
DATABASE_URLesté correctamente configurada
- Verifica que la base de datos esté activa y accesible
- Confirma que la URL de conexión sea correcta
- Ejecuta
npm run seedpara crear el usuario admin - Verifica en Prisma Studio que el usuario exista
- Genera un nuevo secret siguiendo el paso 3
- Reinicia el servidor de desarrollo después de cambiar el
.env.local
# Limpiar caché y reinstalar
rm -rf node_modules .next
npm install- Dado caso de haber eliminado un user/data desde Supabase
# Borra los usuarios
DELETE FROM "User";
# Reinicia la secuencia de la columna id
ALTER SEQUENCE "User_id_seq" RESTART WITH 1;
# Ejecuta el seed del admin-user
npm run seed- Nunca subas el archivo
.env.locala GitHub - El archivo
prisma/seed.jsya está incluido en el repositorio - Cambia la contraseña del admin en producción
- Para ambientes de producción, usa variables de entorno seguras
- Asegúrate de configurar CORS y headers de seguridad en producción
- Conecta tu repositorio con Vercel
- Configura las variables de entorno en el panel de Vercel
- Deploy automático con cada push a main
En el panel de Vercel (Settings → Environment Variables), configura:
| Variable | Valor | Notas |
|---|---|---|
DATABASE_URL |
postgresql://...pooler.supabase.com:6543/... |
Usar Connection Pooling (puerto 6543 o asignado) |
NEXTAUTH_URL |
https://tu-app.vercel.app |
Sin trailing slash (dominio asignado por Vercel) |
NEXTAUTH_SECRET |
[tu-secret-generado] |
Mismo que usas localmente (Generado en GitBash) |
Importante para Supabase:
- Usa la URL de Transaction Pooler (puerto 6543 o asignado) no la conexión directa
- Agrega
?pgbouncer=trueal final de la URL - Encuentra esta URL en: Supabase Dashboard → Settings → Database → Connection Pooling
MIT
Las contribuciones son bienvenidas. Por favor:
- Fork el proyecto
- Crea tu feature branch (
git checkout -b feature/AmazingFeature) - Commit tus cambios (
git commit -m 'Add some AmazingFeature') - Push a la branch (
git push origin feature/AmazingFeature) - Abre un Pull Request
Desarrollado por M1gu3l4ngel con ❤️ usando Next.js y shadcn/ui