Skip to content

Migrate docs site to Pennington (net10, Spectre.Console 0.57)#19

Merged
patriksvensson merged 18 commits into
spectreconsole:mainfrom
phil-scott-78:penn
Jun 16, 2026
Merged

Migrate docs site to Pennington (net10, Spectre.Console 0.57)#19
patriksvensson merged 18 commits into
spectreconsole:mainfrom
phil-scott-78:penn

Conversation

@phil-scott-78

Copy link
Copy Markdown
Contributor

Migrates the Spectre.Console docs site from MyLittleContentEngine to Pennington.

  • Targets .NET 10; bumps Spectre.Console to 0.57.0 and Pennington to 0.1.0-alpha.0.318
  • SPA navigation, auto-generated API reference, and landing-page showcase
  • Rebased on current upstream main (0.56.0 / 0.57.0 release posts integrated)

@patriksvensson, total gut rewrite of the engine. You have a different dev environment so if you can put it through its paces that would be great. If things work not just on the docs site but also regarding Pennington I'm gonna use that a signal it is worth a 0.1.0 release. I'll push and update this PR with that version

…ioned resource URLs, enable flat file redirects, and standardize trailing slashes in page routes.
…amic SPA resource loading, and update layouts for enhanced content rendering.
Swap the content engine and modernize the build for the new pipeline:

- Replace MyLittleContentEngine packages (and the Roslyn/MSBuild
  workspace hack) with Pennington, Pennington.MonorailCss,
  Pennington.UI, and Pennington.TreeSitter. Tree-sitter now backs the
  `:symbol` code fences in place of Roslyn analysis.
- Bump target framework net10.0 -> net11.0 and SDK 10.0 -> 11.0, and
  set `LangVersion` to preview for Pennington's content type unions.
- Rewire DI in `Program.cs` around new typed `MarkdownContentService<T>`
  wrappers (`Services/PageServices.cs`) that filter the shared Pennington
  content pipeline by URL prefix so each source binds the right
  front-matter type.
- Update Razor components, layouts, and all blog/cli/console markdown
  for the new pipeline.
- Remove the obsolete island-render slots (`SpectreArticle.razor`,
  `SpectreArticleIslandRenderer.cs`) and `PageWrapper.razor`.
- Ignore `.playwright-mcp/` and drop leftover debugging-screenshot
  references from the csproj.
…ions

Generates browsable API reference pages from Pennington's reflection-backed
metadata provider, rendered with the existing WidgetApiReference card styling.

- Console (Spectre.Console + Json + ImageSharp) under /console/reference/api/
- CLI (Spectre.Console.Cli) under /cli/reference/api/

The published Pennington (0.281) ships only the metadata provider
(AddApiMetadataFromCompiledAssembly + IApiMetadataProvider), not the
AddApiReference content service, so this renders the metadata itself:

- ApiReferenceView + ApiParameterGrid: shared presentation extracted from
  WidgetApiReference; the inline widget now feeds the same markup via
  ApiReferenceModel (existing 26 widget pages render unchanged).
- ApiReferenceService: maps the provider DTOs into the view model and owns
  the type slug/route scheme (uid-based, so generics like Command<> stay
  distinct from Command).
- ConsoleApiPage / CliApiPage / ApiReferencePage: catch-all @page hosts that
  render inside DocumentationPageContent + MainLayout, inheriting the correct
  section header and sidebar.
- ApiReferenceContentService: registers the routes so the static build emits
  them, and adds the "API Reference" entry under each area's Reference group.

Verified: serve mode and the production static build (432 pages, 0 duplicates).
The TOC entry used HierarchyParts [area, "reference"], which made the entry
*become* the Reference folder node (renaming the group to "API Reference" and
nesting the existing reference pages under it). Pennington's HierarchyParts is
the item's own path, so a third self-segment ([area, "reference", "api"]) is
needed to render it as a leaf inside the Reference group, alongside the existing
reference pages. Verified in the rendered sidebar for both Console and CLI.
Search only indexed the API reference index pages (GetIndexableEntriesAsync
defaulted to the nav TOC entries), so a type that appears nowhere else — e.g.
IAnsiConsole — never surfaced, and types that did only matched the big index
listing instead of their own page. Override GetIndexableEntriesAsync to add one
searchable entry per type (kept out of nav via SearchOnly and out of llms.txt via
ExcludeFromLlms). Verified end-to-end: searching "IAnsiConsole" now returns its
own page as the top hit.

Also de-duplicate the type list by slug (ApiReferenceService.DistinctBySlug):
a type defined in more than one of an area's assemblies (Spectre shares source
across packages, e.g. CharExtensions in Console/Json/ImageSharp) otherwise
produced a duplicate route. Build is back to 0 duplicates.
…pha.0.18

