auto-git:

[add] README.md
 [add] client/.gitignore
 [add] client/README.md
 [add] client/eslint.config.js
 [add] client/index.html
 [add] client/package.json
 [add] client/public/vite.svg
 [add] client/src/App.css
 [add] client/src/App.tsx
 [add] client/src/api.ts
 [add] client/src/assets/react.svg
 [add] client/src/components/EntryCard.tsx
 [add] client/src/components/ItemPanels.tsx
 [add] client/src/components/QuizRunner.tsx
 [add] client/src/components/VideoPlayer.tsx
 [add] client/src/index.css
 [add] client/src/main.tsx
 [add] client/src/pages/EntryPage.tsx
 [add] client/src/pages/OverviewPage.tsx
 [add] client/src/pages/QuizPage.tsx
 [add] client/src/types.ts
 [add] client/tsconfig.app.json
 [add] client/tsconfig.json
 [add] client/tsconfig.node.json
 [add] client/vite.config.ts
 [add] gemini_replicate_batch.py
 [add] package.json
 [add] prompt.txt
 [add] server/package.json
 [add] server/src/index.ts
 [add] server/tsconfig.json
This commit is contained in:
2026-01-07 18:35:20 +01:00
parent f80da70512
commit 1d9e7cbcbb
31 changed files with 2564 additions and 0 deletions

50
README.md Normal file
View File

@@ -0,0 +1,50 @@
# IG Japanese Quizzer
A full-stack web app for drilling Japanese grammar, vocabulary, and phrases from locally stored Instagram posts. The server indexes every `*.mp4` + matching `*.json` pair under `data/` and exposes them to a React/Vite frontend with a quiz wizard.
## Quick start
1. Install dependencies (root workspace):
```bash
npm install
```
2. Run both servers (frontend on 5173, backend on 5174):
```bash
npm run dev
```
- Vite proxies `/api` and `/data` to the Express server, so the client can use relative URLs.
3. Open the app at http://localhost:5173.
### Scripts
- `npm run dev` concurrently runs `server` (Express + ts-node-dev) and `client` (Vite dev server).
- `npm run build` builds the server TypeScript and Vite client.
- `npm run dev --workspace server` / `npm run dev --workspace client` run either side individually.
## Data layout
Files live under `data/` (scanned recursively):
```
data/<POST_ID>/<FILENAME>.mp4
\_ <FILENAME>.json # quiz payload for that video
```
- Base filenames must match. Extra sidecars (`.raw.txt`, `.mp4.json`, images) are ignored.
- The JSON structure is tolerant but expects keys: `meta`, `items`, `quiz`, `ui_hints` (additional fields are ignored).
- `entry_id` is the path from `data/` to the mp4 **without** the `.mp4` extension (e.g., `C1abc/12345`). It is URL-encoded in routes/query params.
- Videos are served statically at `/data/...` by the backend; JSON is only accessible through the API.
## API
- `GET /api/entries` → list of entries `{ id, title, mode, type, counts, video_url }`, sorted by title.
- `GET /api/entry?id=<entry_id>` → full entry JSON plus derived fields `{ id, title, video_url, counts }`.
## Frontend features
- Overview grid of all entries with counts and metadata.
- Entry detail page with embedded video and learning panels.
- Quiz Wizard with three modes:
- All entries (random 10 questions)
- Selected entries (checkbox picker)
- Single entry (linked from detail page)
- Quiz types: cloze input, multiple-choice variants, match pairs, and best reply. Wrong answers reveal explanations and the source video.
## Notes
- The server prevents path traversal by validating resolved paths against the data root and only serving scanned entries.
- Update or add new posts by dropping files into `data/` and restarting the server to rescan.