Skip to content

Writing and publishing documentation ​

Introduction · Tutorial · API overview

DI Bag's documentation starts with ordinary Markdown. The README introduces the library, the tutorial teaches its APIs, and the server guide shows how to use those APIs in applications. TypeDoc generates the exact API reference from the two public TypeScript entry points. VitePress publishes these pages as a searchable website at dany-fedorov.github.io/di-bag.

Work locally ​

Use the repository's Node version, then install both development and documentation dependencies from their lockfiles:

sh
npm ci
npm ci --prefix tools/docs
npm run docs:generate
npm run docs:dev

Open the local URL printed by VitePress with the /di-bag/ path. Edit the original Markdown files; the development command stages changes automatically. After editing API comments, run npm run docs:generate again to update the reference.

To verify and preview the production build:

sh
npm run docs:check
npm run docs:build
npm run docs:preview

Choose the right source ​

What needs changingEdit
First impression, installation, quickstartREADME.md
Concepts and examples for each APItutorial.md
Tradeoffs and comparisons with other librariescomparison.md
Node HTTP, Express, Fastify, Bun, and Deno applicationsserver-integration.md
API navigation and type inventoriesapi-reference.md
A signature's explanation, parameters, return value, or failure behaviorThe public declaration's comment in src, then regenerate
A call's line and example in the API cardThat call's JSDoc summary, @throws, and @example in src, then regenerate
The card's "one way per task" tableapi-card-tasks.json, then regenerate
A rule a coding agent must follow, the per-module check, the fast checkAGENTS.md
The recommended module layoutexamples-modularity.md; copy the block byte for byte into AGENTS.md
How to do one agent taskrecipes.md
A compile-time message family or a DI_BAG_* code: when, cause, fixerrors.md; add the section in the change that adds the code
Site navigation and appearanceVitePress configuration and theme
The list of guides and contributor documentsDocumentation map

Keep docs/reference/ generated. Its Markdown is committed so it can be reviewed in pull requests and read directly on GitHub. Edit source comments instead of patching generated pages. Use import type for type-only API exports; the reference must never suggest that Bag, Builder, or Provider are public runtime constructors.

Write examples with enough context to reproduce them. State whether a snippet continues an earlier example. Keep acquisition, cancellation, and cleanup rules close to the code they explain. Link to the tutorial for a learning path and to the generated reference for exact overloads and generic constraints.

Keep comparison claims specific and link to the other library's official docs or source. Distinguish a typed lookup from checks across the dependency graph, a Promise-valued service from automatically awaited dependencies, and feature availability from stability or performance. Explain when an alternative is a good fit. Record version-sensitive scope and review dates in the comparison guide.

How generation is checked ​

npm run docs:generate uses TypeDoc, its Markdown plugin, and its VitePress theme. It reads only src/index.ts and src/node.ts. The rendering extension prints declarations with TypeScript so constructor constraints, grouping, readonly fields, and const type parameters retain their meaning. TypeDoc supplies the prose, navigation, and source links.

Generation requires comments on exported declarations and checks generated public exports and callable overloads against the TypeScript compiler's view, parses every generated TypeScript block, validates documentation links, and rejects internal compiler witness fields in the public output.

Generation also writes docs/agent/api-card.md from the JSDoc of the runtime surface (DiBag facade members, Builder and Bag methods, the error classes) and the task table in tools/docs/api-card-tasks.json. Each call gets its first summary sentence, the DI_BAG_* codes named in its @throws, and its @example. Generation fails when a runtime call has no @example, a task names an unknown call, or the card exceeds 400 lines. Never edit the card by hand.

npm run docs:check runs the tooling tests, generates a fresh temporary reference, and compares it with the committed files. Added, changed, and removed pages all count as drift. It then checks the agent documentation:

  • Snippets. Every ts block in AGENTS.md and docs/agent/*.md, and every @example in src/, is type-checked in one strict program against declarations emitted from src/ into a temporary node_modules/di-bag, so di-bag and di-bag/node resolve as in a consumer project. No prior build is needed. Leading comment lines are markers: // src/features/x/module.ts makes the block that file, so blocks on one page can import each other; // continues: <heading-id> prepends the last block under that heading on the same page; // expect-error: <text> requires a diagnostic containing the text. An @example without imports gets import { DiBag } from 'di-bag';.
  • Size budgets. AGENTS.md at most 150 lines, each recipe section under 60 lines, and docs/agent/api-card.md at most 400 lines.
  • Layout identity. The text block in AGENTS.md equals the one under "Recommended module layout" in the modularity guide.
  • Errors page. The DI_BAG_* codes in src/ and the code sections of docs/agent/errors.md are the same set; every heading there has an explicit {#id}, a code section's id is the code lower-cased with _ replaced by -, and the six compile-time family sections exist.
  • Message URLs. Every https://dany-fedorov.github.io/di-bag/... URL in src/ names an existing page and heading. docs:build checks them again against the rendered HTML.

It also stages the site and checks that linked repository files exist. npm run docs:build checks website page links while building the production artifact, then verifies rendered anchors and asset paths under the Pages base. Run both before pushing documentation changes.

The pinned tools and their independent lockfile live in tools/docs. TypeDoc uses classic TypeScript 6.0.3 because its compiler API is required for documentation generation. The library's separate native compiler checks remain part of development verification.

Website and package boundaries ​

The site command stages the README, Markdown in docs/guides/ and docs/agent/ (published at /agent/), and generated reference pages into the ignored tools/docs/site/ directory. The site description is read from package.json. It rewrites relative links for the hosted routes; links to examples, source files, and other repository material lead back to GitHub. Nothing else is copied into the site.

The production output is tools/docs/site/.vitepress/dist/. Keep the configured /di-bag/ base when serving it as a GitHub Pages project site. Local search indexes the built Markdown and needs no external search account. Generated pages offer links to their source declarations; handwritten pages offer an edit link.

Documentation dependencies stay in the private tools package. The published library archive contains the manifest, README, license, dist/, AGENTS.md, and docs/agent/, so agents read the rules and recipes in node_modules/di-bag; it does not contain the website or its dependencies.

Publish through GitHub Pages ​

The documentation workflow checks generation and builds the site on pull requests and pushes to main. Only a successful main build deploys its artifact to the github-pages environment. A manual run on main can also rebuild and deploy the site.

The repository's Pages source must be GitHub Actions. The deployment job uses GitHub's short-lived Pages and identity-token permissions; no publishing token belongs in this repository. To publish an update, regenerate changed API pages, run the checks above, commit the sources and generated Markdown, and push. Inspect the Documentation workflow's deployment result before claiming the public site is updated.

Ordinary services. Checked composition. Explicit ownership.