A production-ready, full-stack habit tracking application built with modern technologies. Track your daily habits, maintain streaks, and visualize your progress with beautiful analytics.
- User Authentication - Secure JWT-based authentication with refresh tokens
- Habit Management - Create, edit, archive, and delete habits
- Daily Tracking - Mark habits as complete with a single tap
- Streak System - Automatic streak calculation with longest streak tracking
- Analytics Dashboard - Beautiful charts and GitHub-style heatmap
- Dark/Light Mode - Full theme support with system preference detection
- Responsive Design - Mobile-first, works on all devices
- Data Export - Export your data as CSV or JSON
- Rate limiting and input validation
- Secure password hashing with bcrypt
- Token rotation for refresh tokens
- Soft delete for habits (archive)
- Time-zone aware tracking
- RESTful API with versioning
- Framework: Next.js 14 (App Router)
- Styling: Tailwind CSS
- State Management: Zustand
- Charts: Recharts
- Animations: Framer Motion
- HTTP Client: Axios
- Notifications: React Hot Toast
- Framework: NestJS
- Database: PostgreSQL
- ORM: Prisma
- Authentication: Passport.js + JWT
- Validation: class-validator
- Rate Limiting: @nestjs/throttler
- Containerization: Docker & Docker Compose
- Database Migrations: Prisma Migrate
tracker/
βββ frontend/ # Next.js frontend
β βββ src/
β β βββ app/ # App router pages
β β βββ components/ # React components
β β β βββ ui/ # Base UI components
β β β βββ habits/ # Habit-related components
β β β βββ analytics/ # Chart components
β β β βββ layout/ # Layout components
β β βββ lib/ # Utilities and API client
β β βββ stores/ # Zustand stores
β β βββ types/ # TypeScript types
β βββ Dockerfile
β βββ package.json
β
βββ backend/ # NestJS backend
β βββ src/
β β βββ auth/ # Authentication module
β β βββ users/ # Users module
β β βββ habits/ # Habits module
β β βββ analytics/ # Analytics module
β β βββ prisma/ # Prisma service
β βββ prisma/
β β βββ schema.prisma # Database schema
β βββ Dockerfile
β βββ package.json
β
βββ docker-compose.yml # Docker orchestration
βββ README.md
- Node.js 18+
- PostgreSQL 14+ (or Docker)
- npm or yarn
# Clone the repository
git clone <repository-url>
cd tracker
# Install backend dependencies
cd backend
npm install
# Install frontend dependencies
cd ../frontend
npm install# Create a PostgreSQL database
createdb habit_tracker
# Or use Docker for PostgreSQL
docker run -d \
--name habit-postgres \
-e POSTGRES_PASSWORD=password \
-e POSTGRES_DB=habit_tracker \
-p 5432:5432 \
postgres:15-alpineBackend (.env):
DATABASE_URL="postgresql://postgres:password@localhost:5432/habit_tracker?schema=public"
JWT_SECRET="your-super-secret-jwt-key-change-in-production-123456"
JWT_EXPIRES_IN="15m"
JWT_REFRESH_SECRET="your-super-secret-refresh-key-change-in-production-789"
JWT_REFRESH_EXPIRES_IN="7d"
PORT=3001
NODE_ENV="development"
FRONTEND_URL="http://localhost:3000"
THROTTLE_TTL=60
THROTTLE_LIMIT=100Frontend (.env.local):
NEXT_PUBLIC_API_URL=http://localhost:3001/api/v1cd backend
npx prisma generate
npx prisma migrate dev --name init# Terminal 1 - Backend
cd backend
npm run start:dev
# Terminal 2 - Frontend
cd frontend
npm run devVisit http://localhost:3000
# Clone the repository
git clone <repository-url>
cd tracker
# Copy environment file
cp .env.example .env
# Edit .env with your secrets
# Then start all services
docker-compose up -d
# View logs
docker-compose logs -fThe app will be available at:
- Frontend: http://localhost:3000
- Backend API: http://localhost:3001/api/v1
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/auth/register |
Register a new user |
| POST | /api/v1/auth/login |
Login and get tokens |
| POST | /api/v1/auth/refresh |
Refresh access token |
| POST | /api/v1/auth/logout |
Logout and invalidate token |
| POST | /api/v1/auth/change-password |
Change password |
| GET | /api/v1/auth/me |
Get current user |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/habits |
Get all habits |
| GET | /api/v1/habits/today |
Get today's habits |
| GET | /api/v1/habits/:id |
Get habit by ID |
| POST | /api/v1/habits |
Create new habit |
| PATCH | /api/v1/habits/:id |
Update habit |
| POST | /api/v1/habits/:id/toggle |
Toggle habit completion |
| POST | /api/v1/habits/:id/archive |
Archive habit |
| POST | /api/v1/habits/:id/unarchive |
Restore habit |
| DELETE | /api/v1/habits/:id |
Delete habit |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/analytics/dashboard |
Get dashboard stats |
| GET | /api/v1/analytics/weekly |
Get weekly progress |
| GET | /api/v1/analytics/monthly |
Get monthly progress |
| GET | /api/v1/analytics/heatmap |
Get heatmap data |
| GET | /api/v1/analytics/export |
Export data (CSV/JSON) |
# Register
curl -X POST http://localhost:3001/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "SecurePass123!",
"firstName": "John",
"lastName": "Doe"
}'
# Create Habit
curl -X POST http://localhost:3001/api/v1/habits \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{
"title": "Morning Meditation",
"description": "10 minutes of mindfulness",
"color": "#6366f1",
"frequency": "DAILY"
}'model User {
id String @id @default(uuid())
email String @unique
password String
firstName String
lastName String?
timezone String @default("UTC")
habits Habit[]
refreshTokens RefreshToken[]
}
model Habit {
id String @id @default(uuid())
userId String
title String
description String?
color String @default("#6366f1")
frequency HabitFrequency @default(DAILY)
customDays Int[] @default([])
isArchived Boolean @default(false)
currentStreak Int @default(0)
longestStreak Int @default(0)
user User @relation(...)
logs HabitLog[]
}
model HabitLog {
id String @id @default(uuid())
habitId String
date DateTime @db.Date
completed Boolean @default(false)
habit Habit @relation(...)
@@unique([habitId, date])
}- Password Hashing: bcrypt with 12 rounds
- JWT Authentication: Short-lived access tokens (15m)
- Refresh Token Rotation: New token on each refresh
- Rate Limiting: 100 requests per minute per IP
- Input Validation: All inputs validated and sanitized
- CORS Protection: Configured for specific origins
- Helmet: Security headers middleware
cd frontend
vercel --prodSet environment variable:
NEXT_PUBLIC_API_URL: Your backend API URL
- Connect your repository
- Set environment variables
- Deploy
# Build and run
docker-compose -f docker-compose.yml up -d --build
# Scale if needed
docker-compose up -d --scale backend=3# Backend
npm run start:dev # Development mode
npm run build # Build for production
npm run start:prod # Production mode
npm run prisma:studio # Open Prisma Studio
npm run prisma:migrate # Run migrations
# Frontend
npm run dev # Development mode
npm run build # Build for production
npm run start # Production mode
npm run lint # Run ESLint- Email notifications
- Push notifications (PWA)
- Habit reminders (cron jobs)
- Social features
- Gamification badges
- API rate limiting per user
- Two-factor authentication
- Data backup/restore
MIT License - feel free to use this project for personal or commercial purposes.
Contributions are welcome! Please feel free to submit a Pull Request.
Built with β€οΈ using Next.js, NestJS, and PostgreSQL