Skip to content

Rewrite the docs and README, with an API reference and tested examples - #306

Merged
bensynapse merged 2 commits into
mainfrom
docs/site-rewrite
Oct 6, 2026
Merged

bensynapse merged 2 commits into
mainfrom
docs/site-rewrite

Conversation

@bensynapse

Copy link
Copy Markdown
Owner

This is the docs half of the 2026-10-06 docs review. The code half, the
docstrings and two clearer messages, was #305.

What changes

Truthful about 5.0.9. Every page has a banner: the docs describe 5.0.10,
and PyPI has 5.0.9. Security opens with "If you are on 5.0.9" and a wrapper
that stops 5.0.9 from sending exception messages to clients. It's tested on
5.0.9 and on main, and it keeps the params check working. The 5.0.10 features
have "New in" or "Changed in" notes. Those cover debug, max_batch_size,
per-request validation, NaN, serializer failures, plain methods under
async_dispatch, serve() returning 204, the warnings and the typing changes.

Examples that follow Security. Every example passes max_batch_size=100
and limits the body to 1,000,000 bytes, using each framework's own setting
where it has one. They listen on localhost:8000, which is where the
jsonrpcclient examples connect. The ZeroMQ ones bind 127.0.0.1, not *.
The http.server example answers a missing Content-Length with 411, an
oversized body with 413, and bytes that aren't UTF-8 with a Parse error.
check_examples.py now sends each server an oversized batch and an oversized
body too.

A quickstart you can run. Start serve("localhost", 8000), then call it
with curl and with jsonrpcclient. CI runs the exact curl line from the docs,
and the jsonrpcclient snippet against the real quickstart server.

New pages. The site has an API reference (mkdocstrings) and a migration
guide, from 4.x and from 5.0.9. Errors and logging lists every logger. There are also pages on notifications and batches, context, validation,
typing, testing and threads, and one page per framework. The FAQ and roadmap
were rewritten. The roadmap no longer links the old 6.0 draft pull request.
The changelog, contributing guide, security policy and license are on the
site.

Site. It has the client's overrides, extra.css, copy button fix and
accessibility script. The pink is darkened to #c2185b (5.9:1 on white) and
#f48fb1 for dark-mode links. Pages get their own descriptions and
Open Graph tags, and a visible h1. The site has a social card, a neutral {}
favicon, a 404 page, and a redirect from http to https.

CI. A new site job builds the docs and opens every page in Chromium,
light and dark, at 1280 and 375 pixels. It fails on any serious or critical
axe-core finding, a JavaScript error, a broken internal link or anchor, or a
page that scrolls sideways. axe-core is downloaded by version and checked
against its published hash. tests/test_threading.py calls dispatch from 8
threads at once, and CI runs it on 3.14t too.

README and repo. The README uses the agreed layout and renders on PyPI
without a bare URL. The tagline says "JSON-RPC 2.0" everywhere. The issue
forms send questions to Discussions and say how to find the version. The
release workflow refuses to publish while mkdocs.yml or the README still call
the version unreleased. RELEASING.md lists those steps and the advisory step
for a security release. The changelog heading is now "5.0.10 (not released
yet)". The missing 5.0.1 entry, missing dates and a duplicate 3.4.3 are fixed.

Checked locally

  • pytest with 100% coverage on 3.8, 3.13 and 3.14t (344 tests)
  • ruff check, ruff format, mypy and pyright
  • all 85 runnable doc blocks, with every framework installed
  • all 13 example servers through check_examples.py
  • mkdocs build --strict
  • check_site.py: 33 pages, 4 views each, no problems. On the old site it
    reports 92, so it does catch them.
  • python -m build, twine check, check-wheel-contents and check_metadata

The docs site now has the same layout as jsonrpcclient's, in pink. It adds
one page per framework, an API reference built from the docstrings, and a
migration guide.

Every page is honest about the release that people actually get. A banner
says the docs describe 5.0.10 and PyPI has 5.0.9. Security opens with a
tested wrapper that stops 5.0.9 from sending exception messages to clients.
Each 5.0.10 feature is marked "New in" or "Changed in".

The examples follow the Security page. Each one sets max_batch_size and a
body size limit, and listens on localhost:8000, where the jsonrpcclient
examples connect. CI starts each one and sends it real requests. That includes a batch
over the limit and a body over the limit. The http.server example now handles
a missing Content-Length and bytes that aren't UTF-8. The quickstart starts a
server, calls it with curl and with jsonrpcclient, and both run in CI.

New pages cover notifications and batches, errors and logging (with every
logger), context, validation, typing, testing and threads. A new test calls
dispatch from many threads at once, and runs on free-threaded 3.14t.

The site gets per-page titles and descriptions, a social card, a neutral
favicon, a visible h1 and a 404 page. It also has the client's copy button
fix, accessibility fixes and an HTTPS redirect. The pink is darkened to
#c2185b so links and the header pass WCAG AA. A new CI job opens every page in
Chromium, light and dark, at desktop and phone widths. It fails on any serious
axe-core finding, a broken internal link or anchor, or a page that scrolls
sideways.

The README follows the agreed layout and renders cleanly on PyPI. The release
workflow refuses to publish while the docs still call the version unreleased.
RELEASING.md lists the clean-up steps and the advisory step.
An independent check of the new pages against the code found these.

- 4.x had a debug option that hid exception messages by default. Only 5.0.0
  to 5.0.9 always send them. The docs, SECURITY.md and the advisory range in
  RELEASING.md now say so.
- Up to 5.0.9, a plain return value was logged with a traceback and explained
  to the client in data. Only 5.0.10 sends no details.
- Only dispatch and async_dispatch refuse NaN by default.
  dispatch_to_serializable returns the float as it is.
- aiohttp's and websockets' defaults are 1 MiB, which is more than the
  1,000,000 bytes the examples set.
- ResponseType gives no DeprecationWarning.
- A custom validator can get things other than a dict, and with validation
  off an empty batch gets no response.
- 5.0.9's serve() handled one request at a time and logged its start on the
  root logger.
@bensynapse
bensynapse merged commit 757f696 into main Oct 6, 2026
13 checks passed
@bensynapse
bensynapse deleted the docs/site-rewrite branch October 6, 2026 03:17
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