- Tag filter chip row on /blog (URL-shareable scope)Closes the rev-39 cross-entity tag drill-down at the public blog axis. Top 14 tags surface as clickable chips above the post list; tap a chip to scope the visible cards to that tag without re-typing in the rev-102 search input. Active tag reflects into the URL hash (`/blog#tag=memory`) so an owner sharing a scoped view lands the recipient on the same filter โ mirrors the rev-100 roadmap status filter pattern at the /blog axis. Persists per-browser in localStorage so a returning visitor keeps their preferred scope; URL hash wins over localStorage on first load. One-tap '๐ Copy link' chip appears alongside the active tag for one-tap share โ mirrors the rev-101 roadmap filter share chip + rev-101 changelog permalink chip. Empty-state copy when the filter has no matches in any visible category. Tags went live across artifacts (rev 15), memory (rev 21), tasks (rev 24), task descriptive insight panel (rev 28), focus tags (rev 29), in-app drill-down (rev 39); rev 103 closes the same gap on the public blog surface.
- JSON-LD Article structured data + richer OpenGraph + Twitter cardPure SEO win that pairs with the rev-102 v1 blog endpoint as the second machine-readable surface on the blog axis: v1 returns brand voice for code generators, JSON-LD returns brand voice for SEO crawlers + Google Knowledge Graph + AI tooling roundup newsletters that scrape schema.org markup. Every blog post now emits an inline <script type='application/ld+json'> block with @type=Article, headline, description, datePublished, dateModified, author (Organization), publisher (with logo), mainEntityOfPage, keywords (from tags), wordCount, inLanguage. Plus richer OpenGraph metadata (canonical URL, siteName, twitter card=summary_large_image) so share links to blog posts in Slack/X/LinkedIn render with proper preview cards. Closes the structured-data gap that's been open since the blog launched.
- GET /api/v1/blog/{slug} โ single-post detail on the v1 surfaceCloses the v1 parity gap on the rev-102 blog cluster. Rev 102 added the listing endpoint at /api/v1/blog; rev 103 adds the per-post detail. Returns the full HTML body + tags + read-time + word-count + canonical URL plus 3 related posts via tag overlap so MCP hosts + AI tooling roundup newsletters can render 'you might also like' without a follow-up call per slug. No auth โ same model as /api/v1/blog (the listing endpoint), /badge.svg, /roadmap-*, /changelog. Cache-control public, max-age=300, s-maxage=1800 because content changes only when we publish. OpenAPI 3.1 spec typed in lockstep with the dashboard primitives (cadence pattern from rev 78 onward holds unbroken into rev 103). Pairs with /api/v1/blog (listing) as the two-axis blog read surface โ same depth pattern as the rev-100/101 changelog axis (listing + sinceRev incremental polling).
- '/' keyboard shortcut on /blog search + reading-time chip on every cardMirrors the rev-17 dashboard `WorkspaceSearch` keyboard pattern at the /blog index. Press / from anywhere on the page to focus the rev-102 search input; Esc clears + blurs. Ignored when the user is already typing in another input. Visible '/' kbd hint inside the search box (fades out on focus) for discoverability. Plus every blog card on the index page (FeaturedCard + CategorySection cards) now shows a small clock-icon read-time chip alongside the date so readers can triage by length without opening the post. Same Clock icon vocabulary used elsewhere in the brand. Cumulative micro-polish (every rev 22+ has carried at least one) โ but rev 103's polish is load-bearing because the rev-102 search input was the most-used affordance on /blog and the keyboard-first power-users (the same ones that use rev-17 / on the dashboard, rev-23 โK command palette) now have parity on the public surface.