7.2 KiB
Copilot Instructions for AI Coding Agents
Project Overview
AutoKanban is a FastAPI web app for managing a physical kanban workflow with a 58mm Arduino thermal printer. Users submit tasks via web UI, admins approve and print them to physical cards. Designed for Raspberry Pi deployment but tested on macOS.
Architecture & Data Flow
User submits task → Task (pending) → Admin approves → Task (approved) → Admin prints → Task (printed) → Physical kanban card
Core Components
app/main.py(270 lines): Monolithic FastAPI app containing all routes, business logic, session management, and card rendering. All state managed in-memory with JSON persistence.app/models.py: Single Pydantic modelTaskwith factory methodTask.create()that generates UUID.app/printer.py: Minimal printer wrapper (currently unused in main.py - printer logic is duplicated in/printroute).app/templates/: Jinja2 HTML templates with German localization and inline CSS/JS.app/static/fonts/: Custom fonts (BauPro, HealTheWeb) + Font Awesome 7.1.0 OTFs for semantic icons.
State Management Pattern
- Persistence: Simple JSON file (
data/tasks.json) loaded into in-memory list on startup. Callsave_tasks()after every mutation. - Sessions: Starlette
SessionMiddlewarestores admin auth state and flash messages (login_result,print_result,preview_image) in cookies. - Admin auth: Password-only (no username), checked against
.envvariable. Session flagadmin: True/False.
Dual-Mode Printing Architecture
Key insight: App has two print modes controlled by DEBUG_PRINT_TO_IMAGE flag in main.py:
True(default for testing): Generates PNG previews using Pillow with custom fonts, semantic icons, and card layout toout/directory.False(production): Prints to ESC/POS thermal printer via serial (/dev/ttyUSB0, 19200 baud).
Why this matters: When modifying print logic, update BOTH branches in the /print/{task_id} route (lines 142-244).
Semantic Icon System
KEYWORD_ICONS list in main.py maps German/English keywords to Font Awesome unicode codepoints:
- Pattern:
(['keyword1', 'keyword2'], '\uf0f4') - Matching: Case-insensitive substring search in task content
- Default icon:
\uf328(fa-sticky-note) - Add new mappings by extending this list - requires knowing FA unicode values.
Developer Workflows
Running the App
Preferred method (handles venv automatically):
python start_app.py # Launches uvicorn on 0.0.0.0:8000 with --reload
Manual method:
source .venv/bin/activate
uvicorn app.main:app --reload
First-Time Setup
- Create
.envfile withADMIN_PASSWORD=yourpassword - Ensure
data/directory exists (create if missing - .gitignored) - Install system fonts or update font paths in
main.py(lines 29-31) - For real printing: Set
DEBUG_PRINT_TO_IMAGE = Falseand configure serial device
Testing Print Without Hardware
- Keep
DEBUG_PRINT_TO_IMAGE = True - Submit task → approve → print
- Check
out/task_{uuid}.pngfor rendered card - Preview images shown in web UI after printing
Debugging Font Issues
Font loading uses fallback chain (lines 129-135):
load_font(path, size, fallback=None, font_label="descriptive_name")
- Logs errors but gracefully falls back to default font
- Font errors appended to
font_error_msgs[]and rendered on card preview
Project Conventions
Code Organization
- Monolithic by design: All logic in
main.pyfor simplicity. Don't split unless file exceeds 500 lines. - No database: JSON file persistence is intentional. Don't add SQLite/Postgres without discussion.
- German-first: UI text, card labels, and comments use German. Keep this convention.
Security Patterns
- Never commit:
.env,data/tasks.json,out/*.png(all in.gitignore) - Session secret: Hardcoded as
"CHANGE_THIS_SECRET"(line 18) - should be env var in production - Admin password: Must be set in
.envor app will crash on login attempt
Font Asset Management
- Custom fonts in
app/static/fonts/(committed to repo) - Font Awesome 7.1.0 desktop OTFs (committed) - use Solid 900 weight for card icons
- Paths defined as constants at top of
main.py- update these if fonts move - Required fonts:
FONT_BOLD,FONT_REGULAR,FA_FONT
Task Status Lifecycle
Tasks have exactly 3 states: pending → approved → printed
- Users can only submit (creates
pending) - Admins can approve (
pending→approved) - Anyone can print
approvedtasks - Admins can re-print
printedtasks
Integration Points
Thermal Printer (ESC/POS)
- Library:
python-escposv3.1 - Connection: Serial over USB (
/dev/ttyUSB0on Linux,/dev/tty.usbserial-*on macOS) - Baudrate: 19200 (standard for Arduino thermal printers)
- See
WIRING.mdfor Raspberry Pi GPIO wiring diagram - Permissions: User must be in
dialoutgroup on Linux
Font Awesome Integration
- Version: 7.1.0 Free (Solid weight)
- Format: OTF desktop fonts (not web fonts)
- Icon mapping: Manual unicode lookup required for new icons
- Path:
app/static/fonts/fontawesome-free-7.1.0-desktop/otfs/Font Awesome 7 Free-Solid-900.otf
Critical Code Sections
Card Rendering Logic (lines 142-239)
Complex Pillow-based layout with:
- Dynamic text wrapping based on pixel width (not character count)
- Vertical centering calculation using
getbbox()for text height - Icon positioning in lower-right corner
- Border and padding calculations for 354×236px card
Common pitfalls:
- Font methods (
getlength(),getbbox()) may fail if font is None - wrap in try/except - Text wrapping happens twice: word-based via
textwrap, then pixel-based - Changing card dimensions requires recalculating all spacing
Task Persistence (lines 65-70)
Simple load/save pattern - no locking or concurrency control:
tasks: List[Task] = load_tasks() # On startup
save_tasks() # After every mutation
Risk: Race conditions if multiple requests mutate simultaneously. Not handled - single-user/low-traffic assumption.
Platform-Specific Notes
macOS Development
- Printer device likely
/dev/tty.usbserial-*(checkls /dev/tty.*) - Use
DEBUG_PRINT_TO_IMAGE = Truefor testing without hardware - Font paths may need adjustment (DejaVu fonts not standard on macOS)
Raspberry Pi Deployment
- Enable UART/serial interface via
raspi-config - Add user to
dialoutgroup:sudo usermod -a -G dialout $USER - Default device
/dev/ttyUSB0should work for USB-serial printers - See
WIRING.mdfor GPIO hardware serial wiring (pins 8/10)
When Making Changes
Adding New Routes
- Follow existing pattern: FastAPI route → mutate
taskslist → callsave_tasks()→ redirect with session flash message - Admin-only routes: Check
request.session.get("admin")first
Modifying Card Layout
- Update constants:
CARD_WIDTH_PX,CARD_HEIGHT_PX(lines 25-26) - Test with
DEBUG_PRINT_TO_IMAGE = Truebefore printing to hardware - Remember to update BOTH debug and production print branches
Adding Icon Keywords
- Extend
KEYWORD_ICONSlist (lines 33-58) - Use Font Awesome unicode lookup: https://fontawesome.com/v7/icons
- Format:
(['keyword'], '\ufXXX')where XXX is FA codepoint
Last updated: 2025-11-20