# Technology Stack

**Analysis Date:** 2026-02-15

## Languages

**Primary:**
- JavaScript (ES6+) - Both frontend and backend
- SQL - PostgreSQL database queries in backend

**Secondary:**
- HTML/CSS - Frontend UI styling

## Runtime

**Environment:**
- Node.js 20 (LTS) - Specified in Dockerfiles (`node:20-alpine`)

**Package Manager:**
- npm (Node Package Manager)
- Lockfile: `package-lock.json` present in both `frontend/` and `backend/`

## Frameworks

**Core:**
- **React** 18.2.0 - Frontend UI library (`frontend/package.json`)
- **Express.js** 4.18.2 - Backend REST API framework (`backend/package.json`)

**Frontend:**
- **Vite** 5.0.8 - Frontend build tool and dev server
  - Config: `frontend/vite.config.js`
  - React plugin: `@vitejs/plugin-react` 4.2.1

**Routing:**
- **React Router DOM** 6.21.0 - Frontend client-side routing
  - Configured in `frontend/src/main.jsx` with BrowserRouter and Routes

**Web Server:**
- **Nginx** (Alpine) - Production frontend server
  - Config: `frontend/nginx.conf`
  - Serves static assets, proxies `/api` to backend
  - Gzip compression enabled

## Key Dependencies

**Frontend Critical:**
- `react` 18.2.0 - UI framework
- `react-dom` 18.2.0 - DOM rendering
- `react-router-dom` 6.21.0 - Client-side routing

**Frontend Dev:**
- `vite` 5.0.8 - Build tooling
- `@vitejs/plugin-react` 4.2.1 - React JSX support
- `@types/react` 18.2.43 - TypeScript types
- `@types/react-dom` 18.2.17 - TypeScript types

**Backend Critical:**
- `express` 4.18.2 - HTTP server framework
- `pg` 8.11.3 - PostgreSQL client library
- `jsonwebtoken` 9.0.2 - JWT authentication token generation/verification
- `bcryptjs` 2.4.3 - Password hashing and verification
- `cors` 2.8.5 - Cross-origin resource sharing middleware

**Backend Dev:**
- `nodemon` 3.0.2 - Auto-restart on file changes

## Configuration

**Environment:**
- Database connection via environment variables:
  - `DB_HOST` - PostgreSQL hostname (default: `postgres`)
  - `DB_PORT` - PostgreSQL port (default: `5432`)
  - `DB_USER` - Database user (default: `postgres`)
  - `DB_PASSWORD` - Database password
  - `DB_NAME` - Database name (default: `gravl`)
  - `JWT_SECRET` - JWT signing key (default: `gravl-secret-key-change-in-production`)
  - `PORT` - Backend API port (default: `3001`)

**Build:**
- Frontend: `vite.config.js` - Vite configuration with React plugin
  - Dev server: `0.0.0.0:5173`
  - API proxy: `/api` routes to `http://localhost:3001`
- Backend: Simple Node.js entry point at `backend/src/index.js`

## Database

**Primary:**
- **PostgreSQL** - Relational database
  - Initialized via `db/init.sql`
  - Accessed via `pg` Node.js client library
  - Tables: `users`, `programs`, `program_days`, `exercises`, `program_exercises`, `workout_logs`, `user_measurements`, `user_strength`

## Platform Requirements

**Development:**
- Node.js 20+
- npm 9+
- PostgreSQL 12+
- Docker and Docker Compose (for containerized development)

**Production:**
- Deployment target: Docker containers via Docker Compose
- Frontend container: `node:20-alpine` (build) → `nginx:alpine` (production)
- Backend container: `node:20-alpine`
- Reverse proxy: Traefik (configured in `docker-compose.yml`)
- Network: Homelab environment with internal proxy and homelab networks

## Build Process

**Frontend:**
1. `npm install` - Install dependencies
2. `npm run build` - Vite builds to `dist/` directory
3. Dockerfile multi-stage build:
   - Stage 1: Node 20 Alpine - npm install and build
   - Stage 2: Nginx Alpine - Serve built assets from `/usr/share/nginx/html`

**Backend:**
1. `npm install --production` - Install dependencies (production only)
2. Dockerfile: Node 20 Alpine - Copy src and run `npm start`

## Development Commands

**Frontend:**
- `npm run dev` - Start Vite dev server on `0.0.0.0:5173` with hot reload
- `npm run build` - Production build to `dist/`
- `npm run preview` - Preview production build

**Backend:**
- `npm run start` - Run `node src/index.js` (production)
- `npm run dev` - Run with `nodemon` for auto-restart on file changes

---

*Stack analysis: 2026-02-15*
