A production-ready full-stack dashboard built with Next.js 14 App Router, TypeScript, Prisma, and NextAuth. Features authentication, CRUD operations, server-side filtering, pagination, optimistic UI updates, and comprehensive Playwright E2E tests.
| Feature | Implementation |
|---|---|
| Full-Stack Architecture | Next.js 14 App Router with Server Components + Client Components |
| Authentication | NextAuth.js with credentials provider + JWT sessions |
| Database | Prisma ORM with SQLite (easily swap to PostgreSQL) |
| CRUD Operations | REST API routes with proper HTTP methods and status codes |
| Server-Side Filtering | Status filter + text search with Prisma queries |
| Pagination | Server-side pagination with page/limit controls |
| Optimistic UI | Tasks appear instantly before API confirmation, roll back on error |
| Type Safety | Full TypeScript across frontend, API, and database layers |
| Styling | Tailwind CSS with custom design tokens |
| E2E Testing | Playwright tests covering auth, CRUD, search, filter, pagination |
| CI/CD | GitHub Actions with database seeding and E2E test execution |
- Framework: Next.js 14 (App Router)
- Language: TypeScript 5.4
- Styling: Tailwind CSS 3.4
- Database: SQLite (dev) / PostgreSQL (prod-ready)
- ORM: Prisma 5.12
- Auth: NextAuth.js 4.24
- Icons: Lucide React
- E2E Tests: Playwright
- CI: GitHub Actions
# 1. Install dependencies
npm install
# 2. Set up environment
cp .env.example .env
# 3. Initialize database
npx prisma migrate dev --name init
# 4. Seed demo data
npm run db:seed
# 5. Start development server
npm run dev
# 6. Open app
open http://localhost:3000Demo credentials: demo@example.com / demopassword123
# Install Playwright browsers (first time)
npx playwright install
# Run E2E tests
npm run test:e2e
# Run E2E tests in UI mode (interactive)
npm run test:e2e:uisrc/
├── app/
│ ├── api/
│ │ ├── auth/[...nextauth]/ # NextAuth API route
│ │ └── tasks/ # Task CRUD API
│ ├── dashboard/ # Dashboard page (client component)
│ ├── layout.tsx # Root layout
│ └── page.tsx # Login page
├── components/ # Reusable components
├── lib/
│ ├── auth.ts # NextAuth configuration
│ ├── prisma.ts # Prisma client singleton
│ └── utils.ts # Utility functions (cn helper)
├── globals.css # Tailwind + CSS variables
prisma/
├── schema.prisma # Database schema
└── seed.ts # Demo data seeding
tests/e2e/
├── auth.spec.ts # Authentication flows
└── dashboard.spec.ts # CRUD, search, filter, pagination
- Secure credentials-based login with bcrypt password hashing
- JWT sessions with automatic token refresh
- Route protection — unauthenticated users redirected to login
- Logout with session cleanup
- Create: Add tasks with optimistic UI (appears instantly)
- Read: Paginated list with server-side rendering
- Update: Change status with instant feedback, rollback on error
- Delete: Remove tasks with confirmation dialog, optimistic removal
- Text search: Real-time filtering by task title
- Status filter: Dropdown to show Todo / In Progress / Done
- Pagination: Navigate through large task lists
- All filtering happens server-side for scalability
When you create or update a task:
- UI updates immediately with the expected state
- API request fires in the background
- On success: UI state confirmed with server data
- On error: UI rolls back to previous state + shows error
This pattern delivers a snappy, app-like experience while maintaining data integrity.
model User {
id String @id @default(cuid())
email String @unique
name String?
password String
tasks Task[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Task {
id String @id @default(cuid())
title String
description String?
status Status @default(TODO)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum Status {
TODO
IN_PROGRESS
DONE
}- Login page rendering
- Valid credentials → dashboard redirect
- Invalid credentials → error message
- Logout → redirect to login
- Unauthenticated dashboard access → redirect
- Seeded data display
- Create new task
- Update task status (with visual confirmation)
- Delete task (with confirmation)
- Search filtering
- Status filtering
- Optimistic UI verification
- Pagination controls
GitHub Actions runs on every push:
- Build job: Installs deps, sets up SQLite DB, runs Prisma migrate + seed, builds Next.js
- E2E job: Runs after build success, installs Playwright browsers, executes full E2E suite
Change prisma/schema.prisma:
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}Update .env:
DATABASE_URL="postgresql://user:password@localhost:5432/dashboard"
Run npx prisma migrate dev and you're set.
This isn't a toy app — it demonstrates patterns used in real production dashboards:
- Type safety end-to-end: From database schema to API responses to React props
- Server-side data fetching: No hydration mismatches, better SEO
- Optimistic updates: Modern UX pattern that users expect
- Test coverage: E2E tests protect against regressions in critical flows
- Database migrations: Prisma manages schema evolution safely