ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
Pré-traitez vos paquets Anki en JSON et révisez en tapant les réponses dans le navigateur
Translation pending
AI summary · website and README
EducationHTML · PythonGitHub @antoine123456OnlineOwner 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
Loading the full README. The saved excerpt is shown below.
Fill-in-the-blank study app for Anki decks: pre-process a .apkg export into JSON, import it in the browser, and type out each word of the answer instead of just flipping the card. Scheduling models Anki's actual default algorithm (new → learning steps → review, lapses → relearning). Progress lives in the browser's localStorage — no account, no sync, nothing leaves the browser right now (see "Sync (planned)" below for why the Firestore backend already exists but isn't wired up to anything yet).
Step 1 — Export your deck from AnkiRead the full README ↗Fill-in-the-blank study app for Anki decks: pre-process a .apkg export into JSON, import it in the browser, and type out each word of the answer instead of just flipping the card. Scheduling models Anki's actual default algorithm (new → learning steps → review, lapses → relearning). Progress lives in the browser's localStorage — no account, no sync, nothing leaves the browser right now (see "Sync (planned)" below for why the Firestore backend already exists but isn't wired up to anything yet).
espanol-trainer/
├── index.html ← standalone study app (open in any browser, or via GitHub Pages)
├── extract.py ← CLI: converts a .apkg into JSON for the app (pip install anki recommended)
├── sync_to_anki.py ← CLI: one command pushes downloaded progress straight into your local Anki collection
├── reimport_stats.py ← CLI: writes progress made here back into a .apkg for re-import into real Anki
├── default.json ← bundled deck auto-loaded on first run if no source has been imported yet
├── default_media/ ← its audio/image files
├── add_card.py ← console tool: adds one word pair to the shared "perso" deck (see below)
└── README.md
In Anki: File → Export... + check "with stats"→ format "Anki Deck Package (.apkg)" → pick the deck(s) you want.
pip install anki
python3 extract.py "My Deck.apkg" --out my_deck.json
extract.py imports the .apkg into a throwaway collection and lets Anki's own code render every card, so it handles anything Anki itself handles: sub-decks (Parent::Child, shown as a collapsible tree in the app), Basic/Cloze/custom note types, HTML templates, sound/image references, and both the older plain-SQLite .apkg format and the newer zstd-compressed one (Anki ≥ 2.1.50).
Or skip the export and read your local Anki collection directly (needs pip install anki; quit Anki first, it locks the collection):
python3 extract.py --collection --deck Arbres --out arbres_extrait.json
--collection auto-detects your profile (--profile if you have several, or --collection path/to/collection.anki2). --deck keeps only that deck and its sub-decks; repeat it for several decks. It also works with a .apkg.
Images whose src is a web link (<img src="https://…">) are left as-is, not copied: handy to avoid storing pictures in Anki at all (the Arbres deck uses Wikimedia Commons links), but they won't show offline, in Anki or here.
pip install anki is recommended but not required — without it, the script falls back to a stdlib-only reader (zipfile/sqlite3/json) that only understands the older .apkg format; it will tell you to install anki if it hits a newer, incompatible one.
For each card it renders the answer side, strips HTML/sound/image tags, and splits what's left into the list of words you'll type — the question side is kept as-is (with its HTML) and shown above the blanks. The answer side's own HTML (what follows <hr id=answer>, images included) is kept too, as answer, for the card browser.
Open index.html, click + Importer un fichier .json, and pick the file extract.py produced. Each source you import stays independent (its own progress, own decks), so you can import several exports side by side.
Click 📤 next to the source to download its stats, then run:
ankisync # shell function in ~/.bashrc (see below)
# or: trainervenv/bin/python sync_to_anki.py (Anki must be closed)
ankisync quits Anki if it's open, runs sync_to_anki.py on every ~/Downloads/*_stats*.json, then reopens Anki so its normal sync sends everything to AnkiWeb. The script writes straight into your local Anki collection (auto-detected profile; a backup is made first), so there's no .apkg to re-import. Only cards you actually studied in the app are pushed, and a card you've since reviewed in Anki is left alone. Each pushed card gets a "Manual" entry in Anki's review history, so re-running the command over old downloads is harmless. Cards started for the first time today (in the app or in Anki) are also counted against Anki's daily new-card limit, per deck and its parents, so Anki doesn't offer another 20 new cards on top of what you already did in the app. ankisync --dry-run previews.
Words added with add_card.py / cuatroloop are created in Anki first: one "Basic (and reversed card)" note per pair in the perso deck, with the app's card ids so their progress syncs too. A word is skipped if a note with the same front already exists in Anki, or if its "translation" is identical to the word (e.g. orage → orage).
ankisync() {
local repo="/Users/quang/Documents/espanol-trainer"
local was_open=0
if pgrep -if "Anki.app/Contents/MacOS|aqt\.run" >/dev/null; then
was_open=1
osascript -e 'quit app "Anki"'
while pgrep -if "Anki.app/Contents/MacOS|aqt\.run" >/dev/null; do sleep 0.5; done
fi
"$repo/trainervenv/bin/python" "$repo/sync_to_anki.py" "$@" || return
case " $* " in *" --dry-run "*) [ $was_open = 1 ] && open -a Anki; return ;; esac
open -a Anki
}
reimport_stats.py still exists for the .apkg route, e.g. on a machine without your Anki profile.
ame is accepted for âme.ankisync flags them red, tags them a_corriger, suspends them in Anki and lists them for review.etapeN, e.g. the bundled Grammaire source, grammaire.json, extracted from Anki's 🇪🇸 Espagnol::Grammaire): stage N's new cards stay locked (🔒 badge) until at least 80 % of every earlier stage's cards are in review. ankisync applies the same rule in Anki: locked new cards are suspended with the tag etape_verrou and unsuspended once their stage opens.songs.json (3 songs, from the old lyrics-trainer branch) is bundled as a Chansons source — one deck per song, studied like any other deck. Each distinct lyric line is a card (a repeated chorus line is one card): you type the Spanish line, with its French gloss as the hint. The study screen shows the whole song like a lyrics player — lines you know as text, the active line centred with its blanks, the rest as greyed blanks — and keeps the song's order: due lines and new lines go top to bottom, lines to see again come back in a second pass. ⚙ in the top bar holds options to try out: hint (French gloss / context only / first letters) and new lines (one verse at a time / 5 lines / whole song). Songs in the same JSON format (e.g. generated with the AI prompt from the lyrics-trainer branch) can be added with + Importer. Song cards don't exist in Anki, so ankisync reports them as missing ids.
The app's development follows Paul Nation's four strands: a balanced language course gives roughly equal time to each. They are the GitHub milestones Volet 1–4.
| Strand | What it is | In the app today |
|---|---|---|
| 1 — Comprendre (meaning-focused input) | lots of comprehensible reading/listening (~98 % known words) | songs |
| 2 — Produire (meaning-focused output) | writing/speaking to say something | — (issues #40, #42) |
| 3 — Langue (language-focused learning) | explicit vocabulary, conjugation, grammar | cards, spaced repetition |
| 4 — Fluidité (fluency) | doing it fast with what is already known | quick reviews |
Other findings the design leans on: the testing effect and spaced repetition (recalling beats rereading), the involvement load hypothesis (Laufer & Hulstijn — a word sticks when you must search for it, choose it and use it yourself), the output hypothesis (Swain — producing reveals what you can't say yet), and ~98 % lexical coverage for a text to be understood and useful (Nation, Hu).
git add index.html extract.py README.md
git commit -m "feat: Anki Trainer"
git push
Then, in the repo's Settings → Pages, set the source to this branch, / (root). extract.py never needs to run in the browser — only index.html and the JSON files you import (kept in your own browser's localStorage) are needed there.
There's no sync right now — localStorage is the only place progress lives, same as the app worked before any of this. Two identity models were tried and both set aside for now:
auth, exactly as it was built — this is the intended eventual path.What's left in place on purpose: a Firestore database already exists for this project (type-in-anki), and index.html still initializes firebase.firestore() and carries the full push/merge sync engine (scheduleSync, fetchAndMergeFromFirestore, chunking, etc.) — all of it dormant, since nothing ever sets fbUser anymore. The users/{uid} schema below is written to assume a real Firebase Auth uid, so switching back to the auth branch (or merging its sign-in code back into this one) drops straight into a working sync with no schema migration needed. Nothing has ever been written to it under this scheme, so there's nothing to migrate away from either.
users/{uid} { sources: [...meta], theme, updatedAt }
users/{uid}/sources/{sourceId} { srs, newCount, flagged, updatedAt }
users/{uid}/sources/{sourceId}/cardChunks/{n} { data, index, total } (user-imported decks only)
The bundled default.json deck's card content is never duplicated into Firestore (it's already static), only its progress (srs/newCount/flagged) — under the fixed source id "default" so it matches across devices. User-imported decks' card content is chunked (each doc kept well under Firestore's 1 MiB limit) since it isn't available anywhere else in the cloud.
The first time someone signs in: if the cloud has nothing yet, their local data is uploaded as-is. If both sides have data, they're merged — per-card SRS keeps whichever side was reviewed more recently (lastReview timestamp), flagged cards are unioned — and a timestamped backup of pre-merge local data is saved under a separate localStorage key first. On sign-out, the local copy of that account's data is cleared (so a shared computer doesn't leak it to the next person); nothing in the cloud is touched. (See the auth branch for the actual sign-in/sign-out UI this pairs with — the setup steps, Firestore rules, etc. live in its own README.)
cuatroloop / tresloop)A pair of shell functions (defined in ~/.bashrc) that read words one per
line from stdin, translate each with translate-shell
(the trans CLI), and add the pair as a flashcard — without touching Anki or
re-running extract.py. cuatroloop translates ES→FR, tresloop FR→ES.
Each word goes into the perso sub-deck inside default.json — the same
deck everyone who loads the site gets, since there's no per-person account
system right now (see "Sync (planned)" above). Once real sign-in is back,
this can move to a per-user deck in Firestore instead; for now it's one
shared deck, same as this app worked originally.
brew install translate-shell # provides `trans`
echo "casa" | cuatroloop # adds casa <-> maison to the shared perso deck
or interactively, one word per line, Ctrl-D to stop:
cuatroloop
Type commit as a line (instead of a word to translate) to commit and
push default.json right away, with a message noting which loop added the
words.
Words that already exist in that deck (matched case-insensitively against either side of the pair) are silently skipped instead of duplicated.
can you put that to "project", separate in so-called "ui","machanic","learning" various themes, yeah as you said (keep the readme clean from my ai comments, don't push the comments)
extract.py/.apkg round-trip for some workflows.chinois branch. The Refold Mandarin deck needs more than this app does today: its note type's CSS leaks into the page and its fonts get overridden (fix: render cards in a Shadow DOM), and the generic "type the whole back" rule would ask for hanzi + pinyin + meaning + sentence (fix: a per-note-type field to type, the pinyin here). The branch holds an untested first pass; not merged since bundling that deck's media isn't wanted until decks can be uploaded to a server.image-occlusion-quiz branch. The idea: a labeled diagram (e.g. a car) where you type each part's name instead of flipping a card, built on Anki's native Image Occlusion note type so the same cards work unmodified in real Anki. One note per diagram, one masked region (cloze) per part — confirmed round-tripping correctly through Anki's own import/export with real coordinates (left/top/width/height as 0–1 fractions of the image, e.g. {{c1::image-occlusion:rect:left=.051:top=.415:width=.114:height=.065:oi=1}}, shapes joined by <br> in the note's Occlusion field). car_diagram.svg/.png on that branch is a hand-built reference diagram (10 labeled parts: parabrisas, espejo, volante, asientos, maletero, intermitente, motor, rueda, puerta, carretera) with an example .apkg masking each one. Still to do: extract.py support for reading this note type back into JSON, and a web-app study mode that prompts one part at a time, keeps correct labels visible, requeues wrong/revealed ones, and gives the whole diagram one overall SRS rating once every part's been typed correctly.Tracked as bug issues on the project board.
{
"version": 1,
"source": "My Deck.apkg",
"decks": [
{
"id": "1234567890",
"name": "Parent::Child",
"cards": [
{ "id": "111", "question": "<b>question HTML</b>", "answer": "answer HTML", "words": ["word1", "word2"], "tags": ["tag1"] }
]
}
]
}
front | backanswerindice-fantome, issue #26): on phones the keyboard capitalizes the first letter, typing starts in the middle of the centered blank, and the fixed grey word doesn't line up with what's typed. The hint is back in small orange under the blank.