Backend Architecture
The backend is a Rails 8.1 API application running on PostgreSQL with Solid Queue for background jobs.
Rails Conventions
The app follows standard Rails conventions with a few project-specific patterns:
- API-only mode -- No views, sessions, or cookies. All responses are JSON.
- Namespaced controllers -- All API controllers live under
Api::V1::and inherit fromBaseController, which providesauthenticate_user!andcurrent_user. ApplicationControllervsBaseController--ApplicationControlleris the Rails default.BaseControlleradds JWT authentication. Controllers that need unauthenticated access (like webhooks) skip the before action.
Service Objects
Complex business logic is extracted into service objects under app/services/:
| Service | Purpose |
|---|---|
Ai::TaskParser | Calls Claude Haiku to parse NL into task fields |
Ai::TaskEditor | Calls Claude Haiku to parse NL edit instructions |
Ai::SuggestionGenerator | Generates proactive task suggestions |
JwtService | Encodes/decodes JWT tokens (access + refresh) |
ExpoPushService | Sends push notifications via Expo Push API |
DeepgramService | Generates temporary Deepgram API keys |
RevenuecatService | Syncs subscription state from RevenueCat |
Background Jobs (Solid Queue)
Solid Queue is configured as the default queue adapter. Jobs are stored in the database, eliminating the need for Redis.
| Job | Trigger | Purpose |
|---|---|---|
WeeklyDigestJob | Cron (Sunday, via recurring.yml) | Sends weekly summary push notification |
SendPushNotificationJob | Enqueued by other jobs/services | Delivers a push notification via Expo API |
SyncSubscriptionJob | Enqueued by webhook or manual sync | Syncs user tier from RevenueCat |
Cron schedules are defined in config/recurring.yml.
Database Schema Overview
Key tables:
| Table | Purpose |
|---|---|
users | Auth, subscription tier, points, streak data |
tasks | Core task data with recurrence, reminders, assignment |
task_completions | One row per completion event (for streaks/stats) |
categories | 8 predefined categories (seeded) |
households | Family groups with invite codes |
device_tokens | Expo push tokens per user/device |
pomodoro_sessions | Focus timer sessions (per task) |
Key relationships:
- A
Taskbelongs to aUser(creator) and optionally to anassigned_touser and aHousehold - A
Useroptionally belongs to aHousehold - A
Householdhas anowner(User) and manymembers(Users)
Structured Logging
Lograge is configured (config/initializers/lograge.rb) to output structured JSON logs. Each request log includes:
- HTTP method, path, status, duration
- Controller, action
- User ID (from JWT)
- Request parameters (filtered)
Monitoring
New Relic APM is configured via config/newrelic.yml for production performance monitoring.
Security
- Brakeman for static security analysis
- Bundler Audit for dependency vulnerability scanning
- RuboCop for code style enforcement
- All three run in CI before merge