* refactor(main): build overlay geometry and pointer interaction in the overlay assembly Inject Electron's screen (and the stats-window promotion) into the overlay geometry and visible-overlay interaction runtimes so they load under bun test, then construct both in createOverlayAssembly together with the overlay visibility composer and the mpv subtitle suppression handlers. Replace the three regex tests that pinned the moved Linux input and shape code with behaviour tests on the runtimes. * refactor(main): move the autoplay-ready gate into the playback assembly The autoplay-ready gate, its post-warm subtitle prime, the current-media tokenization gate and managed local subtitle selection all read playback state, and playback signals through the gate, so createPlaybackAssembly now builds them. The overlay reaches the gate through a getter. Replace the last four regex guards with behaviour tests: the gate holds the release until the visible overlay has measured the line and ignores untokenized lines during warmup (playback), cached autoplay priming never paints raw first and the sidebar media path is tagged only after prefetch loads (priming runtime), and dashboard mining overrides the Hachidori Anki server only when the proxy is on (stats server runtime). main-wiring.test.ts is now empty and removed. * refactor(main): move the plugin host, panel and windows into a plugins assembly * refactor(main): move session action dispatch and renderer mpv commands into an assembly createSessionActionsAssembly owns the session action dispatcher, the secondary-subtitle mode cycle, queueing the clipboard's video, and the mpv commands the overlay renderer sends. The runtime option cycle both paths used is now one function. * refactor(main): move Whisper subtitle generation into an assembly * refactor(main): resolve subtitle annotation options in a runtime module The runtime-option-over-config resolution that the texthooker page and the MeCab startup decision share moves out of main.ts into createAnnotationOptions. * test(main): cover a non-boolean runtime annotation option value * docs: describe the plugins, session actions and subtitle generation assemblies Update ownership for overlay geometry and pointer interaction, the autoplay-ready gate, and annotation options; point the overlay priming entry points at their new modules; the main-wiring regex debt is gone. * build: export MpvClientEvents so declaration emit can name the plugins assembly's return type
SubMiner docs
In-repo VitePress documentation source for SubMiner.
Internal architecture/workflow source of truth lives in docs/README.md at the repo root. Keep docs-site/ user-facing.
Local development
bun --cwd docs-site install
bun run docs:dev
Build and preview:
bun run docs:build
bun run docs:preview
bun run docs:test
Direct package commands still work from docs-site/ if you prefer:
cd docs-site
bun install
bun run docs:dev
Cloudflare Pages
- Git repo:
ksyasuda/SubMiner - Production branch:
main - Automatic production and preview deployments: disabled
- Custom domain:
docs.subminer.moeattached to Production - Deployment path: GitHub Actions direct upload with Wrangler
The public docs root is stable-only:
/serves the latest stable release docs./main/serves development docs frommain./v/<version>/serves stable release archives./versions(root build only) lists every published version.- Prerelease tags do not update the docs site.
Only / is indexable. /main/ and every /v/<version>/ page carries a self-referential canonical plus noindex,follow, repeated as an X-Robots-Tag header (by the generated _headers file for /main/, by the archive function for /v/). They stay crawlable so their links still resolve, but ~30 archived copies of every page would otherwise consume the crawl budget the current docs need. Only the root build emits sitemap.xml, and its <lastmod> dates come from git log against the tracked checkout at the released tag, because the build renders from an untracked snapshot that VitePress cannot date itself.
Keep Cloudflare Git auto-deploy disabled. The production deploy is .github/workflows/docs-pages.yml, which uploads .tmp/docs-versioned-site with --branch main so tag-triggered runs update Production instead of creating preview deployments.
Stable archives in R2
/v/<version>/ archives are not part of the Pages deployment. Each one is built once, uploaded to an R2 bucket under v/<version>/, and served by the Pages Function in functions/v/[[path]].ts. Each deploy builds only archives the bucket is missing (an archive counts as present once its _archive.json marker exists), plus the root and /main/ builds. Archive nav links to /versions instead of listing releases, so a new tag never invalidates old archives.
To re-render archives on purpose (theme change, docs fix), run the Docs Pages workflow manually with rebuild_archives set to comma-separated tags or all.
One-time setup:
- R2 bucket for archives; its name goes in the
DOCS_ARCHIVE_R2_BUCKETrepository variable. - R2 API token with Object Read & Write on that bucket; its S3 credentials go in the
DOCS_ARCHIVE_R2_ACCESS_KEY_IDandDOCS_ARCHIVE_R2_SECRET_ACCESS_KEYrepository secrets. - Pages project: Settings > Bindings > R2 bucket, variable name
DOCS_ARCHIVES, pointing at the same bucket.
The first deploy after setup builds and uploads every stable archive; later deploys only add new tags.