chore: initial project setup
Initialize Sneaky Klaus project with: - uv package management and pyproject.toml - Flask application structure (app.py, config.py) - SQLAlchemy models for Admin and Exchange - Alembic database migrations - Pre-commit hooks configuration - Development tooling (pytest, ruff, mypy) Initial structure follows design documents in docs/: - src/app.py: Application factory with Flask extensions - src/config.py: Environment-based configuration - src/models/: Admin and Exchange models - migrations/: Alembic migration setup 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
179
docs/decisions/0001-core-technology-stack.md
Normal file
179
docs/decisions/0001-core-technology-stack.md
Normal file
@@ -0,0 +1,179 @@
|
||||
# 0001. Core Technology Stack
|
||||
|
||||
Date: 2025-12-22
|
||||
|
||||
## Status
|
||||
|
||||
Accepted (Updated 2025-12-22)
|
||||
|
||||
## Context
|
||||
|
||||
Sneaky Klaus is a self-hosted Secret Santa organization application designed for individuals, families, and small organizations who want full control over their data. The application must be:
|
||||
|
||||
- Easy to self-host via containerization
|
||||
- Simple to deploy and maintain
|
||||
- Minimal in external dependencies
|
||||
- Suitable for small-scale usage (dozens of participants, not thousands)
|
||||
- Functional without complex infrastructure
|
||||
|
||||
Key requirements that inform technology choices:
|
||||
|
||||
1. **Self-hosting first**: Users should be able to deploy with a single container
|
||||
2. **Simplicity**: The tech stack should be straightforward and well-documented
|
||||
3. **No participant accounts**: Authentication must support passwordless magic links
|
||||
4. **Email delivery**: Must send transactional emails reliably
|
||||
5. **Background jobs**: Must handle scheduled tasks (reminders, data purging)
|
||||
6. **Data persistence**: Must store user data reliably but doesn't need high-scale database features
|
||||
|
||||
## Decision
|
||||
|
||||
We will use the following core technology stack:
|
||||
|
||||
| Component | Technology | Version Constraint |
|
||||
|-----------|------------|-------------------|
|
||||
| **Backend Framework** | Flask | ^3.0 |
|
||||
| **Language** | Python | ^3.11 |
|
||||
| **Database** | SQLite | ^3.40 (via Python stdlib) |
|
||||
| **Email Service** | Resend | Latest SDK |
|
||||
| **Deployment** | Docker | Latest |
|
||||
| **Package Manager** | uv | Latest |
|
||||
| **Background Jobs** | APScheduler | ^3.10 |
|
||||
| **Template Engine** | Jinja2 | ^3.1 (Flask default) |
|
||||
| **WSGI Server** | Gunicorn | ^21.0 (production) |
|
||||
| **Form Handling** | Flask-WTF (includes WTForms) | ^1.2 |
|
||||
| **Session Management** | Flask-Session | ^0.8 |
|
||||
| **Timezone Validation** | pytz | Latest |
|
||||
| **CSS Framework** | Pico CSS | Latest (via CDN) |
|
||||
|
||||
### Key Technology Rationale
|
||||
|
||||
**Flask**: Lightweight, well-documented, excellent for small-to-medium applications. Large ecosystem, straightforward patterns, and no unnecessary complexity.
|
||||
|
||||
**Python 3.11+**: Modern Python with performance improvements, excellent type hinting support, and active security support.
|
||||
|
||||
**SQLite**: Perfect for self-hosted applications. Zero-configuration, single-file database, excellent for read-heavy workloads with occasional writes. Eliminates need for separate database server.
|
||||
|
||||
**Resend**: Modern transactional email API with excellent deliverability, simple API, and reasonable pricing for small-scale usage.
|
||||
|
||||
**Docker**: Industry-standard containerization. Single container deployment simplifies self-hosting significantly.
|
||||
|
||||
**uv**: Fast, modern Python package manager and project manager. Significantly faster than pip, with better dependency resolution and lockfile support.
|
||||
|
||||
**APScheduler**: In-process job scheduling. Eliminates need for separate job queue infrastructure (Redis, Celery) while still supporting background tasks like reminder emails and data purging.
|
||||
|
||||
**Jinja2**: Flask's default templating engine. Server-side rendering eliminates need for frontend JavaScript framework, simplifying deployment and maintenance.
|
||||
|
||||
**Gunicorn**: Production-ready WSGI server for Flask applications. Well-tested, stable, and appropriate for the scale of this application.
|
||||
|
||||
**Flask-WTF**: Integrates WTForms with Flask, providing form validation, CSRF protection, and secure form handling. Industry-standard for Flask applications.
|
||||
|
||||
**Flask-Session**: Server-side session management for Flask. Stores session data in SQLite, providing secure session handling without client-side storage concerns.
|
||||
|
||||
**pytz**: Standard Python library for timezone validation and handling. Required for validating IANA timezone names in exchange configurations.
|
||||
|
||||
**Pico CSS**: Minimal, classless CSS framework delivered via CDN. Provides clean, semantic styling without requiring a build step or complex class names. Fully responsive and accessible out of the box.
|
||||
|
||||
### Frontend Approach
|
||||
|
||||
**Pure server-side rendering** with Jinja2 templates. No JavaScript framework (React, Vue, etc.). This decision:
|
||||
|
||||
- Eliminates build tooling complexity
|
||||
- Reduces deployment artifacts (no separate frontend bundle)
|
||||
- Simplifies security (no client-side state management)
|
||||
- Ensures full functionality without JavaScript enabled
|
||||
- Maintains mobile-friendliness through responsive CSS
|
||||
|
||||
Progressive enhancement with minimal JavaScript for interactivity (copy-to-clipboard, form validation) is acceptable but not required for core functionality.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- **Simple deployment**: Single container with no external service dependencies (except Resend for email)
|
||||
- **Low resource requirements**: SQLite and in-process job scheduling minimize memory and CPU usage
|
||||
- **Fast development**: Flask's simplicity and Jinja2's straightforward templating accelerate development
|
||||
- **Easy debugging**: All code runs in single process, simplifying troubleshooting
|
||||
- **Predictable performance**: Server-side rendering is fast and consistent
|
||||
- **No build step**: Templates render directly; no frontend compilation required
|
||||
- **Security by default**: Server-side rendering reduces attack surface compared to client-side SPAs
|
||||
- **Excellent for scale target**: Perfect for dozens to hundreds of participants per deployment
|
||||
|
||||
### Negative
|
||||
|
||||
- **SQLite limitations**: Not suitable if application needs to scale to thousands of concurrent users (not a concern for target use case)
|
||||
- **No horizontal scaling**: Single SQLite file prevents multi-instance deployment (acceptable trade-off for simplicity)
|
||||
- **Email vendor lock-in**: Resend is the only supported email provider (could be abstracted later if needed)
|
||||
- **APScheduler constraints**: Job scheduling tied to application process lifetime; jobs don't survive application restarts (acceptable for reminder scheduling)
|
||||
- **Less interactive UI**: Server-side rendering means no SPA-style instant interactivity (acceptable trade-off for simplicity)
|
||||
|
||||
### Neutral
|
||||
|
||||
- **Python expertise required**: Development requires Python knowledge (expected for Flask application)
|
||||
- **Database portability**: SQLite schema could be migrated to PostgreSQL if scaling needs change, but would require development effort
|
||||
- **Email testing**: Requires Resend account for development (free tier available) or mocking in tests
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
### Database Considerations
|
||||
|
||||
SQLite will be configured with:
|
||||
- WAL (Write-Ahead Logging) mode for better concurrency
|
||||
- Foreign keys enabled
|
||||
- Appropriate timeout for locked database scenarios
|
||||
- Regular backups recommended via volume mounts
|
||||
|
||||
### Job Scheduling Considerations
|
||||
|
||||
APScheduler will run in-process with:
|
||||
- JobStore backed by SQLite for job persistence across restarts (for scheduled jobs)
|
||||
- Executor using thread pool for background tasks
|
||||
- Misfire grace time configured appropriately for reminders
|
||||
|
||||
### Email Configuration
|
||||
|
||||
Resend integration will:
|
||||
- Store API key in environment variable (not in code)
|
||||
- Support template-based emails
|
||||
- Handle failures gracefully with logging
|
||||
- Rate limit appropriately
|
||||
|
||||
### Development vs Production
|
||||
|
||||
- **Development**: Flask development server, SQLite in local file
|
||||
- **Production**: Gunicorn with multiple workers, SQLite in mounted volume, proper logging
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
### Database Alternatives
|
||||
|
||||
**PostgreSQL**: More scalable but requires separate database container/service, significantly complicating self-hosting. Overkill for target scale.
|
||||
|
||||
**MySQL/MariaDB**: Same drawbacks as PostgreSQL for this use case.
|
||||
|
||||
### Job Queue Alternatives
|
||||
|
||||
**Celery + Redis**: More robust job processing but requires Redis container, significantly complicating deployment. Overkill for reminder emails and daily data purging tasks.
|
||||
|
||||
**Cron + separate script**: Could work but fragments application logic and complicates deployment.
|
||||
|
||||
### Email Service Alternatives
|
||||
|
||||
**SendGrid**: Viable alternative but more complex API and pricing structure.
|
||||
|
||||
**Amazon SES**: Requires AWS account and more complex setup. Higher barrier for self-hosters.
|
||||
|
||||
**SMTP**: Requires users to configure their own SMTP server, significantly increasing setup complexity and deliverability issues.
|
||||
|
||||
### Frontend Alternatives
|
||||
|
||||
**React/Vue SPA**: Considered but rejected. Would require build tooling, increase deployment complexity, and provide minimal benefit for the application's relatively simple UI needs.
|
||||
|
||||
**HTMX**: Considered for progressive enhancement. May be added later but not required for MVP.
|
||||
|
||||
## References
|
||||
|
||||
- Flask documentation: https://flask.palletsprojects.com/
|
||||
- SQLite documentation: https://www.sqlite.org/docs.html
|
||||
- Resend documentation: https://resend.com/docs
|
||||
- APScheduler documentation: https://apscheduler.readthedocs.io/
|
||||
- uv documentation: https://docs.astral.sh/uv/
|
||||
Reference in New Issue
Block a user