A Tachiyomi-inspired manga reader for Flutter where sources are JS-based extensions/plugins.
Status: early learning & discussion project. This scaffold establishes the architecture and best-practice foundation; features are intentionally minimal.
One app, many sources. Instead of shipping a hardcoded list of sites, fomic
runs community-written JS extensions — the same model Tachiyomi popularized,
but with JavaScript as the extension language. Each extension is a small script
that implements a stable source API; the app hosts the script in an embedded JS
runtime and renders its results.
This is also a learning project: a place to experiment with modern Flutter architecture (state management, persistence, serialization, linting, modular codebases) and to discuss the hard design questions — starting with how the JS extension runtime should work.
- The app shell (
fomic_app) is a plain Flutter app: Material UI, router, theme, bottom navigation. - Sources are JS scripts implementing the source contract from
fomic_core. Each source exposes search, popular titles, chapters, and pages. The full plugin contract and integration guide live indocs/extensions/plugin-spec.md. - The extension engine (
fomic_extensions) hosts those scripts influtter_js(JavaScriptCore on iOS/macOS, QuickJS on Android) behind aJsRuntimeAdapter. Plugins are split into pure URL builders and HTML/JSON parsers; the host (HttpSourceGateway) owns all HTTP — timeouts, retries, headers, and per-request logging — and feeds each response body to the matching parser.queryAll(DarthtmlCSS selectors) is bridged into JS for parsing. - Persistence lives in
fomic_data(drift / SQLite); the library, sources, and reader screens are separate feature modules.
The system works end to end: demo plugins are bundled for local development, and the sources list, source browser (popular/latest/search with filters), manga details, add-to-library, and a paged reader are wired up.
An interactive architecture diagram of the monorepo — packages, the dependency
rule, the JS extension engine, and its externals — is available at
docs/diagrams/fomic-architecture.html.
This is a Melos monorepo built on native Dart pub workspaces. Every module is its own package with an explicit public API and a strictly enforced dependency direction (no cycles):
fomic_app → features/* → fomic_data → fomic_core
features/* → fomic_extensions → fomic_core
| Package | Responsibility |
|---|---|
fomic_core |
Domain models, repository contracts, and the source (extension) API. Pure Dart, no Flutter dependencies. |
fomic_extensions |
JS runtime host + source adapter. Defines the ExtensionEngine contract. |
fomic_data |
drift database and repository implementations. The only package allowed to touch SQLite. |
features/fomic_library |
Library screen, state, and route table. |
features/fomic_sources |
Sources screen, state, and route table. |
features/fomic_reader |
Reader screens and route table. |
fomic_app |
App shell: composition root, theme, root router composed from per-module route tables. |
Feature modules export their own GoRouter route tables (e.g.
libraryRoutes()), which the app shell composes — navigation knowledge stays
inside each feature.
| Concern | Choice |
|---|---|
| State management / DI | Riverpod (flutter_riverpod) |
| Routing | go_router, per-module route tables |
| Persistence | drift (SQLite) + drift_flutter |
| Serialization | freezed + json_serializable |
| JS runtime | flutter_js (JavaScriptCore on iOS/macOS, QuickJS on Android) |
| Linting | very_good_analysis |
| Formatting | dart format (80-col, trailing commas automated) |
| Monorepo tooling | Melos |
Prerequisites: Flutter SDK (3.13+ Dart).
# 1. Install melos (matches the workspace pin)
dart pub global activate melos 7.8.1
# 2. Bootstrap the workspace (installs + links all packages)
melos bootstrap
# 3. Generate code (required after any model/table change)
melos run gen
# 4. Verify everything
melos run analyze
melos run format:check
melos run test
# 5. Run the app (from the shell package)
cd packages/fomic_app && flutter runIn a pub workspace you can also
dart pub get/flutter pub getfrom the repo root directly; melos simply orchestrates the same resolution.
| Command | What it does |
|---|---|
melos run gen |
Runs build_runner in codegen packages (fomic_core, fomic_data) |
melos run analyze |
flutter analyze in every package |
melos run format / format:check |
Formats / verifies formatting in every package |
melos run test |
flutter test in every package |
GitHub Actions runs everything directly via melos and Flutter — no fastlane/Ruby:
ci.yml(PR/push) — bootstrap, codegen (and verify it's committed), analyze, format check, and tests.nightly.yml(scheduled) — Android release APK onubuntu-latestand an iOS debug build (no codesign) onmacos-latest, uploaded as artifacts.
iOS integration: the app keeps CocoaPods (installed on the
macos-latestrunner) as long as Flutter officially supports it. Seedocs/STATUS.mdfor platform notes.
- Extension packaging & distribution — how plugins (JS bundles) are
packaged, versioned, signed, and installed. The runtime is settled on
flutter_js; distribution is the remaining design space. - Download & offline reader — where downloads live (cache vs. library) and how progress/tracking are modeled.
- Extension API surface — how much of the source contract should be configurable per source (pagination, headers, parsing).
- Demo plugins are bundled under
fomic_app/assets/plugins/(pointed at their live sites forflutter run); on first launch the app seeds them into the extensions directory. Sources → Browse → Manga → Read is the tap-through path. - The deterministic end-to-end test lives in
fomic_extensions:test/e2e_test.dartinstalls the same plugin against a local mock server and walks popular → details → chapters → pages. Note the JS engine tests use a real HTTP client (see theHttpOverrides.global = nullin their setup).
This repo intentionally starts small and opinionated. Before adding features,
read AGENTS.md — it encodes the conventions (stack, modularity
rules, commit style) that keep the codebase consistent.
Licensed under the Apache License, Version 2.0.
See the LICENSE file for the full text, and NOTICE for
the copyright attribution. Copyright 2025 fomic contributors.