Plataforma colaborativa futurista de la organización DevLabs: documentos estilo Notion, proyectos y tareas estilo ClickUp, todo con una estética cyberpunk/sci-fi y acceso restringido por whitelist de GitHub.
| Capa | Tecnología |
|---|---|
| Framework | Next.js 15 (App Router + TypeScript) |
| Estilos | Tailwind CSS, Shadcn UI (prefijos ui), Lucide Icons, Framer Motion |
| Autenticación | NextAuth.js (Auth.js) — GitHub OAuth |
| Base de datos | PostgreSQL (Supabase / Neon) + Prisma ORM |
| Editor | Tiptap (bloques, slash-commands, tablas, código, callouts, tasks) |
| Kanban | dnd-kit (drag & drop) |
| Hosting | Vercel (Serverless Functions) |
Nota sobre el editor: originalmente se evaluó BlockNote, pero tiene fricciones conocidas con bundlers modernos (imports internos de ProseMirror como
__serializeForClipboard). Como BlockNote está construido sobre Tiptap, se implementó el editor directamente con Tiptap (opción explícitamente permitida en los requerimientos), lo que da la misma experiencia "slash-command" con mucha mayor estabilidad.
devpulse/
├── app/
│ ├── (dashboard)/ # Zona autenticada con sidebar
│ │ ├── layout.tsx # Layout con sidebar colapsable (Notion)
│ │ ├── page.tsx # Panel de control
│ │ ├── admin/ # Panel de whitelist (solo Owner)
│ │ ├── docs/ # Listado de documentos
│ │ ├── page/[pageId]/ # Editor de documentos (Tiptap + slash)
│ │ ├── projects/ # Kanban / Lista / Calendario
│ │ ├── tasks/[taskId]/ # Detalle de tarea
│ │ └── w/[workspaceId]/ # Detalle de workspace
│ ├── api/
│ │ ├── auth/[...nextauth]/ # NextAuth handler
│ │ ├── admin/whitelist/ # CRUD de la whitelist (Owner only)
│ │ ├── pages/ # CRUD de páginas
│ │ ├── tasks/ # CRUD de tareas
│ │ └── workspaces/ # CRUD de workspaces
│ ├── denied/ # Pantalla "Acceso Denegado / Solicitar"
│ ├── login/ # Login con GitHub
│ ├── globals.css # Tema cyberpunk (CSS vars + efectos)
│ └── layout.tsx
├── components/
│ ├── futurist/ # CyberBackground, GlassPanel, ScanDivider
│ ├── layout/ # AppSidebar (colapsable, estilo Notion)
│ └── ui/ # shadcn: button, dialog, select, etc.
├── lib/
│ ├── auth.ts # Config NextAuth + roles + whitelist
│ ├── api-auth.ts # Helpers para rutas API (owner/auth/parse)
│ ├── prisma.ts # Singleton de PrismaClient
│ └── utils.ts # cn() helper
├── middleware.ts # Protección de rutas + guard de roles
├── prisma/
│ ├── schema.prisma # User, WhitelistedUser, Page, Task, Workspace
│ └── seed.ts # Inserta a "ElMarcels" en la whitelist
├── styles/editor.css # Estilos del editor Tiptap
├── types/ # next-auth.d.ts, tiptap.d.ts
├── .env.example # Variables para local y Vercel
├── vercel.json # Config de build para Vercel
└── package.json
Flujo en lib/auth.ts (callback jwt):
- Tras el login con GitHub se lee el username de GitHub.
- Servidor valida contra la tabla
whitelisted_usersy la constanteOWNER_USERNAME.@ElMarcels→ rolOWNER(acceso a/admin).- Usuario en la whitelist → rol
MEMBER. - Cualquier otro → token marcado como denegado.
- El middleware (
middleware.ts) usa ese token para:- Redirigir a
/denieda los usuarios no autorizados. - Bloquear
/adminpara cualquiera que no seaOWNER.
- Redirigir a
El usuario dueño por defecto está en lib/auth.ts:
export const OWNER_USERNAME = process.env.OWNER_USERNAME || "ElMarcels";Archivo: prisma/schema.prisma
- User — usuarios del sistema (githubId único, role OWNER/MEMBER).
- WhitelistedUser — lista blanca de usernames de GitHub.
- Workspace — espacios de equipo (con
WorkspaceMembership). - Page — documento/nota con
contentJSON (Tiptap) y anidación (parentId). - Task — tareas con status (TODO/IN_PROGRESS/REVIEW/DONE), prioridad, tags, dueDate, githubUrl, assignee y
positionpara ordenar en el Kanban.
- Entra a GitHub → Settings → Developer settings → OAuth Apps → New OAuth App.
- Application name:
DevPulse - Homepage URL:
http://localhost:3000(para pruebas locales) - Authorization callback URL:
http://localhost:3000/api/auth/callback/github
- Application name:
⚠️ Anota el Client ID y el Client Secret. Se usan en.envlocal y en Vercel.
Si el repo pertenece a la organización DevLabs, revisa también la política de OAuth de la org: Settings → Third-party access, para asegurar que la app esté permitida.
Opción Neon (recomendada para Vercel):
- Crea un proyecto en neon.tech.
- Copia la cadena de conexión pooled (con
-pooler) aDATABASE_URL. - Opcional: copia la cadena directa a
DIRECT_URLsi tu proveedor lo exige.
Opción Supabase:
- Crea un proyecto en supabase.com.
- En Project Settings → Database → Connection string, copia la cadena
postgresql://...(usa el modo Transaction / pooled para serverless).
# 1. Instalar dependencias
npm install
# 2. Configurar variables de entorno
cp .env.example .env
# - Edita .env y pega GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, DATABASE_URL
# - Genera NEXTAUTH_SECRET con: openssl rand -base64 32
# 3. Crear la estructura de tablas en la base de datos
npx prisma migrate dev --name init
# (o si prefieres sin migraciones: npx prisma db push)
# 4. Insertar a "ElMarcels" en la whitelist (y workspace DevLabs)
npx prisma db seed
# 5. Levantar en modo desarrollo
npm run devAbre http://localhost:3000 → pulsa "Continuar con GitHub" → inicia sesión con @ElMarcels (owner) o con un usuario de la whitelist (member).
💡 Para probar el flujo de miembro: agrega un username en
/admin(siendo ElMarcels) y luego inicia sesión con esa cuenta de GitHub.
# 1. Asegúrate de estar en la carpeta del proyecto
cd devpulse
# 2. Crea el repositorio dentro de la organización DevLabs:
# GitHub → New repository → Owner: DevLabs → Name: devpulse
# 3. Conecta el remoto (usa la URL que te da GitHub)
git remote add origin git@github.com:DevLabs/devpulse.git
# 4. Confirma y sube
git add .
git commit -m "feat: DevPulse — docs, tareas, kanban y whitelist"
git push -u origin main🛡️ Importante:
.envy.env.localestán en.gitignorey no deben subirse. Solo sube.env.example.
- Ve a vercel.com → Add New Project → Import Git Repository.
- Selecciona la org DevLabs y el repo devpulse.
- Framework Preset: Next.js (se detecta automáticamente).
- En Environment Variables, agrega:
Variable Valor (producción) NEXTAUTH_URLhttps://devpulse.vercel.app← la URL final de tu deployNEXTAUTH_SECRETopenssl rand -base64 32(genera uno nuevo, distinto al local)GITHUB_CLIENT_IDClient ID de la OAuth App GITHUB_CLIENT_SECRETClient Secret de la OAuth App DATABASE_URLCadena de conexión PostgreSQL (pooled) de Neon/Supabase OWNER_USERNAMEElMarcels - Deploy. En el primer deploy Vercel ejecuta el
postinstall(prisma generate).
- Ve a tu OAuth App de GitHub (Settings → Developer settings → OAuth Apps → tu app).
- Añade Authorization callback URL de producción:
https://devpulse.vercel.app/api/auth/callback/github - Añade la Homepage URL de producción:
https://devpulse.vercel.app - Guarda y espera unos segundos.
Puedes tener dos entradas en el callback (una por localhost y una por Vercel) — GitHub permite varios.
En Vercel → proyecto → Settings → Environment Variables ya tienes DATABASE_URL. Ahora crea las tablas y el dueño:
# Opción A (recomendada): desde tu máquina, apuntando a la DB de producción
DATABASE_URL="postgresql://...produccion..." npx prisma migrate deploy
DATABASE_URL="postgresql://...produccion..." npx prisma db seed💡 Recomendado: en Vercel, añade en Build Command:
npx prisma migrate deploy && npm run buildpara que las migraciones se apliquen automáticamente en cada deploy. (Ajusta el
buildCommanddevercel.jsonsi prefieres este enfoque.)
- Panel de control — estadísticas, tareas recientes y accesos rápidos.
- Documentos — editor Tiptap con
/(encabezados, tareas, código con resaltado, callouts, tablas, toggles) y sub-páginas anidadas. - Proyectos/Tareas — vistas Kanban (drag & drop con dnd-kit), Lista y Calendario. Campos: asignado (filtrado por usuarios autorizados), prioridad (Baja/Media/Alta/Urgente), tags, fecha límite y enlace a PR/Issue de GitHub.
- Administración (solo
@ElMarcels) — listar, agregar y eliminar usuarios de la whitelist. - Acceso Denegado — pantalla cyberpunk para usuarios no autorizados con opción de solicitar acceso.
- Dark mode por defecto (forzado), acentos neón azul / violeta cibernético.
- Bordes brillosos sutiles, glassmorphism, grid cyberpunk animado y scanlines.
- Animaciones con Framer Motion (sidebar colapsable estilo Notion, paneles y transiciones).
| Script | Descripción |
|---|---|
npm run dev |
Servidor de desarrollo |
npm run build |
Build de producción (Vercel) |
npm run typecheck |
TypeScript strict check |
npm run db:migrate |
Generar/aplicar migración Prisma (dev) |
npm run db:deploy |
Aplicar migraciones en producción |
npm run db:seed |
Insertar a "ElMarcels" + workspace DevLabs |
npm run db:studio |
Abrir Prisma Studio (UI de la DB) |
lib/api-auth.tscentraliza los guards:requireAuth(),requireOwner().- Las rutas API propias validan la sesión y el rol en el servidor (nunca confiar sólo en el cliente).
- El middleware también bloquea rutas por rol.
- La contraseña/secreto de sesión (
NEXTAUTH_SECRET) debe ser diferente entre entornos.