# Studio EinsZwoVier Web Application **FastAPI-based PDF print cost calculator** with automated ink coverage analysis, Matrix integration, and multi-service hub for Studio EinsZwoVier Maker Space. [![Docker](https://img.shields.io/badge/Docker-Ready-2496ED?logo=docker)](https://www.docker.com/) [![FastAPI](https://img.shields.io/badge/FastAPI-0.104+-009688?logo=fastapi)](https://fastapi.tiangolo.com/) [![Matrix](https://img.shields.io/badge/Matrix-Integrated-000000?logo=matrix)](https://matrix.org/) --- ## 🎯 Features ### Core Application - **πŸ“„ PDF Cost Calculator**: Automated ink coverage analysis with color/B&W detection - **πŸ–ΌοΈ Course Management**: Dynamic course list with image gallery and modal viewer - **πŸ“Š Cost Estimation**: Per-page breakdown with configurable rates (€/mΒ²) - **πŸ’¬ Matrix Integration**: Automatic order submission to Matrix room ### Integrated Services - **πŸ“š BookStack Wiki**: Documentation and knowledge base (port 6875) - **πŸ€– Ollama + Open WebUI**: Local LLM chatbot interface (port 8080) - **πŸ“¨ Matrix Synapse**: Print order collection and payment tracking (port 8008) - **🐳 Portainer**: Container management dashboard (port 9000) - **πŸ”„ Watchtower**: Automatic container updates every 24 hours --- ## πŸ—οΈ Architecture ```mermaid graph TB subgraph "Studio EinsZwoVier Web App (Port 80)" LP[🏠 Landing Page
studio-einszwovier.local] About[ℹ️ About Page
/about
Courses + Team Info] Cost[πŸ’° Cost Calculator
/cost
PDF Analysis] LP --> About LP --> Cost end subgraph "Course Management" CSV[πŸ“ courses.csv
Title, Description, Dates, Image] Images[πŸ–ΌοΈ Course Images
static/images/courses/] Modal[πŸ” Image Modal
Click to Enlarge] About --> CSV CSV --> Images Images --> Modal end subgraph "PDF Processing Pipeline" Upload[πŸ“€ Upload PDF] Analysis[πŸ”¬ Analyze
- Dimensions
- Ink Coverage
- Color Detection] Quote[πŸ“‹ Quote Generation
Per-page Breakdown] Cost --> Upload Upload --> Analysis Analysis --> Quote end subgraph "Matrix Integration" MatrixRoom[πŸ’¬ Matrix Room
Print Orders] PDF_Upload[πŸ“Ž PDF Attachment] Summary[πŸ“Š Order Summary
German Language] Quote --> MatrixRoom Quote --> PDF_Upload Quote --> Summary end subgraph "Integrated Services" BookStack[πŸ“š BookStack Wiki
:6875] Ollama[πŸ€– Ollama LLM
:11434] OpenWebUI[πŸ’­ Open WebUI
:8080] Portainer[🐳 Portainer
:9000] Synapse[πŸ“¨ Matrix Synapse
:8008] LP -.-> BookStack LP -.-> OpenWebUI LP -.-> Portainer OpenWebUI --> Ollama MatrixRoom --> Synapse end subgraph "Data Persistence" Uploads[πŸ“ data/uploads/
PDF Files] Courses[πŸ“‹ data/courses.csv
Course List] MatrixDB[(πŸ—„οΈ Matrix DB
homeserver.db)] BookDB[(πŸ—„οΈ BookStack DB
MariaDB)] Upload --> Uploads CSV --> Courses Synapse --> MatrixDB BookStack --> BookDB end classDef webapp fill:#e3f2fd,stroke:#1976d2,stroke-width:2px classDef service fill:#fff3e0,stroke:#f57c00,stroke-width:2px classDef data fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px classDef matrix fill:#e8f5e9,stroke:#388e3c,stroke-width:2px class LP,About,Cost,Upload,Analysis,Quote webapp class BookStack,Ollama,OpenWebUI,Portainer,Synapse service class Uploads,Courses,MatrixDB,BookDB data class MatrixRoom,PDF_Upload,Summary,CSV,Images,Modal matrix ``` --- ## πŸš€ Quick Start ### Prerequisites - **Docker** & **Docker Compose** installed - **Poppler** (for pdf2image - included in Docker) - **Port availability**: 80, 8008, 8080, 6875, 9000, 11434 ### Installation 1. **Clone the repository:** ```bash git clone https://github.com/arontaupe/124-webapp.git cd 124-webapp ``` 2. **Configure environment:** ```bash cp .env.example .env nano .env # Update SERVER_HOSTNAME and passwords ``` 3. **Start the stack:** ```bash docker compose up -d --build ``` 4. **Access services:** - Web App: http://localhost (or http://your-server) - BookStack: http://localhost:6875 - Open WebUI: http://localhost:8080 - Portainer: http://localhost:9000 - Matrix: http://localhost:8008 ### First-Time Setup 1. **Get Matrix Room ID:** ```bash python get_room_id.py ``` 2. **Update .env with room ID:** ```bash MATRIX_ROOM="!YourRoomID:${SERVER_HOSTNAME}" ``` 3. **Restart web container:** ```bash docker compose restart web ``` --- ## πŸ“š Course Management Courses are managed via CSV file with optional images: ### Add a Course 1. **Edit `data/courses.csv`:** ```csv title,description,dates,offen_fuer,image My Course,Learn cool stuff,"Oct '25",Grade 10,/static/images/courses/my-course.jpg ``` 2. **Add course image (optional):** ```bash cp my-image.jpg static/images/courses/my-course.jpg ``` 3. **Changes apply immediately** (no restart needed) ### Course Image Features - **Thumbnail view**: 80x80px next to course info - **Hover zoom**: Expands to 200x200px on hover - **Click to enlarge**: Opens full-size modal viewer - **Auto-cropping**: `object-fit: cover` ensures uniform display See [data/KURSE_README.md](data/KURSE_README.md) for detailed documentation. --- ## πŸ”§ Configuration ### Environment Variables Key variables in `.env`: ```bash # Server Configuration SERVER_HOSTNAME=your-server.com # Print Rates (€/mΒ²) RATE_PER_M2_BLACK=4.0 RATE_PER_M2_COLOR=5.0 # Matrix Integration MATRIX_USER="@einszwovier:${SERVER_HOSTNAME}" MATRIX_PASS="your_password" MATRIX_HOMESERVER="http://${SERVER_HOSTNAME}:8008" MATRIX_ROOM="!RoomID:${SERVER_HOSTNAME}" # Service Ports SYNAPSE_PORT=8008 OLLAMA_PORT=11434 OPENWEBUI_PORT=8080 BOOKSTACK_PORT=6875 PORTAINER_PORT=9000 ``` See [.env.example](.env.example) for full configuration. --- ## 🐳 Docker Services | Service | Image | Port | Purpose | Resources | |---------|-------|------|---------|-----------| | **web** | Custom (FastAPI) | 80 | Main application | 1 CPU, 1GB RAM | | **synapse** | matrixdotorg/synapse | 8008 | Matrix homeserver | 2 CPU, 2GB RAM | | **ollama** | ollama/ollama | 11434 | LLM inference | 6 CPU, 16GB RAM | | **open-webui** | ghcr.io/open-webui/open-webui | 8080 | LLM chat UI | 2 CPU, 2GB RAM | | **bookstack** | lscr.io/linuxserver/bookstack | 6875 | Documentation wiki | Default | | **bookstack-mariadb** | lscr.io/linuxserver/mariadb | 3306 | Database for BookStack | Default | | **portainer** | portainer/portainer-ce | 9000, 9443 | Container management | Default | | **watchtower** | containrrr/watchtower | - | Auto-updates (24h) | Default | ### Health Checks All services have health checks configured: - **web**: `curl http://localhost:8000/` - **synapse**: `curl http://localhost:8008/_matrix/static/` - **ollama**: `curl http://localhost:11434/` - **open-webui**: `curl http://localhost:8080/` - **bookstack**: `curl http://localhost/` - **mariadb**: MariaDB query test - **portainer**: API status check - **watchtower**: Process check --- ## πŸ“– Documentation - **[SECURITY.md](SECURITY.md)** - Security best practices and secrets management - **[PORTABILITY.md](PORTABILITY.md)** - Server migration guide - **[PRE_RELEASE_CHECKLIST.md](PRE_RELEASE_CHECKLIST.md)** - Pre-publication verification - **[data/KURSE_README.md](data/KURSE_README.md)** - Course management guide --- ## πŸ” Security **Before deploying to production:** 1. βœ… Change all passwords in `.env` 2. βœ… Generate new `BOOKSTACK_APP_KEY` 3. βœ… Update Matrix credentials 4. βœ… Configure firewall (restrict Portainer access) 5. βœ… Set up HTTPS/SSL 6. βœ… Enable automated backups See [SECURITY.md](SECURITY.md) for comprehensive security guidelines. **Security Disclosure:** If you discover a vulnerability, email `einszwovier@gvb-gymnasium.de` instead of opening a public issue. --- ## πŸ”„ Backup & Restore ### Backup All Data ```bash ./backup.sh ``` Creates timestamped backups of: - BookStack database & files - Matrix homeserver data - PDF uploads - Course data & images - Environment configuration ### Restore from Backup ```bash ./restore.sh YYYYMMDD_HHMMSS ``` --- ## 🚒 Deployment & Portability This application is designed to be **fully portable**. To move to a new server: 1. **On old server:** ```bash ./backup.sh ``` 2. **On new server:** ```bash git clone cd 124-webapp cp .env.example .env # Update SERVER_HOSTNAME in .env ./restore.sh YYYYMMDD_HHMMSS docker compose up -d ``` See [PORTABILITY.md](PORTABILITY.md) for detailed migration guide. --- ## πŸ› οΈ Development ### Local Development ```bash # Option 1: Direct Python (with auto-reload) python run_app.py # Option 2: Docker Compose docker compose up --build ``` ### Project Structure ``` . β”œβ”€β”€ main.py # FastAPI application β”œβ”€β”€ cost_calculator.py # PDF analysis logic β”œβ”€β”€ mailer.py # Matrix integration β”œβ”€β”€ templates/ # Jinja2 templates β”‚ β”œβ”€β”€ base.html β”‚ β”œβ”€β”€ landing.html β”‚ β”œβ”€β”€ about.html β”‚ β”œβ”€β”€ cost-calculator.html β”‚ └── result.html β”œβ”€β”€ static/ # CSS, images, fonts β”‚ β”œβ”€β”€ css/style.css β”‚ β”œβ”€β”€ images/ β”‚ └── fonts/ β”œβ”€β”€ data/ β”‚ β”œβ”€β”€ courses.csv # Course database β”‚ └── uploads/ # PDF uploads β”œβ”€β”€ docker-compose.yml # Service orchestration β”œβ”€β”€ Dockerfile # Web app container └── requirements.txt # Python dependencies ``` ### Key Technologies - **FastAPI** - Modern Python web framework - **PyPDF2** - PDF metadata extraction - **pdf2image** - PDF to image conversion - **Pillow + NumPy** - Image processing & ink analysis - **matrix-nio** - Matrix protocol client - **Jinja2** - Template engine - **Gunicorn + Uvicorn** - Production WSGI/ASGI servers --- ## 🀝 Contributing Contributions are welcome! This is part of **Studio EinsZwoVier**, a collaborative Maker Space. 1. Fork the repository 2. Create a feature branch (`git checkout -b feature/amazing-feature`) 3. Commit your changes (`git commit -m 'Add amazing feature'`) 4. Push to the branch (`git push origin feature/amazing-feature`) 5. Open a Pull Request --- ## πŸ“„ License This project is part of Studio EinsZwoVier educational initiative. --- ## πŸ“ž Contact **Studio EinsZwoVier** Gabriele-von-BΓΌlow-Gymnasium Tile-BrΓΌgge-Weg 63, 13509 Berlin (Tegel) - **Email**: einszwovier@gvb-gymnasium.de - **Team**: Aron Petau & Friedrich Weber - **Hours**: Tuesday - Thursday, 11:00 - 16:00 - **Location**: Room 124 --- ## πŸ™ Acknowledgments - Matrix.org for the communication protocol - Ollama team for local LLM support - BookStack for the documentation platform - FastAPI community - All contributors and students of Studio EinsZwoVier --- **Made with ❀️ at Studio EinsZwoVier Maker Space**