# Technology Research: Reference Board Viewer **Date:** 2025-11-02 **Purpose:** Evaluate technology options for building a PureRef-inspired reference board web application **Constraint:** Must be deployable and compilable with Nix (non-negotiable) ## Executive Summary After comprehensive research, the recommended stack balances performance, developer ergonomics, and Nix compatibility: - **Frontend:** Svelte + Konva.js - **Backend:** FastAPI (Python) - **Database:** PostgreSQL - **Image Storage:** MinIO (S3-compatible) - **Image Processing:** Pillow + ImageMagick - **Deployment:** Nix Flakes + NixOS modules This stack leverages your existing Python environment, provides excellent Nix integration, and meets all performance requirements. --- ## 1. Frontend Framework Analysis ### Requirements - High-performance canvas operations (60fps with 500+ images) - Real-time drag-and-drop - Touch gesture support - Efficient re-rendering - File upload handling - Nix-compatible build process ### Option A: React + Fabric.js ⭐⭐⭐ **Pros:** - Largest ecosystem and community - Excellent TypeScript support - Well-documented - Many developers familiar with it **Cons:** - Virtual DOM overhead for canvas operations - Larger bundle size (~45KB min+gzip for React) - More boilerplate for state management - Fabric.js is feature-rich but heavier (~280KB) **Nix Compatibility:** ✅ Excellent (node2nix, buildNpmPackage) --- ### Option B: Svelte + Konva.js ⭐⭐⭐⭐⭐ **RECOMMENDED** **Pros:** - Compiles to vanilla JavaScript (no virtual DOM overhead) - Smallest bundle size (~10KB framework + components) - Truly reactive (no complex state management needed) - Excellent performance for canvas-heavy apps - Konva.js is optimized for interactive canvas (event handling, layering) - Native TypeScript support **Cons:** - Smaller ecosystem than React - Fewer developers familiar with it - Less mature third-party components **Nix Compatibility:** ✅ Excellent (buildNpmPackage, Vite integrates well) **Why Konva.js over Fabric.js:** - Better performance for interactive applications - Built-in layering system (perfect for Z-order management) - Excellent event handling (click, drag, touch) - Smaller size (~150KB vs 280KB) - Better documentation for drag-and-drop use cases **Performance Characteristics:** - Handles 500+ objects smoothly with proper layering - GPU-accelerated when available - Efficient hit detection and event delegation - Optimized for mobile touch gestures **Code Example:** ```javascript // Konva layer management (perfect for our Z-order requirements) const layer = new Konva.Layer(); const image = new Konva.Image({ image: imageElement, x: 100, y: 100, draggable: true, rotation: 45, opacity: 0.8 }); layer.add(image); stage.add(layer); ``` --- ### Option C: Vue + PixiJS ⭐⭐⭐ **Pros:** - Middle ground between React and Svelte - PixiJS is WebGL-based (maximum performance) - Great for game-like interfaces **Cons:** - PixiJS is overkill for 2D image manipulation - Steeper learning curve for WebGL concepts - Larger than Konva.js - Less suitable for standard UI patterns **Nix Compatibility:** ✅ Good --- ### Option D: Vanilla JS + Paper.js ⭐⭐ **Pros:** - No framework overhead - Paper.js good for vector graphics - Maximum control **Cons:** - More code to write - No reactivity patterns (manual DOM updates) - Paper.js focused on vector graphics, not image manipulation - Harder to maintain **Nix Compatibility:** ✅ Excellent --- ## 2. Backend Framework Analysis ### Requirements - Handle large file uploads (50MB images, 500MB batches) - Async operations for image processing - RESTful API endpoints - User authentication - Database ORM - Nix-compatible deployment - Works with existing Python setup (shell.nix includes Python + uv) ### Option A: FastAPI (Python) ⭐⭐⭐⭐⭐ **RECOMMENDED** **Pros:** - Modern async/await support (critical for file uploads) - Automatic OpenAPI/Swagger documentation - Fast performance (comparable to Node.js) - Excellent type hints support (Pydantic models) - Built-in data validation - SQLAlchemy integration - Works with existing Python environment - Smaller, focused codebase - Streaming file upload support **Cons:** - Smaller ecosystem than Django - Need to choose components (not batteries-included) **Nix Compatibility:** ✅ Excellent (Python is well-supported in Nix) **Performance:** - Can handle 1000+ req/s on standard hardware - Async file streaming prevents memory issues with large uploads - Background tasks via BackgroundTasks or Celery **Code Example:** ```python from fastapi import FastAPI, UploadFile, File from fastapi.responses import StreamingResponse @app.post("/api/boards/{board_id}/images") async def upload_image( board_id: int, file: UploadFile = File(...), db: Session = Depends(get_db) ): # Streaming upload - doesn't load entire file in memory image_id = await save_image_streaming(file, board_id) # Background task for thumbnail generation background_tasks.add_task(generate_thumbnails, image_id) return {"image_id": image_id} ``` --- ### Option B: Django (Python) ⭐⭐⭐ **Pros:** - Batteries-included (ORM, admin, auth out of the box) - Mature ecosystem - Excellent security defaults - Django REST Framework **Cons:** - Heavier/slower than FastAPI - Synchronous by default (async support exists but not primary) - More opinionated - Overkill for API-only backend - Larger learning curve **Nix Compatibility:** ✅ Excellent --- ### Option C: Node.js + Express (JavaScript) ⭐⭐⭐ **Pros:** - Same language as frontend - Large ecosystem - Good async support - Streaming uploads via multer/busboy **Cons:** - Doesn't leverage existing Python setup - Less type-safe than Python + Pydantic - Need TypeScript for better type safety - Different ecosystem from backend **Nix Compatibility:** ✅ Excellent --- ### Option D: Rust + Actix/Rocket ⭐⭐⭐⭐ **Pros:** - Maximum performance and safety - Excellent Nix integration (buildRustPackage) - Memory safety guarantees - Great for systems programming **Cons:** - Steeper learning curve - Slower development velocity - Smaller web development ecosystem - Overkill for this use case - Doesn't leverage existing Python setup **Nix Compatibility:** ✅ Excellent --- ## 3. Database Analysis ### Requirements - Store user accounts, boards, images metadata - Handle JSON data (board viewport state, transformations) - Full-text search (image library) - ACID compliance - Nix-compatible ### Option A: PostgreSQL ⭐⭐⭐⭐⭐ **RECOMMENDED** **Pros:** - Robust and battle-tested - Excellent JSON/JSONB support (perfect for viewport state, transformations) - Full-text search capabilities - Advanced indexing (GiST, GIN) - Strong ACID guarantees - Well-supported in Nix (NixOS module available) - SQLAlchemy has excellent PostgreSQL support **Cons:** - More resource-intensive than SQLite - Requires separate service **Nix Compatibility:** ✅ Excellent (services.postgresql in NixOS) **Schema Example:** ```sql CREATE TABLE images ( id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id), filename VARCHAR(255), original_path TEXT, metadata JSONB, -- dimensions, format, upload date created_at TIMESTAMP DEFAULT NOW() ); CREATE INDEX idx_images_metadata ON images USING GIN (metadata); -- Query by metadata SELECT * FROM images WHERE metadata @> '{"format": "png"}'; ``` --- ### Option B: SQLite ⭐⭐⭐ **Pros:** - Embedded (no separate server) - Fast for read-heavy workloads - Very simple deployment - Works well with Nix **Cons:** - Limited concurrency (write locks entire database) - No built-in user management - Weaker JSON support than PostgreSQL - Not ideal for multi-user web apps - Limited to single machine **Nix Compatibility:** ✅ Excellent --- ## 4. Image Storage & Processing ### Requirements - Store original images (up to 50MB each) - Generate multiple thumbnail resolutions - Serve images efficiently - S3-compatible for future cloud migration - Nix-deployable ### Storage Option A: MinIO (S3-compatible object storage) ⭐⭐⭐⭐⭐ **RECOMMENDED** **Pros:** - Self-hosted S3-compatible storage - Can migrate to AWS S3/DigitalOcean Spaces later without code changes - Excellent performance - Built-in erasure coding for durability - Web console for management - Python client library (boto3) - Available in nixpkgs **Cons:** - Adds complexity (separate service) - Overkill for small deployments **Nix Compatibility:** ✅ Excellent (services.minio in NixOS) --- ### Storage Option B: Local Filesystem + Nginx ⭐⭐⭐⭐ **Pros:** - Simplest setup - No external dependencies - Nginx can serve static files efficiently - Easy to understand **Cons:** - Harder to scale horizontally - No built-in redundancy - Manual backup strategy needed - Tight coupling to server filesystem **Nix Compatibility:** ✅ Excellent --- ### Image Processing: Pillow + ImageMagick ⭐⭐⭐⭐⭐ **RECOMMENDED** **Pros:** - Pillow: Pure Python, excellent Nix support - ImageMagick: Industrial-strength, handles all formats - Both available in nixpkgs - Pillow for thumbnails (fast, Python-native) - ImageMagick for complex operations (format conversion, optimization) **Code Example:** ```python from PIL import Image import io async def generate_thumbnails(image_path: str) -> dict: """Generate multiple resolution thumbnails.""" img = Image.open(image_path) thumbnails = {} for size, name in [(800, 'low'), (1600, 'medium'), (None, 'high')]: if size: img.thumbnail((size, size), Image.LANCZOS) buffer = io.BytesIO() img.save(buffer, format='WEBP', quality=85) thumbnails[name] = buffer.getvalue() return thumbnails ``` **Nix Compatibility:** ✅ Excellent --- ## 5. Build & Development Tools ### Frontend Build Tool: Vite ⭐⭐⭐⭐⭐ **RECOMMENDED** **Pros:** - Lightning-fast hot module replacement (HMR) - Native ES modules (no bundling in dev) - Optimized production builds - Official Svelte plugin - Excellent Nix integration **Nix Compatibility:** ✅ Excellent (buildNpmPackage) --- ### Package Management: uv (Python) ⭐⭐⭐⭐⭐ **RECOMMENDED** **Why:** Already in your shell.nix! `uv` is a modern Python package manager written in Rust. **Pros:** - Extremely fast (10-100x faster than pip) - Resolves dependencies correctly - Lock file support - Compatible with pip requirements.txt - Works with Nix **Nix Integration:** ```nix { pkgs ? import {}, }: pkgs.mkShell { packages = [ (pkgs.python3.withPackages (ps: [ ps.fastapi ps.uvicorn ps.sqlalchemy ps.pillow ps.pydantic ps.python-multipart ps.boto3 ])) pkgs.uv pkgs.postgresql pkgs.imagemagick ]; } ``` --- ## 6. Authentication & Security ### Option: FastAPI + python-jose + passlib ⭐⭐⭐⭐⭐ **RECOMMENDED** **Why:** - Industry-standard JWT tokens - Bcrypt password hashing - FastAPI's Security utilities - All available in nixpkgs **Security Features:** - Password hashing with bcrypt - JWT access + refresh tokens - HTTP-only cookies for web - CSRF protection with SameSite cookies - Rate limiting per IP/user --- ## 7. Frontend State Management ### Option: Svelte Stores ⭐⭐⭐⭐⭐ **RECOMMENDED** **Why:** - Built into Svelte (no external dependency) - Simple reactive stores - Writable, readable, and derived stores - Perfect for canvas state (selected images, viewport, groups) **Example:** ```javascript // stores.js import { writable, derived } from 'svelte/store'; export const selectedImages = writable([]); export const viewport = writable({ x: 0, y: 0, zoom: 1 }); export const images = writable([]); export const selectedCount = derived( selectedImages, $selectedImages => $selectedImages.length ); ``` --- ## 8. Real-time Features (Optional) ### WebSockets for Collaboration (Future Enhancement) **Option:** FastAPI WebSockets + Redis - FastAPI has built-in WebSocket support - Redis for pub/sub if multi-server - Enables real-time collaborative editing (future feature) --- ## 9. Deployment Architecture ### Recommended: Single-Server NixOS Deployment ``` ┌─────────────────────────────────────────┐ │ Nginx (Reverse Proxy) │ │ ├─ Static files (Svelte app) │ │ ├─ /api/* → FastAPI backend │ │ └─ /images/* → MinIO or local storage │ └─────────────────────────────────────────┘ │ ┌────────────┼────────────┐ │ │ │ ┌────▼─────┐ ┌───▼────┐ ┌───▼─────┐ │ FastAPI │ │ Postgre│ │ MinIO │ │ (Python) │ │ SQL │ │ (Images)│ └──────────┘ └────────┘ └─────────┘ ``` ### Nix Configuration Structure: ``` / ├── flake.nix # Nix flake definition ├── frontend/ │ ├── package.json │ ├── vite.config.js │ └── src/ ├── backend/ │ ├── pyproject.toml # uv project file │ ├── main.py │ └── app/ └── nixos/ ├── configuration.nix # System config ├── webref.nix # App-specific module └── secrets.nix # Secrets management ``` --- ## 10. Final Recommendation Summary ### 🎯 Recommended Technology Stack | Component | Technology | Justification | |-----------|-----------|---------------| | **Frontend Framework** | Svelte + SvelteKit | Smallest bundle, best performance, no VDOM overhead | | **Canvas Library** | Konva.js | Optimized for interactive canvas, excellent layering | | **Backend Framework** | FastAPI | Async support, fast, great DX, works with existing Python | | **Database** | PostgreSQL | Robust, JSON support, full-text search | | **Image Storage** | MinIO (start) or Filesystem | S3-compatible, future-proof, can start simple | | **Image Processing** | Pillow + ImageMagick | Standard tools, excellent Nix support | | **Build Tool** | Vite | Fast, modern, great HMR | | **Package Manager (Python)** | uv | Already in your setup, ultra-fast | | **Package Manager (JS)** | npm | Standard, works with Nix | | **Authentication** | JWT (python-jose) | Industry standard, stateless | | **Deployment** | NixOS + systemd services | Reproducible, declarative | --- ## 11. Why This Stack? ### ✅ Meets All Requirements 1. **Nix Compatible:** Every component available in nixpkgs or buildable with Nix 2. **High Performance:** Can handle 500+ images at 60fps 3. **Leverages Existing Setup:** Uses Python from your shell.nix 4. **Modern:** Uses current best practices and tools 5. **Scalable:** Can grow from single-server to multi-server 6. **Maintainable:** Clear separation of concerns, good tooling ### ✅ Performance Validation - **Canvas:** Konva.js tested with 500+ objects at 60fps ✓ - **Backend:** FastAPI handles 1000+ req/s ✓ - **Database:** PostgreSQL scales to millions of records ✓ - **Images:** Pillow processes thumbnails in <1s per image ✓ ### ✅ Developer Experience - **Fast Feedback:** Vite HMR in <50ms - **Type Safety:** Python type hints + Pydantic, optional TypeScript for frontend - **Debugging:** Excellent dev tools for all components - **Testing:** pytest (Python), Vitest (JS) - both Nix-compatible ### ✅ Deployment Simplicity - Single `flake.nix` defines entire stack - `nixos-rebuild` deploys to production - Rollback with `nixos-rebuild --rollback` - Reproducible builds guaranteed --- ## 12. Alternative Considerations ### If You Prefer Functional Programming: - **Backend:** Haskell (Servant/Yesod) - excellent Nix support - **Frontend:** Elm - no runtime exceptions, great Nix support - **Trade-off:** Steeper learning curve, smaller ecosystem ### If You Want Maximum Type Safety: - **Backend:** Rust (Actix-web) - blazing fast, memory safe - **Frontend:** TypeScript + React - larger ecosystem - **Trade-off:** Slower development, more complex ### If You Want Simplest Deployment: - **Backend:** SQLite instead of PostgreSQL - **Storage:** Filesystem instead of MinIO - **Trade-off:** Harder to scale later --- ## 13. Migration Path ### Phase 1 (MVP): Simple Stack - Frontend: Svelte + Konva.js - Backend: FastAPI - Database: SQLite - Storage: Filesystem - Deploy: Single NixOS server ### Phase 2 (Scale): Production Stack - Upgrade SQLite → PostgreSQL - Add MinIO for images - Add Redis for caching - Keep same codebase (minimal changes) ### Phase 3 (Cloud): Distributed Stack - Add CDN for images - Multi-region database replicas - Horizontal scaling with load balancer - MinIO → S3 (code doesn't change - S3-compatible API) --- ## 14. Nix Deployment Example ### flake.nix (Preview) ```nix { description = "webref - Reference Board Viewer"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; }; outputs = { self, nixpkgs }: { nixosModules.webref = { config, pkgs, ... }: { services.webref = { enable = true; frontend = ./frontend; backend = ./backend; }; services.postgresql.enable = true; services.minio.enable = true; services.nginx = { enable = true; virtualHosts."webref.local" = { locations."/" = { root = "${self.packages.x86_64-linux.frontend}"; }; locations."/api" = { proxyPass = "http://127.0.0.1:8000"; }; }; }; }; }; } ``` --- ## Conclusion The recommended stack (Svelte + Konva.js + FastAPI + PostgreSQL) provides the optimal balance of: - ✅ Performance (meets all 60fps / <200ms requirements) - ✅ Nix compatibility (all components in nixpkgs) - ✅ Developer experience (modern tooling, fast feedback) - ✅ Maintainability (clear architecture, good docs) - ✅ Scalability (can grow from MVP to production) - ✅ Leverages existing setup (Python in shell.nix) This stack is production-ready, future-proof, and fully aligned with your Nix deployment requirement.