Updates the Pennington packages (Pennington, ApiMetadata.Reflection, MonorailCss,
UI, TreeSitter) to 0.1.0-alpha.0.282 and Spectre.Console/ImageSharp/Json to
0.55.3-alpha.0.18. The API reference builds clean against the new versions.
The page carried a snake_case is_draft key (an MLCE leftover that Pennington binds to IsDraft), which hid it from the production build and left the /live/async redirect pointing at a 404. Drop the key to publish it, and remove a link to a non-existent best-practices page (previously the build's only broken-link warning).
Pennington reads _meta.yml, not the MLCE-era _index.metadata.yml, so the how-to folder sidecars were inert. Rename them and add a _meta.yml set for the CLI section so the sidebar follows Diataxis order (Tutorials, How-To, Reference, Explanation) instead of sorting Explanation before Reference.
PageHeader declared Tags and Theme parameters that the markup never rendered; callers computed and forwarded values that were silently dropped. Remove the parameters and their forwarders from the documentation pages.
…-ins

- Delete XmlDocumentationService (~230 lines) and rewire WidgetApiReference onto the existing ApiReferenceService / IApiMetadataProvider stack via a by-type-name lookup, so inline widget docs and the API reference pages share one renderer.
- Source MarkdownContentService<T> pages from the pipeline (IContentService.ParseContentAsync) instead of re-reading and re-parsing every file from disk per request; drop the FrontMatterParser dependency.
- Collapse the duplicated section-prefix filter into a shared SectionPrefix helper.
- Remove the unused TwoColumn/Column components and the inert dotnet-compile-error ExtraStyles rule.

Static build routes and rendered HTML verified byte-identical.
Per-widget landing showcase samples (Spectre.Docs.Examples/Showcase) with their VCR tapes and rendered SVGs, the Ghost component, and the updated home page and shared header. Also pins the MonorailCss and MonorailCss.Discovery package references.
Updated VCR tapes and re-rendered SVG screenshots, plus the Screenshot component and a new rule.gif asset.
The SpinnerList animation gated on DOMContentLoaded, which never fires on
SPA region swaps — so spinners froze on their first frame whenever the
reference page was reached via client-side navigation, and the setInterval
timers leaked onto detached nodes on navigate-away. Run the script
immediately (the SPA engine re-executes region scripts on commit) and
self-terminate each interval via element.isConnected.

Merge Generate-WidgetScreenshots-Native.ps1 into the canonical
Generate-WidgetScreenshots.ps1: keep the parallel browserless path (no ttyd,
no concurrency linefeed bug) but drive the globally-installed vcr tool
instead of a hardcoded local build.
Move global.json and the docs project off the net11 preview SDK onto net10
(dropping LangVersion=preview and the MonorailCss/Watch items), and bump
Pennington 0.282 -> 0.318 and Spectre.Console 0.55.3-alpha -> 0.57.0 (plus
ImageSharp/Json). Adjust Program.cs, Screenshot.razor, and the API/page
services for the updated package APIs, and drop the now-obsolete
.hot-reload-workaround.txt.

Regenerate all 53 widget and CLI screenshots against Spectre.Console 0.57.
The 0.56.0 and 0.57.0 release posts came in from upstream using the previous
engine's PascalCase front-matter keys (Title/Description/Date). Pennington
reads case-sensitive lowercase keys (title/description/date) like every other
post in Content/blog, so as imported these two would render with no title or
date and fall out of the blog listing, RSS, and date sorting. Convert them to
the lowercase schema.
Spectre.Console 0.57 marks Canvas.PixelWidth and CanvasImage.PixelWidth
[Obsolete] ("Not used anymore. Will be removed in future update.") — they are
now inert no-ops. Upstream's 0.57 update removed the PixelWidth demonstrations
from the example files accordingly, which left the "Pixel Width" reference
sections describing a dead feature with an example that no longer shows it.
Remove those sections from the Canvas and CanvasImage reference pages rather
than re-adding deprecated usage (which also reintroduced CS0618 warnings).
@phil-scott-78

Copy link
Copy Markdown
Contributor Author

forgot to mention, the VCR# tool was redone too. You'll want to upgrade that global tool if you want to mess with the TAPE files. The good news is that the new version doesn't take any external dependencies so it should be smoother dev experience.

@patriksvensson

Copy link
Copy Markdown
Contributor

Checking it out now 🙂

@patriksvensson

Copy link
Copy Markdown
Contributor

Works like a charm! Things look better as well, and I really like the new landing page! Big improvement if you ask me!

If I understand things properly, you don't want me to merge this before you've released 0.1.0 of Pennington?

@phil-scott-78 phil-scott-78 changed the title WIP: Migrate docs site to Pennington (net10, Spectre.Console 0.57) Migrate docs site to Pennington (net10, Spectre.Console 0.57) Jun 16, 2026
@patriksvensson
patriksvensson merged commit df85f18 into spectreconsole:main Jun 16, 2026
3 checks passed
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