REST API for Live Better productivity application.
Main documentation: See ../README.md for project overview and setup.
# Install dependencies
bun install
# Setup environment
touch .env # Then edit with your credentials (DATABASE_URL, JWT_SECRET, OPENAI_API_KEY)
# Create PostgreSQL database
podman run --name livebetter-postgres \
-e POSTGRES_USER=livebetter \
-e POSTGRES_PASSWORD=livebetter \
-e POSTGRES_DB=livebetter \
-p 5432:5432 \
-d postgres:17
# Setup database schema
bunx drizzle-kit generate # Generate migrations
bunx drizzle-kit migrate # Apply migrations
# Run server
bun run dev # http://localhost:3000- Create the PostgreSQL database (
live_better) - Update
.envwith your actual database credentials - Set a secure
JWT_SECRET(min 32 characters) - Get your OpenAI API key from platform.openai.com/api-keys
# Run all tests
bun test
# Coverage report
bun test --coverage
# Watch mode
bun test --watch
# Specific tests
bun test src/services/ai.test.tsCoverage: 375 tests (100% pass rate), 82% line coverage, 80% function coverage
Image: leaaboujaoude/livebetter-backend:latest
# Build
docker build -t leaaboujaoude/livebetter-backend:latest .
# Run
docker run -p 3000:3000 \
-e DATABASE_URL="postgresql://..." \
-e JWT_SECRET="..." \
-e OPENAI_API_KEY="sk-..." \
leaaboujaoude/livebetter-backend:latestAzure: Migrations run automatically on container start.
Base URL: http://localhost:3000/api
curl -X POST http://localhost:3000/api/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"pass123","name":"John"}'curl -X POST http://localhost:3000/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"pass123"}'curl -X GET http://localhost:3000/api/auth/profile \
-H "Authorization: Bearer YOUR_TOKEN"curl -X PUT http://localhost:3000/api/auth/profile \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"Jane","userContext":"I prefer mornings","preferredTimeSlots":["morning","night"]}'curl -X POST http://localhost:3000/api/goals \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"Learn TypeScript","description":"Master TS","targetDate":"2025-12-31"}'curl -X GET http://localhost:3000/api/goals \
-H "Authorization: Bearer YOUR_TOKEN"curl -X GET http://localhost:3000/api/goals/1 \
-H "Authorization: Bearer YOUR_TOKEN"curl -X PUT http://localhost:3000/api/goals/1 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"Master TypeScript","completed":false}'curl -X DELETE http://localhost:3000/api/goals/1 \
-H "Authorization: Bearer YOUR_TOKEN"curl -X POST http://localhost:3000/api/tasks \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"Study","timeSlot":"morning","duration":60,"goalId":1}'curl -X GET http://localhost:3000/api/tasks \
-H "Authorization: Bearer YOUR_TOKEN"curl -X GET http://localhost:3000/api/tasks/all \
-H "Authorization: Bearer YOUR_TOKEN"curl -X PUT http://localhost:3000/api/tasks/1 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"completed":true}'curl -X DELETE http://localhost:3000/api/tasks/1 \
-H "Authorization: Bearer YOUR_TOKEN"curl -X POST http://localhost:3000/api/tasks/1/validate-photo \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"photoUrl":"https://example.com/photo.jpg"}'curl -X POST http://localhost:3000/api/goals/tasks/ai-create-all \
-H "Authorization: Bearer YOUR_TOKEN"Response:
{
"tasks": [
{
"id": 1,
"title": "Morning study session",
"timeSlot": "morning",
"duration": 60,
"goalId": 1,
"aiGenerated": true
}
],
"reasoning": "Scheduled based on your morning preference"
}curl -X GET http://localhost:3000/api/goals/tasks/daily-limit-check \
-H "Authorization: Bearer YOUR_TOKEN"{
id: serial
email: varchar(255) unique
password: varchar(255)
name: varchar(255)
userContext: text
preferredTimeSlots: varchar
createdAt: timestamp
aiGenerationsToday: integer
lastAiGenerationDate: date
}{
id: serial
userId: integer → users.id
title: varchar(255)
description: text
targetDate: date
completed: boolean
createdAt: timestamp
}{
id: serial
userId: integer → users.id
goalId: integer → goals.id
title: varchar(255)
description: text
timeSlot: varchar(50)
specificTime: timestamp
duration: integer
completed: boolean
aiGenerated: boolean
photoUrl: varchar(500)
createdAt: timestamp
}- Runtime: Bun 1.2.21
- Framework: Hono 4.9.6
- Database: PostgreSQL + Drizzle ORM
- Auth: JWT + bcryptjs
- Validation: Zod
- AI: OpenAI GPT-4
- Testing: Bun Test
# Database
DATABASE_URL=postgresql://user:pass@localhost:5432/live_better
# Authentication (min 32 chars)
JWT_SECRET=your-super-secret-jwt-key-min-32-chars
# AI Service
OPENAI_API_KEY=sk-your-openai-api-key| File | Functions | Lines | Tests |
|---|---|---|---|
utils/time.ts |
100% | 100% | 45 |
utils/auth.ts |
100% | 95.65% | 38 |
middleware/auth.ts |
100% | 100% | 25 |
services/ai.ts |
93.33% | 100% | 18 |
routes/auth.ts |
100% | 92.05% | 52 |
routes/goals.ts |
70.83% | 65.99% | 79 |
routes/tasks.ts |
100% | 68.24% | 69 |
services/photoValidation.ts |
25% | 6.19% | 6 |
utils/validation.ts |
20% | 38.89% | 49 |
| Overall | 79.55% | 82.08% | 375 |
The test suite includes comprehensive coverage with:
- Unit tests for utilities and services
- Integration tests for API endpoints with real database
- Authentication tests for JWT and bcrypt
- Validation tests for input sanitization
- AI service tests with mocked OpenAI responses
All tests use an isolated test database and include proper setup/teardown.
Coverage Improvements:
- Auth middleware: 100%
- Time utilities: 100%
- Auth utilities: 95.65%
- Core routes: 68-92%
See commit 47ee9b1 for full details.
lsof -ti:3000 | xargs kill -9- Ensure
JWT_SECRETis at least 32 characters - Check token hasn't expired (7-day limit)
- Verify
Authorization: Bearer TOKENformat
- Verify
OPENAI_API_KEYis valid - Check quota at platform.openai.com
- Ensure internet connection
- Main README - Project overview
- Frontend README - Frontend docs