Skip to content

How comparable projects structure their docs

Generated from docs/meta/docs-study.md when the site was built at 7aa23e2.

Preparation for niso’s docs: what fourteen cross-platform projects and runtimes do, what the web’s compatibility dashboards do, and what that suggests for niso. Pages were read in November 2026; links go to the page each claim comes from. The prototype in docs/site/ (see its README) builds the information architecture and tooling proposed at the end, so the shape can be judged on a running site rather than on this page.

Project Top-level sections Platforms and languages “What works” and compatibility Native features Tooling, reference generation Versions, search, playground
Tauri Start, Concepts, Guides (develop, distribute, security), Plugins, Reference (JS, Rust, config, CLI) Package-manager tabs on every install command (npm, yarn, pnpm, deno, bun, cargo) Per-plugin “Supported Platforms” table with a level and notes per OS (notification) One page per plugin: platform table, setup (automatic and manual tabs), usage, permissions Starlight; Rust reference on docs.rs, linked from each plugin page Major version in the host name (v2.); latest only
Capacitor Getting started, Basics, Main concepts, Guides, iOS, Android, Web, Plugins/APIs, CLI Separate iOS, Android and Web sections; per-plugin ## Android and ## iOS blocks None for web APIs: “If it works in the browser, it probably works” Plugin pages with permissions, manifest entries, per-OS caveats, and a “Since” column per option (local notifications) Docusaurus; plugin API from TypeScript JSDoc by capacitor-docgen into each README, then into the site Version dropdown (v8)
React Native Guides, Components, APIs, Architecture, Contributing Android/iOS/Web tabs for prose aimed at each background; @platform badges on props (platform-specific code) Not about web APIs; per-prop platform badges Native modules and components as guides Docusaurus, hand-written component pages Version dropdown; embedded Snack runs examples on iOS, Android and web
Expo Home, Guides, EAS, Reference (SDK per version), Learn Platform chips at the top of each SDK page (“Android, iOS”) Platform chips, known issues on the page One SDK page per capability with config-plugin setup and permissions (notifications) Custom site; SDK reference generated from the packages’ types Reference per SDK version (/versions/v58.0.0/), Snack, llms.txt and a .md for every page
Flutter Get started, UI, Data, Platform integration (per OS), Packages, Testing, Deployment; API on a separate site “Platform integration” section per OS Per-platform support shown per package on pub.dev Per-OS pages such as iOS app extensions (widgets, share) Custom Dart site rebuilt on Jaspr; API at api.flutter.dev by dartdoc DartPad embeds
Lynx Guide, API (elements, CSS, Lynx API), React, Rspeedy, Help Tabs for the sandbox (iOS Simulator, Android, HarmonyOS), remembered in the URL A BCD-shaped database, lynx-compat-data, renders a Baseline-style badge (“Widely available”) and an MDN-style table with versions per platform (fetch, how it works) Native modules and custom elements guides Rspress; an <APITable> component reads compat JSON named in front matter llms.txt, llms-full.txt, “Copy Markdown”; live web preview plus QR code per example
NativeScript Introduction, Setup, Guide, UI, Plugins, Reference Per-flavor (Angular, Vue, React, Svelte, Solid) code Not applicable (no DOM) Platform APIs from JS as a concept VitePress Preview app
Electron Tutorial, Processes, Best practices, Examples, API, Glossary Platform tags on API members (Notification.handleActivation is Windows; app events tagged macOS) Points renderers at the web Notifications API (Notification) API pages name the OS framework and its requirements (code signing for macOS notifications) Docusaurus; API Markdown in the main repo, parsed by docs-parser into JSON “Open in Fiddle” on examples
Dioxus Tutorial, Core concepts, Guides Per-platform guides (web, desktop, mobile, fullstack) Not applicable Platform guides Custom site built with Dioxus; Rust API on docs.rs Version in the URL (/learn/0.7/), live examples
Slint Guide, Concepts, Reference, Tutorial, Language integrations Separate reference per language binding (Rust, C++, JS, Python) Not applicable Backends and platforms in the guide Starlight; bindings by each language’s doc tool latest/ and next/ in the URL with a banner; SlintPad “run” button on snippets
Ionic Getting started, Developing, Layout, Theming, Components, Native, CLI Two switchers per example: framework (Angular, JS, React, Vue) and mode (iOS, MD) Not applicable Native plugins come from Capacitor Docusaurus; component API from Stencil’s generated docs Version dropdown, editable example per switcher state
Servo Running servoshell, Hacking, Architecture, Embedding Per-OS build pages Not covered in the book Not applicable mdBook; embedding API by rustdoc Latest only; unedited chapters marked with *
Deno Runtime, Deploy, Examples, API (Deno, Web, Node) Not applicable Web API reference by category, plus a Web Platform APIs page with spec deviations per API; for availability it sends readers to MDN’s tables Not applicable Custom site; API pages generated from type declarations Latest only
Bun Runtime, Package manager, Bundler, Test runner, Guides Not applicable Node.js compatibility per module, 🟢/🟡/🔴 plus the share of Node’s own test suite that passes; Web APIs as a table of names linking to MDN Not applicable Mintlify Latest only
MDN Learn, Guides, Reference per interface and member Not applicable Baseline banner at the top, BCD table at the bottom, specification table Not applicable Markdown in mdn/content on MDN’s own renderer; BCD and web-features are separate data packages Unversioned; interactive examples
webstatus.dev Feature list, a page per feature A column per browser Baseline status, availability, WPT pass rate per browser, usage, CSV export Not applicable web-features, BCD, WPT; an API that the <baseline-status> widget reads Filters, sortable columns
wpt.fyi Results by test directory Columns per browser and channel Pass counts per directory; browser-specific failures over time Not applicable Uploaded runs Query language, links per run
caniuse One page per feature Rows per browser version Support per version, notes, known issues, and a Baseline line Not applicable Its own data plus BCD Search-first
  1. A compatibility database separate from prose, rendered by a component. Lynx keeps lynx-compat-data in BCD’s shape and places a table with <APITable /> or an api: front matter key (Documenting APIs); the same data drives the badge at the top of the page. niso already has the data: the IDL says what exists, tests/wpt/baseline.json says how much of each web feature passes, and web-features’ compat_features maps BCD keys (api.WebSocket.send) to feature ids. A page can join all three.

  2. Baseline’s vocabulary for status. MDN’s banner and Lynx’s “Widely available” badge show readers already know it. niso can reuse it with its own measurement: “Baseline widely available on the web; 88% of its WPT subtests pass in niso” is two facts a web developer can act on. Never say a feature is Baseline in niso: Baseline is about browsers.

  3. Deviations per API, next to the API. Deno’s Web Platform APIs says, in the fetch section, that Deno doesn’t follow the same-origin policy and so doesn’t implement CORS. niso has the same kind of fact (fetch has no CORS, docs/wpt.md) and should put it on the fetch page, not only in a test log.

  4. A coarse status, backed by the test suite’s number. Bun marks each Node module 🟢/🟡/🔴 and says how much of Node’s test suite passes (Node.js compatibility). niso’s number is the WPT pass rate per web feature; the readable status (works, partial, mostly missing, not run) comes first and the number backs it.

  5. Synced platform and language tabs. Starlight’s syncKey (Tabs) and Lynx’s URL parameters remember “I’m on Android” or “I write Kotlin” across pages. niso has both axes, so two sync keys: platform and language.

  6. Platform badges on members, not only on pages. Electron tags single methods Windows or macOS; React Native badges single props. niso’s differences are mostly per member (a control drawn natively on iOS and Android but not by iced), so its notes belong on members.

  7. One page per native capability: platform table, setup per OS, usage. Capacitor’s local notifications and Tauri’s notification plugin both do this. niso’s surfaces need it too, since an App Group or a Glance receiver is setup a page can’t do.

  8. “Run this” next to examples. Snack, Fiddle, SlintPad and Lynx’s web preview plus QR code cut the distance between reading and seeing. niso’s cheapest version is a side-by-side of the same page in Chrome and on each device, which tests/screens already renders; later, a QR code that opens a page in the host app.

  9. Machine-readable docs. Expo and Lynx publish llms.txt and Markdown for each page. Cheap to add, and agents are a real audience for an API this broad.

  10. Reference from the source of truth, in the build. Electron (docs-parser), Capacitor (docgen), Deno and Expo (types) never hand-write member lists. niso’s WebIDL is that source, and generating it at build time fits DECISIONS’ “no generated source”: nothing generated is committed.

  • “If it works in the browser it probably works.” Capacitor can say that because it ships a browser; niso can’t, and a vague claim is worse than an honest 19% (grid’s pass rate today). Every API page shows its status, even when that’s “not tested”.
  • A status without its reason. A pass rate alone hides that grid’s 727 reftests don’t run yet. baseline.json says why (notRun, needs-reftests); the docs must show it, as docs/wpt.md’s caveats do (“Unknown isn’t failing”).
  • A separate site for the API. Flutter keeps api.flutter.dev apart from docs.flutter.dev, so search is split and guides and reference link to each other less. One site, one search.
  • Hand-maintained compatibility lists. Bun’s Web APIs table is names linking to MDN, with no per-member status, and it will drift. niso generates from the IDL and test results.
  • Copying MDN’s prose. MDN content is CC BY-SA. Link to MDN for semantics and spend niso’s words on what differs: rendering, missing members, deviations.
  • Versioning before there’s a release. Expo needs per-SDK reference because apps pin an SDK; niso has no release. Ship latest only, stamped with the commit it was built from, and add versions with the first release (Slint’s latest/ and next/ is the light way).
  • Per-platform sections that repeat each other. Capacitor’s iOS and Android sections each carry setup prose; prefer one page with platform tabs, and keep platform pages for what only that platform has (entitlements, App Groups, Glance, signing).
  • Switchers that multiply examples. Ionic’s four frameworks times two modes is eight versions of each example. niso should show plain HTML and DOM first, Svelte only where it adds something.

