# Carry Your Live - Backend API REST API for the Carry Your Live task management app with offline-first sync support. ## Tech Stack - **Runtime**: Node.js 20+ with TypeScript - **Framework**: Express.js - **Database**: PostgreSQL with Drizzle ORM - **Authentication**: JWT (JSON Web Tokens) - **Validation**: Zod ## Quick Start ### Option A — Docker (Postgres + API in containers) Requires Docker. Runs the database **and** the Node API together: ```bash docker compose up --build ``` This starts: - `carry-your-live-db` — PostgreSQL 16 on port 5432 - `carry-your-live-api` — the API in dev mode (tsx watch, hot reload) on port 3000, schema auto-applied on start Server runs at `http://localhost:3000` (health check: `GET /health`). For production-style serving of the built app: ```bash # Build and run the slim prod image instead docker build --target prod -t carry-your-live-api:prod . docker run --rm -p 3000:3000 --env-file .env carry-your-live-api:prod ``` ### Option B — Local Node + Docker Postgres ### Prerequisites - Node.js 20+ - PostgreSQL 16+ (or use Docker) ### Setup 1. **Start PostgreSQL** (using Docker): ```bash docker-compose up -d postgres ``` 2. **Install dependencies**: ```bash npm install ``` 3. **Configure environment**: ```bash cp .env.example .env # Edit .env with your settings ``` 4. **Run database migrations**: ```bash npm run db:push ``` 5. **Start development server**: ```bash npm run dev ``` Server runs at `http://localhost:3000` ## API Endpoints ### Authentication - `POST /api/auth/register` - Register new user - `POST /api/auth/login` - Login - `GET /api/auth/me` - Get current user ### Categories - `GET /api/categories` - List categories - `POST /api/categories` - Create category - `PATCH /api/categories/:id` - Update category - `DELETE /api/categories/:id` - Delete category ### Tasks - `GET /api/tasks` - List tasks (with filters) - `GET /api/tasks/:id` - Get task with subtasks - `POST /api/tasks` - Create task - `PATCH /api/tasks/:id` - Update task - `DELETE /api/tasks/:id` - Delete task - `POST /api/tasks/batch` - Batch operations ### Subtasks - `GET /api/subtasks/task/:taskId` - List subtasks for task - `POST /api/subtasks/task/:taskId` - Create subtask - `PATCH /api/subtasks/:id` - Update subtask - `DELETE /api/subtasks/:id` - Delete subtask ### Users - `GET /api/users/me` - Get user with settings - `PATCH /api/users/me/settings` - Update settings ### Sync (Offline-first) - `GET /api/sync?since=` - Pull changes since timestamp - `POST /api/sync/push` - Push local changes ## Database Schema See `src/db/schema.ts` for Drizzle schema definitions. ## Sync Protocol The sync endpoint uses a cursor-based approach: 1. **Pull**: Client sends `since` timestamp, server returns all changes since then 2. **Push**: Client sends batched changes with `lastPulledAt`, server applies with conflict resolution (last-write-wins) ## Environment Variables | Variable | Description | Default | |----------|-------------|---------| | `DATABASE_URL` | PostgreSQL connection string | Required | | `JWT_SECRET` | Secret for JWT signing | Required (32+ chars) | | `PORT` | Server port | 3000 | | `NODE_ENV` | Environment | development | | `FRONTEND_URL` | CORS origin | http://localhost:8081 | ## Production Deployment 1. Set `NODE_ENV=production` 2. Use strong `JWT_SECRET` (32+ random chars) 3. Configure proper `DATABASE_URL` 4. Run `npm run build` then `npm start` 5. Use process manager (PM2, systemd) or container orchestration The included `Dockerfile` has a `prod` stage that builds TypeScript and serves `dist/` with production-only dependencies on a minimal `node:20-alpine` image. ## License MIT