Tipword looks like a small vocabulary product from the outside: search for a word, understand it, write a few examples and practise it later. Underneath, those actions cross three different kinds of data: a shared lexical source, a learner-specific memory record and generated feedback.
Keeping those responsibilities separate is the central architectural decision. Dictionary facts remain deterministic and traceable. Learning state belongs to one user. A language model is used only after relevant evidence has been retrieved and assembled.
1. Importing a lexical source instead of querying one at runtime
Open English WordNet is distributed as structured JSON. We download a pinned export and import it into SQLite as a build-time data operation. The application therefore does not depend on a public dictionary API for ordinary search or word-of-the-day requests.
OEWN JSON
Entries, synsets and examples
Import
Normalise and preserve source IDs
SQLite
Indexed lexical relations
wordfreq
Zipf usage scores
The importer first loads synsets into memory, then walks the lexical entries. Each write happens inside one SQLite transaction. Re-importing replaces only rows belonging to the OEWN source, so the database cannot be left with mixed versions of that source.
We preserve OEWN’s sense and synset identifiers. They are better deduplication keys than definition text, which may be reworded between releases even when the underlying meaning has not changed.
2. Headwords and meanings are different entities
A spelling is not a meaning. The headword charge, for example, can be a noun or a verb and has several meanings inside each part of speech. Flattening all of that into one row would make examples, synonyms and future retrieval ambiguous.
| Table | Responsibility | Important identity |
|---|---|---|
word_entries | Display and normalised headword | Source + normalised word |
word_meanings | Part of speech and definition | Source + sense ID |
word_examples | Usage attached to one meaning | Meaning + example text |
word_synonyms | Related lemmas for one meaning | Meaning + synonym |
word_frequencies | Modern usage score | Entry + frequency source |
Foreign keys cascade from an entry to its meanings and then to examples and synonyms. Unique indexes make the import idempotent. Normalised headwords support exact lookup and prefix search, while source IDs keep lexical identity stable.
3. Frequency is a filter, not the curriculum
OEWN tells us what a word means; it does not tell us whether that word is a useful next choice for a modern learner. We enrich each entry with a Zipf frequency score from wordfreq. A score around 4 means roughly one occurrence per ten thousand words, which is a productive band for words that are useful without being elementary.
The daily candidate query applies a Zipf band of 3.2–4.05, then checks practical quality constraints:
- The headword is between 5 and 13 lowercase alphabetic characters.
- The primary meaning is an adjective or verb.
- Obvious inflected endings are excluded from the candidate surface.
- At least one example contains the displayed headword itself.
Candidates are sorted by frequency and normalised spelling. We convert the UTC date to an integer and use it as a deterministic offset, so all learners receive the same result for the day without storing a daily row or relying on randomness.
day = floor(utc_midnight / 86_400_000)
candidate = ordered_candidates[day % candidate_count]4. Shared lexical facts, private learning state
Dictionary data is shared. The learner’s relationship to a word is not. A personal vocabulary record stores the origin of the word, when it was added, when it was learnt and the learner’s own examples. The combination of user and word is unique, making “add this word” naturally idempotent.
A word becomes learnt after three full examples pass a structured usage check. We retain the verdict for each sentence, not just the final result. That provides evidence for reminders: a word that was initially uncertain returns sooner than one used naturally several times.
5. Retrieval happens before generation
The writing coach is implemented as a LangGraph workflow. The model is asked for strict structured output validated with Zod: a summary, score, exact phrases worth improving, suggested alternatives and concise reasons. Invalid free-form output never becomes an API response.
RAG adds a retrieval stage before that analysis node. Each lexical sense is indexed as a document containing its headword, part of speech, definition, examples and synonyms. Learner-written examples are indexed separately because they are evidence of personal usage, not dictionary truth.
Learner input
Writing, speaking or a practice response
Hybrid retrieval
Semantic fit plus exact lexical matches
Personal filter
Only this learner's active and learnt words
Structured guidance
Validated suggestions with reasons and provenance
Retrieval is hybrid. Exact and prefix matching catches direct lexical evidence; semantic matching catches ideas expressed with different words. Results are filtered by the authenticated user’s vocabulary, then reranked using semantic relevance, learning status, recall history and the word’s frequency band.
Only the top few meanings enter the model context. Each carries its stable sense ID, so a suggestion can be traced back to the definition and examples that justified it. The model cannot silently introduce a different meaning of the same spelling.
The model generates the explanation. Retrieval decides which words it is allowed to explain.
6. Reminder scheduling uses the same evidence
Every recall attempt updates a compact memory state: last practised time, success, response mode and current interval. The scheduler scores words by how overdue they are, how difficult previous attempts were and whether they have appeared in recent free writing.
This means reminders and RAG are not separate systems. When the learner naturally uses a word, that successful retrieval is recorded. When they repeatedly miss it, the word becomes eligible for an earlier, more supported exercise.
7. The request path stays deliberately small
The web application is React with TanStack Router and shadcn components. Hono exposes authenticated TypeScript APIs. Drizzle owns the relational schema, while prepared SQLite queries handle the read-heavy dictionary paths. LangGraph coordinates model work, and Zod defines the boundary between generated output and product data.
input
→ authenticate
→ retrieve learner vocabulary
→ retrieve and rerank relevant senses
→ assemble bounded context
→ run structured analysis
→ validate
→ persist recall evidence
→ respondThe useful property of this design is not the number of technologies. It is that each one has a narrow job. SQLite answers lexical questions. The learner tables answer memory questions. Retrieval selects evidence. The model turns that evidence into guidance.
What this architecture protects
Vocabulary software can easily become a thin prompt wrapped around a dictionary. Tipword’s architecture protects the product from that outcome. Meanings remain structured, daily choices remain reproducible, personal data remains scoped to one learner and every generated suggestion is grounded in retrievable evidence.
That gives us room to improve models, ranking and scheduling without changing the core promise: Tipword helps you reach for words you have genuinely learnt.
Related reading
Read the product story behind the architecture.