Treatment Finder is a full-stack course project for discovering treatments, matching clinics, booking appointments, and rating completed visits.
The platform supports:
- treatment discovery (keyword search and AI semantic consultation),
- clinic comparison,
- appointment booking and management,
- post-visit rating and clinic score updates.
- Frontend: React + Vite + Tailwind CSS
- Backend: FastAPI + SQLModel + SQLite
- Communication: Frontend consumes backend REST APIs (
/api).
api/- HTTP routes/controllers and response wiringservices/- business rules and orchestrationrepositories/- SQLModel/SQLAlchemy data accessschemas/- request/response contracts and validationcore/+database.py- DB engine/session lifecycle and compatibility helpers
- Uses a dynamic DB-backed service catalog as prompt context (no hardcoded treatment mapping for matching).
- Model strategy:
- Primary: Groq (Llama 3.1 family)
- Failover: Gemini
- Fallback: local keyword-style matching when providers are unavailable.
- Returns structured output with:
matched_service_ids,matched_service_names,- clinic recommendations,
reason,explanation, andconfidence_score.
Create root .env from .env.example. The frontend Vite app is configured with
envDir: '..', so npm run dev from frontend/ also reads VITE_* variables
from the repository-root .env.
Important
💡 Quick Setup: Before booting any services, make sure to copy .env.example to a local .env file at the project root and fill in the missing key configurations.
| Variable Name | Default / Example Value | Purpose / Description |
|---|---|---|
DATABASE_URL |
sqlite:///./treatment_finder.db |
Local development database URL. When running uvicorn from backend/, this relative SQLite file is created under the backend working directory. Docker Compose overrides this with sqlite:////data/treatment_finder.db and a named volume. |
SECRET_KEY |
replace-with-a-long-random-secret-min-16-chars |
Required JWT signing secret. Use a long random value in production; the same value is used for token encode and decode. |
| Variable Name | Default / Example Value | Purpose / Description |
|---|---|---|
GROQ_API_KEY |
empty | Optional Groq API key for the primary AI consultation provider. |
GROQ_MODEL |
llama-3.1-8b-instant |
Groq chat model used by the Smart AI Semantic Consultant. |
GEMINI_API_KEY |
empty | Optional Google Gemini API key used as the AI failover provider. |
| Variable Name | Default / Example Value | Purpose / Description |
|---|---|---|
GOOGLE_CLIENT_ID |
empty | Google OAuth 2.0 Web client ID from Google Cloud Console. |
GOOGLE_CLIENT_SECRET |
empty | Google OAuth 2.0 Web client secret from Google Cloud Console. |
GOOGLE_OAUTH_ALLOW_INSECURE |
true |
Allows local http://localhost OAuth redirects. Use only for local development, not production. |
FRONTEND_PUBLIC_URL |
http://localhost:3000 |
URL where the API redirects after Google login. Must match the SPA URL opened in the browser; this repo's Vite dev server uses port 3000. |
| Variable Name | Default / Example Value | Purpose / Description |
|---|---|---|
REDIS_URL |
redis://localhost:6379/0 |
Redis URL for caching, Celery-compatible broker defaults, and scripts/refresh.py. |
CELERY_BROKER_URL |
redis://localhost:6379/0 |
Celery broker URL for background worker jobs. Docker Compose points this at the redis service. |
CELERY_RESULT_BACKEND |
redis://localhost:6379/1 |
Celery result backend URL. Docker Compose points this at the redis service. |
VITE_API_BASE_URL |
/api |
Frontend API base path. In local development, Vite proxies /api to the backend. |
VITE_BACKEND_URL |
http://localhost:8000 |
Public FastAPI origin used when the browser leaves the Vite origin, especially for the Google sign-in redirect flow. |
The backend needs the fastapi-sso PyPI package (import fastapi_sso). It is listed in requirements.txt / backend/requirements.txt; install or refresh deps with pip install -r ../requirements.txt (from backend/) or pip install "fastapi-sso>=0.16.0,<1.0.0" if you see ModuleNotFoundError: fastapi_sso.
In Google Cloud Console, create OAuth 2.0 Web credentials and add an Authorized redirect URI that matches your API callback, for example http://localhost:8000/api/auth/google/callback (same host/port you use for uvicorn). The frontend Continue with Google button needs VITE_BACKEND_URL (e.g. http://localhost:8000) so the browser can open the API’s /api/auth/google/login (Vite only proxies /api, not OAuth).
Open two terminals from repository root.
Before starting services, create the root env file once:
cp .env.example .envcd backend
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r ../requirements.txt
python -m app.init_db
uvicorn app.main:app --reloadWindows / zoneinfo: Named zones such as Asia/Jerusalem need the tzdata package (it is in requirements.txt). If startup fails with ZoneInfoNotFoundError or No module named 'tzdata', reinstall deps: pip install -r ../requirements.txt or pip install tzdata.
python -m app.init_db seeds the database once for local runs (including the default admin admin@example.com / admin123). Uvicorn startup no longer re-runs seeding; rerun python -m app.init_db manually if you intentionally want to refresh seed data.
cd frontend
npm install
npm run devAccess:
- Frontend (local
npm run dev): http://localhost:3000 (same port as Docker; Vite is configured withserver.port: 3000) - Backend docs: http://localhost:8000/docs
cd backend
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r ../requirements.txt
python -m app.init_db
uvicorn app.main:app --reloadRun tests (from backend/ so app resolves):
cd backend
pytest -qcd frontend
npm install
npm run devRun lint:
npm run lintRun from repository root:
docker compose -f compose.yaml up --buildAccess:
- Frontend: http://localhost:3000
- Backend docs: http://localhost:8000/docs
Notes:
- Python dependencies include
tzdatasozoneinfo(e.g.Asia/Jerusalem) works on Windows hosts and in containers consistently. compose.yamlloads root.envfor secrets (SECRET_KEY, optional AI keys, etc.). Compose overridesDATABASE_URLfor backend and worker tosqlite:////data/treatment_finder.dbwith a named volume mounted at/data, so the SQLite file persists correctly (avoid mounting a volume onto a single file path).- Google login redirect: the
backendservice setsFRONTEND_PUBLIC_URL=http://localhost:3000explicitly (not from root.env), so after OAuth the browser always returns to the SPA on port 3000 (the published frontend). Update your own root.envtohttp://localhost:3000as well if you run the API outside Docker, so behavior matches. - Services:
backend,frontend,redis,worker(Celery). See docs/EX3-notes.md.
The backend image uses backend/entrypoint.sh to run python -m app.init_db exactly once before starting Uvicorn. That executes seed_initial_data() in backend/app/init_db.py, which creates table data and always ensures a default admin exists (matched by email, password hash refreshed). Worker containers pass through the same image entrypoint without running API seeding.
Default admin (demo passwords — change in production):
| Role | Password | |
|---|---|---|
| Admin | admin@example.com |
admin123 |
| Demo user | henya@example.com |
demo123 |
Full detail: docs/EX3-notes.md.
Stop:
docker compose -f compose.yaml downSign in to the UI with seeded accounts after init_db (see docs/EX3-notes.md); JWT is required for appointment cancellation.