One site, eight top-level sections. The prototype builds this sidebar; pages marked stub there are placeholders.

Start

  • What is niso: the DOM as a native UI API, for web and for native developers.
  • Getting started: a Svelte page on the iOS Simulator, the Android emulator, a desktop window and headless.
  • Native apps: the same app driving the DOM from Rust, C, Zig, Go or Java (examples/lang).
  • niso and WebViews: what’s native, what’s niso’s own, what’s missing.

Concepts

  • The DOM as the API: node ids, handles, the C ABI, bindings generated from WebIDL.
  • Rendering: the render stream, native views at the core’s frames.
  • Native controls: which elements are native controls, their CSS property sets, radio groups as segmented controls.
  • Surfaces: widgets, Live Activities and ongoing notifications from data-niso-surface; timers that count by themselves.
  • Platform style: the niso-platform-style meta, --niso-* tokens, safe areas.
  • System settings: text size, bold text, contrast, dark mode and accent colors as CSS.
  • Text: Parley’s layout, the platform’s drawing.
  • Engines and the event loop: QuickJS, Porffor, Node-API; who owns the loop.
  • Storage and the app origin.
  • Native modules: native code giving pages an API from one IDL file.
  • Accessibility: the AccessKit tree from the DOM and ARIA.

Guides

  • Build a Svelte app; build a plain HTML app.
  • Add a home screen widget; add a Live Activity; media session (stub).
  • Write a native module.
  • Port a web app with niso-run --missing.
  • Test pages headless with niso-run.
  • Navigation and system back.

