A full-stack habit tracking application with streak calculation. Built with modern TypeScript technologies and designed for scalability.
- NestJS - Progressive Node.js framework
- GraphQL - Query language with Apollo Server
- PostgreSQL - Relational database
- Prisma ORM - Type-safe database client
- Passport JWT - Cookie-based authentication
- Pino - Structured logging
- React - UI library
- TanStack Router - Type-safe routing
- TanStack Query with Codegen - Automatic types
- Tailwind CSS - Utility-first styling
- Vite - Build tool and dev server
- Docker - Containerization
- Docker Compose - Multi-container orchestration
- pnpm - Fast, disk space efficient package manager
- User authentication with JWT (cookie-based)
- Create and manage daily habits
- Automatic streak calculation
- Track habit completion history
- Responsive design with Tailwind CSS
- GraphQL API with computed field resolvers
- REST endpoints for authentication
- Production-ready error handling and logging
- REST API - Authentication endpoints (
/auth/login,/auth/register) - GraphQL API - Habit management with queries and mutations
- Hybrid approach - Using the right tool for each use case
Users
├── id (UUID)
├── fullName
├── email (unique)
├── password (hashed)
└── timestamps
Habits
├── id (UUID)
├── userId (FK)
├── habitName
├── description
└── timestamps
HabitEntries
├── id (UUID)
├── habitId (FK)
├── date (DATE)
├── completed (BOOLEAN)
└── timestamps
└── UNIQUE(habitId, date)
POST /auth/register- Register a new userPOST /auth/login- Login and receive JWT cookiePOST /auth/logout- Logout and clear cookieGET /auth- Get current authenticated user
# Get all habits for authenticated user
query {
habits {
id
habitName
description
currentStreak
completedToday
entries {
date
completed
}
}
}# Create a new habit
mutation {
createHabit(input: { habitName: "Exercise", description: "30 minutes daily" }) {
id
habitName
}
}
# Toggle habit completion
mutation {
toggleHabit(input: { habitId: "uuid" }) {
completed
}
}
# Update habit
mutation {
updateHabit(input: { id: "uuid", habitName: "New name" }) {
id
habitName
}
}
# Delete habit
mutation {
deleteHabit(id: "uuid")
}commit-daily/
├── backend/ # NestJS backend
│ ├── src/
│ │ ├── authentication/ # Auth module (REST)
│ │ ├── habits/ # Habits module (GraphQL)
│ │ ├── users/ # Users module
│ │ ├── prisma/ # Prisma service
│ │ └── common/ # Shared utilities
│ ├── prisma/
│ │ ├── schema.prisma # Database schema
│ │ └── migrations/ # Database migrations
│ ├── test/ # Tests
│ ├── Dockerfile
│ └── package.json
├── web/ # React frontend
│ ├── src/
│ │ ├── auth/ # Authentication
│ │ ├── components/ # Reusable components
│ │ ├── routes/ # Route components
│ │ ├── queries/ # GraphQL queries
│ │ └── hooks/ # Custom hooks
│ ├── Dockerfile
│ └── package.json
├── docs/ # Documentation
├── docker-compose.yml
└── README.md
- TypeScript for type safety
- ESLint for code quality
- Prettier for formatting (run
pnpm format)