working dev environment
This commit is contained in:
@@ -6,27 +6,19 @@ Renders a hero page, about page, broadcast schedule, donation tiers, upcoming ev
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Option A — Docker Compose (recommended)
|
||||
### Option A — Dev Container (recommended)
|
||||
|
||||
```bash
|
||||
# Start all services
|
||||
docker compose up --build
|
||||
|
||||
# Seed the database (first run only)
|
||||
docker compose exec api python seed.py
|
||||
```
|
||||
Open the repo in VS Code and click **Reopen in Container** (or run `Dev Containers: Reopen in Container` from the command palette). The dev container starts both the backend (port 8000) and frontend (port 4200) automatically.
|
||||
|
||||
Open [http://localhost:4200](http://localhost:4200).
|
||||
|
||||
### Option B — Manual (frontend + backend separately)
|
||||
|
||||
```bash
|
||||
# Database
|
||||
createdb kmountain
|
||||
export KMTN_DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/kmountain
|
||||
|
||||
# Backend
|
||||
cd backend && pip install -r requirements.txt
|
||||
# Backend (uses SQLite for local dev — no database server needed)
|
||||
cd backend
|
||||
pip install -r requirements.txt
|
||||
export KMTN_DATABASE_URL="sqlite+aiosqlite:///./kmountain.db"
|
||||
uvicorn app.main:app --reload
|
||||
|
||||
# Frontend (new terminal)
|
||||
@@ -39,11 +31,10 @@ Open [http://localhost:4200](http://localhost:4200) and ensure the backend is ru
|
||||
|
||||
| Requirement | Version | Notes |
|
||||
|---|---|---|
|
||||
| Docker + Docker Compose | 24+ | For the Docker Compose path |
|
||||
| Node.js | 20+ | For manual frontend development |
|
||||
| Node.js | 20+ | For frontend development |
|
||||
| npm | 11+ | |
|
||||
| Python | 3.12+ | For manual backend development |
|
||||
| PostgreSQL | 16+ | For manual backend development (Docker handles it) |
|
||||
| Python | 3.12+ | For backend development |
|
||||
| PostgreSQL | 16+ | For production only (dev uses SQLite) |
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -58,29 +49,28 @@ Open [http://localhost:4200](http://localhost:4200) and ensure the backend is ru
|
||||
┌────▼─────┐ ┌──────▼─────┐
|
||||
│ Nginx │ /api/* │ FastAPI │
|
||||
│ (static) │─ proxy ──▶ │ :8000 │
|
||||
└────┬─────┘ └──────┬─────┘
|
||||
│ │
|
||||
┌────▼─────┐ ┌──────▼─────┐
|
||||
│ Angular 21│ │ PostgreSQL │
|
||||
│ SPA │ │ :5432 │
|
||||
└──────────┘ └────────────┘
|
||||
└──────────┘ └──────┬─────┘
|
||||
│
|
||||
┌──────▼─────┐
|
||||
│ PostgreSQL │
|
||||
│ :5432 │
|
||||
└────────────┘
|
||||
```
|
||||
|
||||
**Three tiers:**
|
||||
|
||||
1. **Frontend** — Angular 21 SPA built via multi-stage Dockerfile and served by Nginx. In production, Nginx serves the static files and proxies `/api/*` requests to the backend. In development, both run on separate ports and the browser talks directly to both.
|
||||
1. **Frontend** — Angular 21 SPA. In production, served by Nginx. In development, served by the Angular dev server on port 4200.
|
||||
2. **Backend** — Python FastAPI with async SQLAlchemy. Provides CRUD REST endpoints for programs (broadcast schedule), events (upcoming events), and donation tiers. Auto-generates Swagger/OpenAPI docs at `/docs`.
|
||||
3. **Database** — PostgreSQL 16. Schema contains three tables: `programs`, `events`, `donation_tiers`. Initial data is loaded via [seed.py](backend/seed.py).
|
||||
3. **Database** — PostgreSQL 16. Schema contains three tables: `programs`, `events`, `donation_tiers`. Initial data is loaded via [seed.py](backend/seed.py). Local development uses SQLite for convenience.
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
.
|
||||
├── docker-compose.yml # 3-service stack (db, api, frontend)
|
||||
├── Dockerfile # Multi-stage: Angular build → Nginx serve
|
||||
├── nginx.conf # Static files + /api/* proxy
|
||||
├── .env.example # Environment variable template
|
||||
├── docker-compose.dev.yml # Dev-sidecar compose (dev container)
|
||||
├── .devcontainer/ # VS Code dev container
|
||||
│ ├── Dockerfile # Alpine Python 3.12 + Node.js + Angular CLI
|
||||
│ └── devcontainer.json # Dev container config
|
||||
│
|
||||
├── src/ # Angular 21 frontend
|
||||
│ ├── app/ # Standalone components
|
||||
@@ -95,7 +85,6 @@ Open [http://localhost:4200](http://localhost:4200) and ensure the backend is ru
|
||||
│ └── _themes.scss # SCSS → CSS custom properties
|
||||
│
|
||||
└── backend/ # FastAPI backend
|
||||
├── Dockerfile # Python gunicorn/uvicorn
|
||||
├── requirements.txt
|
||||
├── seed.py # Initial data for all models
|
||||
└── app/
|
||||
@@ -112,43 +101,40 @@ Open [http://localhost:4200](http://localhost:4200) and ensure the backend is ru
|
||||
|
||||
## Local Development
|
||||
|
||||
### Docker Compose
|
||||
### Dev Container (recommended)
|
||||
|
||||
```bash
|
||||
docker compose up --build # Start all services
|
||||
docker compose exec api python seed.py # Seed database (first run)
|
||||
docker compose logs -f api # Stream backend logs
|
||||
docker compose down # Stop and remove containers
|
||||
```
|
||||
|
||||
The `pgdata` volume persists the database across container restarts.
|
||||
Open the repo in VS Code → **Reopen in Container**. The dev container starts both services automatically. See [.devcontainer/](.devcontainer/) for the configuration.
|
||||
|
||||
### Manual Development
|
||||
|
||||
Run all three layers in parallel:
|
||||
Run both layers in parallel — development uses SQLite (no database server needed):
|
||||
|
||||
```bash
|
||||
# 1. Database (install PostgreSQL 16 locally)
|
||||
createdb kmountain
|
||||
|
||||
# 2. Backend (new terminal)
|
||||
# 1. Backend (new terminal)
|
||||
cd backend
|
||||
pip install -r requirements.txt
|
||||
export KMTN_DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/kmountain
|
||||
export KMTN_DATABASE_URL="sqlite+aiosqlite:///./kmountain.db"
|
||||
export KMTN_CORS_ORIGINS='["http://localhost:4200"]'
|
||||
uvicorn app.main:app --reload
|
||||
|
||||
# 3. Frontend (another terminal)
|
||||
# 2. Frontend (another terminal)
|
||||
npm install
|
||||
ng serve
|
||||
```
|
||||
|
||||
The database auto-seeds on first startup. To reset and re-seed at any time:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/api/admin/reset
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
| Variable | Default | Where | Description |
|
||||
|---|---|---|---|
|
||||
| `KMTN_DATABASE_URL` | `postgresql+asyncpg://postgres:postgres@localhost:5432/kmountain` | [backend/app/config.py](backend/app/config.py) | Async PostgreSQL connection string |
|
||||
| `KMTN_DATABASE_URL` | `postgresql+asyncpg://...` (prod) / `sqlite+aiosqlite:///./kmountain.db` (dev) | [backend/app/config.py](backend/app/config.py) | Database connection string |
|
||||
| `KMTN_CORS_ORIGINS` | `["http://localhost:4200"]` | [backend/app/config.py](backend/app/config.py) | CORS allowlist (JSON array) |
|
||||
| `KMTN_ENV` | `development` | [backend/app/config.py](backend/app/config.py) | Set to `production` to disable admin endpoints |
|
||||
| `apiBaseUrl` | `http://localhost:8000` (dev) / `''` (prod) | [src/environments/](src/environments/) | Where the Angular app finds the API |
|
||||
|
||||
Environment variables are prefixed with `KMTN_` in the backend. For production, set `KMTN_DATABASE_URL` to your managed PostgreSQL connection and update `KMTN_CORS_ORIGINS` to your actual domain.
|
||||
@@ -158,21 +144,17 @@ Environment variables are prefixed with `KMTN_` in the backend. For production,
|
||||
```bash
|
||||
# Frontend (produces dist/radio-station/browser/)
|
||||
ng build --configuration production
|
||||
|
||||
# Backend Docker image
|
||||
docker build -t kmountain-api -f backend/Dockerfile backend/
|
||||
|
||||
# Full production stack
|
||||
docker compose up --build -d
|
||||
```
|
||||
|
||||
For production deployment, serve the built static files with Nginx and run the backend behind it.
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
ng test # Angular + Vitest
|
||||
```
|
||||
|
||||
The backend API is self-documented at [http://localhost:8000/docs](http://localhost:8000/docs) (Swagger UI). Run `docker compose exec api python seed.py` and visit that URL to interactively test endpoints.
|
||||
The backend API is self-documented at [http://localhost:8000/docs](http://localhost:8000/docs) (Swagger UI). The database auto-seeds on first startup — visit that URL to interactively test endpoints.
|
||||
|
||||
## API Reference
|
||||
|
||||
@@ -200,33 +182,41 @@ Full interactive API docs at [http://localhost:8000/docs](http://localhost:8000/
|
||||
|
||||
## Deployment
|
||||
|
||||
### Production (Docker Compose on a VPS)
|
||||
### Production
|
||||
|
||||
For production, you'll need to set up:
|
||||
- A PostgreSQL database (managed or self-hosted)
|
||||
- The FastAPI backend (gunicorn/uvicorn)
|
||||
- Nginx to serve the Angular build and proxy `/api/*` to the backend
|
||||
|
||||
```bash
|
||||
# 1. Clone repo on server
|
||||
git clone <repo-url> kmountain
|
||||
cd kmountain
|
||||
# 1. Build the frontend
|
||||
ng build --configuration production
|
||||
|
||||
# 2. Edit docker-compose.yml
|
||||
# - Change POSTGRES_PASSWORD to a strong value
|
||||
# - Update KMTN_CORS_ORIGINS to your domain
|
||||
# - Optionally set KMTN_DATABASE_URL to a managed PostgreSQL
|
||||
# 2. Configure the backend
|
||||
export KMTN_DATABASE_URL="postgresql+asyncpg://user:pass@host:5432/kmountain"
|
||||
export KMTN_CORS_ORIGINS='["https://yourdomain.com"]'
|
||||
export KMTN_ENV="production"
|
||||
|
||||
# 3. Build and start
|
||||
docker compose up --build -d
|
||||
# 3. Start the backend
|
||||
cd backend
|
||||
pip install -r requirements.txt
|
||||
uvicorn app.main:app --host 0.0.0.0 --port 8000
|
||||
|
||||
# 4. Seed the database
|
||||
docker compose exec api python seed.py
|
||||
# 4. Serve the frontend with Nginx (or your preferred web server),
|
||||
# pointing /api/* requests to http://localhost:8000
|
||||
```
|
||||
|
||||
The database auto-seeds on first startup.
|
||||
|
||||
### Production hardening checklist
|
||||
|
||||
- [ ] Change the default `POSTGRES_PASSWORD` in [docker-compose.yml](docker-compose.yml)
|
||||
- [ ] Use a managed PostgreSQL database (RDS, Cloud SQL, etc.)
|
||||
- [ ] Update `KMTN_CORS_ORIGINS` to your actual domain (not `localhost`)
|
||||
- [ ] Set `KMTN_DATABASE_URL` to a managed PostgreSQL connection (RDS, Cloud SQL, etc.)
|
||||
- [ ] Set `KMTN_ENV="production"` to disable admin endpoints
|
||||
- [ ] Add a reverse proxy (Caddy, Traefik) in front of Nginx for HTTPS
|
||||
- [ ] Set up log rotation for Docker containers
|
||||
- [ ] Configure Docker image registry and push/pull workflow
|
||||
- [ ] Set up log rotation
|
||||
- [ ] Configure a process manager (systemd, PM2) for the backend
|
||||
|
||||
## Development Tools
|
||||
|
||||
@@ -245,6 +235,6 @@ docker compose exec api python seed.py
|
||||
| Styling | SCSS with design tokens (variables → mixins → CSS custom properties) |
|
||||
| Routing | Angular Router (lazy loaded) + Nginx SPA fallback |
|
||||
| HTTP | RxJS observables (frontend → FastAPI) |
|
||||
| Containers | Docker Compose (3 services: db, api, frontend) |
|
||||
| Containers | Dev container (VS Code Remote - Containers) |
|
||||
| CI/CD | _(not yet configured)_ |
|
||||
| Testing | Vitest (via Angular CLI) |
|
||||
|
||||
Reference in New Issue
Block a user