# Monorepo Scaffold — Implementation Document
> **Issue:** [#1 — Set up monorepo scaffold with Yarn workspaces for Web and API](https://gitea-dev.codescripters.org/crisleo-hermes/job-tracker/issues/1)
>
> **Branch:** `feature/setup-monorepo-scaffold`
>
> **Status:** ✅ Implemented
## Project Structure
```
job-tracker/
├── package.json # Yarn workspaces root ("web", "api")
├── docker-compose.yml # PostgreSQL 15 + Django API + React/Vite web
├── README.md
├── .gitignore
│
├── api/ # Django REST API (Python 3.12)
│ ├── Dockerfile
│ ├── pyproject.toml # uv-managed Python dependencies
│ ├── uv.lock
│ ├── manage.py # Django management CLI entrypoint
│ └── project/
│ ├── __init__.py
│ ├── settings.py # PostgreSQL config via DATABASE_URL
│ ├── urls.py # Root URL configuration
│ └── wsgi.py # WSGI application
│
└── web/ # React 19 + Vite frontend
├── Dockerfile
├── package.json # React 19, Vite 6, @vitejs/plugin-react
├── vite.config.js # Dev server on 0.0.0.0:3000, polling
├── index.html # HTML entry point
└── src/
├── main.jsx # ReactDOM.createRoot mount
└── App.jsx # Basic App component
```
---
## 1. Root `package.json` — Yarn Workspaces
**File:** `package.json`
```json
{
"name": "job-tracker",
"private": true,
"workspaces": ["web", "api"]
}
```
- Declares `web` and `api` as Yarn workspace members.
- Dependencies from each workspace are hoisted to the root `node_modules/` where possible.
> **Note:** `"api"` is listed as a workspace member purely for the monorepo structure. The actual Python/Django dependencies are managed via `uv` (see Section 3).
---
## 2. Docker Compose — Development Environment
**File:** `docker-compose.yml`
Three services orchestrated for local development:
### `db` (PostgreSQL 15)
| Setting | Value |
|------------------|------------------------------------------|
| Image | `postgres:15` |
| DB Name | `jobtracker` |
| User / Password | `jobtracker` / `jobtracker` |
| Port | `5432` |
| Volume | `postgres_data:/var/lib/postgresql/data` |
| Health Check | `pg_isready -U jobtracker -d jobtracker` (5s interval, 10 retries) |
### `api` (Django)
| Setting | Value |
|------------------|-----------------------------------------------|
| Build Context | `./api` |
| Port | `8000` |
| Env Vars | `DATABASE_URL=postgres://jobtracker:...@db:5432/jobtracker` |
| Volumes | `./api:/app` (live code reload) |
| Command | `python manage.py migrate && python manage.py runserver 0.0.0.0:8000` |
| Depends On | `db` → `condition: service_healthy` |
### `web` (React + Vite)
| Setting | Value |
|------------------|-----------------------------------------------|
| Build Context | `./web` |
| Port | `3000` |
| Env Vars | `REACT_APP_API_URL=http://localhost:8000` |
| Volumes | `./web:/app` + `/app/node_modules` (live reload) |
| Depends On | `db` → `condition: service_healthy` |
### How to start
```bash
docker compose up
```
- **Web:** http://localhost:3000
- **API:** http://localhost:8000
- **DB:** `postgres://jobtracker:jobtracker@localhost:5432/jobtracker`
---
## 3. Django API (`/api`)
### Dependency Management with `uv`
**File:** `api/pyproject.toml`
```toml
[project]
name = "api"
version = "1.0.0"
requires-python = ">=3.12"
dependencies = [
"django>=5.1,<6.0",
"psycopg2-binary>=2.9",
]
```
Install and verify:
```bash
cd api
uv sync
uv run python manage.py check
# → System check identified no issues (0 silenced).
```
### Database Configuration (`settings.py`)
The `DATABASES` setting is built dynamically from the `DATABASE_URL` environment variable:
```python
DATABASE_URL = "postgres://user:password@host:port/dbname"
```
Parsed into the standard Django `DATABASES` dict with:
- `ENGINE`: `django.db.backends.postgresql`
- `NAME`, `USER`, `PASSWORD`, `HOST`, `PORT` — all extracted from the URL
Default value when `DATABASE_URL` is unset:
`postgres://jobtracker:jobtracker@localhost:5432/jobtracker`
### Installed Apps (Minimal)
```python
INSTALLED_APPS = [
"django.contrib.contenttypes",
"django.contrib.auth",
]
```
### Files Created
| File | Purpose |
|----------------------|--------------------------------------------|
| `api/Dockerfile` | Python 3.12-slim + uv + libpq → Django dev |
| `api/manage.py` | Django CLI entrypoint |
| `api/pyproject.toml` | uv project config with Django + psycopg2 |
| `api/project/__init__.py` | Python package marker |
| `api/project/settings.py` | Django settings with PostgreSQL |
| `api/project/urls.py` | Root URL configuration |
| `api/project/wsgi.py` | WSGI application |
---
## 4. React Frontend (`/web`)
### Dependencies
| Package | Version | Type |
|----------------------|---------|----------------|
| `react` | ^19.0.0 | dependency |
| `react-dom` | ^19.0.0 | dependency |
| `vite` | ^6.0.0 | devDependency |
| `@vitejs/plugin-react` | ^4.3.0 | devDependency |
### Vite Configuration
**File:** `web/vite.config.js`
```js
export default defineConfig({
plugins: [react()],
server: {
host: "0.0.0.0",
port: 3000,
watch: { usePolling: true }, // required for Docker volume mounts
},
});
```
### Entry Point
**File:** `web/src/main.jsx` — mounts `
Welcome to the Job Tracker application.