dartdoc_modern
Fork of dart-lang/dartdoc with modern docs backends for generating polished API documentation as either a Jaspr docs app or a VitePress site instead of default HTML.
Status
jaspr: default modern backend for teams that want a Dart-native docs app scaffoldvitepress: mature alternative for teams that want the strongest static-site ecosystemhtml: originaldartdocoutput remains available for compatibility
This project is already good enough to show publicly and collect feedback from real Dart and Flutter package maintainers.
Live docs:
Why This Exists
Default dartdoc HTML is useful, but many teams want a documentation site that feels more like a modern product docs experience:
- better search
- guide pages next to API pages
- clearer navigation and breadcrumbs
- theming that does not feel like an afterthought
- a scaffold they can actually extend
dartdoc_modern keeps dartdoc's analyzer-driven API model and adds multiple output backends on top of it.
What Is Different From dartdoc?
| Feature | dartdoc | dartdoc_modern |
|---|---|---|
| Output format | Static HTML | `--format html |
| Search | Built-in (basic) | VitePress local search, Jaspr staged local search |
| Guide docs | Not supported | Auto-discovers doc/ and docs/ |
| Workspace mode | Not supported | --workspace-docs for mono-repos |
| Build speed / file count | Many HTML pages | Much faster, far fewer generated files |
| Sidebar data | HTML nav | Generated TS or typed Dart data |
| Theming | CSS customization | VitePress theme or Jaspr ContentTheme presets |
| Extensibility | HTML templates | Open markdown output plus scaffold you can extend |
The speedup comes from page strategy, not from cutting features.
Standard dartdoc creates a separate HTML page for every single member. Every method, property, constructor, and constant gets its own page with full HTML chrome around it. dartdoc_modern keeps members inline on the type or library page instead.
To put that in perspective:
- Flutter
Iconshas roughly 2,000 static constants.dartdocturns that into about 2,001 pages for one class.dartdoc_modernkeeps it on one page. - The full Dart SDK with
dartdocis roughly 15,000+ HTML files.dartdoc_modernis about 1,800 markdown files, around 52 MB of source markdown. - Packages like
material_design_icons_flutterwith 7,000+ static const icons become 7,000+ pages in standarddartdoc, but a single page indartdoc_modern.
This is deliberate. It cuts file-system churn and I/O, which makes builds much faster, and it is also a better browsing model for developers: you can search within the whole class, jump with the outline, and use full-text search without opening dozens of tiny member pages.
Which Backend Should You Choose?
Choose jaspr when:
- you want a Dart-native docs application
- you want typed generated sidebar data and theming closer to the Dart toolchain
- you want the default
dartdoc_modernpath today - you want to extend the docs shell without dropping into Vue or TypeScript
Choose vitepress when:
- you want the strongest static-site ecosystem
- your team already works comfortably with Vue, VitePress, and Node tooling
- you want the lowest-risk path to a polished docs site today
The honest framing is:
jaspris the Dart-first backendvitepressis the ecosystem-first backend
That message is stronger and more credible than pretending one output replaces the other for everyone.
Installation
If you want to use the tool as a normal package consumer:
dart pub global activate dartdoc_modernThis package exposes both:
dartdoc_moderndartdoc_vitepress(legacy alias)dartdoc
For public examples and support requests, prefer dartdoc_modern in docs and snippets so it is obvious that the multi-backend fork is being used.
Quick Start
Jaspr is the default modern path. VitePress remains available when you specifically want the Vue/VitePress ecosystem.
Using The Installed Package
# One-time install for local Jaspr preview/build
dart pub global activate jaspr_cli
# Default modern path: generate and preview Jaspr docs
dartdoc_modern --format jaspr --output docs-site
cd docs-site && dart pub get && jaspr serve
# Alternative static-site path: generate and preview VitePress docs
dartdoc_modern --format vitepress --output docs-site
cd docs-site && npm install && npx vitepress devPackage Maintainer Recipes
Start with the Jaspr recipe unless you specifically want the VitePress ecosystem.
Jaspr Recipe (Default)
dart pub global activate jaspr_cli
dartdoc_modern --format jaspr --output docs-site
cd docs-site
dart pub get
jaspr serveFor deployment:
cd docs-site
jaspr build --dart-define DOCS_THEME=oceanDeploy:
docs-site/build/jaspr
VitePress Recipe
dartdoc_modern --format vitepress --output docs-site
cd docs-site
npm install
npx vitepress buildDeploy:
docs-site/.vitepress/dist
Run the strongest package-level release gate before posting or publishing:
dart run tool/task.dart validate package-releaseUsing The Local Source
Use the local source while evaluating or developing the project:
# Generate and preview Jaspr docs for a single package
dart run ./bin/dartdoc_modern.dart \
--format jaspr \
--output docs-site
cd docs-site && dart pub get && jaspr serve
# Generate and preview VitePress docs for a single package
dart run ./bin/dartdoc_modern.dart \
--format vitepress \
--output docs-site
cd docs-site && npm install && npx vitepress devWorkspace Example
dart pub global activate jaspr_cli
dart run /path/to/dartdoc_modern/bin/dartdoc_modern.dart \
--format jaspr \
--workspace-docs \
--exclude-packages 'package_a,package_b' \
--output docs-sitePreview Jaspr output:
cd docs-site && dart pub get && jaspr serveBuild Jaspr for deployment:
cd docs-site && jaspr build --dart-define DOCS_THEME=oceanPreview VitePress instead:
dart run /path/to/dartdoc_modern/bin/dartdoc_modern.dart \
--format vitepress \
--workspace-docs \
--exclude-packages 'package_a,package_b' \
--output docs-site
cd docs-site && npm install && npx vitepress devFastest Way To Evaluate The Jaspr Backend
If you only want the shortest serious evaluation path, run the launch gate:
dart run ./tool/task.dart validate jaspr-launchIf Playwright is installed outside /tmp/pw-run, set PLAYWRIGHT_DIR explicitly.
That single command now checks the practical quality bar for a community-facing Jaspr preview:
- scaffold generation and buildability
- theme and preview flow
- browser route and navigation smoke
- subpath/base-path deploy smoke
- search performance smoke
If you want the stricter release-facing gate before a public post or publish attempt, run:
dart run ./tool/task.dart validate jaspr-releaseThat adds:
- repo-wide
dart analyze --fatal-infos dart pub publish --dry-run- the full
jaspr-launchbrowser and build checks
If you want the broader package-wide gate before a release that should represent both modern backends, run:
dart run ./tool/task.dart validate package-releaseThat adds:
- the full
jaspr-releasegate - the full
vitepressend-to-end smoke suite
Why The Jaspr Backend Is Interesting
The jaspr backend is not a bare markdown dump. It generates a real Jaspr docs application scaffold with the strongest UX ideas carried over from the VitePress backend.
Current Jaspr capabilities:
- SPA-style navigation feel
- staged local search for API docs and guides
- persisted light and dark theme toggle
- breadcrumbs and right-side outline
- API auto-linking for inline code references
- DartPad embeds
- Mermaid diagrams
- build-time
<<<code import expansion for guides - generated typed Dart sidebar data instead of TypeScript strings
- preset-driven theming on top of
jaspr_content
How It Works
Dart source -> analyzer -> PackageGraph -> GeneratorBackend -> format-specific scaffold- API docs become markdown pages under
api/orcontent/api/ - Guide docs from
doc/anddocs/becomeguide/orcontent/guide/ - A backend-specific scaffold is generated around those pages
- Navigation, search, and theme assets are generated for the selected backend
Generated Structure
Jaspr
docs-site/
├── content/
│ ├── api/
│ ├── guide/
│ └── index.md
├── lib/
│ ├── app.dart
│ ├── main.server.dart
│ ├── main.client.dart
│ ├── generated/
│ │ ├── api_sidebar.dart
│ │ └── guide_sidebar.dart
│ ├── layouts/
│ ├── components/
│ └── theme/
├── web/
│ ├── index.html
│ └── generated/
└── pubspec.yamlVitePress
docs-site/
├── .vitepress/
│ ├── config.ts
│ └── generated/
│ ├── api-sidebar.ts
│ └── guide-sidebar.ts
├── api/
├── guide/
├── index.md
└── package.jsonReal Proof, Not Just Toy Screenshots
The Jaspr backend has been verified on a real Flutter workspace:
- package root: a production-style
headlessworkspace used as a large-project proof run 206public libraries5701generated files0errors in the verified run
That does not mean “done forever”, but it does mean this is well beyond a toy-package-only prototype.
CI/CD Example For Jaspr
For a static Jaspr deployment to GitHub Pages, generate the scaffold, build it, and upload build/jaspr.
Root Hosting
Use this when the deployed site lives at the domain root.
name: Deploy Jaspr Docs
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with:
channel: stable
cache: true
- name: Activate Jaspr CLI
run: dart pub global activate jaspr_cli
- name: Generate Jaspr docs
run: dart run ./bin/dartdoc_modern.dart --format jaspr --output docs-site
- name: Build static Jaspr site
run: |
dart pub get
jaspr build --dart-define DOCS_THEME=ocean
working-directory: docs-site
- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v3
with:
path: docs-site/build/jaspr
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: $\{\{ steps.deployment.outputs.page_url \}\}
permissions:
pages: write
id-token: write
steps:
- id: deployment
uses: actions/deploy-pages@v4Project Site Or Any Subpath Hosting
Use this when the deployed site lives under a path prefix like https://example.github.io/my-package-docs/.
- name: Build static Jaspr site
run: |
dart pub get
jaspr build \
--dart-define DOCS_THEME=graphite \
--dart-define DOCS_BASE_PATH=/my-package-docs
working-directory: docs-siteJaspr Static Deploy Summary
The Jaspr backend generates a real app scaffold that you build and then deploy as static files:
dartdoc_modern --format jaspr --output docs-site
cd docs-site
dart pub get
dart pub global activate jaspr_cli
jaspr build --dart-define DOCS_THEME=oceanDeploy:
docs-site/build/jasprIf the site is hosted under a subpath, add:
--dart-define DOCS_BASE_PATH=/your-site-pathUse DOCS_BASE_PATH whenever the generated site is hosted under a subpath rather than the domain root.
CI/CD Example For VitePress
A simple GitHub Pages flow can generate docs from the local source checkout instead of relying on a global install:
name: Deploy Documentation
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with:
channel: stable
cache: true
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: docs-site/package-lock.json
- name: Generate API docs
run: dart run ./bin/dartdoc_modern.dart --format vitepress --output docs-site
- run: npm ci
working-directory: docs-site
- run: npx vitepress build
working-directory: docs-site
- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v3
with:
path: docs-site/.vitepress/dist
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: $\{\{ steps.deployment.outputs.page_url \}\}
permissions:
pages: write
id-token: write
steps:
- id: deployment
uses: actions/deploy-pages@v4Key CLI Options
| Option | Description |
|---|---|
--format jaspr | Generate a Jaspr content site instead of HTML |
--format vitepress | Generate VitePress markdown instead of HTML |
--workspace-docs | Document all packages in a Dart workspace |
--exclude-packages 'a,b,c' | Skip specific packages |
--output <dir> | Output directory |
--guide-dirs 'doc,docs' | Directories to scan for guide markdown |
All original dartdoc options such as --exclude, --include, and --header remain available.
Honest Known Differences
- member docs are still rendered inline on the owning API page rather than split into separate member pages
- Jaspr search is local and staged, not backed by an external hosted service
- public hosted-demo infrastructure is still a presentation task rather than a generator-core task
Those are real limitations, but none of them invalidate the current community-preview quality bar.
Upstream
Based on dart-lang/dartdoc v9.0.5-wip and synced through commit a57f497a.
The VitePress and Jaspr outputs are implemented as additional GeneratorBackend variants rather than replacing the original HTML generation.
License
Same as dartdoc: BSD-3-Clause.
Libraries
| Library | Description |
|---|---|
| dartdoc | A documentation generator for Dart. |
| options | Fork of dartdoc with VitePress and Jaspr backends for generating modern API and guide documentation sites. |