Publish a machine-readable sample index for Toolkit components #819
Jaylyn-Barbee
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Toolkit samples are a great source of well-documented XAML samples on Windows, and right now the only way to get at them programmatically is to scrape the repo. I'd like to propose publishing a generated JSON index of them instead.
Why this comes up now
I work on winappCli, a CLI for Windows app development. One of its commands,
winapp find ui, answers "how do I build X" by searching a local corpus of Windows UI samples and handing back pasteable XAML. Toolkit is one of its sources. Today we get that corpus by scraping this repo — parsingcomponents/*/samples/*.mdfrontmatter, matching> [!Sample X]markers to[ToolkitSample]attributes, and pulling the.xamlfiles. It's about 1,050 lines of code and ~105 HTTP requests per refresh.It works, but it's the wrong shape. We maintain a 34-entry override table and a 28-entry filename map purely to guess which control a given sample belongs to, because one component often holds several controls (
SettingsControlsholds SettingsCard and SettingsExpander;Sizersholds ContentSizer, GridSplitter and PropertySizer). Those tables are us reconstructing, badly, a mapping your authors already wrote down in the.mdfiles. When someone adds a sample here, we get its control name wrong until a human notices.This has been asked for before, from inside
Tooling-Windows-Submodule#82, "Generate search index for Sample App", opened by @michael-hawker in 2022 and still open, proposes sourcing "Markdown Document Metadata (Title, Description, Keywords), Sample Metadata (Title, Description), Sample Option Info". That's the same data, for in-app search rather than an external contract, but one artifact serves both.
The proof point
We did this with WinUI Gallery first. microsoft/WinUI-Gallery#2232 added a standalone
tools/CatalogExporterconsole tool, a checked-incatalog/windows-samples.json, 73 tests, and one CI step that byte-compares the committed file against a fresh generate so it can't go stale. It merged on 2026-09-16 and we deleted our Gallery scraper against it.The thing that made a large PR from an outside contributor reviewable wasn't the code, it was the failure handling: the staleness check, a gate asserting nothing ships that a consumer would silently discard, stable ordering, and an explicit pinned list of anything deliberately withheld. I'd bring the same four gates here.
What I'm proposing
A small standalone exporter (not a source generator —
ToolkitSampleMetadataGeneratoris anIIncrementalGeneratorandAddSourceonly emits C#, so JSON has to live outside it) that walks the components and emits one checked-in JSON file, plus a CI step that fails if it's out of date.Keyed by the documentation file: one entry per
components/*/samples/*.md, carrying its frontmatter (title,description,keywords,category,subcategory) with its samples resolved through that file's[!Sample]markers, each sample carrying thedisplayNamefrom its[ToolkitSample]attribute and its XAML.Two details worth deciding up front rather than discovering later:
Publish the page body, not the page. All 129 sample
.xamlfiles carryx:Classand 128 have a<Page>root, neither of which is pasteable into someone else's app. A well-formed fragment is more useful than a verbatim file. Rewriting namespaces and class names to fit the consumer's project is our job, not yours.Sample options need handling. 36 of 129 samples declare
ToolkitSampleBoolOption/TextOption/NumericOption/MultiChoiceOption, and 34 of thosex:Bindto the generated members across 88 bindings. Those members only exist inside the sample app, so published verbatim that XAML binds to something a consumer doesn't have. Gallery had the identical problem with its$(Token)placeholders. Either resolve them to their defaults or drop the carrying attribute, and gate on it so it can't regress. We already have working detection code for this and I'm happy to hand it over rather than have anyone write it twice.Who else this helps
The immediate beneficiary is any coding agent. Every assistant answering "how do I use
SettingsExpander" today is either working from training data of unknown vintage or scraping this repo the way we do. A published index is a stable contract: fetch one file, get every sample with its real title, description, keywords and category, and know when it changed.It also lands the thing #82 originally wanted — in-app sample search — since the same artifact feeds the sample app, the Labs site, and docs tooling.
And it makes your own data testable. Generating this surfaced a handful of defects that are invisible today precisely because nothing machine-readable reads them: three samples declaring a copy-pasted
displayName(BackdropInvertBrushSample,BackdropSaturationBrushSampleandBackdropSepiaBrushSampleall say "BackdropGammaTransferBrush", so all three render under the wrong title in the sample app right now), two[!Sample]markers pointing at class names that don't exist, and one sample with a valid attribute that no.mdreferences. I'll send those as a separate small PR regardless of what happens with this proposal.What I'd like to know
CommunityToolkit/Windowsor inTooling-Windows-Submodule? Tooling is arguably the better long-term home, but the pin here is currently ~16 commits behind toolingmain, so a tooling-first route means two PRs and a submodule bump. I'd rather start inWindowsand move it if you'd prefer to own it there.There's a JSON schema that Gallery's index conforms to. It's not fixed — it'd grow a
toolkitextension object for things that only apply here — but it means a consumer can read both sources with one parser.All reactions