Skip to content

docs: rebuild the docs site around reader tasks, with a landing page and real-vault screenshots - #403

Merged
chhoumann merged 31 commits into
masterfrom
docs/overhaul
Oct 12, 2026
Merged

chhoumann merged 31 commits into
masterfrom
docs/overhaul

Conversation

@chhoumann

@chhoumann chhoumann commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

Summary

The docs site at podnotes.obsidian.guide is rebuilt around what a reader is trying to do. Every page follows one standard, every screenshot comes from a script that shows PodNotes in a real, lived-in vault, and the site carries the PodNotes mark.

  • Landing page. / is now a splash page. It says what PodNotes is in one line and shows the plugin in a real vault (the episode note and its timestamps on phones). It offers "Get started", a card per job, and three start steps.

  • Sidebar by task. The groups are Start here, Listen, Take notes, Your library, Automate, Reference, and Help. There are three new pages:

    • /notes/ (Create episode notes).
    • /settings/ (every setting in the order the settings tab shows them).
    • /playlists/ (queue and playlists, split out of /podcasts/).
  • Every page rewritten to docs/STYLE.md, a one-page checklist distilled from Lee Robinson's docs guide, Diátaxis, the Google style guide, Write the Docs, and the Obsidian Help style guide. Each page:

    • Has one job and starts with the common case.
    • Uses verb headings for tasks and numbered steps with one action each.
    • Spells UI labels exactly as PodNotes and Obsidian show them.
    • Describes only the latest release, 2.21.1.
  • Screenshots of the real plugin. node docs/scripts/screenshots.mjs builds a vault from a committed seed (docs/screenshots/) and opens it in an isolated, headless Obsidian 1.13.7 at 2x. The vault has:

    • Nine real public feeds and the Minimal theme.
    • Notes created by PodNotes' own commands, with captured timestamps and a Bases view.

    The script writes every shot in light and dark, with phone crops from Obsidian's phone layout where a desktop shot is unreadable at 390 px. It also writes the README demo GIFs and the social preview. Rerun it after the UI redesign.

  • The PodNotes mark ("Captured moment", the owner's pick) is the header logo and the favicon:

    • One source SVG, docs/public/brand/podnotes-mark.svg, drawn on a 16 px grid so the 16 px icon stays sharp.
    • node docs/scripts/brand.mjs builds favicon.svg, 16 and 32 px PNGs, and a 180 px apple-touch-icon.png from that file.
    • The social preview shows no brand, so it is unchanged.
  • Theme and polish:

    • Inter, the QuickAdd docs palette, and quieter code chips.
    • Tables that stack on phones, and paths that wrap after a slash.
    • Theme-matched <picture> screenshots.
    • OG and Twitter meta, plus a phone theme switch on the landing page.
  • Nothing breaks. Every page keeps its URL, and every heading id the site has published (MkDocs and Starlight, 112 ids) still resolves. The build enforces this through legacy-fragments.json. llms.txt, llms-full.txt, and the raw .md pages are unchanged in shape.

Before and after (desktop and phone, light and dark)

Landing page before and after
Getting started before and after
Template tags before and after
FAQ before and after

Screenshots from the seeded vault

Landing hero Phone hero (dark) Phone toolbar
Landing hero Phone hero, dark Phone toolbar with the capture button
Episode note (dark) Bases
Episode note, dark Bases table of episode notes

The mark

Header at 1440 and 390 px, light and dark Icons at real size and enlarged, on light and dark
Docs header with the PodNotes mark at desktop and phone width, light and dark The 16 px, 32 px, and 180 px icons at real size and enlarged, on light and dark

Verification

Commands on 0bc5694, Node v22.23.2:

npm run lint            # pass
npm run format:check    # pass
npm run typecheck       # pass
npm run build           # pass
npm run size            # pass: 282,491 raw, 89,833 gzip
npm run test            # pass: 1,589 tests in 96 files
npm run docs:build      # pass: internal links, sidebar completeness, all 112 legacy fragments

npm run test now also runs docs/src/tables.test.mjs. vitest.config.ts includes docs/src/**/*.test.mjs for it.

CodeQL. The three alerts this PR raised are fixed in code:

  • docs/src/tables.mjs reads a header cell's text with a tag-aware scan and escapes &, ", <, and >. A test shows that <scr<b>ipt>x leaves no markup in the label.
  • docs/scripts/screenshots.mjs sends every value to the page as an argument of one fixed Runtime.callFunctionOn function, never as source text.

Old URLs. The old site published 51 stable URLs: pages, raw Markdown, llms.txt and llms-full.txt, images, the favicon, and sitemaps. Its hashed _astro assets and pagefind index change with every build, so they are left out. All 51 return 200 against the fc65831 build under wrangler pages dev, so _redirects applies as it does on Cloudflare. Each also has the content type its kind expects, and no page serves the 404 page.

Lighthouse 12.8 on python -m http.server, before (current site) and after (three runs on fc65831; the later commits change only text on /QuickAdd/ and /local_files/):

Page Before (perf, a11y, best practices, SEO, LCP, bytes) After
Home, mobile 78, 100, 100, 92, 5.9 s, 4,022 KiB 93-94, 100, 100, 100, 3.0-3.2 s, 368 KiB
Home, desktop 98, 100, 100, 92, 1.2 s, 4,022 KiB 100, 100, 100, 100, 0.6-0.7 s, 461 KiB
Template tags, mobile 89, 100, 100, 100, 3.6 s, 575 KiB 94-95, 100, 100, 100, 2.7-2.9 s, 395 KiB
Template tags, desktop 100, 100, 100, 100, 0.7 s, 575 KiB 100, 100, 100, 100, 0.6 s, 395 KiB

Review rounds. There were eleven rounds on the local build. Each round had four reviewers, except round 8, whose visual reviewer stopped on a rate limit. Round 9's visual review covered it.

  • A cold reader from each model family (Claude and GPT), with ten to twelve real tasks and only the site to go on.
  • A standards and facts reviewer, checking every claim against git show 2.21.1:src/....
  • A visual reviewer, checking pages at 1440 and 390 px in light and dark, plus the screenshots.

Coverage was not the same in every round. In rounds 4 and 5 the standards reviewer checked only that round's changes, and before round 6 the visual reviews never covered seven of the pages. Rounds 6 to 11 checked every page in every role, apart from round 8's visual review. The standards and visual roles switched model families from round to round.

Rounds 1 to 4 each found at least one major issue. Round 5 found none, but its coverage was narrow, so an audit of the review trail reopened the review at full coverage. Rounds 6 to 10 each found at least one major issue. All were fixed. Round 11 found none, which ended the review. It covered the mark too.

My fixes for round 11's minor findings were new wording, so three more checks reviewed that diff alone. They found four problems, all fixed:

  • A missing Save step in the QuickAdd recipe.
  • A download-link sentence that dropped "while the feed still lists it".
  • The prompt template name without .md. QuickAdd matches the end of the file's path, so the name needs it. This bug dated from round 10.
  • Provider steps that did not match QuickAdd's picker.

The third check found no major.

Findings worth knowing:

  • Fact errors at 2.21.1, among them:
    • What Episode list returns to.
    • Imports dropping protected private-feed URLs.
    • The forward-skip end guard.
    • Refresh episodes in Played.
    • The range commands inserting a link even with a plain {{time}} format.
  • Wrong Obsidian labels, checked against the 1.13.7 app bundle: the Sync toggle is Installed community plugins, and the Restricted mode button is Exit Restricted mode.
  • The QuickAdd recipes are checked against QuickAdd 2.32.1's source, not only its docs.
  • Screenshot framing: a stray tooltip, half rows, and a phone shot that cut off the Add buttons.

Runtime. The screenshots are runtime evidence. The script drives PodNotes in Obsidian 1.13.7 the way a user does: it adds feeds in Settings, plays, captures timestamps, and creates notes. They are captured from a build of tag 2.21.1, so they show the released UI.

Release impact

None for the plugin: no src/, settings, storage, API, or URI changes.

The pages describe 2.21.1. These need updating when the merged but unreleased changes ship:

Porting #397. #397 can be ported section by section after the release, because every section id it touches still resolves here:

  1. Replace the body of "Changes on two devices" with docs(sync): explain merged persistence and save recovery #397's section, and add its "When PodNotes saves" after it.
  2. Replace "Unreadable plugin data" with docs(sync): explain merged persistence and save recovery #397's version, including "Restore saving after a notice".
  3. Apply its other sync.md edits to "What PodNotes saves", "API keys and private feeds on each device", "Downloads on another device", and "Removed downloads and existing links".
  4. In "Use PodNotes on two devices", drop step 4 and its "Step 4 matters" line.
  5. Replace the FAQ progress answer with docs(sync): explain merged persistence and save recovery #397's.
  6. Rewrite the first item of mobile.md "Limits on phones" to match.

Follow-ups found while capturing, all PodNotes UI and not changed here:

  • In Obsidian's phone layout, the search results' Add buttons sit off screen.
  • Long queue titles run under the row's menu button.
  • The volume and speed sliders show their value twice.
  • Playlist rows added from Latest Episodes show no artwork.
  • AGENTS.md still says npm install under Common Commands. npm ci keeps the lockfile unchanged.

Note

Rebuild docs site around reader tasks, with landing page and screenshots

  • Rewrites all documentation pages as task-oriented guides (getting started, podcasts, notes, timestamps, playlists, sync, transcripts, settings), organized in a seven-group sidebar in site.mjs.
  • Adds a custom Starlight hero landing page in index.md and Hero.astro, with light/dark and phone screenshot variants.
  • Adds an automated screenshot workflow: a seeded capture vault and an Obsidian-driven capture script in screenshots.mjs generate the real-vault screenshots used across the site.
  • Applies new PodNotes theming (self-hosted Inter font, accent palette, stacked responsive tables) via custom.css and astro.config.mjs; documents the standard in STYLE.md.
  • Behavioral Change: sidebarSections in markdown.ts no longer creates a synthetic ungrouped Docs section and now omits external sidebar links; legacy heading IDs are preserved via legacy-fragments.json.

Macroscope summarized 0bc5694.

docs/STYLE.md is the checklist every docs page follows.
docs/scripts/screenshots.mjs builds a lived-in vault from docs/screenshots,
drives PodNotes in a private Obsidian capture instance, and writes light and
dark screenshots to docs/public/screenshots.
…nd calmer headings

Screenshots whose text is unreadable on a phone get a -phone crop from Obsidian's phone layout, served through <picture>. The hero folds its properties away so the timestamps sit mid-window, the Bases shot fits its columns, and the mobile player is cropped to the drawer.

Tables span the column on desktop, settings tables share fixed columns, paths in table cells break on phones, and short code chips stay on one line. Group headings above a question get a rule, anchor icons hide on touch screens, external sidebar links show an arrow, and the dark phone menu button no longer glares.
…ero, and cleaner crops

The episode-note screenshot now sits under the template that produced it. Phones see the episode note with its timestamp links in the landing hero, and the desktop hero sits higher so its timestamps show above the fold. Note, Bases, player, and toolbar crops lose their stray edges, caret, and tooltip.

The phone search crop is gone: in Obsidian's phone layout, PodNotes places each result's Add button off screen, so phones get the desktop shot. Code in settings tables wraps instead of overlapping the next column.
…s, and clearer steps

Phone captures park the pointer where no tooltip can open and clear the floating header's shadow. The search shot is the settings card alone, with an even margin, and the README demo starts at the note's artwork.

Paths in tables break after a slash, the settings Default column is wider, and phone table cells align to the top. Adding by RSS URL is its own steps, the top buttons are named by position, and the FAQ's plain-text fix matches the timestamps page.
# Conflicts:
#	docs/src/content/docs/podcasts.md
…n Sync toggle correctly

Obsidian labels the second Vault configuration sync toggle Installed community plugins, and it carries each plugin's settings, which hold the PodNotes library. The notes page labels its template as an example that replaces the default, Getting started points to it, the phone toolbar step names the clock button, and the player times are explained.

Inline paths and URLs break after a slash. The hero's theme twins load lazily, so a visit downloads only the one it shows. Screenshots are now captured from the 2.21.1 release bundle. The phone note shot has room below its callout, and the demo window shows whole queue rows.
@macroscopeapp

macroscopeapp Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Macroscope skipped reviewing this pull request. Per-review cost limit exceeded (workspace setting).

This review would cost an estimated $12.70, which exceeds your per-review limit of $10.00.

The top 3 files driving up this estimate:

File Diff Size Estimate
docs/scripts/screenshots.mjs 33.83KB $1.69
docs/src/content/docs/templates.md 22.19KB $1.11
docs/src/content/docs/sync.md 14.55KB $0.73

Tip

To get this pull request reviewed, you can:

  1. Comment @macroscope-app on this PR to request a manual review (monthly spend limits still apply).
  2. Exclude the file(s) above from review by adding a pattern to your .macroscope/ignore.md — note that creating this file replaces Macroscope's built-in default ignores rather than extending them.
  3. Raise your cost limit in your workspace billing settings.

Turn off this reminder going forward

Comment thread docs/src/tables.mjs Fixed
Comment thread docs/scripts/screenshots.mjs Fixed
Comment thread docs/scripts/screenshots.mjs Fixed
…ble labels

The screenshot script ran every step in Obsidian as code built with JSON.stringify'd values. It now sends fixed code through Runtime.callFunctionOn and passes the values as the call's argument, including waitFor, click, fill, and crop rects, so no value is written into code.

Stacked table labels take the header's text with a tag-aware scan instead of one regex pass, and escape <, >, &, and ". A test covers a nested tag.
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Deploying podnotes with  Cloudflare Pages  Cloudflare Pages

Latest commit: 0bc5694
Status: ✅  Deploy successful!
Preview URL: https://9f6ea439.podnotes.pages.dev
Branch Preview URL: https://docs-overhaul.podnotes.pages.dev

View logs

# Conflicts:
#	docs/src/content/docs/api.md
#	docs/src/content/docs/commands.md
#	docs/src/content/docs/podcasts.md
#	docs/src/content/docs/timestamps.md
At 2.21.1 PodNotes sends audio to Deepgram only when speaker labels are on with Deepgram as the provider. The landing page and the transcription page implied a Deepgram key alone could transcribe.
A full-site standards pass found three claims that the earlier diff-only rounds could not see. The transcription steps sent OpenAI users to a hidden Deepgram field. Sync and import described a data-format check as a plugin-version check. All three are fixed, and Getting started now creates the episode note before capturing into it.

Restricted mode's control is named as Obsidian shows it, Exit Restricted mode. The API headings carry the method name, with the signature in a code block below, so they fit a phone. Code blocks wrap, headings balance their lines, and command IDs stay whole on desktop. STYLE records the tutorial and FAQ exceptions to the one-owner rule.
The transcription page opened by saying it needs an OpenAI account, which contradicted its own table, where Deepgram needs no OpenAI key. The opening now states which provider runs when, and the landing card and description stay neutral. Refresh episodes is scoped to the lists where it fetches, and the import warning names Import settings.

Section headings balance their lines, menu paths stay on one line, the QuickAdd offset call sits in its own code block, and the phone toolbar shot is framed closer under the note.
The template tag rules claimed to cover every template, but Speaker label format only replaces {{speaker}}. The rules now exclude it, and the page says what it does. The QuickAdd page gives the transcript-prompt macro its own steps, instead of linking in a circle with the API page, and says a timestamp with a comment needs no macro.

The queue sentences say they hold only with the automatic queue on, Refresh episodes says what it does in a playlist, and a flat notes path warns that same-titled episodes share a note. Landing card titles take the link color.
Refresh episodes fetches in Played too, not only in Latest Episodes and a podcast's list. The episode menu table now matches Downloads and local files: Remove from Local Files keeps your own file. The QuickAdd transcript recipe carries its script and its AI Assistant prerequisite, and the API page points to it.

The private-feed notice, the FAQ's private-feed triggers, and the speaker label format's location and Deepgram labels match 2.21.1.
The range commands insert a link only with the default capture format. With {{time}}, they insert a plain-text range, so the Commands and Capture timestamps pages now say so. The QuickAdd transcript recipe runs from setting up the AI Assistant to a summary written into your note, using the labels in QuickAdd's own docs.

Six instructions written as prose are numbered steps now: playing an episode, the automatic queue, downloading the playing episode, the Bases table, capturing a range, and the speaker label format.
The queue and playlists page shows how to remove an episode from a list, and the podcasts page promises only what it covers. Links to your own files need their Local Files entry, and the FAQ and Local Files say how to restore them. The list controls on the podcasts page are bullets, and the transcript prompt script builds its prompt from quoted lines.
The owner chose the Captured moment mark: a waveform with one moment pinned. docs/public/brand/podnotes-mark.svg is the single source. It is drawn on a 16 px grid so the smallest favicon stays sharp, and docs/scripts/brand.mjs builds the SVG favicon, the 16 and 32 px favicons, and the Apple touch icon from it. The header shows the mark beside the name.
The steps that select a choice by name now show it as a UI label, like the rest of the site.
The QuickAdd AI recipe names each control, from Add AI Assistant command to the capture's write position, and the page says to install QuickAdd and to create scripts in a text editor. A range captured with {{time}} is plain text. The player's Queue list has no list controls, the queue move items say when they appear, and deleting a playlist keeps its episodes. Links to your own file stop working until you play the file with PodNotes again.
QuickAdd matches the prompt template by the end of its path, so the field takes the file name with .md, and the AI Assistant's settings need Save. The recipe splits into setting up the AI Assistant, building the prompt, and writing the summary, one action per step. Links to a download stream from the feed only while the feed lists the episode.
QuickAdd lists OpenAI and Gemini under Providers from the start, so the setup selects one and sets its API key. Other providers connect from their card with a key. The AI Assistant command sets a model, so the run does not stop to ask for one.
The published /podcasts/#when-a-feed-cannot-be-reached landed at the top of the page. A short section now describes what 2.21.1 shows when a podcast's feed cannot be fetched, and the build checks the id.
@chhoumann
chhoumann merged commit 527878d into master Oct 12, 2026
11 checks passed
@chhoumann
chhoumann deleted the docs/overhaul branch October 12, 2026 18:45
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