|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +Flaredown is a chronic-illness symptom tracker. It is a monorepo with three deployable apps: |
| 6 | + |
| 7 | +- `backend/` — Rails 7.1 API (Ruby 3.2.3), the only backend for all clients. |
| 8 | +- `frontend/` — Ember.js 2.18 web app (the production web client at app.flaredown.com), proxies API calls to the backend. |
| 9 | +- `native/` — Expo / React Native + TypeScript app (newer, in-progress replacement for the Ember client). |
| 10 | + |
| 11 | +The root `app/` directory is a stray remnant (single `g-recaptcha.js`), not a fourth app. |
| 12 | + |
| 13 | +## Commands |
| 14 | + |
| 15 | +Everything is Dockerized; `make` wraps `docker compose`. Prefer these over running services natively. |
| 16 | + |
| 17 | +- `make start` / `make stop` — run the full dev stack (backend + workers + Ember frontend) via the `dev` profile. |
| 18 | +- `make startNative` / `make stopNative` — run backend + React Native (`native` profile). |
| 19 | +- `make build` — rebuild the backend image. Do this before running specs if backend code/deps changed. |
| 20 | +- `make seed` — seed databases (`rails app:setup`). |
| 21 | +- `make console` — Rails console. |
| 22 | +- Web app: http://localhost:4300 (Ember). Native: http://localhost:19006. Backend API: http://localhost:3000. |
| 23 | + |
| 24 | +### Tests |
| 25 | + |
| 26 | +- All backend specs: `make specs` (equivalently `script/backend rspec spec spec`). |
| 27 | +- A single spec: `script/backend rspec spec/services/weather_retriever_spec.rb`. The `script/backend` wrapper runs any command inside the backend container (`docker compose --profile dev run --rm backend $@`). |
| 28 | +- Add `debugger` to Ruby code to break into an interactive shell under rspec. |
| 29 | +- Frontend (Ember): `cd frontend && npm test` (`ember test`). |
| 30 | +- Native: `cd native && npm test` (jest), `npm run tsc` (typecheck). |
| 31 | + |
| 32 | +### Lint (all enforced in CI; run before pushing) |
| 33 | + |
| 34 | +- Ruby: `script/backend standardrb` (StandardRB, not RuboCop). |
| 35 | +- ERB: `script/backend erb_lint --lint-all`. |
| 36 | +- Native: `cd native && npm run lint` (eslint + prettier), `npm run lint:fix` to autofix. |
| 37 | + |
| 38 | +CI (`.github/workflows/{backend,frontend,native}.yml`) uses path filters — backend jobs only run when `backend/**` changes, etc. StandardRB, ERB lint, rspec, and frontend build are required for merge. |
| 39 | + |
| 40 | +## Architecture |
| 41 | + |
| 42 | +### Dual database — the most important thing to understand |
| 43 | + |
| 44 | +The backend uses **both PostgreSQL and MongoDB simultaneously**, split by data type: |
| 45 | + |
| 46 | +- **PostgreSQL (ActiveRecord)** — relational/reference data: `User` (Devise auth), `Condition`, `Symptom`, `Treatment`, `Food`, `Tag`, `Profile`, `Weather`, and the `user_*` join tables. These models subclass `ActiveRecord::Base` and carry a `# == Schema Information` header. Schema lives in `db/schema.rb` + `db/structure.sql`; migrations in `db/migrate/`. |
| 47 | +- **MongoDB (Mongoid 8)** — high-volume, user-generated, schemaless data: `Checkin` (the core daily symptom/treatment/tag log), `Comment`, `Reaction`, `Pattern`, `Notification`, `HarveyBradshawIndex`, `Feedback`, `PromotionRate`, `OracleRequest`. These `include Mongoid::Document`. Config in `config/mongoid.yml`. |
| 48 | + |
| 49 | +The two stores are linked by an **encrypted foreign key**: Mongo documents store `encrypted_user_id` (symmetric-encryption gem, see `config/symmetric-encryption.yml`) rather than a plain `user_id`, and dereference it back to the Postgres `User`. When querying check-in data by user, filter on `encrypted_user_id`, not `user_id`. `Checkin` embeds condition/symptom/treatment sub-documents inline. |
| 50 | + |
| 51 | +### API layer |
| 52 | + |
| 53 | +Versioned JSON API under `app/controllers/api/v1/`, routed via `namespace :api { scope module: :v1 }` in `config/routes.rb`. Serialization uses `active_model_serializers` 0.9 (`app/serializers/`). Auth is Devise + `devise_invitable` + Facebook OmniAuth; authorization is CanCanCan with a Mongoid adapter (`app/models/ability.rb`). Business logic lives in `app/services/` (e.g. `weather_retriever`, `pattern_creator`, `chart_list_service`) — controllers should stay thin. |
| 54 | + |
| 55 | +### Background work |
| 56 | + |
| 57 | +Sidekiq (`config/sidekiq.yml`, `worker` process in `Procfile`) backed by Redis, with jobs in `app/jobs/` (check-in reminders, data exports, notification dispatch, top-posts mailers). Recurring schedules are defined in `config/cronotab.rb` (Crono) and rake tasks under `lib/tasks/` invoked by Heroku Scheduler. |
| 58 | + |
| 59 | +### External integrations |
| 60 | + |
| 61 | +Tomorrow.io (weather, via `tomorrowio_rb`), Pusher (realtime), Geocoder + `nearest_time_zone` (location → timezone for reminders), AWS SES (inbound/bounce handling in `aws_ses_controller`). |
| 62 | + |
| 63 | +## Deployment |
| 64 | + |
| 65 | +Heroku, via `rake` tasks in the root `Rakefile`. Frontend and backend are separate Heroku apps deployed with `git subtree split` (`rake production:deploy` / `rake staging:deploy`). Commits to `master` auto-deploy to staging. Postgres/Redis are Heroku addons; MongoDB is hosted at mongodb.com. |
| 66 | + |
| 67 | +## Gotchas |
| 68 | + |
| 69 | +- Node is pinned to **12.22.6** for the Ember frontend (`.tool-versions`); the native app uses a modern toolchain independently. Don't assume one Node version across the repo. |
| 70 | +- Env files: `cp backend/env-example backend/.env` and `cp backend/env-example frontend/.env`. A `FACEBOOK_APP_ID` is needed in `frontend/.env` or the app renders a blank beige screen on first load (see README "Common Problems" for the workaround). |
0 commit comments