AI-powered meal recommendations for people with dietary restrictions and medical conditions.
Food4U takes a user's dietary preferences, allergies, and medical profile (including ICD-10-CM condition codes) and generates personalized, safe meal suggestions. Built solo for my first hackathon — designed like a production system.
Two independently deployed services communicating over authenticated HTTP:
┌─────────────────────────────┐ ┌──────────────────────────────┐
│ Frontend — Cloudflare │ JWT │ Backend — Python FastAPI │
│ Remix (React) on Pages │ ◄─────► │ hosted on Render │
│ • D1 (SQLite) user accounts │ token │ • Repository/Service/Route │
│ • KV session storage │ exchange│ layered architecture │
│ • React Hook Form + Zod │ │ • CockroachDB (Postgres) │
└─────────────────────────────┘ │ • Qdrant vector store │
│ • LlamaIndex + Gemini API │
└──────────┬───────────────────┘
│
External data: USDA FoodData Central,
Spoonacular, Google Gemini
Why two servers? Separation of concerns and independent deployment: the edge-rendered frontend stays fast and cheap on Cloudflare's free tier, while the Python backend owns AI orchestration and data-heavy integrations. Each side scales and deploys on its own cadence.
| Layer | Technology |
|---|---|
| Frontend | Remix (React), TypeScript, React Hook Form, Zod, Tailwind CSS |
| Edge platform | Cloudflare Pages + Workers, D1 (SQLite), KV, Wrangler |
| Auth | JWT token exchange between services (@tsndr/cloudflare-worker-jwt, bcrypt) |
| Backend | Python, FastAPI, SQLAlchemy 2.0 (async), asyncpg, Uvicorn |
| AI / Retrieval | Google Gemini, LlamaIndex, Qdrant vector store |
| Food data | USDA FoodData Central API, Spoonacular API |
| Datastores | CockroachDB (backend), D1 + KV (frontend) |
frontend/ Remix app — routes, components, form flows, D1 schema, Wrangler config
backend/ FastAPI app — routers, services, repositories, schemas, AI pipeline
The backend follows a repository → service → route pattern: routers handle HTTP, services hold business logic, repositories own data access. Pydantic schemas validate every boundary, mirrored by Zod schemas on the frontend.
cd frontend
npm install
npm run d1:local-initialize # seed local D1 database
npm run dev # Remix dev server (Vite)Deploy: npm run deploy (builds and pushes to Cloudflare Pages).
cd backend
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
uvicorn server:app --reloadInteractive OpenAPI docs are auto-generated by FastAPI at /docs.
Both services expect environment variables for API keys (Gemini, Spoonacular, FDC), database URLs, and the shared JWT secret — see frontend/wrangler config and backend/app/config.
Inspiration. Someone special to me is affected by dietary food restrictions, and I've watched how poorly many restaurants accommodate that community. (I don't like onions myself — I know the pain of a remade lunch on a short break.) Food4U's long-term goal is to hold businesses accountable for getting orders right the first time.
Hackathon reality. The team started at five; I finished as the last one standing. Highlights of what that taught me:
- Aggressive feature-branching keeps a solo sprint focused on user stories.
- Cloudflare's proxy and Wrangler behave differently from the Vite dev server — don't
response.json()a body twice. - Async session hygiene matters: one session per instance, always closed, no leaks.
- Real AI features need more than an API call — vector stores, prompt engineering, and careful variable analysis.
- Documentation is a MUST, not a nice-to-have.
What's next. Fine-tuned suggestions from medical datasets, delivery-app integrations, and a UI pass. Ultimately: safer, faster dining for anyone with dietary restrictions.