PraxaLing / README.md
Reubencf's picture
Fix Hugging Face Space OAuth launch
cb1e313
|
Raw
History Blame Contribute Delete
3.84 kB
---
title: PraxaLing
emoji: 🦜
colorFrom: yellow
colorTo: gray
sdk: docker
app_port: 7860
pinned: false
hf_oauth: true
hf_oauth_scopes:
- email
- inference-api
---
# PraxaLing
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:
1. **Sign in with HuggingFace** (OAuth).
2. **Practice** β€” read short stories matched to your CEFR level and target language; tap any word for a translation. Generate new stories on demand.
3. **Camera** β€” take or upload a photo; the backend runs BLIP captioning, DETR detection, NLLB translation, and Mistral-generated example sentences.
## Stack
| 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 |
## Getting started (web)
```bash
# 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 dev
```
Required 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/new, or use the Space metadata `hf_oauth: true` and the app will read Hugging Face's injected `OAUTH_CLIENT_ID` / `OAUTH_CLIENT_SECRET`
- `HF_TOKEN` β€” read token from https://huggingface.co/settings/tokens
- Optional: `BLOB_READ_WRITE_TOKEN` for Vercel Blob
Redirect URIs to register on the HF OAuth app:
- `http://localhost:3000/api/auth/callback/huggingface`
- `http://localhost:3000/api/auth/callback/huggingface?client=mobile`
- `https://<SPACE_HOST>/api/auth/callback/huggingface`
- `https://<SPACE_HOST>/api/auth/callback/huggingface?client=mobile`
For the hosted Space, use the direct `*.hf.space` host, not the `huggingface.co/spaces/...` page, for redirect URIs and mobile `API_BASE_URL`.
## Getting started (mobile)
```bash
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 run
# Hosted backend / physical device
flutter run --dart-define=API_BASE_URL=https://<SPACE_HOST>
```
See `docs/API.md` for the endpoints the app consumes.
## Architecture notes
- **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.ts` is now `proxy.ts`; dynamic APIs (`cookies`, `headers`, `params`) are async; Turbopack is default. See `node_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`.
## Scripts
| 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 |