Jaraco Reader — A Mobile Linux Reader for Markdown, Mermaid, and EPUB
Anyone who reads on Linux knows the problem: on the desktop, many
Markdown and EPUB readers work extremely well. On mobile devices,
however, the experience quickly becomes uncomfortable. That is exactly
why we built jaraco-reader.
The idea was simple: create a reader that runs cleanly on postmarketOS,
renders Markdown documents including Mermaid diagrams, and makes EPUB
books easy to read — without forcing desktop-style workflows onto a
smartphone.
Why This Project Exists
Most existing readers are optimized for desktop usage:
- Window-heavy interfaces instead of touch-first interaction\
- Unclear navigation on smaller displays\
- Limited support for technical Markdown content with diagrams
jaraco-reader was built as a pragmatic mobile solution. The goal was
not a theoretical showcase, but a tool that makes technical documents
and books genuinely readable in everyday use.
In one sentence:
This reader was developed because Markdown and EPUB readers work great
in desktop mode, but not nearly as well on mobile devices. So we built
jaraco-reader to make Markdown documents with Mermaid diagrams and
EPUB books significantly easier to read.
Project Overview: How jaraco-reader Works
The application is based on GTK3 + WebKit2GTK 4.1 and uses Python as its
runtime. This combines native application control with robust HTML/CSS
rendering.
What the reader actually does:
- EPUB files are unpacked, chapters merged, and displayed as a
continuous reading page\ - Markdown is converted to HTML, including fenced code blocks, tables,
and structural elements\ - Mermaid blocks are automatically detected and rendered as diagrams\
- Images and relative assets are resolved correctly\
- Reading position and font size are stored per book and restored when
reopening
Mobile-Focused Features
To make the reader truly practical on a smartphone, we deliberately
implemented simple and direct interactions:
- Edge buttons for fast forward/backward navigation\
- A Go-to-Page dialog for direct jumps\
- Zoom in / Zoom out for adjustable readability\
- A recent list (up to 5 books) on startup\
- Tap on empty view opens the file dialog\
- Stable behavior in both portrait and landscape mode
This creates exactly the difference that many desktop-centered readers
lack: short interaction paths, clear touch controls, and reliable
behavior on small displays.
Technical Core (Short Overview)
The processing pipeline is straightforward:
- Open file (
.epub,.md,.markdown)\ - Normalize content (EPUB parsing or Markdown rendering)\
- Load HTML into
WebKit2.WebView\ - Periodically capture scroll position and store it as a fraction\
- Restore position and zoom level when reopening
EPUB content is cached under ~/.cache/jaraco-reader/ to ensure local
asset availability. State information such as recent, last_book,
fraction, and font_size is stored in
~/.config/jaraco-reader/positions.json.
Why It Fits Naturally on postmarketOS
postmarketOS provides a real Alpine Linux system on a smartphone. This
means:
- Transparent packaging with
APKBUILDandabuild\ - Direct installation and testing on the device\
- No proprietary platform layer for a simple reader
As a result, jaraco-reader stays close to traditional Linux
development principles: transparent, packageable, and maintainable.
Conclusion
jaraco-reader emerged from a concrete pain point: desktop readers are
strong, but mobile readability for technical content is often weak. By
combining GTK, WebKit2GTK, Markdown rendering, and Mermaid support, the
project delivers exactly the functionality missing on mobile Linux
devices.
For us, the key outcome is not „just another reader,“ but a practical
tool that makes Markdown documents with diagrams and EPUB books
significantly easier to read on postmarketOS.
Why Tailored Software Matters
Many modern applications are highly general-purpose. They try to cover
everything, but in daily use they often do too much — or too little
where it actually matters. That is where friction emerges: more clicks,
more compromises, less focus.
Purpose-built tools that support your exact workflow are more achievable
today than ever.
If you are facing similar challenges and wondering whether a more
tailored solution exists, feel free to reach out. We would be happy to
support you.
Appendix: Relevant Commands
./app/jaraco-reader /path/to/book.epub\
Starts the reader directly with an EPUB file../app/jaraco-reader /path/to/doc.md\
Opens a Markdown document with HTML rendering and Mermaid support.abuild -F\
Builds the APK package from theAPKBUILDfile.apk add --allow-untrusted /home/user/packages/projects/aarch64/jaraco-reader-<version>.apk\
Installs the built package on the device.
Copy the replication spec below to rebuild the project.
Jaraco Reader Replication Spec
1. Objective
Replicate jaraco-reader, a GTK-based mobile-friendly reader for postmarketOS/Alpine Linux that:
- Opens
.epub,.md, and.markdownfiles. - Renders EPUB and Markdown content in a WebKit view.
- Supports Mermaid diagrams in Markdown documents.
- Preserves reading position and font size per book.
- Provides touch-friendly navigation for mobile devices.
2. Scope
In scope:
- Single-process Python application (
app/jaraco-reader). - GTK3 + WebKit2GTK UI.
- EPUB parsing + extraction to cache.
- Markdown-to-HTML rendering with Mermaid integration.
- Local state persistence (
positions.json). - Alpine APK packaging via
APKBUILD. - Desktop integration (
.desktop, appdata, icon, post-install defaults).
Out of scope:
- Cloud sync.
- Annotation/highlight features.
- DRM-protected EPUB support.
- Network content fetching.
3. Target Environment
- OS: postmarketOS (preferred) or Alpine Linux.
- Runtime:
python3py3-gobject3py3-markdowngtk+3.0webkit2gtk-4.1adwaita-icon-theme
- Build tooling:
abuildalpine-sdk
Install prerequisites:
apk add abuild alpine-sdk python3 py3-gobject3 py3-markdown gtk+3.0 webkit2gtk-4.1 adwaita-icon-theme
4. Source Layout
Required files and purpose:
app/jaraco-reader: Main executable Python app.data/mermaid.min.js: Bundled Mermaid runtime loaded by Markdown renderer.data/io.jaraco.Reader.desktop: Desktop launcher + MIME registration.data/io.jaraco.Reader.appdata.xml: Software metadata.data/io.jaraco.Reader.svg: App icon.APKBUILD: Alpine packaging recipe.jaraco-reader.post-install: Post-install MIME defaults hook.
4.1 Mermaid JS Download Instructions
jaraco-reader expects Mermaid at data/mermaid.min.js during build, which is then installed to:
/usr/share/jaraco-reader/mermaid.min.js
Recommended source:
- jsDelivr CDN (Mermaid v10 distribution):
https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js
Download command (run from repository root):
curl -L -o data/mermaid.min.js "https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"
Optional verification:
ls -lh data/mermaid.min.js
Notes:
- Keep the filename exactly
mermaid.min.js. - If this file is missing, Markdown still opens, but Mermaid diagrams will not render.
5. Functional Requirements
5.1 File Open and Rendering
- Accept optional CLI path argument.
- If no file is provided:
- Attempt to open last-read book.
- Else show prompt with recent books and browse option.
.epub:- Read
META-INF/container.xml, find OPF rootfile. - Parse manifest/spine.
- Extract archive to cache directory.
- Merge chapter bodies into a single HTML document.
- Resolve relative links/images to
file://absolute paths.
- Read
.md/.markdown:- Convert Markdown to HTML with extensions:
fenced_codetablestocsane_lists
- Convert mermaid fenced blocks to
<div class="mermaid">.... - Inject Mermaid JS (
/usr/share/jaraco-reader/mermaid.min.js) if present.
- Convert Markdown to HTML with extensions:
5.2 Reading UX
- Header controls:
- Open file
- Zoom out
- Zoom in
- Go to page
- Overlay edge buttons:
- Previous page
- Next page
- Page scroll movement per action:
~0.9 * viewport height. - Click/tap behavior:
- Empty state click opens file prompt.
5.3 Persistence
- Config path:
~/.config/jaraco-reader/positions.json. - Cache path:
~/.cache/jaraco-reader/. - Persist per book:
fraction(scroll position ratio)font_size
- Persist global:
_last_book_recent(max 5 entries)
- Restore
fractionandfont_sizeon reopen.
6. Non-Functional Requirements
- Mobile-friendly interaction on small screens.
- No network dependency for rendering Mermaid (local JS file).
- Works in portrait and landscape.
- Robust against malformed EPUB files (fail gracefully with visible error in title area).
7. Implementation Notes
- GI versions:
Gtk=3.0WebKit2=4.1Gdk=3.0
- Keep JavaScript enabled in WebKit settings.
- Poll scroll state on timer (~1000ms) and debounce config writes (~500ms).
- Use atomic config writes (
tmp+os.replace). - Use SHA-256(path) prefix as EPUB extraction directory key.
8. Packaging Requirements (APK)
APKBUILD must:
- Install executable to
/usr/bin/jaraco-reader. - Install desktop file to
/usr/share/applications/io.jaraco.Reader.desktop. - Install appdata to
/usr/share/metainfo/io.jaraco.Reader.appdata.xml. - Install icon to
/usr/share/icons/hicolor/scalable/apps/io.jaraco.Reader.svg. - Install Mermaid JS to
/usr/share/jaraco-reader/mermaid.min.js. - Declare runtime dependencies listed in section 3.
Post-install (jaraco-reader.post-install) must:
- Register default app for:
application/epub+ziptext/markdowntext/x-markdown
- Run
update-desktop-databasewhen available.
9. Build and Install Procedure
Build:
abuild -F
Expected package output path:
/home/user/packages/projects/aarch64/
Install:
apk add --allow-untrusted /home/user/packages/projects/aarch64/jaraco-reader-<version>-r<rel>.apk
Run:
jaraco-reader /path/to/book.epub
jaraco-reader /path/to/doc.md
10. Verification Checklist
- Open EPUB with images; confirm content renders end-to-end.
- Open Markdown with Mermaid fenced block; confirm diagram renders.
- Change zoom, close app, reopen same file; confirm zoom restored.
- Scroll mid-document, close/reopen; confirm position restored.
- Open >5 files over time; confirm recent list is capped to 5.
- Test page jump + edge navigation controls.
- Start without argument; confirm recent/browse startup dialog behavior.
- Confirm app is available from launcher and opens associated
.epub/.md.
11. Acceptance Criteria
Replication is successful when:
- All functional requirements in section 5 pass.
- Packaging and installation steps in section 9 produce installable APK.
- Verification checklist in section 10 passes on target device.