Learn languages through short stories and the world around you, powered by HuggingFace for identity and inference.
Two clients, one backend:
- Web — Next.js 16 App Router (also acts as the shared API).
- Mobile — Flutter (latest stable), calls the same HTTP endpoints.
Three flows:
- Sign in with HuggingFace (OAuth).
- Practice — read short stories matched to your CEFR level and target language; tap any word for a translation. Generate new stories on demand.
- Camera — take or upload a photo; the backend runs BLIP captioning, DETR detection, NLLB translation, and Mistral-generated example sentences.
| Concern | Tech |
|---|---|
| Web | Next.js 16.2 · React 19 · Tailwind v4 · Turbopack |
| Mobile | Flutter 3.41 · Riverpod · go_router · dio |
| Auth | HuggingFace OAuth (arctic) · JWT (jose) |
| DB | Postgres · Drizzle ORM |
| Storage | Vercel Blob (optional) |
| Inference | @huggingface/inference · Mistral-7B-Instruct · BLIP · DETR · NLLB-200 |
# 1. Install deps
npm install
# 2. Bring up Postgres
docker compose up -d
# 3. Configure env — copy and fill in
cp .env.example .env.local
# 4. Apply schema
npm run db:push
# 5. (Optional) seed stories
npm run db:seed
# 6. Run dev server
npm run devRequired env:
AUTH_SECRET— any 32+ char random string (openssl rand -base64 32)HF_OAUTH_CLIENT_ID/HF_OAUTH_CLIENT_SECRET— from https://huggingface.co/settings/applications/newHF_TOKEN— read token from https://huggingface.co/settings/tokens- Optional:
BLOB_READ_WRITE_TOKENfor Vercel Blob
Redirect URIs to register on the HF OAuth app:
http://localhost:3000/api/auth/callback/huggingfacehttp://localhost:3000/api/auth/callback/huggingface?client=mobile
cd mobile
flutter pub get
# iOS simulator — host loopback is 127.0.0.1 by default
flutter run --dart-define=API_BASE_URL=http://127.0.0.1:3000
# Android emulator — host loopback is 10.0.2.2 (default)
flutter runSee docs/API.md for the endpoints the app consumes.
- Auth: both clients exchange an HF OAuth code for our own short-lived JWT. Web stores it in an httpOnly cookie; mobile in
flutter_secure_storage.lib/auth/session.ts#getSession()handles both. - Next.js 16 specifics:
middleware.tsis nowproxy.ts; dynamic APIs (cookies,headers,params) are async; Turbopack is default. Seenode_modules/next/dist/docs/01-app/02-guides/upgrading/version-16.md. - Data flow for camera: multipart → BLIP + DETR in parallel → dedupe labels → translate each to target lang → Mistral generates 3 sentences keyed on caption + objects → persisted in
vision_jobs.
| Command | Purpose |
|---|---|
npm run dev |
Next.js dev server |
npm run build |
Production build |
npm run db:push |
Apply schema to Postgres |
npm run db:generate |
Generate migration from schema |
npm run db:migrate |
Apply pending migrations |
npm run db:seed |
Insert hand-curated stories |
npm run db:studio |
Drizzle Studio UI |