A full-stack productivity app built around the Pomodoro technique. Track focus sessions, take structured breaks, and build better work habits with a clean interface and secure authentication.
π Live Demo: pomodoro-murex-beta.vercel.app
- Pomodoro Timer β 25-minute focus sessions with 5-minute short breaks and 15-minute long breaks
- Session History β Review completed pomodoros and track progress over time
- Secure Auth β JWT-based authentication with optional 2FA (TOTP), plus Google and GitHub OAuth
- Validation β Client and server-side validation with clear error messages
- Responsive UI β Modern interface built with Next.js and Tailwind CSS
| Layer | Technologies |
|---|---|
| Frontend | Next.js 16, React 19, Tailwind CSS, Zustand, React Hook Form, Zod |
| Backend | NestJS 11, TypeORM, PostgreSQL, Passport.js, bcrypt |
| Auth | JWT, Passport (local, JWT, Google, GitHub), 2FA (TOTP) |
| Deployment | Vercel (frontend), Railway (backend + PostgreSQL) |
- Node.js 18+
- npm or pnpm
- PostgreSQL 14+ (or use Docker)
- Docker (optional, for running PostgreSQL via Docker Compose)
git clone https://github.com/estherdev03/pomodoro-app.git
cd pomodoro-app
cd frontend && npm install
cd ../backend && npm installUsing Docker:
cd backend
docker compose up -dOr connect to an existing PostgreSQL instance.
Create a .env in the backend directory:
# Database
DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=postgres
DB_NAME=pomodoro_app
# JWT
JWT_SECRET=your-secret-key-change-in-production
JWT_EXPIRATION=1d
# Server
PORT=8000
CORS_ORIGIN=http://localhost:3000
# OAuth redirects
FRONTEND_URL=http://localhost:3000
# Google OAuth (optional)
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
# GitHub OAuth (optional)
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secretCreate a .env.local in the frontend directory:
NEXT_PUBLIC_API_URL=http://localhost:8000Terminal 1 β Backend
cd backend
npm run start:devTerminal 2 β Frontend
cd frontend
npm run dev- Frontend: http://localhost:3000
- Backend API: http://localhost:8000
This project is deployed with the frontend on Vercel and the backend + PostgreSQL on Railway.
- Go to vercel.com β New Project β Import this repo
- Set the Root Directory to
frontend - Add environment variable:
NEXT_PUBLIC_API_URL=https://your-railway-backend.up.railway.app - Click Deploy
- Go to railway.app β New Project
- Add a PostgreSQL database service
- Add a second service β Deploy from GitHub β set Root Directory to
backend - Set Build Command:
npm run build - Set Start Command:
npm run start:prod - Add environment variables:
DB_HOST=${{Postgres.PGHOST}} DB_PORT=${{Postgres.PGPORT}} DB_USERNAME=${{Postgres.PGUSER}} DB_PASSWORD=${{Postgres.PGPASSWORD}} DB_NAME=${{Postgres.PGDATABASE}} JWT_SECRET=your-strong-secret JWT_EXPIRATION=1d PORT=8000 CORS_ORIGIN=https://your-vercel-frontend.vercel.app FRONTEND_URL=https://your-vercel-frontend.vercel.app GOOGLE_CLIENT_ID=your-google-client-id GOOGLE_CLIENT_SECRET=your-google-client-secret GITHUB_CLIENT_ID=your-github-client-id GITHUB_CLIENT_SECRET=your-github-client-secret
- Click Generate Domain under Public Networking on the backend service
Update the redirect URIs in your OAuth provider consoles to point to your Railway backend:
| Provider | Callback URL |
|---|---|
https://your-backend.up.railway.app/auth/google/callback |
|
| GitHub | https://your-backend.up.railway.app/auth/github/callback |
- Google: console.cloud.google.com β Credentials β OAuth Client β Authorized Redirect URIs
- GitHub: github.com/settings/developers β OAuth App β Authorization Callback URL
pomodoro-app/
βββ backend/ # NestJS API
β βββ src/
β β βββ auth/ # Auth, JWT, 2FA, OAuth strategies
β β βββ users/ # User entities and service
β β βββ pomodoro-session/ # Pomodoro session logic
β β βββ main.ts
β βββ docker-compose.yml # PostgreSQL service
β βββ package.json
βββ frontend/ # Next.js app
β βββ app/ # App router pages
β βββ components/ # UI and auth components
β βββ lib/ # API client, stores, types
β βββ package.json
βββ README.md
| Method | Endpoint | Description |
|---|---|---|
| POST | /auth/register |
Register a new user |
| POST | /auth/login |
Login with email and password |
| POST | /auth/logout |
Logout and clear session |
| GET | /auth/profile |
Get current user (JWT required) |
| GET | /auth/google |
Initiate Google OAuth |
| GET | /auth/github |
Initiate GitHub OAuth |
| POST | /auth/2fa/generate |
Generate 2FA secret |
| POST | /auth/2fa/verify |
Verify 2FA TOTP code |
| POST | /auth/2fa/enable |
Enable 2FA for the user |
| Method | Endpoint | Description |
|---|---|---|
| POST | /pomodoro-session/start |
Start a new pomodoro session |
| PATCH | /pomodoro-session/:id/end |
End an active session |
| GET | /pomodoro-session/current |
Get the current active session |
| GET | /pomodoro-session/history |
List the user's session history |
| Command | Description |
|---|---|
npm run start:dev |
Start dev server with watch mode |
npm run build |
Build for production |
npm run start:prod |
Run the production build |
npm run test |
Run unit tests |
| Command | Description |
|---|---|
npm run dev |
Start Next.js dev server |
npm run build |
Build for production |
npm run start |
Run the production build |
MIT License