Web application for filtering and customizing iCalendar feeds. Subscribe to calendars, apply custom filters, and get a personalized iCal feed URL.
Live Application: https://filter-ical.de
Filter-iCal allows users to:
- Subscribe to existing iCalendar feeds
- Apply custom filters to events (by keyword, date range, category, etc.)
- Generate a new filtered iCal feed URL
- Subscribe to the filtered feed in any calendar application
Use Case: Remove unwanted events, focus on specific categories, or customize shared calendars without modifying the source.
Backend
- Python 3.11+ with FastAPI
- PostgreSQL 16 (user data, filters, subscriptions)
- Uvicorn ASGI server with hot reload
- Alembic for database migrations
Frontend
- Vue 3 with Composition API
- Pinia for state management
- Tailwind CSS v4
- Vite build tool with hot reload
- Vue DevTools integration
Infrastructure
- AWS Lambda (Python 3.13, serverless compute)
- AWS RDS PostgreSQL (t4g.micro, Single-AZ)
- CloudFront + S3 (frontend hosting)
- EventBridge (scheduled calendar sync every 30 min)
- SST v3 (infrastructure as code)
- Python 3.11+
- Node.js 20+
- Docker (for PostgreSQL)
- WSL2 (if on Windows)
# Clone repository
git clone https://github.com/duersjefen/filter-ical.git
cd filter-ical
# Start full environment (PostgreSQL + Backend + Frontend)
make devAccess:
- Frontend: http://localhost:8000 (auto-increments to 8001, 8002 if port in use)
- Backend API: http://localhost:3000 (auto-increments to 3001, 3002 if port in use)
- API Docs: http://localhost:3000/docs
- PostgreSQL: localhost:5432
Development Features:
- β Hot reload for both frontend and backend
- β Vue DevTools automatically available
- β PostgreSQL in Docker (no local install needed)
- β Automatic dependency installation
- β Multiple dev instances can run simultaneously (auto port increment)
- β Isolated dev AWS resources (separate CloudFormation stacks)
# Development
make dev # Start all services (dev stage)
make stop # Stop database (ports auto-increment if in use)
make health # Check service status
make reset-db # Reset local database
# Testing
make test # Run unit tests
make test-all # Run complete test suite
make preview # Build and test production frontend locally
# SST Deployment (Full Stack: Lambda + RDS + S3)
npx sst deploy --stage staging # Deploy full stack to staging.filter-ical.de
npx sst deploy --stage production # Deploy full stack to filter-ical.de
npx sst remove --stage dev # Remove dev stage AWS resources
npx sst console # Open SST console (monitoring, logs)
# Database
make reset-db # Reset local database
make logs-db # View PostgreSQL logsWhy Native? Maximum performance with instant hot reload.
- Backend: Native Python with uvicorn (hot reload on .py changes)
- Frontend: Native Node.js with Vite (hot reload on .vue/.js changes)
- Database: Docker PostgreSQL (consistent, isolated, disposable)
This hybrid approach combines the speed of native development with the consistency of containerized databases.
filter-ical/
βββ backend/
β βββ app/
β β βββ data/ # Pure functions (business logic)
β β βββ main.py # FastAPI app (I/O orchestration)
β β βββ core/ # Configuration, middleware
β βββ tests/ # pytest unit + integration tests
β βββ alembic/ # Database migrations
β
βββ frontend/
β βββ src/
β β βββ components/ # Vue 3 components
β β βββ composables/ # Pure functions (data transformations)
β β βββ stores/ # Pinia stores (state + I/O)
β β βββ views/ # Page-level components
β βββ tests/ # Vitest + Playwright E2E tests
β
βββ docker-compose.dev.yml # PostgreSQL only (for local dev)
1. Functional Core, Imperative Shell
- Pure functions in
/data/and/composables/ - Side effects isolated in
main.pyand stores - 100% testable business logic
2. Contract-Driven Development
- OpenAPI specifications define API contracts
- Contract tests ensure compliance
- Frontend and backend develop independently
3. Test-First Development (TDD)
- Write failing tests first (
@pytest.mark.future) - Implement minimum code to pass
- Refactor safely with test coverage
| Environment | URL | Database | AWS Resources | Trigger |
|---|---|---|---|---|
| Dev | http://localhost:8000 | filterical_development |
Isolated CloudFormation stacks | npm run dev |
| Staging | https://staging.filter-ical.de | RDS staging | Lambda + RDS + CloudFront | npx sst deploy --stage staging |
| Production | https://filter-ical.de | RDS production | Lambda + RDS + CloudFront | npx sst deploy --stage production |
Note: Each stage has completely isolated AWS resources (separate Lambda functions, RDS instances, CloudFormation stacks).
# 1. Develop locally
npm run dev # SST dev mode with hot reload
# 2. Run tests
cd backend && pytest tests/ -m unit -v
# 3. Commit changes
git add .
git commit -m "Add feature X"
git push
# 4. Deploy to staging (full stack: Lambda + RDS + S3)
npx sst deploy --stage staging
# 5. Run migrations
npx sst shell --stage staging --command "cd backend && alembic upgrade head"
# 6. Verify on staging
curl https://api-staging.filter-ical.de/health
# 7. Deploy to production
npx sst deploy --stage production
npx sst shell --stage production --command "cd backend && alembic upgrade head"- AWS CLI: Configured with
filter-icalprofile - AWS Region: eu-north-1 (Stockholm)
- Node.js: 20+ (for SST)
- Secrets: Set via
npx sst secret set(see CLAUDE.md)
AWS Lambda + RDS: eu-north-1
- Backend: Lambda Python 3.13 (FastAPI + Mangum)
- Sync Task: Lambda (EventBridge, every 30 min)
- Database: RDS PostgreSQL 16 (t4g.micro)
- Frontend: CloudFront + S3 (Vue 3 SPA)
- Infrastructure: SST v3 (TypeScript)
Cost: ~$17/month (Lambda free tier + RDS $12 + CloudFront $2 + Secrets $2.40)
PostgreSQL runs in Docker (no local installation needed):
# Connection details
Host: localhost
Port: 5432
Database: filterical_development
User: filterical_dev
Password: dev_password_change_meALWAYS use Alembic for schema changes:
cd backend
# Create migration
alembic revision --autogenerate -m "Add user preferences table"
# Apply migration
alembic upgrade head
# Rollback migration
alembic downgrade -1- Unit Tests: Pure functions, business logic (
tests/unit/) - Integration Tests: API endpoints, database interactions (
tests/integration/) - E2E Tests: Full user workflows with Playwright (headless only)
- Contract Tests: OpenAPI specification compliance
# Fast unit tests (for commits)
make test
# Complete test suite
make test-all
# Frontend tests
cd frontend && npm test
# E2E tests (headless)
cd frontend && npm run test:e2eBoth servers automatically reload on file changes:
- Backend: Changes to
.pyfiles trigger uvicorn reload - Frontend: Changes to
.vue/.jsfiles trigger Vite HMR
No manual restarts needed!
make healthShows status of:
- PostgreSQL container
- Backend API
- Frontend dev server
Frontend: Vue DevTools available at http://localhost:8000 Backend: Interactive API docs at http://localhost:3000/docs
Port 3000 or 8000 already in use:
- No action needed! SST/Vite automatically increment to next available port
- Multiple dev instances can run simultaneously
Port 5432 already in use:
docker ps -a | grep postgres
docker stop <container-name>Services won't start:
make stop
make devDatabase needs reset:
make reset-db
cd backend && alembic upgrade headClean up dev stage AWS resources:
make sst-remove-dev- CLAUDE.md - AI assistant instructions (architecture principles, TDD workflow)
- Create feature branch:
git checkout -b feature/your-feature - Write tests first (TDD workflow)
- Implement feature
- Run tests:
make test - Commit:
git commit -m "Add feature X" - Push:
git push origin feature/your-feature - Create Pull Request
Code Review Checklist:
- β
Tests pass (
make test-all) - β Pure functions have no side effects
- β API changes documented in OpenAPI spec
- β Database migrations included (if schema changed)
- β No console.log statements
- β Follows naming conventions (no "New", "Updated", etc.)
[Your License Here]
Maintained by: [Your Name/Team] Production Status: β Live at https://filter-ical.de