Ben Gutteridge4k downloadsRead, search, highlight, and annotate PDFs with themes, searchable notes, local storage, and performance-focused rendering.
Read, search, highlight, and annotate PDFs inside Obsidian with a calm interface designed to stay out of the document's way.

Lumen is a PDF reader for research-heavy vaults on desktop, phone, and tablet. It combines document themes, contextual full-PDF search, fast text markup, searchable notes, and local recovery files without modifying the source PDF or sending its contents anywhere.
| Contextual PDF search | Individual annotation editor |
|---|---|
![]() |
![]() |


The screenshots show the running plugin in Obsidian using an original demo document created for this repository.
Lumen was built around large documents and dense annotation sets rather than optimized after the fact.
A private synthetic benchmark used during 1.0.5 development inserted and search-indexed 100,000 annotations across 1,000 pages in 209.77 ms, traversed every page bucket in 12.80 ms, and searched all annotations in 18.13 ms on the development machine. A separate extreme run indexed 250,000 annotations across 2,000 pages in 576.63 ms, applied 10,000 edits in 72.80 ms, fetched a 12-card inspector window from the middle of the collection in 6.99 ms, traversed all page buckets in 34.76 ms, filtered the full collection in 60.07 ms, and sorted it in 10.76 ms. Those figures describe the in-memory index. A 100,000-record storage run restored the compact snapshot in 550.01 ms while returning to the host between 1,000-record batches, then produced a 28.24 MB compact checkpoint in 252.40 ms.
The production bundle was also exercised inside Obsidian 1.13.7 with a synthetic 3,000-page PDF. Rapid forward scrolling and a separate forward/reverse run each recorded zero sampled frame gaps above 34 ms; the worst sampled gap was 33 ms. The first page painted in under a second; jumps to pages 1,500 and 3,000 returned to 0% idle CPU; twelve rapid distant-page jumps completed in 3.77 seconds; and the process settled between roughly 62 MB and 84 MB resident memory instead of growing with every visited page. A rare full-document search reached and highlighted its only match on page 3,000 while yielding control throughout. Results vary by machine and document, but the numbers make the intended scale concrete.
The source PDF is never edited. Lumen hashes its bytes with SHA-256 and stores a recoverable bundle in your vault:
.lumen-pdf/
bundles/
sha256/
<document-hash>/
manifest.json
annotations.snapshot.json
annotations.snapshot.previous.json
annotations.journal.jsonl
document.pdf # only when automatic recovery copies are enabled
file-index/
<path-key>.json
The append-only JSONL journal protects recent changes between checkpoints, while the previous compact snapshot provides a recovery fallback. The export command creates a readable Markdown representation whenever you want one. Existing Markdown snapshots remain supported as migration and corruption fallbacks. Because identity comes from PDF content, annotations remain associated when the original file is renamed or moved.
Everything stays in the vault: no account, telemetry, remote processing, CDN scripts, or dynamic code loading.
Lumen stores each device's reading page in its own reading-position.<device-id>.json beside that PDF's annotation bundle under .lumen-pdf/. Devices read the newest synced position but write separate files, so Git does not have to merge simultaneous page updates. Include .lumen-pdf/ in GitSync on both devices. Keep device clocks accurate and finish syncing before moving between devices. Zoom preferences stay device-specific in local storage; older zoom values are imported from plugin settings, and PDF reading no longer rewrites data.json. On first open after upgrading, Lumen reads the newest position from 1.0.28's reading-position.json, 1.0.27's Markdown state, or older plugin state, then records future page changes in a per-device JSON file. Existing Git merge conflicts with conflict markers must be resolved once before Obsidian can read those files.
Once Lumen is accepted into the community directory:
main.js, manifest.json, and styles.css from the latest release.<your-vault>/.obsidian/plugins/lumen-pdf-annotator/.Lumen supports Obsidian 1.13.7 or newer on desktop, iOS, and Android.
Open any PDF after enabling Lumen. The PDF search, table of contents, and annotation inspector begin closed every time a document opens. When the PDF supplies a navigable outline, the toolbar shows a table-of-contents icon; its floating panel filters heading titles, preserves the PDF hierarchy, wraps long headings beside their page numbers, marks the current heading, and jumps to the heading's exact destination. Opening the panel brings the current heading into the middle of the list unless it is too close to either end. PDFs without an outline keep the button hidden. The current theme is shown as one compact icon whose menu contains Light, Sepia, and Dark. Lumen restores each PDF's saved page and zoom after its reader is ready, even when Obsidian opens another note in a new tab during startup.
On desktop, pinch the trackpad over the PDF to zoom around the pointer, or hold Ctrl while scrolling the mouse wheel. Ordinary two-finger scrolling still moves the document. Desktop pinch zoom supports 50–400% with finer 1% steps and saves the final scale; the zoom buttons and hotkeys move between the usual 25% stops. On mobile, pinch with two fingers inside the PDF to zoom from 25–400% in 5% steps around the moving finger midpoint. Existing page, text, search, and annotation layers scale together during the gesture before rendering at the final size. One finger still scrolls or selects text; reset zoom returns to fit-to-width. Gestures apply only to the PDF reading area.
Select text to open the compact markup palette. Choose a colour first, then choose a mark type to apply it immediately—there is no separate confirmation step. Choosing the comment type also opens the individual editor so you can add its note. Nothing is saved merely by choosing a swatch. Click an existing mark to open its individual editor. On desktop, an inspector card does the same; on mobile, tapping a card navigates to the mark and its pencil icon opens the editor. Use the sticky-note icon or Place a page note command to place a note anywhere on a page. PDF search marks every exact match on the rendered page, upgrades visible results to PDF.js's exact text-range geometry at every zoom level, and strengthens the selected result. The toolbar's theme controls affect the reading surface and editor together; the chosen theme persists and Lumen button text and icons follow your Obsidian accent colour in every PDF theme.
Right-click a saved mark on desktop, or long-press it on mobile, and choose Copy link to highlight. Paste the resulting Markdown link into any note in the same vault; following it opens the PDF, scrolls to the linked annotation, flashes it, and opens its editor. To add more text to a saved annotation, open its editor and use the scan-text icon. Navigate if needed, select the additional text, check the opaque quote preview with muted text beneath the floating Extend annotation action, and confirm. New selections and their extensions retain page-text positions, so text selected before or after a mark appears in document order and overlapping characters appear once. Cross-page segments share colour, style, note, tags, link target, inspector card, and deletion as one annotation. Long quotes scroll inside the individual editor; focus the quoted text to scroll it with the keyboard.
Quoted text uses the PDF's selectable text layer, restores spaces at line boundaries, and expands correctly mapped Latin ligatures such as fi to fi. For missing or NUL Unicode mappings, Lumen can recover letters from validated standard glyph names in an embedded TrueType font. This repairs selection, copy, PDF search and new quotes using the bundled PDF worker on desktop and mobile, without OCR, downloads or changes to the PDF. Recovery is limited to fonts with usable semantic names; unresolved glyphs still appear as � in quotes. Font names alone and surrounding words are never used to infer letters.
Existing saved quotes remain unchanged when you update the plugin. Older annotations without source positions use their saved page and mark geometry when you extend them, so they support prepending and appending; exact overlap handling is more reliable for newly created annotations. Pages containing recovered glyphs have separately versioned offsets. Extending an old mark on such a page uses its saved geometry rather than combining incompatible character positions. Unaffected pages keep exact range-based overlap handling.
On phones, the compact toolbar has two rows. Tap the chevron in the top row to smoothly hide or reveal the lower tools row and leave more room for reading. Page navigation, zoom buttons, and the zoom percentage stay available. Each PDF remembers its last expanded or collapsed state on this device, including after Obsidian restarts or the PDF is renamed or moved. PDF search, the table of contents, and the annotation inspector open as full-size floating panels that remain raised when the keyboard closes. Tapping a search result, outline heading, or annotation card navigates to the PDF and closes its panel. The selection palette and individual editor remain safe-area-aware floating sheets. Mobile PDF scrollbars stay hidden while touch scrolling remains available. On tablets the toolbar returns to one row and the side tools remain docked to the nearest edge. The last-read page is shared through vault sync, while a phone's fit-to-width scale never changes the same document's desktop zoom.
Default hotkeys:
| Action | macOS | Windows/Linux |
|---|---|---|
| Toggle PDF search (while a Lumen PDF tab is active) | Cmd+F |
Ctrl+F |
| Toggle annotation inspector | Cmd+Shift+A |
Ctrl+Shift+A |
| Zoom in | Cmd+Shift+= |
Ctrl+Shift+= |
| Zoom out | Cmd+- |
Ctrl+- |
| Reset zoom | Cmd+0 |
Ctrl+0 |
Previous page, next page, page-note placement, annotation checkpoint, export, legacy import, backup verification, recovery, and Open current PDF in Lumen annotator are also available in Obsidian's command palette and can be assigned custom hotkeys.
.lumen-pdf/exports/. In Settings → Lumen PDF Annotator → Export annotations, choose individual annotated PDFs or select all filtered matches and export them together. Each PDF gets a separate, uniquely named Markdown note with the source PDF path, page headings, quoted highlight text, attached notes, tags, and links back to the exact annotation. Multi-page highlights stay grouped with their one associated note. Exports do not include raw recovery JSON and do not change the source PDFs.Lumen PDF annotation index/. Obsidian Search finds their quoted text and notes; Omnisearch also indexes them when installed. Search results open a generated note with a nearby link to the exact annotation in Lumen. Existing saved annotations are indexed in the background without opening their PDFs, and later edits update the copies after a short pause. Turning the setting off removes only Lumen's generated search copies and their folder when empty. Edit annotations in their PDFs because the generated notes are replaced during synchronization..lumen-pdf/recovered/.Make Lumen the default PDF viewer is enabled initially. Disable it if you want to keep Obsidian's built-in PDF view and open selected PDFs through Lumen's command instead. Restart Obsidian after changing this setting. PDF theme sets the persistent light, sepia, or dark reading theme. Use printed page numbers chooses whether annotation cards and editors use printed page numbers or page positions in the PDF. A manually entered page number is always displayed, regardless of this preference. Default mobile toolbar chooses Expanded or Collapsed for PDFs first opened on this device; changing it keeps every previously opened PDF's saved toolbar state. Expanded is the initial default. Create automatic PDF recovery copies is disabled by default; enable it only if you want a background bundle copy in addition to your source PDF. Include PDF annotations in vault search is also disabled by default, so existing vaults have no new search files or indexing work until you opt in.
Issues, feature requests, pull requests, forks, and independent builds are welcome. Start with CONTRIBUTING.md for the development workflow and project boundaries.
npm ci
npm run typecheck
npm run build
The production build is written to dist/. For a live development build, set LUMEN_PDF_ANNOTATOR_PLUGIN_DIR to a dedicated test-vault plugin directory and run npm run dev.
Planned work includes additional portable export formats and performance profiling across a wider range of scanned and malformed PDFs and mobile devices.
Please report a reproducible document issue through the bug template. Do not upload a private PDF; use a minimal public or synthetic reproduction whenever possible.
Lumen is an independent rewrite from a standalone product specification. Zotero and Alex Annotator helped identify useful interaction concepts in the broader PDF-annotation space, but no source code, assets, styles, or Git history from either project are included. The compatibility importer only reads user-owned annotation data; the interface, current storage format, performance architecture, and implementation are Lumen's own.
MIT © 2026 Ben Gutteridge. Bundled dependency notices are listed in THIRD_PARTY_NOTICES.md.