A production-ready todo list application with a Next.js frontend, Express.js backend, and PostgreSQL database, designed to be deployed on Kubernetes with multiple replicas for high availability.
- Features
- Architecture
- Tech Stack
- Project Structure
- Getting Started
- Kubernetes Deployment
- API Documentation
- Database Schema
- ✅ Create, read, update, and delete todos
- ✅ Mark todos as complete/incomplete
- ✅ Set priority levels (Low, Medium, High)
- ✅ Add due dates to tasks
- ✅ Filter todos by status (All, Active, Completed)
- ✅ Search todos by title or description
- ✅ Real-time updates with React Query
- ✅ Responsive design for mobile and desktop
- ✅ Clean, modern UI with Tailwind CSS
- ✅ Kubernetes-ready with multiple replicas
- ✅ Health checks and readiness probes
- ✅ Horizontal pod autoscaling support
- ✅ Rolling updates with zero downtime
- ✅ PostgreSQL with persistent storage
- ✅ Connection pooling for database efficiency
- ✅ Environment-based configuration
- ✅ Docker containerization
┌─────────────────┐
│ Ingress │
│ (todolist.local)│
└────────┬────────┘
│
┌────┴────┐
│ │
┌───▼──────┐ ┌▼──────────┐
│ Frontend │ │ Backend │
│ (Next.js)│ │ (Express) │
│ 2 replicas│ │ 3 replicas│
└──────────┘ └─────┬─────┘
│
┌──────▼─────────┐
│ PostgreSQL │
│ (StatefulSet) │
└────────────────┘
- Framework: Next.js 14 (App Router)
- Language: TypeScript
- Styling: Tailwind CSS
- State Management: TanStack React Query
- HTTP Client: Axios
- Framework: Express.js
- Language: TypeScript
- Database Client: node-postgres (pg)
- Validation: express-validator
- Logger: Morgan
- Database: PostgreSQL 15
- Features: Indexed queries, connection pooling
- Containerization: Docker (multi-stage builds)
- Orchestration: Kubernetes
- Deployment: Rolling updates
- Ingress: NGINX Ingress Controller
.
├── devops-bootcamp-todolist-backend-api/
│ ├── src/
│ │ ├── config/
│ │ │ └── database.ts # PostgreSQL connection pool
│ │ ├── controllers/
│ │ │ └── todoController.ts # Business logic
│ │ ├── models/
│ │ │ └── todoModel.ts # Database queries
│ │ ├── routes/
│ │ │ └── todoRoutes.ts # API routes
│ │ └── server.ts # Express app setup
│ ├── Dockerfile # Backend container image
│ ├── package.json
│ └── tsconfig.json
│
├── devops-bootcamp-todolist-frontend/
│ ├── src/
│ │ ├── app/
│ │ │ ├── layout.tsx # Root layout with QueryClient
│ │ │ ├── page.tsx # Main page
│ │ │ └── globals.css # Global styles
│ │ ├── components/
│ │ │ ├── TodoForm.tsx # Add todo form
│ │ │ ├── TodoItem.tsx # Todo item display
│ │ │ └── FilterBar.tsx # Filter & search
│ │ └── lib/
│ │ ├── api.ts # API client
│ │ └── types.ts # TypeScript types
│ ├── Dockerfile # Frontend container image
│ ├── package.json
│ ├── next.config.js
│ └── tailwind.config.ts
│
└── k8s/
├── namespace.yaml # Namespace definition
├── postgres/
│ ├── secret.yaml # Database credentials
│ ├── statefulset.yaml # PostgreSQL deployment
│ └── service.yaml # Database service
├── backend/
│ ├── configmap.yaml # Backend config
│ ├── deployment.yaml # Backend deployment (3 replicas)
│ └── service.yaml # Backend service
├── frontend/
│ ├── configmap.yaml # Frontend config
│ ├── deployment.yaml # Frontend deployment (2 replicas)
│ └── service.yaml # Frontend service
└── ingress.yaml # Ingress configuration
- Node.js 20+
- PostgreSQL 15+
- Docker (for containerization)
- Kubernetes cluster (for K8s deployment)
# Create database
createdb todolist
# Or using psql
psql -U postgres
CREATE DATABASE todolist;cd devops-bootcamp-todolist-backend-api
# Install dependencies
npm install
# Create .env file
cp .env.example .env
# Edit .env with your database credentials
# DATABASE_HOST=localhost
# DATABASE_PORT=5432
# DATABASE_NAME=todolist
# DATABASE_USER=postgres
# DATABASE_PASSWORD=postgres
# PORT=5000
# NODE_ENV=development
# Run development server
npm run devBackend will be available at http://localhost:5000
cd devops-bootcamp-todolist-frontend
# Install dependencies
npm install
# Create .env.local file
echo "NEXT_PUBLIC_API_URL=http://localhost:5000/api" > .env.local
# Run development server
npm run devFrontend will be available at http://localhost:3000
- Kubernetes cluster (local or cloud)
- kubectl configured
- Docker for building images
# Build backend image
cd devops-bootcamp-todolist-backend-api
docker build -t todo-backend:latest .
# Build frontend image
cd ../devops-bootcamp-todolist-frontend
docker build -t todo-frontend:latest .# Create namespace
kubectl apply -f k8s/namespace.yaml
# Deploy PostgreSQL
kubectl apply -f k8s/postgres/
# Deploy Backend
kubectl apply -f k8s/backend/
# Deploy Frontend
kubectl apply -f k8s/frontend/
# Deploy Ingress
kubectl apply -f k8s/ingress.yaml# Check all pods are running
kubectl get pods -n todolist
# Check services
kubectl get svc -n todolist
# Check ingress
kubectl get ingress -n todolistAdd to your /etc/hosts:
127.0.0.1 todolist.local
Access the application at http://todolist.local
# Scale backend
kubectl scale deployment backend -n todolist --replicas=5
# Scale frontend
kubectl scale deployment frontend -n todolist --replicas=3GET /api/todos
Query Parameters:
- completed: boolean (optional)
- priority: low|medium|high (optional)
- search: string (optional)GET /api/todos/:idPOST /api/todos
Body:
{
"title": "string (required)",
"description": "string (optional)",
"priority": "low|medium|high (optional, default: medium)",
"due_date": "ISO 8601 date string (optional)"
}PUT /api/todos/:id
Body:
{
"title": "string (optional)",
"description": "string (optional)",
"completed": "boolean (optional)",
"priority": "low|medium|high (optional)",
"due_date": "ISO 8601 date string (optional)"
}PATCH /api/todos/:id/toggleDELETE /api/todos/:idGET /health # Liveness probe
GET /ready # Readiness probe (checks DB connection)CREATE TABLE todos (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
description TEXT,
completed BOOLEAN DEFAULT false,
priority VARCHAR(20) CHECK (priority IN ('low', 'medium', 'high')) DEFAULT 'medium',
due_date TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Indexes for performance
CREATE INDEX idx_todos_completed ON todos(completed);
CREATE INDEX idx_todos_due_date ON todos(due_date);
CREATE INDEX idx_todos_priority ON todos(priority);DATABASE_HOST: PostgreSQL hostDATABASE_PORT: PostgreSQL port (default: 5432)DATABASE_NAME: Database nameDATABASE_USER: Database userDATABASE_PASSWORD: Database passwordPORT: Backend port (default: 5000)NODE_ENV: Environment (development/production)
NEXT_PUBLIC_API_URL: Backend API URL
- High: Red color indicator, urgent tasks
- Medium: Yellow color indicator, normal priority
- Low: Green color indicator, low priority
- All: Show all todos
- Active: Show only incomplete todos
- Completed: Show only completed todos
Real-time search across todo titles and descriptions
- Fork the repository
- Create a feature branch
- Commit your changes
- Push to the branch
- Create a Pull Request
This project is licensed under the ISC License.
Created for DevOps Bootcamp
- Next.js team for the amazing framework
- Express.js community
- PostgreSQL contributors
- Kubernetes community