A mobile-first Markdown viewer for iOS and Android, built with
Flutter. Designed to be the best reading experience for .md documents
on a phone — including Mermaid diagrams, LaTeX math, syntax-highlighted
code, tables, footnotes, and admonitions.
v1.3.0 — released 2026-04-21. Live on the App Store and Google Play.
Phases 0–7 complete. v1.3 is a small library-ergonomics release driven
by post-launch user feedback: a collapse-all button next to the search
bar so deep folder dives do not strand the user with a tower of open
expansion tiles, and a Rename action on folder / synced-repo sources
so long GitHub paths (cemililik/markdown-viewer-mobile) can be
shortened to a readable alias in the drawer.
v1.2 consolidated the findings from three parallel 2026-04-19 reviews
(code / security / performance — 134 findings total). v1.2.1 patched
the large-repo sync error message, document sharing, and the nested
folder tree display bug. v1.0 shipped after a full-application code
review (128 findings across 8 streams — all P0/P1 findings closed,
architecture layer refactored), a dedicated security review, and
leak_tracker globally enabled in the test harness. See
docs/roadmap.md for the full delivery history and
post-v1 candidates.
- CommonMark + GFM — tables, task lists, strikethrough, autolinks
- Mermaid diagrams — 12 diagram types rendered in a sandboxed WebView with an LRU cache and dark/light theming
- LaTeX math — inline and block equations via
flutter_math_fork - Syntax-highlighted code — 100+ languages, themed to the active color scheme
- Admonitions — GitHub-style
> [!NOTE],[!WARNING],[!TIP], etc. - Footnotes — rendered as tap-to-open bottom sheets
- Table of contents drawer with tap-to-jump navigation
- In-document search with inline highlighting (browser find-in-page style)
- Reading comfort toolbar — font scale, reading width, line height
- Immersive scroll with auto-hide AppBar and FAB
- Light, dark, and sepia themes
- Keep-screen-on toggle
- Text selection, copy, and share
- In-document anchor links
- Reading time estimate
- PDF export with Mermaid diagrams and math preserved
- Mermaid fullscreen viewer — expand icon on every diagram opens an edge-to-edge pinch-zoomable view with reset / recenter and tap-to-toggle chrome, so dense flowcharts, ER diagrams and mindmaps are actually readable on a phone
- Folder browser with iOS security-scoped bookmarks and Android SAF
- GitHub repository sync — one URL syncs an entire
.mdtree offline - Optional Personal Access Token stored in the platform Keychain / Keystore
- Incremental re-sync using SHA-based change detection
- Recent documents, self-cleaning stale entries
- Cross-library full-text search — typing three or more characters
into the library search field scans every recent, folder and synced
repository for content matches (runs inside a
compute()isolate) - Pull-to-refresh on every source — Recents, folder, synced repo; swiping down re-enumerates a folder or re-syncs a repo
- First-run onboarding with a pre-loaded example library
- Default
.mdfile handler on iOS and Android - Adaptive splash screens and app icons (Material You on Android 12+)
- Accessibility — semantic annotations, 44 dp touch targets
- Sentry crash reporting (opt-in, consent-gated)
- Offline-first — no network required after the initial sync; the network is only touched on explicit user action against an allow-listed host
- Privacy-respecting — no accounts, no telemetry, no background traffic;
PATs are encrypted in the OS keychain, scoped to
first_unlock_this_deviceon iOS, and protected against screen capture / mirroring while the PAT field is on screen (AndroidFLAG_SECURE, iOSUIScreen.isCapturedcollapse) - Production-grade pipeline — tag-triggered CI/CD, signed builds,
R8 obfuscation, symbolication,
leak_trackerin tests
If you want to remove the GitHub Personal Access Token the app is holding — lost device, handing off the phone, or rotating the token on GitHub — either of these paths fully wipes it:
- Inside the app — open the sync screen, tap the clear affordance next to the PAT field, then start a sync without entering a new token. The next successful write deletes the stored value.
- Remove every synced repo — the
removeSyncedRepouse-case automatically wipes the stored PAT once the last synced repository is removed from the library (per ADR-0012's wipe-on-sign-out contract). - Revoke on GitHub — open github.com/settings/tokens (classic PATs) or github.com/settings/personal-access-tokens (fine-grained) and delete / revoke the token there. The app's stored copy becomes inert; any future sync attempt surfaces an "invalid token" error so you know to clear or replace it.
PATs never leave the device except during a user-triggered sync, and they are filtered out of crash-report payloads. Reference: security-review SR-20260419-030.
All product, engineering, and process documentation lives under
docs/. Start here:
| Audience | Start with |
|---|---|
| New contributor | docs/README.md → CONTRIBUTING.md |
| Engineer | docs/architecture.md → docs/standards/ |
| Product / planning | docs/vision.md → docs/roadmap.md |
| Decision history | docs/decisions/ (14 ADRs) |
Flutter 3.41 · Dart 3.11 · Riverpod · go_router · Material 3 · drift · markdown_widget · flutter_inappwebview (Mermaid) · flutter_math_fork · dio (repo sync). Full inventory in docs/tech-stack.md.
git clone https://github.com/cemililik/markdown-viewer-mobile.git
cd markdown-viewer-mobile
flutter pub get
flutter gen-l10n
dart run build_runner build --delete-conflicting-outputs
bash tool/fetch_mermaid.sh # downloads the pinned mermaid.min.js (not committed)
bash tool/install-hooks.sh # installs the mandatory pre-commit hook
flutter test
flutter runSee CONTRIBUTING.md for the full development workflow.
| Platform | Minimum | Target |
|---|---|---|
| iOS / iPadOS | 14.0 | 17.x |
| Android | API 26 (8.0) | API 35 (15) |
HarmonyOS native support is out of scope for v1 — see ADR-0009. HarmonyOS devices that support Android apps can install the Android build.
Licensed under the Apache License, Version 2.0. Copyright © 2026 Cemil ILIK.