design final

This commit is contained in:
Aron Petau 2025-10-07 13:02:29 +02:00
parent a0d2188f6f
commit 99a690972e
1414 changed files with 2389 additions and 1455 deletions

144
.github/copilot-instructions.md vendored Normal file
View file

@ -0,0 +1,144 @@
# Copilot Instructions for Studio EinsZwoVier Web Application
## Project Overview
This is a **FastAPI-based web application** serving as a multi-service hub for Studio EinsZwoVier, a collaborative print studio. The main app provides a PDF print cost calculator with automated ink coverage analysis, integrated with a Matrix server for order collection and payment tracking.
## Architecture & Service Boundaries
### Core FastAPI Application (`main.py`, port 80→8000)
- **Landing page** (`/`) with presence state management (studio open/closed indicator)
- **Cost calculator** (`/cost`) for PDF analysis and price estimation
- **About page** (`/about`)
- **Order submission** via Matrix integration
### Multi-Container Stack (Docker Compose)
The application orchestrates 7+ containerized services:
- **web**: FastAPI app (this repo's code)
- **synapse**: Matrix server for print job collection (port 8008)
- **ollama**: Local LLM inference (port 11434)
- **open-webui**: LLM chat interface (port 8080)
- **bookstack + mariadb**: Documentation wiki
- **docmost + postgres + redis**: Knowledge management system
- **watchtower**: Auto-updates all containers every 24h
### PDF Processing Pipeline (`cost_calculator.py`)
1. **Upload** → Validate `.pdf` extension only
2. **Page-by-page analysis**:
- Extract dimensions from `CropBox` (preferred) or `MediaBox`
- Convert PDF points to meters: `(points / 72.0) * 0.0254`
- Render at 150 DPI using `pdf2image`
- Calculate ink coverage: pixels with RGB < 250 = ink
- Detect color vs B&W: HSV saturation analysis (>0.1% pixels with sat>10 = color)
3. **Cost calculation**: area (m²) × rate (from env vars `RATE_PER_M2_BLACK`/`COLOR`)
### Matrix Integration (`mailer.py`)
- Uses `matrix-nio` async client to send orders
- **Critical**: Must set `MATRIX_USER`, `MATRIX_PASS`, `MATRIX_HOMESERVER` env vars
- Sends structured summary (German language) + PDF upload to hardcoded room ID
- **Synchronous wrapper** `send_order_sync()` bridges async/sync contexts for FastAPI
## Developer Workflows
### Local Development
```bash
# Option 1: Direct Python execution (auto-reload)
python run_app.py
# Option 2: Full stack with Docker Compose
docker-compose up --build -d
# Access at: http://localhost (or einszwovier.local in local network)
```
### Environment Configuration
Create `.env` file with:
```bash
# Print rates (€/m²)
RATE_PER_M2_BLACK=4.0
RATE_PER_M2_COLOR=5.0
# Matrix integration
MATRIX_USER=@bot:homeserver
MATRIX_PASS=secret
MATRIX_HOMESERVER=http://einszwovier.local:8008
# Service ports
SYNAPSE_PORT=8008
OLLAMA_PORT=11434
OPENWEBUI_PORT=8080
BOOKSTACK_PORT=6875
# BookStack/DB configs (see docker-compose.yml for full list)
```
### Debugging Matrix Integration
Use `get_room_id.py` to discover Matrix room IDs:
```python
# Connects to local Matrix server, joins room, prints room IDs
python get_room_id.py
```
Then update the hardcoded room ID in `main.py` line 127: `room_id="!eFW..."`
## Project-Specific Conventions
### Presence State Management
- In-memory global `presence_state` dict tracks studio open/closed status
- API endpoints: `GET /presence`, `POST /presence`, `POST /presence/toggle`
- Background task `update_presence_periodically()` runs every 5 min (currently no-op placeholder)
### German UI/UX
- Templates use German language exclusively
- Error/success messages in German (e.g., "Dein Auftrag wurde erfolgreich gesendet!")
- Cost calculator displays "S/W" (Schwarz/Weiß) vs "Farbe" (color)
### File Organization
- **Uploads persist** in `data/uploads/` (mounted volume in Docker)
- **Templates** in `templates/` (Jinja2, extending `base.html`)
- **Static assets** in `static/` (CSS, fonts, images)
- **Service data** in dedicated dirs: `bookstack/`, `docmost/`, `matrix/`, `ollama/`, `open-webui/`
### Docker Production Command
The `Dockerfile` uses **Gunicorn with Uvicorn workers** for production:
```bash
gunicorn main:app -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000 --workers 4 --timeout 120
```
But `docker-compose.yml` overrides with `--reload` for dev convenience.
## Critical Integration Points
### PDF Analysis Return Structure
`analyze_pdf()` returns:
```python
{
"filename": str,
"pages": [{"page": int, "width_m": float, "height_m": float,
"area_m2": float, "ink_pct": float, "is_color": bool, "cost": float}],
"total_area_black": float,
"total_area_color": float,
"total_cost_black": float,
"total_cost_color": float,
"grand_total": float
}
```
### Matrix Room ID Hardcoding
⚠️ **Known technical debt**: Room ID is hardcoded in `send_order_endpoint()`. Update when Matrix server changes or for different deployment environments.
### Async/Sync Bridge Pattern
Matrix client is async, but FastAPI endpoint is sync. Pattern used:
```python
def send_order_sync(...):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(send_order(...))
loop.close()
```
## External Dependencies
- **Poppler** (system): Required for `pdf2image` (installed in Dockerfile)
- **OpenCV** (system): Requires `libgl1`, `libglib2.0-0` (installed in Dockerfile)
- **Font files**: Custom fonts in `static/fonts/` (BauPro, HealTheWebA/B, SISTEMAS)
## Testing & Utilities
- `test_send_pdf.py`: Manual test script for Matrix integration
- No automated test suite currently implemented