Add Captain's Bridge — novel doc reading experience#41
Merged
nomadicmehul merged 4 commits intomainfrom Apr 14, 2026
Merged
Conversation
Introduces a brand-new doc reading layout that layers on top of Docusaurus
without replacing its DOM, keeping all existing markdown untouched.
Components (website/src/components/CaptainsBridge/):
- BridgeTelemetry: sticky top strip with live progress %, section X/Y,
reading-time ETA, focus/rail/help/classic toggles.
- BridgeRail: fixed right rail replacing stock TOC. Three tabs:
Contents — headings with per-section read checkmarks
Commands — auto-extracted CLI lines (kubectl, docker,
terraform, helm, aws, az, gcloud, ansible,
git, hcl, yaml, dockerfile…) with one-click copy
Concepts — auto-extracted inline-code + bold terms with
mention counts, linked to first occurrence
- BridgeConsole: fixed bottom console exposing vim-style shortcuts,
mark-read button, prev/next doc, read counter.
- BridgeHelp: modal overlay listing all shortcuts.
- Focus mode: dims all paragraphs except the one at viewport center,
iA Writer-style, via scroll-synced class toggling.
Hooks:
- useScrollProgress: computes progress, active heading, reading-time ETA.
- useExtractors: scans article DOM for CLI commands and key concepts.
- useReadProgress: localStorage-backed per-page read-section state.
Keyboard shortcuts: j/k scroll, gg/G jump, f focus, t toggle rail,
m mark read, n/p next/prev doc, / search, ? help, Esc.
Layout integration:
- Swizzled theme/DocItem/Layout as a --wrap, so all upstream updates still
flow through. BrowserOnly prevents SSR issues.
- Global CSS in custom.css hides stock .theme-doc-toc-desktop when the rail
is open, reserves 56px bottom padding for the console, and adds
focus-mode dimming (respects prefers-reduced-motion).
- Fully responsive: rail hides under 996px, key descriptions compress
under 600px.
Persistence:
- cloudcaptain.bridge.enabled — Bridge on/off, FAB re-enables.
- cloudcaptain.bridge.focus — focus mode.
- cloudcaptain.bridge.rail — rail open/closed.
- cloudcaptain.bridge.read.{path} — read-section state per page.
Replaces the v1 layered-overlay approach (which clashed with Docusaurus's
3-column row layout) with a purpose-built CSS Grid canvas that fully owns
the doc page structure.
Architecture
- Eject-swizzled DocItem/Layout. When Bridge is enabled (default), renders
BridgeLayout. When disabled, falls back to ClassicLayout (verbatim stock
Docusaurus). SSR uses ClassicLayout to avoid hydration flash.
- Four-region CSS Grid: telemetry (header), gutter (left), main (center),
rail (right). Console stays fixed. No more fixed/absolute positioning
overlapping article content.
- Widened & centered article column (max-width 860px) for better readability.
New chapter UX
- ChapterEnhancements: traverses the article DOM post-render and injects
host <div>s before each H2 + after the last block of each H2 section.
React portals render chapter cards and 'Mark section complete' buttons
into those hosts — markdown stays untouched.
- Chapter card shows: read bubble (○/●), per-section reading-time estimate
(derived from section word count), and an auto-inferred difficulty badge
(beginner/intermediate/advanced) computed from code-block + inline-code
density + prose length.
- End-of-section 'Mark section complete' dashed button; toggles to solid
green when clicked.
Reading gutter
- Thin 2px vertical ribbon on the left of the article. Fills top-down
proportional to scroll progress. H2 markers overlaid at their relative
position — click to jump, green when read.
Resume banner
- Appears above the article when some sections are read and some aren't.
Shows progress count/percentage and links to the first unread section.
Files
- website/src/theme/DocItem/Layout/index.tsx — thin delegator
- website/src/theme/DocItem/Layout/styles.module.css — stock Docusaurus styles (used by ClassicLayout)
- website/src/components/CaptainsBridge/
BridgeLayout.tsx — grid orchestrator, all state, keyboard shortcuts
ClassicLayout.tsx — stock fallback
BridgeTelemetry.tsx — top strip (unchanged from v1)
BridgeRail.tsx — right rail (unchanged from v1)
BridgeConsole.tsx — bottom console (unchanged from v1)
BridgeHelp.tsx — shortcuts modal (unchanged from v1)
BridgeGutter.tsx — NEW
ResumeBanner.tsx — NEW
ChapterEnhancements.tsx — NEW
useScrollProgress.ts — unchanged
useExtractors.ts — unchanged
useReadProgress.ts — unchanged
- website/src/css/custom.css — removed v1 layered-overlay hacks; now only
contains focus-mode paragraph dimming
…ghter cards
CompletionToast (website/src/components/CaptainsBridge/CompletionToast.tsx)
- Fires a brief celebratory pill when a section is marked complete.
- Shows '🎉 <title> complete — N / M' or '🏁 Page complete' on final section.
- Animated particle burst (5 dots radiate out from the toast), cubic-bezier
slide-in, fade-out over ~2.4s. Respects prefers-reduced-motion.
- Fires only on 'add' transitions in readSections (not unmarks).
SidebarSpine (website/src/components/CaptainsBridge/SidebarSpine.tsx)
- Cross-page progress dots injected into every left-sidebar doc link.
- '●' for pages where readCount >= totalSections (complete, green glow).
- '◐' for pages with partial progress (cyan glow).
- Uses MutationObserver on the sidebar so dots survive expand/collapse and
route changes. Listens to:
- window 'cc-bridge-read-change' (same-tab custom event, dispatched
by useReadProgress on every write)
- window 'storage' event (cross-tab)
- document 'visibilitychange' (when user returns to the tab)
- Requires useReadProgress to persist totalSections alongside readSections,
which it now does (see useReadProgress.ts update).
useReadProgress
- Now persists {readSections, totalSections, lastUpdated}.
- Exports setTotalSections() — BridgeLayout calls this whenever the scroll
observer detects a new section count, so SidebarSpine can correctly
classify 'complete' vs 'partial'.
- New export getAllReadEntries() scans every
'cloudcaptain.bridge.read.*' localStorage key and returns a Map<path,
{readCount, totalSections, lastUpdated}>. SidebarSpine consumes this.
- Writes dispatch a 'cc-bridge-read-change' CustomEvent so same-window
listeners update without a storage event (which doesn't fire same-tab).
Commands-tab download (BridgeRail.tsx)
- New toolbar above the commands list with:
'⬇ .sh' — downloads a runnable bash script of all extracted commands,
including a shebang, set -euo pipefail, a header with the
page title / URL / timestamp, and each command labelled
with its detected language. Filename is the slugified
page title, e.g. 'docker-fundamentals-commands.sh'.
'⎘ all' — copies every command to clipboard, newline-separated.
- Shows 'N commands' counter aligned right.
Chapter card density tuning (styles.module.css)
- Replaced the full-width card with an inline left-border-only indicator:
22px → 18px bubble, no background fill, no hover-lift. 85% opacity by
default, 100% on hover/read. Much less intrusive, lets the heading
remain the visual anchor.
All new features are reactive — completing a section on the current page
instantly updates the chapter card, rail entry, gutter dot, sidebar spine,
toast, and console counter in one frame.
The auto-extracted Concepts tab (bolded/inline-code terms deduped by count)
wasn't pulling its weight — most entries had count=1, truncation was ugly,
and it overlapped with Ctrl-F. Kill > half-fix.
- BridgeRail: drop the third tab. Rail now shows Contents + Commands only.
- BridgeLayout: Tab type narrowed to 'contents' | 'commands'; previously
persisted 'concepts' preference silently migrates to 'contents'.
- useExtractors: drop extractConcepts() and the Concept type; extractor
now returns {commands} only.
- styles.module.css: drop .railConcepts / .railConcept / .railConceptCount.
- No API/data migration needed beyond the silent tab fallback.
🚀 Preview DeploymentYour changes have been deployed to a preview URL: https://cloudcaptain-pr-41.surge.sh This preview will be updated on every push to this PR. Deployed by GitHub Actions |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduces Captain's Bridge — a purpose-built doc reading layout that replaces Docusaurus's stock three-column row with a CSS-Grid canvas tailored for learning content. Ships as the default reading mode for all doc pages, with a one-click toggle back to the classic Docusaurus layout remembered per-browser.
Four commits, each reviewable independently:
45d4fc69baf119DocItem/Layoutreplacement via eject-swizzle. Pure CSS Grid. Adds chapter cards (per-H2 progress bubble + ETA + auto-difficulty), reading gutter (left ribbon), resume banner, mark-section-complete buttons.0aa4d98.sh, tuned chapter card density.0dfc2baWhat users see
⚓ BRIDGE | progress 47% | section 04/12 | eta 6 minplusfocus/rail/?/classicbuttons.⬇ .shdownload (generates a runnable#!/usr/bin/env bashscript with header,set -euo pipefail, and each command labelled by detected language) and⎘ allcopy-all.j k gg G f t m n p / ? Esc), read counter (N/M read), prev/next doc, help.f) — dims all paragraphs except the one at viewport center; scroll-tracked viarequestAnimationFrame. Respectsprefers-reduced-motion.◐partial,●complete) based on localStorage state. Live-updates across tabs viastorageevent + in-tab via acc-bridge-read-changeCustomEvent.🎉 <section> complete — 4/12gradient pill with 5-particle CSS burst.🏁 Page completeon the final section.⚓FAB re-enables. Preference persists.?) — modal listing every shortcut.Architecture
Swizzle-ejected
theme/DocItem/Layout. The layout picks between:header/gutter/main/rail/footer-console. Consumes unswizzled sub-components (DocItemContent,DocItemFooter,DocItemPaginator,DocBreadcrumbs,DocVersionBanner,ContentVisibility) so markdown, MDX, admonitions, mermaid, and every content plugin continue to work unchanged.BrowserOnlyswaps to Bridge client-side.Key hooks
useScrollProgress— computes active heading + progress % + ETA,rAF-throttled.useExtractors— scans code blocks for CLI commands by language + keyword heuristics (kubectl, docker, terraform, helm, git, aws, az, gcloud, etc.).useReadProgress— localStorage-backed{readSections, totalSections, lastUpdated}per pathname. Emits a window-scopedcc-bridge-read-changeCustomEvent on every write so SidebarSpine updates without a tab switch. ExportsgetAllReadEntries()for cross-page aggregation.Chapter enhancements
ChapterEnhancements.tsxtraverses the post-rendered DOM and injects invisible host<div>s before each H2 + after the last block of each H2 section. React portals then render the chapter card and mark-complete button into those hosts — the markdown itself is never mutated, so hot-reload and MDX compilation are unaffected.Difficulty heuristic
Per-section auto-classified from code-block density + inline-code count + word length:
Tune weights in
ChapterEnhancements.tsx.Persistence keys
cloudcaptain.bridge.enabledcloudcaptain.bridge.focuscloudcaptain.bridge.railcloudcaptain.bridge.railTabcontentsorcommands)cloudcaptain.bridge.read.{pathname}{readSections, totalSections, lastUpdated}Trade-offs
DocItem/Layoutupstream changes won't auto-merge into the custom branch;ClassicLayout.tsxremains a verbatim copy for diffing on major Docusaurus bumps.DocItem/Layoutchanges roughly twice a year in upstream.Test plan
/docs/tools/docker/fundamentals) — telemetry strip renders at top, gutter fills as you scroll, chapter cards appear above every H2, rail populates Contents + Commands.j/k/gg/Gscrolling,ffocus,trail toggle,mmark read,n/pprev/next doc,/search focus,?help.⬇ .shdownloads a runnable script;⎘ allcopies to clipboard.classicin telemetry — layout falls back to stock Docusaurus;⚓FAB re-enables Bridge.prefers-reduced-motion— focus mode + toast burst degrade to linear fade.npm run buildinwebsite/— passes with no new warnings introduced by this branch.Files
Not in this PR
feature/learn-lab-split./progresspage.