Platforms

  • iOS, Android, Desktop (iced), Web, Headless and servers, Planned (Windows, watchOS, CarPlay, MCUs).

Languages

  • JavaScript (QuickJS, Porffor, Node, Deno, Bun), Rust, C, Zig and Go, Java and Kotlin, Swift (stub).

Reference

  • Web APIs: one generated page per WebIDL interface, grouped by IDL file, with members, exposure, C function names, per-platform notes and WPT/Baseline status.
  • HTML elements and native controls; CSS (@media (platform), prefixed properties, --niso-* tokens); niso attributes (data-niso-surface, data-timer-*); meta tags.
  • C API (niso.h, niso_runtime.h, niso_app.h); Rust (rustdoc); CLI (niso-run, niso-node, niso-wpt); IDL extended attributes (Niso*).

Compatibility

  • Baseline dashboard: every web feature with its Baseline status, niso’s pass rate, coverage and why tests didn’t run; filterable. Fed from tests/wpt/baseline.json.
  • Real apps: Bluesky, VS Code for the web, the Svelte playground (today’s docs/compat).
  • Known differences from browsers, per API.
  • How niso is tested: WPT and its gate, Acid, screen comparisons, test262.

Internals (for contributors)

  • Architecture, decisions, crate contracts, repros, running WPT: mostly the repo’s existing docs.

The per-API status shows in two places on purpose: on each reference page, where a developer decides whether to call an API, and in the dashboard, where someone decides whether niso can run their app or what to work on next. Both read the same JSON, so they can’t disagree.

Starlight, with a build-time generator script for the reference and an Astro page for the dashboard.

  • Reference from niso’s WebIDL, with nothing generated committed. A Node script parses idl/*.webidl with webidl2 (all 19 files parse as they are, Niso* extended attributes included) and writes Markdown into a git-ignored directory before astro build. Comments above members (// NisoHeld: …) come through webidl2’s trivia, so the IDL can carry short notes.
  • It joins the data niso already has. The same script reads tests/wpt/baseline.json and web-features (pinned to the version tests/wpt/fetch.sh uses) to give each member its web feature, Baseline status and pass rate.
  • Per-platform notes as data. Notes the IDL can’t hold live in one YAML file keyed by interface, member and platform, merged by the generator, which fails on a key that names no member, so notes can’t go stale silently.
  • Synced tabs for platform and language (syncKey), asides, badges and MDX components: the patterns above without a custom theme.
  • Search by Pagefind, built with the site; no service.
  • Static output and one build command.
  • Tauri and Slint, the nearest projects in the Rust ecosystem, use it.

Alternatives: Rspress (Lynx) has the compat-table pattern proven, but a smaller ecosystem and nothing niso needs that Starlight lacks. Docusaurus has built-in versioning, which niso doesn’t need yet, for a heavier React stack. mdBook is Rust-native and simple, but has no tabs, no components and no good way to render generated data; it would suit only the Internals section. VitePress is close to Starlight; Starlight wins on content collections and synced tabs.

One change in niso would help later: niso-idl could emit its model as JSON, with the C and JVM names it already computes, so the docs generator doesn’t reimplement naming. The prototype derives C names the way crates/niso-idl/src/emit.rs does and marks that with a TODO.