Skip to content

Content is chosen from a catalogue rather than handed over - #48

Open
vgomx wants to merge 2 commits into
mainfrom
feat/content-packs
Open

Content is chosen from a catalogue rather than handed over#48
vgomx wants to merge 2 commits into
mainfrom
feat/content-packs

Conversation

@vgomx

@vgomx vgomx commented Aug 16, 2026

Copy link
Copy Markdown
Owner

How content was offered

Every install wrote the whole library: 22 decks, 165 cards across four languages, and all 24 grammar notes — most of it in languages the reader had not picked and would never open. Your Dutch decks were not yours because you chose Dutch; they were the rows every install starts with, alongside Portuguese, English and Spanish.

That is the opposite of a catalogue. There is nothing to add when everything is already there, and no way to tell what you chose from what you were given.

What a pack is

A rule, the words that exercise it, and the verbs to drill it on.

That shape was already in the app, unconnected. The grammar notes are the theme list — six per language, exactly the ones people trip over: de or het?, ser or estar?, What triggers the subjunctive?, Separable verbs come apart. The decks are the practice. A pack pairs them.

It is a view over that content, not a second copy. A pack names a deck id and note ids and installs them through the same buildDeck the first seed uses, so a pack added months later writes the records a fresh install would, and cannot drift from the material it offers.

22 packs, every id resolving, every seeded deck claimed exactly once.

The verbs are a focus list, not data

The drill already loads every verb the language has — NL, ES and PT ship whole conjugation tables. So a pack does not carry forms; it says which verbs the theme is about. It narrows the pool rather than reweighting it, because the point of the pack is that it is these verbs — and the distractors still come from the whole language, so a wrong option does not give itself away by its stem.

Four of the eight Dutch lemmas I first wrote from memory — opbellen, uitgaan, meedoen, opruimenare not in the table Wiktionary gave us. They are replaced with verbs that are. A focus list naming verbs the drill cannot ask about is a pack that quietly does nothing.

A fresh install

One starter pack, in the language it opens in. Measured on a wiped database: 1 deck, 6 cards, 1 note, 1 language.

Nobody loses anything

  • ensureSeeded is still guarded on the database being empty, so an existing library is untouched.
  • A pack whose deck is already on the shelf reads as added — a weaker claim than the packs store makes, and the right one for a database seeded before the catalogue existed. Verified by clearing the store against two decks: two marked added, three still offered.
  • ensureNotesSeeded is a no-op rather than deleted, so a database seeded by an older build keeps every note it has. Notes now arrive with the pack that explains them.

Checked

fresh install 1 deck, 6 cards, 1 note, NL only
catalogue 5 NL packs listed, 1 already added
adding Separable verbs 2 decks, 12 cards, 2 notes, 2 packs
pre-catalogue install 2 marked added, 3 still addable
drill focus asks about ophouden — one of the pack's eight, out of thousands in the table

IndexedDB goes to v6 and the backup to format 6, both carrying the packs: restoring decks without them would offer back what the reader had already picked.

Known

The catalogue adds but does not remove. Deleting the deck already exists and is the honest way out; a Remove that took back cards you have been grading is a different and more dangerous feature.

Every pack's cards come from the existing seed. The themes with a note but no matching deck — Dutch er, the Spanish personal a — ride along with a related pack rather than having practice of their own. New card sets are the next content job, not this one.

vgomx and others added 2 commits August 16, 2026 01:58
Every install wrote the whole library: twenty-two decks and a hundred and
sixty-five cards across four languages, plus all twenty-four grammar
notes, most of it in languages the reader had not picked and would never
open. That is the opposite of a catalogue. There is nothing to add when
everything is already there, and no way to tell what you chose from what
you were given.

A fresh install now arrives with one starter pack in the language it
opens in — measured on a wiped database: one deck, six cards, one note,
one language.

A pack is a rule, the words that exercise it, and the verbs to drill it
on. That shape was already in the app and unconnected: the notes are the
grammar themes, six per language and exactly the ones people trip over —
de or het, ser or estar, what triggers the subjunctive, separable verbs
come apart — and the decks are the practice. A pack pairs them.

It is a view over that content rather than a second copy. A pack names a
deck id and note ids, and installs them through the same buildDeck the
first seed uses, so a pack added months later writes the records a fresh
install would and cannot drift from the material it offers.

The verbs are a focus list, not data. The drill already loads every verb
the language has — NL, ES and PT ship whole tables — so what a pack
contributes is which of them the theme is about. It narrows the pool
rather than reweighting it, because the point of the pack is that it is
these verbs, and the distractors still come from the whole language so a
wrong answer does not give itself away. Checked: with Separable verbs
installed, the drill asks about ophouden.

Four of the eight Dutch lemmas I first wrote — opbellen, uitgaan,
meedoen, opruimen — are not in the table Wiktionary gave us. They are
replaced with verbs that are. A focus list naming verbs the drill cannot
ask about is a pack that quietly does nothing.

Nobody loses anything. ensureSeeded is still guarded on the database
being empty, so an existing library is untouched, and a pack whose deck
is already on the shelf reads as added — a weaker claim than the packs
store makes, and the right one for a database seeded before the catalogue
existed. Verified by clearing the store against two decks: two marked
added, three still offered.

ensureNotesSeeded is now a no-op rather than deleted, so a database
seeded by an older build keeps every note it has. Notes arrive with the
pack that explains them.

The store goes to v6 and the backup to format 6, both carrying the packs;
restoring decks without them would offer back what the reader had already
picked.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three things the catalogue was wrong about, all found by looking at it.

**Decks, not packs.** The reader is offered a deck: that is the word this
app already uses for a set of cards you practise, and a second word for
the thing that becomes one would be a word to learn for something they
can already name. The code keeps `Pack` for the offer, because `Deck` is
the record it installs and one of them has to give.

**They were thin.** Six to eight cards is a deck you finish before it
teaches you anything. 165 cards across 22 decks becomes 301, none of them
under ten, most between fourteen and seventeen.

Two things the checks caught rather than I did. Forty-one of the cards I
wrote were words those decks already had — whereas, sin embargo, de
collega, ficar — and the later copy is dropped, so the originals and
their illustrations stand. And no card names an illustration that does
not exist, because the palette was built by reading public/openmoji
first rather than by guessing and finding out.

**New deck was desktop-only.** The plus sat in the deck sidebar's header,
and a phone never shows that sidebar — so on an app whose point is the
cards you write, writing one was possible at a desk and nowhere else.
That is the honest answer to "why can't the user add their own": on a
phone they could not.

It is in the top bar now, which every screen and every size has. 44px
under a thumb and 36 under a pointer, rather than the 14px glyph it was.
Only inside Flashcards and Review, though — a button that makes a deck
while you are reading an etymology has wandered away from the thing it
acts on. Measured across five routes and two widths: present on the four
where it belongs, absent on the two where it does not.

The deck list's empty state names both ways in as well, since the
catalogue is a starting point rather than the only source of cards.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant