Skip to content

docs: a rustdoc-based documentation system - #71

Merged
Kilerd merged 1 commit into
mainfrom
docs/rustdoc-system
Aug 1, 2026
Merged

docs: a rustdoc-based documentation system#71
Kilerd merged 1 commit into
mainfrom
docs/rustdoc-system

Conversation

@Kilerd

@Kilerd Kilerd commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Four changes that together make the generated documentation the real one.

1. docs.rs was showing half the framework

There was no [package.metadata.docs.rs], so docs.rs builds with default features only — which is just http1. That means #[api], Schematic, Operable, ParameterProvider and the entire OpenAPI layer never appeared on docs.rs at all: the framework's headline capability was invisible to anyone reading the published docs.

All three crates now declare:

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

2. Feature-gated items say which feature they need

Building with all features would otherwise imply everything is unconditionally available. #[cfg_attr(docsrs, doc(cfg(feature = "...")))] puts a "requires feature X" badge on each gated item. Nightly-only, so it applies on docs.rs and is skipped elsewhere.

3. #![deny(missing_docs)] — and the 64 items that needed it

Every public item across gotcha and gotcha_core is now documented: struct fields, trait methods, the macro-generated router methods (get/post/…), the Operable descriptor, the task scheduler. Denied rather than warned, so an undocumented public item fails the build instead of quietly accumulating — which is exactly how it reached 64.

4. The README is the crate documentation

#![doc = include_str!("../README.md")], so the crate front page and the repository landing page cannot drift apart — and the README's examples become doctests. The README had already rotted once (#28); now it can't.

Three of its five examples compile and are tested. The two that need an optional feature (#[api] needs openapi, TaskScheduler needs task) are marked ignore, because an included README cannot be feature-gated and the matrix runs combinations where those features are off.

The flagship examples were also fixed rather than merely annotated — the Advanced Trait API example referenced an undefined AppState and get_user, so nobody copying it could have compiled it. It now defines both, and demonstrates #[config] / #[state] extraction.

Two traps worth recording

include_str! pointing outside the crate directory breaks the published crate. Caught with cargo publish --dry-run:

error: couldn't read `src/../../README.md`: No such file or directory

Cargo packages the README at the package root, so the workspace path and the packaged path differ. gotcha/README.md is now a symlink to the repository README, which makes include_str!("../README.md") resolve correctly in both.

A bare ``` fence is compiled as Rust by rustdoc. The architecture diagram failed 28 parse errors until it was marked text.

Verification

  • Doctests: 34 passed, 0 failed
  • Every feature combination builds and tests (none / openapi / all)
  • cargo clippy --all-features --workspace, cargo fmt --check
  • Nightly RUSTDOCFLAGS="--cfg docsrs" cargo doc --all-features with no warnings (the LICENSE relative link was made absolute, since rustdoc can't resolve it)

🤖 Generated with Claude Code

Four changes that together make the generated documentation the real one.

**docs.rs showed half the framework.** With no `[package.metadata.docs.rs]`, docs.rs builds with
default features only — which is `http1` — so `#[api]`, `Schematic`, `Operable` and the whole
OpenAPI layer never appeared online at all. All three crates now build there with every feature
and with `--cfg docsrs`.

**Feature-gated items say so.** `#[cfg_attr(docsrs, doc(cfg(feature = "...")))]` puts a "requires
feature X" badge on each gated item, so the all-features build does not imply everything is
available unconditionally.

**`#![deny(missing_docs)]`, and the 64 items that needed it.** Documented every public item across
`gotcha` and `gotcha_core` — struct fields, trait methods, macro-generated router methods, the
`Operable` descriptor, the task scheduler. Denied rather than warned so this cannot silently
accumulate again.

**The README is the crate documentation.** `#![doc = include_str!("../README.md")]` means the
front page and the landing page cannot drift, and the examples become doctests — the README had
already rotted once (#28). Three of its five examples now compile and are tested; the two that
need an optional feature are marked `ignore`, since an included README cannot be feature-gated.

Two traps worth recording:

- `include_str!` pointing outside the crate directory breaks the *published* crate — verified with
  `cargo publish --dry-run`, which failed with `couldn't read src/../../README.md`. `gotcha/README.md`
  is now a symlink to the repository README, so the path resolves both in the workspace and in the
  package, where cargo places the README at the package root.
- A bare ``` fence is compiled as Rust by rustdoc; the architecture diagram needed `text`.

Verified: doctests pass (34), every feature combination builds and tests, `clippy --all-features`,
`fmt`, and a nightly `--cfg docsrs` doc build with no warnings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Kilerd
Kilerd merged commit a0165f4 into main Aug 1, 2026
11 checks passed
@Kilerd Kilerd mentioned this pull request Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant