Skip to content

Docs: Refined layout, optimized for useability and efficient loading - #1870

Draft
xormania wants to merge 7 commits into
oraios:mainfrom
xormania:docs/layout
Draft

Docs: Refined layout, optimized for useability and efficient loading#1870
xormania wants to merge 7 commits into
oraios:mainfrom
xormania:docs/layout

Conversation

@xormania

@xormania xormania commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

The whole of it is running here: https://xormania.github.io/serena/ — the current documentation rebuilt, this branch together with the docs PRs that follow it, so the result can be judged as one site rather than as diffs.

This PR is the piece the rest stand on: the theme. It is deliberately the smallest reviewable step — everything else in that preview is content, and lands separately.

The measurable part: the landing page drops from 1035.8 KB to 242.1 KB gzipped, 32 requests either side. The rest of the change is what a number cannot carry — navigation that keeps its state, a layout that holds from a 320px phone to a wide desktop, controls that do what they say — itemised below.

One new directory and three lines of config, all inside docs/. docs/_themes/serena/ inherits sphinx-book-theme — its templates extend the parent's blocks via super(), so asset digests stay the parent's business.

Note

Deleting docs/_themes/serena/ and the three html_theme* lines in docs/_config.yml restores stock behaviour exactly.

The shell is four layers deep — jupyter-book → sphinx-book-theme → pydata-sphinx-theme → Bootstrap 5 — and a few of its defaults work against a reader. None are Serena decisions; none are reachable from _config.yml.

Weight

pydata-sphinx-theme delivers its icons twice — a webfont stylesheet in the head, the SVG-with-JS kit at the end of the body — and either one alone draws every icon on this site. The kit goes; so do the preloads for the two font faces no page draws a glyph from; the one face in use is replaced at the same path by a copy subset to the glyphs actually drawn (the regeneration command is a comment in layout.html). Per asset, landing page, gzipped:

asset before after change
FontAwesome SVG-with-JS kit (all.min.js) 530.6 KB -530.6 KB
fa-solid-900.woff2 — subset to the 24 glyphs drawn 152.8 KB 2.5 KB -150.3 KB
fa-brands-400.woff2 115.1 KB -115.1 KB
fa-regular-400.woff2 24.8 KB -24.8 KB
prefetch of the next page (020_programming-languages.html) 10.1 KB +10.1 KB
this theme's script (serena-docs.js) 9.6 KB +9.6 KB
this theme's stylesheet (serena-docs.css) 7.5 KB +7.5 KB
everything else (28 requests) 212.4 KB 212.2 KB under 1 KB either way
total (32 requests either side) 1035.8 KB 242.1 KB -793.7 KB

A little of the saving is spent back on the reader: where the browser supports speculation rules, neighbouring pages load ahead of the click, so moving through the docs feels immediate.

Two template overrides, both minimal: layout.html filters the duplicate icon delivery out of the parent's own rendered blocks via super() rather than reproducing them, so anything the parent adds to those blocks keeps arriving untouched; empty.html exists because setting secondary_sidebar_items to nothing at all aborts the build with a pydata extension error.

Both sides measured the same way, at 93ec0431 (upstream main) and 139e93bb (this branch): the rev built clean in a throwaway worktree, the landing page loaded in Chromium, and every same-origin resource it requested gzipped on disk and summed — gzipped because that is what a static host sends.

Moving between pages

behaviour stock here
a section row link and expander at once — the label navigates, the chevron expands, a few pixels apart an expander; the page it pointed at becomes the section's first child, so both actions remain, one control each
expand/collapse resets on every navigation persists both directions until the reader changes it
previous/next flows with the content — on a long page, only at the end pinned to the bottom of the window, in the page block's box so it centres on the page

On a wide screen

  • The article floats mid-viewport because it is centred twice: by .bd-container around the three-column block, then by .bd-main .bd-content. Both left-aligned now; the article keeps a 72em measure — set by what the parameter tables need, and uniform across pages so the text edge does not shift between sections — and the page block its 88rem cap.
  • Identifiers in table cells do not break mid-name, so columns are sized by their longest name and the description column takes the surplus.
  • Both sidebars are position: sticky with their own overflow-y — three scroll regions. Static on desktop, so the page scrolls as one document.
  • The right-hand "Contents" rail returns on demand: a pill at the content's right edge expands into the page's heading tree — hover on a pointer device, tap on touch, Escape everywhere — with the current section marked as the reader moves. It renders only on pages with five or more headings, so short pages stay clean, and collapsed it costs the article nothing.

On a phone, or zoomed in

what the reader hits stock mechanism here
the nav panel's last entries sit below the fold, unreachable sized in vh: on a phone that is the viewport without the browser's bars sized in dvh, vh as fallback
the drawer shuts and reopens on every link no state crosses a page load stays open across pages, restored before first paint; Escape closes it, and that is remembered
one identifier pushes the page sideways at 320px on 01-about/035_tools, jet_brains_find_referencing_symbol renders 294px wide inside <code><span class="pre">; white-space: pre makes it unbreakable — 64px past the viewport a wrap rule takes it to 0

The stored state is replayed only at drawer widths: from 992px up, sphinx-book-theme reads that same checkbox as "hide the sidebar", the inverse of its meaning below.

Chrome

  • The colour-scheme button cycles three states in one fixed order everywhere; the parent's order follows the OS setting. Its name says the current state and the next, not "light/dark" in all three.
  • The fullscreen button is off: it duplicates the browser's own controls and fails silently where the API is unavailable.
  • "Back to top" shows once the page is past the header, not only while scrolling upwards.
  • "Download .md" pointed at the page source, which browsers display rather than save; it now carries download.
  • A link that leaves the site opens in a new tab, with rel="noopener"; same-site links stay in this one, and an author's explicit target is respected.
  • Motion is dropped under prefers-reduced-motion; links prefetch on hover where speculation rules exist.

Verification

check result
poe doc-build (sphinx -W) build succeeded, 0 warnings
poe lint clean
landing page, gzipped — before 1035.8 KB gzipped across 32 requests for /index at upstream 93ec043
landing page, gzipped — after 242.1 KB gzipped across 32 requests for /index at 139e93b
browser checks (chromium, webkit, firefox) 15 skipped 138 passed (29.0s)
worst horizontal page overflow 0px worst horizontal page overflow at 320 / 390 / 1280, over 3 page(s)
source changes 8 files changed, 1424 insertions(+), 1 deletion(-)

Generated by re-running each check at 139e93bb.

Checklist

  • This PR follows the guidelines in CONTRIBUTING.md regarding the scope of PRs.
  • For changes that add features or fix problems, I have added an entry to CHANGELOG.md, which concisely describes the change.

docs/_themes/serena/ inherits sphinx-book-theme and changes only what
works against a reader. Its templates render the parent's own blocks and
filter them, so asset digests stay the parent's business; deleting the
directory and the three html_theme* lines in _config.yml restores stock
behaviour exactly.

Navigation keeps its state across pages and stays reachable on a phone
(dvh, not vh). Section rows get one control per action. Previous/next is
pinned with the article it belongs to. Long identifiers wrap instead of
widening the page. The landing page falls from 1035.8 KB to 238.9 KB
gzipped: the duplicate FontAwesome delivery goes, and the one icon face
in use is subset to the 24 glyphs the site draws.
At the 52em measure a four-column parameter table is starved: the
browser squeezes the type column to 87px and breaks "string" as
stri/ng, relative_path as relative_p/ath — the wrap-anywhere rule
meant for prose overflow lets a table column shrink to almost
nothing — while a third of a 1280px window sits empty.

Two rules: a page that carries a table widens its article container
to 72em from 992px up (:has(), so prose-only pages keep their
measure; browsers without it keep today's rendering), and inside a
cell an identifier does not break mid-name, so columns are sized by
their longest name and the description column takes the surplus.
Measured at 1280px: the description column grows from 263px to
445px, and every identifier renders on one line.
These docs are a working reference: a reader mid-setup who follows a
GitHub or video link should keep their place in the instructions.
Applied by the theme at load, because only .md content passes through
MyST — the generated reference's links and the theme's own chrome
never see its links_external_new_tab option. The test is the origin,
so same-site links are untouched, an author's explicit target wins,
and rel gains noopener so the opened page holds no handle back.
@MischaPanch

MischaPanch commented Aug 14, 2026

Copy link
Copy Markdown
Member

Hi @xormania . Not sure why you thought our docs needs revision. This destroys the content nav on the right that we have
image

The docs as linked above introduce a new subpage showing tool interfaces, which we deliberately don't expose as they are not part of the MCP contract (except for names) and I doubt that our users are all too interested in them. I also find the wider style and larger letters less appealing visually, and it would force us to maintain our own theme.

I think our docs (using the default jupyter book theme) are pretty ok and it's far from mission critical to decrease the page size. My instinct is to close this and to stop further work on docs unless the core team explicitly opens issues on that.

@opcode81 wdyt?

@xormania

Copy link
Copy Markdown
Contributor Author

@MischaPanch I first discovered Serena a couple months ago, i looked at the docs and decided it would be easier to just go straight to the code (no offense - although it did lead to me contributing). I have a fresh perspective (I'm new) and I feel that this is important to do.

You should consider it - maybe not all of it - but there's a lot of benefits to be had from a rigorous documentation system. Both users and contributors face a steep learning curve as it stands. I believe Serena can be a contender - and this is something worth doing sooner than later.

Its a start - and its flexible - it doesn't lock you into anything. Its all upside. And I'd be happy to get your input for improving it. It has a little bling to it, but not misplaced.

ps - the right nav is bad idea - the area is still available for other things, but don't put nav there (its bad design).

The conditional widening (:has(table)) gave table pages 72em and prose
pages 52em, and the text edge then shifted between sections — read as
a glitch, not as typography. The tables earned the width; the rest of
the site now follows them, and the conditional goes.
A wide measure needs room around the text as much as beside it. Fuller
paragraph leading, clearer separation between blocks, table cells that
hold their content with space to spare, sections that announce
themselves. Space, not size — the type stays exactly as it is.
The stock right rail repeated on-screen headings and reserved width
whether or not it had anything to say. Its replacement is a pill at the
content block's right edge that expands into the page's heading tree:
hover on a pointer device, tap on touch, click and Escape everywhere,
current section marked as the reader moves. It renders only where
navigation earns its place — five or more section headings — and
collapsed it costs the article nothing.

Getting the jump right exposed a site-wide bug: content-visibility
renders sections lazily at estimated sizes, so ANY hash navigation
landed on an estimate and drifted as real sections rendered in — tens
of thousands of pixels off on long pages. Navigation now forces one
fully-rendered frame and jumps on real geometry; the intrinsic-size
auto keyword keeps the true sizes afterwards. Wired for TOC clicks,
arrival on a shared #link, and hash changes alike.
@xormania

xormania commented Aug 15, 2026

Copy link
Copy Markdown
Contributor Author

@MischaPanch - check it out - i got the benefits of the that right nav back into it (just for you - and frankly i like it - good call to press me on it - thank you). Also yanked tools ref. And I got my newbie contrib wishlist added.

remember that the preview site is multiple PRs - so its not tied to the new layout. I did a lot with the existing bootstrap doc setup to get it there (personally - i'm a tailwind/flowbite turbo kinda guy).

What do you think?

@xormania xormania closed this Aug 15, 2026
@xormania xormania reopened this Aug 15, 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.

2 participants