Repository navigation
AppHost-language selector: teach the docs site about Go #1926
Description
Part of microsoft/aspire#21115
The docs site remembers each reader's AppHost language (aspire-lang) and uses it to switch synced tab groups, PivotSelector pages and the inline API reference chips. Every one of those places only knows C# and TypeScript, so a Go AppHost reader cannot be represented: a Go tab in an aspire-lang group would not update the preference, ?aspire-lang=go is ignored and a stored go is overwritten with typescript. An open stack of PRs (#1634 through #1638) would replace the hard-coded lists with a registry, so the first item is a decision. Target branch is release/17.0; line numbers are microsoft/aspire.dev release/17.0 at 5c48cfb, and they hold on main (fa51b99), where the cited files are identical except one unrelated table row in app-host/configuration.mdx (L116). Everything below is by code reading, not run in a browser.
Related: #1634 (Add the config-driven AppHost language foundation), #1638 (Enable every Aspire AppHost language), #1681 (fix: preserve client navigation lifecycles across pages and deployments), #1917 (Add Go API reference), #1924 (Document the Go AppHost: getting started, conventions and CLI references), #700 (Document Go language support for polyglot AppHosts).
Checklist
- Decide how Go reaches the selector for 17.0: land the registry stack or patch the lists in place. Add the config-driven AppHost language foundation #1634 (draft, base
main, reported as conflicting, last updated 2026-09-17) addssrc/frontend/src/data/apphost-languages.json, where Go isenabled: false,experimental: truewith the aliasgolang(69e3c6b, L47-58), and edits most of the files below;Head.astrothen builds its labels, aliases and default from that registry (L8, L23 and L76-106). Enable every Aspire AppHost language #1638 (changes requested, updated 2026-09-24) sets Goenabled: true(83dda4c, L49-50). The stack's tree has nocomponents/pivot-selector.ts, which fix: preserve client navigation lifecycles across pages and deployments #1681 added to bothmainandrelease/17.0on 2026-09-17, and none of the five PRs changesApiReference.astroorutils/api-reference*. In all, eight of the files cited below (pivot-selector.ts,ApiReference.astro,api-reference-core.ts,api-reference/registry.ts,dev-hub.ts,dev-layout.spec.tsand the two unit tests) are absent from the stack's trees, because its merge-base withmain(61fe0a9) is dated 2026-09-10, so the stack as written leaves them with their hard-coded C# and TypeScript lists. Whether the stack is still meant for 17.0 is unverified. Fix: a maintainer picks one path; a hand patch of the same files would conflict with the stack, so the items below are written to apply to either. - Teach the head script about Go.
src/frontend/src/components/starlight/Head.astrokeeps labels for two languages (appHostLangLabels, L106-109) andnormalizeAppHostLang(L112-125) returns onlytypescript,csharpor an empty string. The tab click and keyboard handlers (L162-191) sync only a non-empty result,?aspire-lang=gois dropped (L195, becausepersistAppHostLangreturns an empty string at L138) andrestorePreferences(L209) replaces any other stored value withtypescript. Fix: add Go (labelGo, plus the aliasgolang) to the label map and the normalizer, or read both from the registry if the stack lands. Match Go exactly rather than by substring like the existing checks (L114, L117-121), which would also accept any value that merely contains "go". - Let the pivot mirror a Go choice into the tab sync. In
src/frontend/src/components/pivot-selector.ts,apply(L116-129) stores the choice (L118) but copies it to the Starlight tab sync and todata-apphost-langonly whenkey === 'aspire-lang' && (id === 'csharp' || id === 'typescript')(L120-126), while L127-129 still writes?aspire-lang=<id>. A Go option would therefore update the URL and the stored value but leave synced tabs and chips on the previous language, and the next page load (Head.astroL209) would replace the storedgo. Separately, on a page whoseaspire-langpivot has no Go option (all three pivot pages below today), the initial selection (L165-170) takes the first of the URL value, the stored value andvalidOptions[0]that is a valid option, andapply(current, false)then stores it (L118), so merely visiting such a page overwrites a storedgowithtypescript, even afterHead.astrois fixed.PivotSelector.astroL16-23 also ordersaspire-langoptions as TypeScript, C#, then the rest. Fix: replace the two-id test with a lookup of the known AppHost languages (label per id), decide where Go sorts, and do not persist the first-option fallback chosen at L165-170. - Decide what the inline API reference chip does for Go.
src/frontend/src/components/ApiReference.astrotakes a C# member name (L5-9), lists only C# and TypeScript (languages, L34-37) and shows a chip only whendata-apphost-langequals its language (L93-96; the C# chip also shows when the attribute is absent, L98-100).Head.astroreplaces any other stored value withtypescript(L209), so a Go reader gets the TypeScript chip today; once the attribute can bego, no chip matches and both stay hidden (.ar-lang { display: none; }, L89-91). The resolver is built from a C# provider and one TypeScript provider (src/frontend/src/utils/api-reference-core.tsL128-138) andutils/api-reference/registry.tsL43-53 hard-codescsharpandtypescriptfields in every resolution. Add Go API reference #1917 adds Go API pages and extends the existing cross-language navigation test to Go (tests/e2e/api-cross-language-navigation.spec.tsL17 and L83 at d7d7633; onrelease/17.0andmainthey list onlycsharpandtypescript) but does not changeApiReference.astro,api-reference-core.tsor the registry. Fix: either add a third provider that maps a C# member name to its Go member plus a Go chip, or link the existing chip to the Go pages; choose one and record why.ApiReference.astroL43-44 falls back to the TypeScript target for any language id other thancsharpthat has notargetsentry, so a Go chip added without a Go target would silently link to the TypeScript page. - Add Go to the other two-language components, after confirming how Go names should be shown.
components/ContainerImages.astrobuilds only C# and TypeScript labels (apiLabels, L49-54; the comment at L45-48 notes that the TypeScript label lowercases the first letter), has its own normalizer (L185-191, which returns null for anything but TypeScript or C#) and anapplythat falls back totypescript(L202);components/SimpleAppHostCode.astrodestructures onlycsharpCodeandtypescriptCode(L20) into one<Tabs syncKey="aspire-lang">(L27);components/IntegrationCard.astrotypeswithLangas'csharp' | 'typescript'(L60-64);components/AppHostBuilder.client.tshard-codes the language type and check (L1, L13-15, L135, L653);components/home/HomePage.astrodoes the same (L700, L704-706). Confirm the Go name shape against the generated Go SDK before adding labels. Fix: add Go to each, or read the list from the registry if the stack lands. - Add a Go option to a pivot page only together with its Go content, and revisit the dev hub card.
get-started/first-app.mdx(L21-28; its description at L4 says "either a C# or TypeScript AppHost"),get-started/deploy-first-app.mdx(L27-34) andapp-host/configuration.mdx(L18-26) each definePivotSelector key="aspire-lang"with C# and TypeScript options and use<Pivot id="typescript">blocks (5, 7 and 1 in the English pages). Insrc/frontend/src/data/dev-hub.ts, L26-27 link the C# and TypeScript cards to/get-started/first-app/?aspire-lang=csharpand...=typescript, while the Go card (L29, "Add a Go service") links to the Go get-started page, where Document the Go AppHost: getting started, conventions and CLI references #1924 rewrites step 2 ("Optionally try the Go AppHost templates") into "Write the AppHost in Go", linking to the new/app-host/go-apphost/(L73 and L81 at c4a58eb), and adds a see-also link (L92). Add Go API reference #1917 also editsdev-hub.ts(one more "Go API" link inreferenceLinks, after the lines cited here), so coordinate with it. Fix: decide per page whether to add a Go option with its content or to leave it out on purpose (an option with no content is worse than none), and whether the Go card should point at the Go AppHost page. - Extend the tests.
src/frontend/tests/e2e/pivot-selector.spec.ts(L160-251 for the chips following the selection through every entry point, L253 onward for the first-app defaults),tests/e2e/integrations-gallery.spec.ts(L81-100, L217-241 and L244-261),tests/e2e/dev-layout.spec.ts(L135-139) and the unit teststests/unit/pivot-selector-lifecycle.vitest.test.tsandtests/unit/api-reference.vitest.test.tsassert only the two existing languages.tests/unit/navigation-preferences.vitest.test.tsruns theHead.astroinline script in a VM (rows at L56-58) and is the natural home for the Go cases; Add Go API reference #1917 already adds a/reference/api/go/row there (L57 at d7d7633). Fix: add Go cases for the preference set from a Go tab,?aspire-lang=go, a storedgosurviving navigation (including a visit to a pivot page with no Go option), and the chip behavior chosen above.
Recommended order
Decide first, because the decision picks the files. Then the preference plumbing (Head.astro and pivot-selector.ts), so a Go choice survives navigation; then the API reference chip and providers; then the other components; then the pivot pages and the dev hub card, each with its Go content; with the matching tests in each step.
Done when
Choosing Go in a selector or in an aspire-lang tab group, or opening a page with ?aspire-lang=go, keeps Go selected across navigation, including through pages that have no Go option, and updates the synced tab groups and the inline API reference chip. Each pivot page either has Go content or deliberately has no Go option, and the unit and end-to-end tests cover Go.
Activity
Document the Go AppHost: getting started, conventions and CLI referen…