The plugin used to call dictionaryapi.dev for every lookup, which was slow, rate-limited, and broke offline. It now ships a local SQLite file (~23MB, ~167K English entries from Wiktionary via the MattDodsonEnglish/english-dictionary project) and queries it locally via sql.js. Plumbing: - DictionaryStore loads the SQLite from <vault>/.obsidian/plugins/lexophile/dictionary.sqlite, downloads on demand from a configurable URL (default: a release asset on this repo), and exposes a synchronous lookup() that returns a WordEntry or null. - lookupWord is now an async wrapper around store.lookup that throws WordNotFoundError on null. DictionaryNotReadyError surfaces the pre-download state so modals can fail fast with a helpful message. - sql.js initialization moved to its own module (src/sqlite.ts) and reused by both the Kobo import and the new dictionary store. - AddWordModal / MassImportModal / KoboImportModal each take the store via constructor and guard against the not-ready state before starting work. - Settings tab gains a "Local dictionary" section with a status pill (Ready / Downloaded-not-loaded / Not downloaded), an entry count and size summary, a Download/Re-download button, and a configurable URL. - Removed the inter-request rate limit (was 350ms for API throttling) — local lookups are sub-millisecond, so a 0ms yield is enough to let the progress line repaint. Bundled dictionary data is hosted as a release asset on bryanmanio/obsidian-lexophile (tag: dictionary-v1). The plugin does not call dictionaryapi.dev at any point during normal use. The Chrome extension still uses the API for its own lookups — out of scope here. Build artifacts: - scripts/build-dictionary.py converts the upstream parquet (167,585 entries) to the compact SQLite schema we ship; documented for reproducibility. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|---|---|---|
| scripts | ||
| src | ||
| .gitignore | ||
| esbuild.config.mjs | ||
| LICENSE | ||
| main.js | ||
| manifest.json | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| versions.json | ||
Lexophile — Personal Dictionary
Build your vocabulary one word at a time.
An Obsidian plugin that turns any word you read into a permanent, searchable dictionary note in your vault.
Install · How it works · Privacy · Support
What it does
- Right-click on the web → "Add to Lexophile" → a definition note appears in your Obsidian vault. (Requires the Chrome extension.)
- Inside Obsidian → run
Lexophile: Add word to lexiconfrom the command palette and type or paste the word. - Plug in your Kobo → import every word you saved from "My Words" in one shot, with each word linked back to the book it came from.
Every word becomes a note in your Dictionary/ folder with the part of speech, definition, example sentence, and a clickable source link. A Bases view auto-generates so you can see your whole vocabulary in one table.
Features
- 📖 One-click capture from the web via the companion Chrome extension
- ✍️ Manual entry from inside Obsidian
- 📱 Kobo import — pull "My Words" from
KoboReader.sqliteand link each word back to its book - 🗂️ Auto-generated Bases view of your full lexicon (Word, Word class, Definition, Example, Source, Date added)
- 🔗 Books library integration — Kobo imports become
[[wikilinks]]to book notes - 🔒 Local-only — your words never leave your machine except for the dictionary lookup itself
- 🎨 Customizable note template with frontmatter properties for everything
How it works
The plugin ships with a local SQLite dictionary (~23MB, ~167K entries). Lookups happen entirely offline — the dictionary file downloads once on first use, then everything stays on your machine.
┌──────────────┐ POST /word ┌────────────────────────────────┐
│ Chrome │ ───────────────► │ Obsidian plugin │
│ extension │ Bearer <tok> │ (HTTP server on :27124) │
└──────────────┘ │ │
│ ┌──────────────────────┐ │
│ │ dictionary.sqlite │ │
Mass-import / Kobo / manual ►──┼──►│ (167K entries, local)│ │
│ └──────────────────────┘ │
│ │
│ creates note in vault → │ → 📓 Dictionary/serendipity.md
└────────────────────────────────┘
Dictionary data is derived from MattDodsonEnglish/english-dictionary (CC BY-SA 3.0, originally from Wiktionary via dictionaryapi.dev). The Chrome extension still calls dictionaryapi.dev for its own lookups; the plugin itself makes no network calls during normal use.
The Chrome extension and the plugin authenticate to each other with a shared secret token (auto-generated during onboarding) so random websites can't write to your vault.
Installation
From the Obsidian community store (coming soon)
Search for Lexophile in Settings → Community plugins → Browse.
Manual install
- Download
main.js,manifest.json, andversions.jsonfrom the latest release. - Create the folder
<vault>/.obsidian/plugins/lexophile/. - Copy the three files into that folder.
- In Obsidian: Settings → Community plugins → toggle Lexophile - Personal Dictionary on.
Chrome extension
Install the companion extension from the lexophile-chrome-extension repo.
Setup
- Open Settings → Lexophile → Local dictionary and click Download. The plugin fetches ~23MB once and stores it inside your vault's plugin folder. The "Ready" pill confirms it loaded.
- (Optional, for web capture) The Chrome extension opens a welcome tab on install. It auto-generates an API token; copy it and paste it into Settings → Lexophile → API token, then click Test connection.
Usage
From the web
Highlight a word on any page, right-click, and choose Add "" to Lexophile. A toast confirms it was saved. The page URL is captured as the word's source.
Inside Obsidian
Cmd+P → Lexophile: Add word to lexicon → type or paste a word, hit Enter. The source for these is manual.
From your Kobo eReader
- Settings → Lexophile → enable Kobo import, set your books folder.
- Plug in your Kobo via USB.
Cmd+P→ Lexophile: Import words from Kobo.- The default path (
/Volumes/KOBOeReader/.kobo/KoboReader.sqliteon macOS) is pre-filled. Click Read words. - A preview lists each book with the Kobo title, an editable Title Case name, a word count, and autocomplete against existing book notes in your library.
- Edit any name or pick an existing book, then Import.
Every imported word gets source: "[[Book Name]]" in its frontmatter. If the book note doesn't exist yet, the plugin creates a stub (configurable).
Settings reference
| Setting | Default | Notes |
|---|---|---|
| Dictionary folder | Dictionary |
Auto-created if missing |
| Note naming | As-is | lowercase and Title Case also available |
| Duplicate handling | Skip | Or append, or overwrite |
| Auto-create dictionary base | On | Creates _Dictionary List.base for the table view |
| Local server port | 27124 |
Change if it conflicts with another plugin |
| API token | (auto-generated) | Must match the Chrome extension |
| Enable Kobo import | Off | Reveals the books library settings |
| Books folder | Books |
Where book notes live |
| When a book isn't in your library | Auto-create stub | Or link without creating, or use plain text |
Privacy
The plugin is fully local after the initial dictionary download. No analytics, no telemetry, no account, no cloud. The only network call after setup is when you click Re-download in settings.
The Chrome extension does call dictionaryapi.dev when you right-click to capture a word — that's outside the plugin and only happens when you use the extension.
Development
npm install
npm run dev # watch mode
npm run build # production bundle
The plugin bundles sql.js (used by the Kobo import) which is why main.js is ~1 MB.
For the Chrome extension, see lexophile-chrome-extension — no build step, just load unpacked.
Support
Need help, hit a bug, or have an idea?
- 🐛 Bug or feature request → open an issue
- ☕ Like it? → Buy me a coffee
License
MIT © Bryan Maniotakis