Skip to content

Repository files navigation

Fluide

French chunking practice app based on the method by Français avec Pierre. Practice selecting chunks, drilling pronunciation, writing sentences (with optional grammar check), and a timed mini-monologue. Includes a chunk library (add/edit/delete custom chunks) and practice history.

Setup

  1. Install dependencies: npm install
  2. Set up Cloudflare Worker secrets for local development:
    cp .dev.vars.example .dev.vars
    Generate a secret and add it to .dev.vars:
    openssl rand -base64 32
    API_KEY_COOKIE_SECRET=<your-generated-secret>
    
  3. For deployed environments, set API_KEY_COOKIE_SECRET as a Worker secret (see Production deployment).

Development

The app uses a Cloudflare Worker BFF to store API keys in an encrypted HttpOnly cookie. Run both processes:

# Terminal 1 — build static assets + serve API routes
npm run build && npm run dev:worker

# Terminal 2 — Vite dev server (proxies /api to the worker)
npm run dev

Open http://localhost:5173. Enter your Gemini API key in Settings — it is sent once to /api/session and stored in an HttpOnly cookie, not in localStorage.

Get a Gemini key at Google AI Studio.

Production deployment

Fluide deploys as a Cloudflare Worker with static assets (not Cloudflare Pages). The Worker serves the Vite-built SPA from dist/ and handles /api/* BFF routes.

Manual deploy

npm run deploy

This runs npm run build then wrangler deploy, uploading both the Worker and dist/ assets in one step.

Cloudflare Workers Builds (CI/CD)

The fluide Worker is connected to GitHub. Configure in Workers & Pages → fluide → Settings → Build:

Setting Value
Build command npm run build
Deploy command (production branch) npm run deploy or npx wrangler deploy
Non-production branch deploy command npm run deploy:preview or npx wrangler versions upload
Production branch main

Enable Builds for non-production branches under Settings → Build → Branch control so PRs get preview URLs.

Required secrets and environment variables

Set these in Workers & Pages → fluide → Settings → Variables & Secrets:

Name Type Required Description
API_KEY_COOKIE_SECRET Secret Yes 32+ byte random string used to seal user Gemini API keys in the HttpOnly cookie. Generate with openssl rand -base64 32.
API_KEY_COOKIE_SECRET_PREVIOUS Secret No Previous secret for zero-downtime rotation. The worker accepts cookies sealed with either secret.

Preview branches: Worker secrets are shared across all versions of the fluide worker (production and preview). Set API_KEY_COOKIE_SECRET once on the worker — preview deployments from PR branches will use the same secret. Use a dedicated preview secret only if you create a separate Wrangler environment/worker for previews.

Do not commit .dev.vars, .env.local, or real secret values to git.

API routes (BFF)

Method Path Purpose
POST /api/session Store encrypted Gemini API key in HttpOnly cookie
POST /api/revoke Clear the session cookie
GET /api/session/status Check whether a valid session exists
POST /api/grammar-check Proxy grammar check to Gemini
POST /api/extract-phrases Proxy phrase extraction to Gemini

Architecture

  • Frontend: Vite + React + TypeScript + Tailwind CSS
  • BFF: Cloudflare Worker (worker/) proxies grammar check and phrase extraction to Gemini
  • Auth: User-provided Gemini API keys are sealed with AES-256-GCM and stored in a __Host-fluide_user_api_key HttpOnly cookie

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages