ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
An AI tutor for German — guided chat, spaced-repetition vocabulary and translation drills.
EducationJavaScript · PLpgSQLGitHub @blackhebrewisraeliOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
A guided German-learning PWA — AI chat tutor (Anna), Leitner SRS vocab, alphabet & translation drills, and a progress dashboard. Built as a language-agnostic learning engine + swappable content packs. React + Vite, Claude-powered.
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
Deutsch· — German practice with engineering depth
An offline-first German-learning app — on the web and as native iOS and
Android builds — that blends focused practice, deterministic gamification,
secure cross-device sync, and AI where it genuinely helps.
Six tabs, one codebase on three platforms, and considerably more thought about merge semantics than a language app has any right to contain.Read the full README ↗SPRACHSCHULE · BUILT FOR CURIOUS MINDS
An offline-first German-learning app — on the web and as native iOS and Android builds — that blends focused practice, deterministic gamification, secure cross-device sync, and AI where it genuinely helps.
Try the app · Run it locally · See the architecture · Read the wiki
Six tabs, one codebase on three platforms, and considerably more thought about merge semantics than a language app has any right to contain.
[!NOTE] Accounts are optional. Lessons, vocabulary, speech, SRS, progress, streaks, and quests all work locally, with no sign-up. Signing in (passwordless: an email code or link, Google, GitHub, and Apple where the provider is enabled) adds cross-device sync, weekly leagues, a followable profile, and quest tokens; generative features require the server API.
| Experience | What it does |
|---|---|
| 💬 Scene-based conversation | The AI opens a scene in character — a barista, an airport check-in agent — caps sentence length by CEFR level, and corrects you inline. |
| 🪜 Scaffolding that fades | Chat and Translate share one input ladder: word bank, choose the word, type the word, free typing. Start where your level puts you; switch anytime. |
| 🧠 Vocabulary & SRS | Leitner review over preset, lexicon, grammar-drill, interest-topic, and custom AI-generated decks, plus a Travel Basics phrasebook. |
| 🔤 Alphabet & listening | German speech synthesis, confusable-letter quizzes, and a browsable pronunciation grid. |
| 🧭 Optional placement | Start at A1 straight away, or take nine offline questions to place at A1, A2, or B1. The app suggests it again at 500 XP. |
| 🎮 Motivation that respects the learner | XP, streak freezes, earned-only badges, daily quests that pay tokens, and optional weekly leagues. |
| 👥 Social, opt-in | Pick a handle, find people, follow them, and choose whether your profile is public or private. |
| 🤖 Cost-aware AI routing | Fast, Balanced, and Capable profiles sit behind server-enforced access ceilings and daily usage accounting; guest and Free requests currently resolve to Fast. |
| Vocabulary practice |
|---|
The device's localStorage is the offline authority; Supabase is an optional
cross-device layer. Reconciliation happens client-side, so each state slice
gets semantics that fit its data instead of one risky "newest blob wins" rule.
| State slice | Merge strategy | Why |
|---|---|---|
| Daily stats & XP | Server-owned event log | Each answer queues locally with its own ID; one idempotent RPC applies it. The client never writes. |
| SRS cards | Per-card LWW on lastReviewed | Reviewing one card should not overwrite another card's state. |
| Settings | Whole-record LWW, with explicit carve-outs | Ordinary preferences share a clock; special data does not. |
| CEFR level | Independent LWW clock | A newer unrelated setting cannot roll B1 back to A1. |
| Learned words & deck mastery | Union merge | Learning on either device remains learned. |
| Custom decks | Per-deck LWW + tombstones | Offline deletion competes with edits by timestamp instead of resurrecting removed decks. |
Daily stats are the strictest case. Every XP reader — streaks, lifetime XP, league standings — sums one table, so clients may read it but never write it. Offline answers wait in a durable queue; on reconcile the client rebuilds each day as server rows + unflushed queue, so an answer is neither lost nor counted twice, and a browser cannot mint XP.
Deck deletion is the other interesting edge case. An upsert-only system cannot express absence, so a stale device would recreate a deleted deck. Deutsch· keeps a timestamped tombstone; the same per-deck LWW comparison then decides whether an edit or deletion is newer.
→ Offline-First Sync Model in the wiki.
Three daily quests are derived—not stored—from a stable seed:
seed = seedFor(userId, todayKey); // hash(`${userId ?? 'guest'}:${todayKey}`)
quests = pickQuests(QUEST_CATALOGUE, seed, 3);
progress = readExistingDailyCounters(todayKey);
The same learner gets the same quests all day, on every device, even offline. There is no quest table to maintain, synchronize, or accidentally reshuffle.
Difficulty adapts without chasing outliers. Targets use the median of the previous seven days, excluding today, then apply per-quest multipliers. A single heroic study binge cannot make tomorrow miserable, and today's progress cannot move today's goalposts.
A finished quest pays tokens, never XP. The balance is a server-side
ledger: the award_tokens RPC picks the amount, caps it per day, and is
idempotent on (reason, key) with the key todayKey:questId — so a quest pays
once, however many devices claim it. League XP stays tied to actual graded
practice.
flowchart LR
subgraph Client["Web PWA · iOS · Android — works offline"]
UI["React 18 UI\n(Capacitor shell on native)"]
Local[("localStorage\nSRS · stats · progress queue")]
SW["Service worker (web)"]
UI <--> Local
UI <--> SW
end
subgraph Vercel["Vercel"]
API["Versioned serverless API\nai · content · progress · league\nsocial · account · admin · push"]
end
subgraph Supabase["Supabase"]
Auth["Auth · email link + OAuth"]
DB[("Postgres + RLS\nprogress · sync · quota accounting")]
Storage[("Avatar Storage")]
end
AI["Anthropic\nHaiku · Sonnet · Opus"]
UI -->|"lessons · progress events · leagues · social · AI"| API
API --> AI
API -->|"RPC · the only XP writer"| DB
UI -.->|"signed-in sync: SRS · settings · decks · tokens"| DB
UI -.-> Auth
UI -.-> Storage
Learner-progress merges stay in pure client-side functions — deterministic, testable, and usable before the network returns. Every XP-bearing write goes through one Postgres RPC behind
POST /api/v1/progress/events, so the database has exactly one writer for the numbers leagues are decided on.
Prerequisites: Node.js 22 (see .nvmrc) and npm.
git clone https://github.com/blackhebrewisraeli/Sprachschule-app.git
cd Sprachschule-app
npm install --legacy-peer-deps
npm run dev
Open http://localhost:5173. The offline-first learning flows work with no Supabase, Vercel, or Anthropic credentials at all.
| Command | Purpose |
|---|---|
npm run dev | Start the Vite UI |
npm run dev:full | Start Vite plus the Vercel functions (AI, leagues, social) |
npm test | Run the main Vitest suite |
npm run lint | Run ESLint |
npm run format:check | Check Prettier formatting |
npm run test:rls | Run the RLS policy suite (needs Docker + supabase start) |
npm run build:mobile | Build against production and sync into ios/ and android/ |
npm run smoke:learning-path | Browser smoke test for the anonymous core learning loop |
npm run screenshots:capture | Capture and validate native store artwork |
Accounts, sync, leagues, avatars, and the AI endpoints each need a little more
setup — local Supabase via Docker, a few VITE_* flags, and an
ANTHROPIC_API_KEY. The full matrix, every npm script, and the usual
"why is sync doing nothing locally?" answer live in
Local Development.
ios/ and android/ are committed Capacitor 8 projects that wrap the same web
bundle. Every push to main builds an iOS simulator app and an Android debug
APK in CI. Native release builds pin the production API and Supabase project,
enable sync, leagues, Google, GitHub, and Apple sign-in, and deliberately keep
push, ads, and saved tutor history dark until their release runbooks are
complete. The source is at version 1.0.1, build 7; what has actually been
uploaded to TestFlight or Google Play is tracked separately, in the release
status at the top of
docs/STORE_SUBMISSION_CHECKLIST.md.
For signed builds, auth deep links, and store copy, see
docs/NATIVE_BUILD.md,
docs/MOBILE_AUTH_SETUP.md, and
docs/store-metadata/.
Deep documentation lives in the project wiki.
| Page | What's there |
|---|---|
| Architecture Overview | The two-lane design, tech stack, and repository map |
| Offline-First Sync Model | Merge semantics, tombstones, and independent LWW clocks |
| Lesson Engine | Data-driven lessons, the exercise registry, and progress events |
| Security & Role Architecture | Key boundaries, RLS, the AI boundary, and the avatar pipeline |
| Operations Runbooks | OAuth, email templates, migrations, and the production drill |
| Local Development | Full setup, every npm script, and troubleshooting |
| Contributing & Quality | Testing philosophy, conventions, and the PR flow |
Versioned material stays in the repository, where it is reviewed alongside the
code it describes: API contracts in docs/api/, design specs
and implementation plans in docs/superpowers/, and
deliberately deferred work in docs/BACKLOG.md.
Bug reports, accessibility findings, architecture questions, and focused pull
requests are all welcome. Please read AGENTS.md first — it is
the single source of truth for this project's conventions and product
boundaries — and Contributing & Quality
for the testing philosophy behind them.
Released under the MIT License. Vocabulary sources — Wiktionary,
Tatoeba, the Leipzig Corpora Collection, and the Wikivoyage phrasebook — and
their attribution are documented in CONTENT_LICENSE.md.
Built to help people learn German—and to make the hard parts of frontend engineering visible.