- Root package.json with Yarn workspaces (web, api) - /web: React 19 + Vite 6 + @vitejs/plugin-react - index.html, src/main.jsx, src/App.jsx, vite.config.js - /api: Django 5.x managed with uv - pyproject.toml with Django + psycopg2-binary - project/settings.py with PostgreSQL config from DATABASE_URL - project/urls.py, project/wsgi.py, manage.py - docker-compose.yml with db (postgres:15), api, web services - Health check for db, live code volumes, dependency ordering - Dockerfiles for both web (node:20-alpine) and api (python:3.12-slim) - .gitignore updated for Python build artifacts and venv - docs/implementation-issue-1-monorepo-scaffold.md
8.4 KiB
Monorepo Scaffold — Implementation Document
Issue: #1 — Set up monorepo scaffold with Yarn workspaces for Web and API
Branch:
feature/setup-monorepo-scaffoldStatus: ✅ 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
{
"name": "job-tracker",
"private": true,
"workspaces": ["web", "api"]
}
- Declares
webandapias 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 viauv(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
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
[project]
name = "api"
version = "1.0.0"
requires-python = ">=3.12"
dependencies = [
"django>=5.1,<6.0",
"psycopg2-binary>=2.9",
]
Install and verify:
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:
DATABASE_URL = "postgres://user:password@host:port/dbname"
Parsed into the standard Django DATABASES dict with:
ENGINE:django.db.backends.postgresqlNAME,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)
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
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 <App /> inside React.StrictMode on the #root element.
Component
File: web/src/App.jsx — minimal functional component:
function App() {
return (
<div>
<h1>Job Tracker</h1>
<p>Welcome to the Job Tracker application.</p>
</div>
);
}
Files Created
| File | Purpose |
|---|---|
web/Dockerfile |
Node 20-alpine + yarn → dev server on :3000 |
web/package.json |
React 19 + Vite 6 dependencies |
web/vite.config.js |
Vite dev server config with polling |
web/index.html |
HTML shell loading /src/main.jsx |
web/src/main.jsx |
React entry point |
web/src/App.jsx |
Basic App component |
5. Dockerfiles
api/Dockerfile
FROM python:3.12-slim
WORKDIR /app
RUN apt-get update && apt-get install -y libpq-dev gcc && rm -rf /var/lib/apt/lists/*
COPY pyproject.toml ./
RUN pip install uv && uv sync --frozen
COPY . .
EXPOSE 8000
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
web/Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package.json ./
RUN yarn install --frozen-lockfile
COPY . .
EXPOSE 3000
CMD ["yarn", "dev"]
Verification
Django (standalone)
cd api
uv sync
uv run python manage.py check
# → System check identified no issues (0 silenced).
Frontend (standalone)
cd web
yarn install
yarn dev
# → Vite dev server running on http://localhost:3000
Full stack (Docker)
docker compose up --build
Environment Variables Summary
| Variable | Default | Used By |
|---|---|---|
DATABASE_URL |
postgres://jobtracker:jobtracker@localhost:5432/jobtracker |
API |
REACT_APP_API_URL |
http://localhost:8000 |
Web |
DJANGO_SECRET_KEY |
django-insecure-change-me-in-production |
API |
DJANGO_DEBUG |
True |
API |