Proyecto: Aplicacion SaaS Full-Stack
Descripcion General del Proyecto
Este es el proyecto final del Modulo IV. Vamos a construir FlowTask --- no solo una landing page esta vez, sino el producto completo. Una aplicacion SaaS de gestion de tareas con autenticacion de usuarios, base de datos, proyectos, tareas con estados y prioridades, un dashboard en tiempo real y todas las operaciones CRUD que hacen que un producto realmente funcione.
Esta leccion combina todo lo del bootcamp entero: prompt engineering, configuracion de CLAUDE.md, flujos de trabajo con Git, componentes de frontend, API routes del backend, diseno de bases de datos, autenticacion y testing. Si puedes construir esto, puedes construir cualquier cosa.
Lo Que Vamos a Construir
- Autenticacion: Iniciar sesion con GitHub, rutas protegidas, gestion de sesiones
- Proyectos: Crear, leer, actualizar y eliminar proyectos
- Tareas: Gestion completa de tareas dentro de proyectos --- crear, editar, asignar, cambiar estado, establecer prioridades y fechas limite
- Dashboard: Tarjetas de estadisticas, graficos de actividad y un feed de actividad reciente
- Configuracion: Gestion del perfil de usuario
Stack Tecnologico
- Next.js 14 con App Router
- Prisma como ORM
- SQLite para desarrollo (facil de cambiar a PostgreSQL para produccion)
- NextAuth.js para autenticacion
- Tailwind CSS para estilos
Configurando el Proyecto
Antes de escribir cualquier codigo, necesitamos una base solida. Comienza creando el CLAUDE.md del proyecto para que la IA entienda el contexto de cada prompt en esta sesion.
El CLAUDE.md del Proyecto
Crea un archivo .claude/CLAUDE.md en la raiz de tu proyecto:
# FlowTask SaaS Application
## Tech Stack
- Next.js 14 (App Router)
- Prisma with SQLite (dev) / PostgreSQL (prod)
- NextAuth.js with GitHub provider
- Tailwind CSS
- TypeScript (strict mode)
## Project Structure
- /app — Next.js App Router pages
- /app/(marketing) — Public pages (landing, pricing)
- /app/(app) — Authenticated app pages (dashboard, projects, tasks)
- /components — Reusable React components
- /lib — Utility functions, database client, auth config
- /prisma — Schema and migrations
## Conventions
- Use Server Components by default, Client Components only when needed
- Use Server Actions for mutations
- All API routes under /app/api/
- Tailwind for all styling, no CSS modules
- Commit messages: conventional commits (feat:, fix:, refactor:)
## Current State
- Phase 1: Project scaffolding and database schema
Este archivo es el cerebro de tu proyecto. Actualiza la seccion "Current State" a medida que construyes cada funcionalidad. La IA lee esto antes de cada prompt, manteniendo todas las respuestas consistentes con tu arquitectura.
El Prompt Inicial de Scaffold
Create a Next.js 14 project with TypeScript and Tailwind CSS. Set up the
following structure:
- App Router with two route groups: (marketing) for public pages and (app)
for authenticated pages
- Prisma with SQLite database
- NextAuth.js configured but not yet connected to a provider
- A basic layout for the (app) route group with a sidebar navigation
- A placeholder dashboard page at /dashboard
Install all dependencies and configure tsconfig for strict mode.
Despues de que la IA genere el scaffold, verifica que funciona:
npm run dev
Visita http://localhost:3000 y confirma que ves el dashboard placeholder. Luego haz commit:
git add .
git commit -m "feat: initial project scaffold with Next.js, Prisma, NextAuth"
Diseno del Esquema de Base de Datos
La base de datos es la columna vertebral de cualquier aplicacion SaaS. Necesitamos tres tablas principales: users, projects y tasks.
El Prompt
Create a Prisma schema with these models:
User:
- id (cuid, primary key)
- name (string, optional)
- email (string, unique)
- emailVerified (datetime, optional)
- image (string, optional)
- accounts (relation to Account model for NextAuth)
- sessions (relation to Session model for NextAuth)
- projects (relation to Project[])
- createdAt, updatedAt
Project:
- id (cuid, primary key)
- name (string)
- description (string, optional)
- color (string, default "#6366f1")
- userId (string, foreign key to User)
- tasks (relation to Task[])
- createdAt, updatedAt
Task:
- id (cuid, primary key)
- title (string)
- description (string, optional)
- status (enum: TODO, IN_PROGRESS, DONE, default TODO)
- priority (enum: LOW, MEDIUM, HIGH, URGENT, default MEDIUM)
- dueDate (datetime, optional)
- projectId (string, foreign key to Project)
- assigneeId (string, optional, foreign key to User)
- createdAt, updatedAt
Include the NextAuth required models (Account, Session, VerificationToken).
Add appropriate indexes on foreign keys and frequently queried fields.
Ejecutando Migraciones
Despues de que la IA genere el esquema, aplicalo:
npx prisma migrate dev --name init
Esto crea el archivo de base de datos SQLite y aplica el esquema. Puedes inspeccionar la base de datos con:
npx prisma studio
Prisma Studio abre un explorador visual de la base de datos en http://localhost:5555. Guarda esto en tus favoritos --- es increiblemente util para depurar problemas de datos durante el desarrollo.
El Cliente de Prisma
La IA tambien deberia crear un cliente singleton de Prisma:
// lib/prisma.ts
import { PrismaClient } from "@prisma/client";
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined;
};
export const prisma = globalForPrisma.prisma ?? new PrismaClient();
if (process.env.NODE_ENV !== "production") {
globalForPrisma.prisma = prisma;
}
Este patron singleton previene la creacion de multiples conexiones a la base de datos durante el desarrollo cuando Next.js hace hot-reload.
Flujo de Autenticacion
La autenticacion es innegociable para una app SaaS. NextAuth.js lo hace sencillo.
El Prompt
Set up NextAuth.js with the GitHub provider. Configure:
1. The auth configuration in lib/auth.ts using the Prisma adapter
2. The API route handler at app/api/auth/[...nextauth]/route.ts
3. A sign-in page at app/(marketing)/login/page.tsx with a "Sign in with
GitHub" button
4. A sign-out button component
5. Middleware that protects all /dashboard and /projects routes — redirect
to /login if not authenticated
6. A getCurrentUser helper function that gets the session user with their
database record
Use environment variables for GITHUB_ID, GITHUB_SECRET, NEXTAUTH_SECRET,
and NEXTAUTH_URL.
Variables de Entorno
Crea un archivo .env.local (nunca hagas commit de esto):
GITHUB_ID=your_github_oauth_app_id
GITHUB_SECRET=your_github_oauth_app_secret
NEXTAUTH_SECRET=generate_with_openssl_rand_base64_32
NEXTAUTH_URL=http://localhost:3000
Para obtener las credenciales de OAuth de GitHub, ve a GitHub Settings, luego Developer Settings, luego OAuth Apps, y crea una nueva app con la callback URL http://localhost:3000/api/auth/callback/github.
Protegiendo Rutas
El archivo de middleware es critico. Intercepta cada solicitud y verifica la autenticacion:
// middleware.ts
import { withAuth } from "next-auth/middleware";
export default withAuth({
pages: {
signIn: "/login",
},
});
export const config = {
matcher: ["/dashboard/:path*", "/projects/:path*", "/settings/:path*"],
};
Prueba el flujo: visita /dashboard sin estar logueado. Deberias ser redirigido a /login. Inicia sesion con GitHub. Deberias llegar a /dashboard. Asi funciona el guardián de autenticacion.
git add .
git commit -m "feat: add NextAuth.js with GitHub provider and route protection"
El Dashboard
El dashboard es lo primero que ven los usuarios despues de iniciar sesion. Necesita comunicar actividad y progreso de un vistazo.
El Prompt
Build the dashboard page at /dashboard. It should include:
1. Welcome header: "Welcome back, {user.name}" with today's date
2. Stats cards row (4 cards):
- Total Tasks (count of all user's tasks)
- Completed Today (tasks marked DONE today)
- In Progress (tasks with IN_PROGRESS status)
- Overdue (tasks past due date that aren't DONE)
Each card has an icon, the number in large text, and a label
3. A chart showing tasks completed over the last 7 days (bar chart or line
chart using recharts library)
4. Recent Activity list showing the last 10 task updates with:
- Task title
- What changed (created, status changed, completed)
- Timestamp (relative: "2 hours ago")
- Project name
Fetch all data server-side using Prisma queries in the page component.
Use a grid layout: stats cards in a 4-column row, chart takes 2/3 width
with recent activity taking 1/3 on desktop.
Iterando sobre el Dashboard
La primera version sera funcional pero probablemente necesite pulido. Iteraciones comunes:
The stats cards look flat. Add a subtle gradient background to each card
(indigo-50 to indigo-100 for the first, green-50 to green-100 for
completed, etc.). Add an arrow icon showing trend direction compared to
yesterday.
The chart looks basic. Add gridlines, softer colors, rounded bar corners,
and tooltips showing the exact count on hover. Use indigo-500 as the bar
color.
El dashboard es un componente vivo. A medida que agregues mas funcionalidades, regresaras y anadiras mas widgets. Por ahora, deja el layout base correcto y haz commit.
Operaciones CRUD para Proyectos
CRUD significa Create, Read, Update, Delete --- las cuatro operaciones fundamentales de cualquier aplicacion basada en datos.
El Prompt
Build the complete projects feature:
1. Projects list page at /projects showing all of the current user's
projects in a grid of cards. Each card shows project name, description
preview, task count, and a colored dot matching the project color.
2. Create project: a modal form triggered by a "New Project" button. Fields:
name (required), description (optional), color picker. Use a Server Action
to create the project in the database.
3. Project detail page at /projects/[id] showing the project header (name,
description, edit button, delete button) and a list of all tasks in that
project.
4. Edit project: clicking "Edit" opens a modal pre-filled with current
values. Server Action to update.
5. Delete project: clicking "Delete" shows a confirmation dialog. "Are you
sure? This will delete all tasks in this project." Server Action to
delete the project and all associated tasks.
Use Server Actions for all mutations. Revalidate the path after each
mutation so the UI updates immediately.
Patron de Server Actions
La IA deberia generar Server Actions como este:
"use server";
import { prisma } from "@/lib/prisma";
import { getCurrentUser } from "@/lib/auth";
import { revalidatePath } from "next/cache";
export async function createProject(formData: FormData) {
const user = await getCurrentUser();
if (!user) throw new Error("Unauthorized");
const name = formData.get("name") as string;
const description = formData.get("description") as string;
const color = formData.get("color") as string;
await prisma.project.create({
data: {
name,
description,
color: color || "#6366f1",
userId: user.id,
},
});
revalidatePath("/projects");
}
Este patron --- autenticar, validar, mutar, revalidar --- se repite para cada operacion CRUD. Una vez que la IA lo establece para proyectos, aplicara el mismo patron a las tareas.
Operaciones CRUD para Tareas
Las tareas son el nucleo de FlowTask. Necesitan mas funcionalidades que los proyectos porque son el objeto principal con el que interactuan los usuarios.
El Prompt
Build the complete tasks feature within projects:
1. Task creation: "Add Task" button within a project page opens an inline
form (not a modal — it should feel quick). Fields: title (required),
description (optional), status dropdown, priority dropdown, due date
picker. Server Action to create.
2. Task list view within the project page: show tasks grouped by status
(TODO, IN_PROGRESS, DONE). Each task shows title, priority badge
(color-coded), due date (red if overdue), and an assignee avatar.
3. Task detail view: clicking a task opens a slide-over panel from the right
showing all task fields, an edit form, and a comments section placeholder.
4. Inline editing: clicking a task's status badge cycles through statuses
without opening the detail view. Use optimistic updates.
5. Drag and drop: tasks can be dragged between status columns in a kanban
view. Add a toggle between "List view" and "Board view" at the top of
the project page.
Use Server Actions for all mutations. Add loading states and optimistic
updates for a snappy feel.
El Tablero Kanban
La vista kanban con drag-and-drop es el elemento de interfaz mas complejo. La IA probablemente usara una libreria como @hello-pangea/dnd o dnd-kit:
import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd";
const onDragEnd = async (result: DropResult) => {
if (!result.destination) return;
const taskId = result.draggableId;
const newStatus = result.destination.droppableId as TaskStatus;
// Actualizacion optimista
setTasks((prev) =>
prev.map((task) =>
task.id === taskId ? { ...task, status: newStatus } : task
)
);
// Actualizacion en el servidor
await updateTaskStatus(taskId, newStatus);
};
Si la implementacion del kanban no funciona bien, descomponla:
The drag and drop isn't working smoothly. Let's simplify: use @hello-pangea/dnd
with three columns (TODO, IN_PROGRESS, DONE). Each column is a Droppable, each
task card is a Draggable. On drop, call the updateTaskStatus Server Action and
use optimistic updates.
Busqueda y Filtrado
Una vez que los usuarios tienen docenas de tareas, necesitan formas de encontrarlas rapidamente.
El Prompt
Add search and filtering to the tasks list:
1. Search bar at the top of the project page that filters tasks by title
(client-side filtering for instant results)
2. Filter dropdowns:
- Status: All, TODO, IN_PROGRESS, DONE
- Priority: All, LOW, MEDIUM, HIGH, URGENT
- Due date: All, Overdue, Due Today, Due This Week, No Due Date
3. Sort options: Created (newest/oldest), Due Date (nearest/farthest),
Priority (highest/lowest)
4. Show active filter count on a "Filters" button. Clicking "Clear All"
resets all filters.
Store filter state in URL search params so filters survive page refresh.
Client-Side vs Server-Side
Para este proyecto, el filtrado del lado del cliente funciona bien porque la cantidad de tareas por proyecto es manejable. La IA deberia usar useMemo para filtrar eficientemente:
const filteredTasks = useMemo(() => {
return tasks
.filter((task) => {
if (statusFilter && task.status !== statusFilter) return false;
if (priorityFilter && task.priority !== priorityFilter) return false;
if (searchQuery && !task.title.toLowerCase().includes(searchQuery.toLowerCase()))
return false;
return true;
})
.sort((a, b) => {
if (sortBy === "dueDate") return compareDates(a.dueDate, b.dueDate);
if (sortBy === "priority") return comparePriority(a.priority, b.priority);
return compareCreatedAt(a.createdAt, b.createdAt);
});
}, [tasks, statusFilter, priorityFilter, searchQuery, sortBy]);
Para conjuntos de datos mas grandes, moveras el filtrado al servidor con condiciones de consulta de Prisma. El prompt cambiaria para solicitar un Server Component que acepte search params y consulte la base de datos con clausulas where.
Pagina de Configuracion
Toda aplicacion SaaS necesita una pagina de configuracion donde los usuarios puedan gestionar su cuenta.
El Prompt
Create a settings page at /settings with these sections:
1. Profile: Display and edit name, email (read-only), and avatar. Use a
form with Server Action to update the name.
2. Preferences: Toggle for email notifications (task assigned, task
completed, weekly digest). Store in a UserPreferences model or JSON
field.
3. Danger Zone: Account deletion. A red-bordered section with "Delete
Account" button. Clicking it shows a confirmation that requires typing
"DELETE" to confirm. Server Action deletes the user and all associated
data, then signs them out.
Use a tab or sidebar navigation to switch between settings sections.
La confirmacion de eliminacion de cuenta es un patron UX importante. Previene la perdida accidental de datos:
const [confirmText, setConfirmText] = useState("");
const canDelete = confirmText === "DELETE";
Carga de Archivos
Adjuntar archivos a las tareas hace que FlowTask sea mas util para trabajo real.
El Prompt
Add file attachments to tasks:
1. Add an Attachment model to Prisma: id, filename, url, size, mimeType,
taskId, uploadedBy, createdAt
2. File upload component: drag-and-drop zone + click to browse. Accept
images, PDFs, and documents up to 10MB.
3. Store files locally in /public/uploads during development. Create an
API route POST /api/upload that handles multipart form data.
4. Display attachments in the task detail view: show filename, size, upload
date, and a download link. Images show a thumbnail preview.
5. Delete attachment button with confirmation.
Run the migration for the new Attachment model.
Para produccion, reemplazarias el almacenamiento local con S3 o un servicio similar. El prompt para hacer ese cambio despues es directo:
Replace local file storage with S3-compatible storage using the @aws-sdk/
client-s3 package. Use environment variables for bucket name, region,
access key, and secret key. Update the upload API route to stream files
directly to S3 and store the S3 URL in the database.
La Secuencia Completa de Prompts
Demos un paso atras y veamos toda la secuencia de prompts usada para construir FlowTask:
- Scaffold --- Configuracion del proyecto con Next.js, Prisma, NextAuth, Tailwind
- Schema --- Modelos de base de datos para User, Project, Task
- Auth --- GitHub OAuth, rutas protegidas, gestion de sesiones
- Dashboard --- Tarjetas de estadisticas, grafico, actividad reciente
- Projects CRUD --- Listar, crear, editar, eliminar proyectos
- Tasks CRUD --- Listar, crear, editar, eliminar, cambios de estado
- Kanban --- Vista de tablero con drag-and-drop
- Busqueda/Filtrado --- Filtrado del lado del cliente con estado en URL
- Configuracion --- Perfil, preferencias, eliminacion de cuenta
- Carga de Archivos --- Adjuntos en tareas
Son diez prompts principales, mas quiza veinte a treinta prompts de iteracion para correcciones y pulido. En total, podrias invertir de cuatro a seis horas construyendo FlowTask con vibe coding.
Para comparar, un desarrollador tradicional construyendo la misma aplicacion desde cero --- disenando la base de datos, escribiendo cada componente, implementando autenticacion, manejando casos limite --- probablemente tardaria un minimo de cuarenta a sesenta horas. El vibe coding comprime esa linea de tiempo en un orden de magnitud.
La idea clave: cada prompt se construye sobre el contexto establecido por los prompts anteriores. El archivo CLAUDE.md mantiene todo coherente. Y como haces commit despues de cada funcionalidad, siempre puedes revertir si algo sale mal.
Que Sigue
FlowTask es una aplicacion SaaS funcional, pero sigue siendo un sistema cerrado. En la proxima leccion, vamos a abrirlo. Construiremos una API publica para que otras aplicaciones puedan interactuar con FlowTask, agregaremos soporte de webhooks para integraciones en tiempo real y nos conectaremos a servicios externos como procesadores de pagos y proveedores de email. Tu app esta a punto de convertirse en parte de un ecosistema mas grande.