Files
job-tracker/docs/implementation-issue-1-monorepo-scaffold.md
T
Marko (Hermes Implementer) b91b7c364e feat: set up monorepo scaffold with Yarn workspaces, Django API, React/Vite web, and Docker Compose
- 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
2026-05-24 07:38:14 +00:00

296 lines
8.4 KiB
Markdown

# 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 `<App />` inside `React.StrictMode` on the `#root` element.
### Component
**File:** `web/src/App.jsx` — minimal functional component:
```jsx
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`
```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`
```dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package.json ./
RUN yarn install --frozen-lockfile
COPY . .
EXPOSE 3000
CMD ["yarn", "dev"]
```
---
## Verification
### Django (standalone)
```bash
cd api
uv sync
uv run python manage.py check
# → System check identified no issues (0 silenced).
```
### Frontend (standalone)
```bash
cd web
yarn install
yarn dev
# → Vite dev server running on http://localhost:3000
```
### Full stack (Docker)
```bash
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 |