System overview
Technology stack
Runtime and tools
- Bun - Primary runtime for API and build tooling
- Bun workspaces - Monorepo management
- Node.js 24 - Required for certain tooling
- Docker - Containerization and PostgreSQL
Backend
Elysia
Fast, type-safe web framework for Bun with automatic OpenAPI generation
Drizzle ORM
Type-safe ORM with
bun:sql adapter for PostgreSQLBetterAuth
Authentication library with passkey support and OAuth providers
ical.js
ICS parsing library for calendar event extraction
Frontend
Vue 3
Reactive UI framework with Composition API
Vite
Fast build tool with HMR
DaisyUI
Tailwind CSS component library
Workbox
Service worker for offline PWA functionality
Testing
- Bun test - Unit and integration tests
- Playwright - End-to-end browser tests
Architecture principles
Offline-first
PlanningSup is designed to work without network connectivity:- Service worker caches app shell and assets
- Database backups store ICS data for offline access
- Network-first strategy with DB fallback
- Background sync refreshes stale data when online
Type safety
End-to-end type safety across the stack:- Drizzle generates types from database schema
- Elysia provides runtime validation with compile-time types
- Eden Treaty enables type-safe API client (
packages/libs/src/client/) - BetterAuth generates session and user types
Clients use the Eden Treaty client instead of raw
fetch() for automatic type inference and IDE autocomplete.Monorepo structure
Bun workspaces organize code into focused packages:apps/*- Deployable applicationspackages/*- Shared libraries and configsresources/*- Static data (planning JSON files)test/*- Test suites
Data flow
Planning request lifecycle
API resolves planning
The API:
- Looks up planning in
flattenedPlannings(loaded from JSON at startup) - Deduplicates concurrent requests for the same planning
- Attempts to fetch ICS from upstream URL
Network-first strategy
- Network success
- Network failure
- Parse ICS events
- Return formatted events
- Asynchronously write to database backup
Event parsing pipeline
- Blocklist filtering - Hide events matching keywords
- Category detection - Classify as lecture/lab/tutorial
- Timezone conversion - Convert between user and target timezones
- Teacher highlighting - Identify events missing teacher info
- Location cleanup - Normalize location strings
Database backup system
PlanningSup maintains PostgreSQL backups for offline resilience:- Backup tables
- Backfill job
- Refresh worker
plannings- Metadata for each planning (fullId, title, etc.)
plannings_backup- ICS event data (JSON column)
- Last updated timestamp
plannings_refresh_state- Last successful fetch
- Consecutive failures
- Disabled until timestamp
plannings_refresh_queue- Priority queue for background refreshes
- Retry attempts and next attempt time
Background jobs
Jobs run whenRUN_JOBS=true:
- Backfill interval increases
- Refresh retries are delayed
- Workers remain idle unless queue is very backed up
Authentication system
BetterAuth integration
WhenAUTH_ENABLED=true, PlanningSup uses BetterAuth for:
- OAuth providers - Discord, GitHub
- Passkey authentication - WebAuthn/FIDO2
- User preferences sync - Syncs settings across devices
User data model
BetterAuth extends the user table with custom fields:Preferences sync
apps/web/src/composables/useUserPrefsSync.ts implements bidirectional sync:
Merge with local
Use
prefsMeta timestamps to resolve conflicts:- If server value is newer, use it
- If local value is newer, push to server
API design
OpenAPI documentation
Elysia automatically generates OpenAPI specs from route definitions:- Automatic request validation
- Type-safe parameters
- OpenAPI schema generation
- API documentation UI
Response schemas
API responses include structured metadata:Eden Treaty client
Type-safe API client inpackages/libs/src/client/:
Frontend architecture
Vue 3 Composition API
All components use<script setup> with Composition API:
State management
PlanningSup uses Vue’s reactivity system and composables rather than Vuex/Pinia:useUserPrefsSync- User preferences and authusePlanning- Selected planning and eventsuseCalendar- Calendar view state
PWA architecture
Service worker (apps/web/public/sw.js):
- Precaches app shell and critical assets
- Uses Workbox for cache strategies
- Handles offline fallbacks
apps/web/public/manifest.json):
- Defines PWA metadata
- Icon sets for all platforms
- Display mode and theme colors
- Desktop via browser prompt
- Mobile via “Add to Home Screen”
- Tauri for native desktop experience
Desktop and mobile
Tauri application
apps/app/ wraps the Vue PWA in a native shell:
- Rust backend - Native OS integration
- Web frontend - Reuses Vue app
- Deep links - OAuth callback handling
- System tray - Quick access on desktop
Browser extension
apps/extension/ provides one-click planning access:
- Reads university domain from current tab
- Opens planning page with pre-selected university
- Available on Chrome Web Store
Performance optimizations
Request deduplication
Concurrent requests for the same planning are coalesced:Database indexing
Critical indexes for query performance:plannings_backup.planning_full_id- Unique index for O(1) lookupsplannings_refresh_queue.next_attempt_at- Index for queue pollingplannings_refresh_state.disabled_until- Index for filtering disabled plannings
Caching strategies
- Planning metadata - Loaded once at startup, cached in memory
- ICS data - Network-first with DB fallback
- Static assets - Precached by service worker
- API responses - No server-side caching (always fresh)
Security considerations
Input validation
All API inputs are validated with Elysia’s type system:CORS configuration
Strict CORS policy usingTRUSTED_ORIGINS:
Operations security
Admin endpoints requirex-ops-token header:
OPS_TOKEN makes endpoints return 404 (not 401) to avoid discovery.
Authentication security
- Passkeys - FIDO2/WebAuthn for phishing-resistant auth
- OAuth - Uses BetterAuth’s secure flow with state validation
- Session tokens - HTTP-only cookies with CSRF protection
- Rate limiting - Built into BetterAuth (100 req/min, 5 req/10s for passkeys)
Monitoring and operations
Health endpoints
/api/ping - Simple health check:
/api/ops/plannings - Detailed system health:
- Queue statistics (depth, ready, locked)
- Backup coverage (total, covered, disabled)
- Worker states (backfill, refresh worker)
- Recent failures by host and planning
- Last backup write info
Logging
Structured logging with Elysia logger:Docker health checks
Built into the image:Deployment architecture
Single-server deployment
High-availability deployment
Future architecture considerations
Potential enhancements:
- Redis for distributed caching and job queues
- Separate job worker containers (horizontal scaling)
- GraphQL API for complex client queries
- WebSocket support for real-time updates
- S3/object storage for planning JSON files
- Multi-region deployment with geo-routing
Next steps
Contributing
Start contributing to PlanningSup
API reference
Explore the API endpoints