Skip to content

Commit cae6f91

Browse files
authored
Refactor AppHost docs and add a localized site tour (#666)
* feat: Refactor AppHost language pivot component and update documentation - Introduced `AppHostLangPivot` component to streamline language-specific code presentation in documentation. - Updated `resource-mcp-servers.mdx` to utilize the new `AppHostLangPivot` for C# and TypeScript code examples. - Modified `what-is-aspire.mdx` to implement `AppHostLangPivot` for improved clarity in multi-language AppHost examples. - Adjusted Japanese documentation to reflect changes in links and content structure. - Enhanced CSS for sidebar responsiveness and improved layout for API reference pages. - Fixed links in various documentation files to point to the correct paths for creating Aspire applications. * fix: Correct markdown syntax for code blocks in contributor guide * feat(tour): implement site tour functionality with step definitions and UI components - Added SiteTour component to manage and display a guided tour for users. - Integrated tour steps for key UI elements including app host selector, sidebar toggle, and page actions. - Enhanced PageTitle and Sidebar components with data attributes for tour targeting. - Introduced new SVG icon for help in site navigation. - Updated prerequisites documentation to include margin for better layout. * Refactor code structure for improved readability and maintainability * fix: Update references from dotnet to microsoft for aspire-samples repository * Add analytics tracking scripts for event capturing - Introduced 1ds.js to initialize Application Insights for analytics tracking. - Added track.js to bind click event tracking for elements with data attributes. - Implemented checks to prevent multiple initializations and bindings. - Enhanced debugging output for better traceability during analytics operations. * style: Enhance sidebar and integration grid styles for improved layout and usability * fix: Update route data handling and normalize path function for breadcrumbs * Add site tour translations for multiple languages - Implemented site tour translations in Indonesian, Italian, Japanese, Korean, Brazilian Portuguese, European Portuguese, Russian, Turkish, Ukrainian, and Simplified Chinese. - Each language includes labels, tooltips, hints, and steps for the site tour feature. * chore: rewrite add existing app for scenarios, avoiding bias. * chore: add `tmp/` to .gitignore and delete patches. * feat: enhance sidebar functionality and improve breadcrumb utility - Refactored getContentBreadcrumbs function for cleaner syntax. - Added functionality to dismiss site tour consent if visible in e2e tests. - Implemented waitForTopicSidebarReady helper to ensure topic sidebar is ready before interactions. - Created tests for topic sidebar controls, ensuring they persist state and respond correctly to user actions. - Added checks for sidebar collapse state and filter reset on reload. * Add end-to-end and unit tests for site tour functionality - Implemented a new end-to-end test for the site tour feature in `site-tour.spec.ts`, covering scenarios such as opening the tour, resuming progress, and completing the tour on larger screens. - Added a test to ensure the site tour is disabled on narrow viewports. - Created unit tests in `site-tour.vitest.test.ts` for various helper functions related to site tour step definitions, state parsing, and filtering logic. - Verified the correct order of site tour steps and ensured proper handling of malformed stored states. * fix: update footer preferences heading to use paragraph tag for consistency test: refactor pivot selector tests to improve clarity and maintain state * fix: rename variables for site tour props to avoid conflicts * fix: update documentation and styles for improved clarity and consistency * fix: improve inline code handling in markdown content for better readability * fix: remove unnecessary 'prev' field from documentation for clarity * fix: refactor Playwright configuration and enhance E2E test support with cookie consent handling * fix: refactor prerequisites documentation to streamline language selection and enhance clarity * fix: refactor TypeScript API routes and enhance slug generation for better uniqueness * fix: update links in documentation for consistency and clarity * fix: remove inline-block display from code elements for better wrapping behavior * fix: enhance header actions for better accessibility and responsiveness in mobile view * fix: refactor site tour feature to enable/disable based on environment variable
1 parent b732bf9 commit cae6f91

File tree

113 files changed

+8617
-5589
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

113 files changed

+8617
-5589
lines changed

.github/skills/doc-writer/SKILL.md

Lines changed: 66 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ Optional frontmatter fields:
7373
Import Starlight components at the top of your MDX file:
7474

7575
```tsx
76-
import { Aside, CardGrid, LinkCard, Steps, Tabs, TabItem, Icon, FileTree } from '@astrojs/starlight/components';
76+
import { CardGrid, LinkCard, Steps, Tabs, TabItem, Icon, FileTree } from '@astrojs/starlight/components';
7777
```
7878

7979
Additional commonly used imports:
@@ -104,24 +104,24 @@ When you introduce or change a custom component that is used by docs pages:
104104

105105
#### Aside (Callouts)
106106

107-
Use for tips, notes, cautions, and warnings:
107+
Prefer fenced `:::` callouts for tips, notes, cautions, and warnings. Use the `Aside` component only when a JSX-only composition pattern is required.
108108

109109
```mdx
110-
<Aside type="tip" title="Pro Tip">
110+
:::tip[Pro Tip]
111111
This is a helpful tip for users.
112-
</Aside>
112+
:::
113113

114-
<Aside type="note">
114+
:::note
115115
Important information users should be aware of.
116-
</Aside>
116+
:::
117117

118-
<Aside type="caution">
118+
:::caution
119119
Proceed with care - this may have unexpected consequences.
120-
</Aside>
120+
:::
121121

122-
<Aside type="danger">
122+
:::danger
123123
Critical warning - this could cause data loss or security issues.
124-
</Aside>
124+
:::
125125
```
126126

127127
#### Steps
@@ -165,6 +165,8 @@ Press F5 to start debugging.
165165
</Tabs>
166166
```
167167

168+
If a heading should appear in the **On this page** table of contents, keep that heading outside the `Tabs` component. Headings placed inside `TabItem` content may be skipped by the generated TOC.
169+
168170
#### Pivot/PivotSelector
169171

170172
Use for programming language selection that persists across page:
@@ -188,6 +190,22 @@ Python specific content here.
188190
</Pivot>
189191
```
190192

193+
If a heading needs to appear in the **On this page** table of contents, keep the heading outside the `Pivot` content and put only the variant-specific body content inside each `Pivot`.
194+
195+
For Aspire AppHost docs, use a single page-level `PivotSelector` with `key="aspire-lang"` when the surrounding section flow should switch as one unit. If a page would otherwise need multiple `aspire-lang` selectors, keep the page-level selector for the main flow and use synced `Tabs`/`TabItem` with `syncKey='aspire-lang'` for repeated language-specific examples later on the page.
196+
197+
```mdx
198+
<Tabs syncKey='aspire-lang'>
199+
<TabItem id='csharp' label='C#'>
200+
C# example content here.
201+
</TabItem>
202+
203+
<TabItem id='typescript' label='TypeScript'>
204+
TypeScript example content here.
205+
</TabItem>
206+
</Tabs>
207+
```
208+
191209
#### CardGrid and LinkCard
192210

193211
Use for navigation and feature highlights:
@@ -246,10 +264,10 @@ For more information, see [Service Defaults](/fundamentals/service-defaults/).
246264
</LearnMore>
247265
```
248266

249-
The component renders an open-book icon alongside the provided content. Place it after a section or code example to point readers to deeper documentation. It works well inside `<Aside>` blocks or after `<Steps>`:
267+
The component renders an open-book icon alongside the provided content. Place it after a section or code example to point readers to deeper documentation. It works well inside fenced `:::` callouts or after `<Steps>`:
250268

251269
````mdx
252-
<Aside type="tip" title="Feature flag">
270+
:::tip[Feature flag]
253271
Enable polyglot support by running:
254272

255273
```bash
@@ -259,7 +277,7 @@ aspire config set features:polyglotSupportEnabled true --global
259277
<LearnMore>
260278
For more information, see [aspire config command reference](/reference/cli/commands/aspire-config-set/)
261279
</LearnMore>
262-
</Aside>
280+
:::
263281
````
264282

265283
#### Aspire Custom Components
@@ -333,20 +351,20 @@ Aspire supports both **C# AppHosts** (`AppHost.cs`) and **TypeScript AppHosts**
333351

334352
### Core Principles
335353

336-
1. **Always show both languages**: Every AppHost code example must include both C# and TypeScript variants unless the feature is genuinely language-specific.
354+
1. **Always show both languages**: Every AppHost-focused example or walkthrough must include both C# and TypeScript variants unless the feature is genuinely language-specific.
337355
2. **Use neutral framing**: Write prose that applies to both languages. Say "In your AppHost" not "In your C# project". Say "Add a Redis resource" not "Call `builder.AddRedis()`".
338356
3. **Neither language is the default**: Don't present C# first as the "real" example and TypeScript as an afterthought. Both tabs are equal peers.
339357
4. **Verify TypeScript APIs exist**: Before writing a TypeScript example, confirm the API exists in the TypeScript AppHost SDK. Do not invent TypeScript samples — if you are unsure whether an API is available, flag it for review.
340358

341-
### Tab Pattern for AppHost Code
359+
### AppHostLangPivot Pattern for AppHost Content
342360

343-
Use `<Tabs syncKey="apphost-lang">` so the reader's language choice persists across the page and across pages:
361+
Use `AppHostLangPivot` for AppHost-specific content that changes between C# and TypeScript. The component is controlled by the site-wide AppHost selector in the sidebar, so it should be the default choice for AppHost walkthroughs, code samples, and prose that should switch together.
344362

345363
````mdx
346-
import { Tabs, TabItem } from '@astrojs/starlight/components';
364+
import AppHostLangPivot from '@components/AppHostLangPivot.astro';
347365

348-
<Tabs syncKey="apphost-lang">
349-
<TabItem label="C#">
366+
<AppHostLangPivot>
367+
<div slot="csharp">
350368

351369
```csharp title="AppHost.cs"
352370
var builder = DistributedApplication.CreateBuilder(args);
@@ -359,8 +377,8 @@ builder.AddProject<Projects.Api>("api")
359377
builder.Build().Run();
360378
```
361379

362-
</TabItem>
363-
<TabItem label="TypeScript">
380+
</div>
381+
<div slot="typescript">
364382

365383
```typescript title="apphost.ts"
366384
import { createBuilder } from './.modules/aspire.js';
@@ -375,17 +393,23 @@ await api.withReference(cache);
375393
await builder.build().run();
376394
```
377395

378-
</TabItem>
379-
</Tabs>
396+
</div>
397+
</AppHostLangPivot>
380398
````
381399

400+
Use `AppHostLangPivot` for more than code blocks when needed. Entire paragraphs, lists, asides, or multi-step sections can live inside the `csharp` and `typescript` slots when the workflows differ. The pivot itself is the shared wrapper; the slot names are the language discriminator.
401+
402+
Use `Tabs` for other concerns such as CLI vs IDE, deployment targets, or platform choices. Do not use `Tabs syncKey="apphost-lang"` for new AppHost content.
403+
404+
If a section heading should appear in the **On this page** table of contents, keep that heading outside `AppHostLangPivot`. Headings inside the `csharp` and `typescript` slots can be missed by the TOC generator, so the recommended pattern is a shared heading followed by an `AppHostLangPivot` containing only the language-specific body content.
405+
382406
### Conventions
383407

384408
| Aspect | C# | TypeScript |
385409
|---|---|---|
386410
| File title | `title="AppHost.cs"` | `title="apphost.ts"` |
387-
| Tab label | `C#` | `TypeScript` |
388-
| Sync key | `apphost-lang` | `apphost-lang` |
411+
| Pivot wrapper | Shared `AppHostLangPivot` container | Shared `AppHostLangPivot` container |
412+
| Language slot | `slot="csharp"` | `slot="typescript"` |
389413
| Builder creation | `DistributedApplication.CreateBuilder(args)` | `import { createBuilder } from './.modules/aspire.js';` then newline for space followed by `await createBuilder();` |
390414
| Method casing | PascalCase (`AddRedis`) | camelCase (`addRedis`) |
391415
| Async pattern | Synchronous fluent calls | `await` each builder call |
@@ -400,19 +424,19 @@ When writing narrative text around AppHost examples:
400424
- ❌ "Call `builder.AddRedis()` in your _Program.cs_" (C#-specific)
401425
- ❌ "Add the following C# code to your AppHost" (when both languages should be shown)
402426

403-
When a concept differs between languages (e.g., configuration files, async patterns), explain both within the tabs or in language-neutral prose above the tabs.
427+
When a concept differs between languages (e.g., configuration files, async patterns), explain both within the AppHostLangPivot slots or in language-neutral prose above the pivot.
404428

405429
### When TypeScript Is Not Yet Supported
406430

407-
If a hosting integration does not yet have TypeScript AppHost support, show only the C# example **without tabs** and add a note:
431+
If a hosting integration does not yet have TypeScript AppHost support, show only the C# example without `AppHostLangPivot` and add a note:
408432

409433
```mdx
410434
<Aside type="note">
411435
TypeScript AppHost support for this integration is not yet available.
412436
</Aside>
413437
```
414438

415-
Do **not** wrap a single language in a `<Tabs>` component — that creates a misleading UI suggesting another option exists.
439+
Do **not** wrap a single language in `AppHostLangPivot` or a single-language `<Tabs>` component — that creates a misleading UI suggesting another option exists.
416440

417441
## Integration Documentation
418442

@@ -443,7 +467,8 @@ title: [Technology] integration
443467
description: Learn how to use the [Technology] integration with Aspire.
444468
---
445469

446-
import { Aside, Tabs, TabItem } from '@astrojs/starlight/components';
470+
import { Aside } from '@astrojs/starlight/components';
471+
import AppHostLangPivot from '@components/AppHostLangPivot.astro';
447472
import InstallPackage from '@components/InstallPackage.astro';
448473
import Image from 'astro:assets';
449474

@@ -459,8 +484,8 @@ Brief description of the technology and what the integration enables.
459484

460485
### Add [Technology] resource
461486

462-
<Tabs syncKey="apphost-lang">
463-
<TabItem label="C#">
487+
<AppHostLangPivot>
488+
<div slot="csharp">
464489

465490
```csharp title="AppHost.cs"
466491
var builder = DistributedApplication.CreateBuilder(args);
@@ -471,8 +496,8 @@ var tech = builder.AddTechnology("tech");
471496
builder.Build().Run();
472497
```
473498

474-
</TabItem>
475-
<TabItem label="TypeScript">
499+
</div>
500+
<div slot="typescript">
476501

477502
```typescript title="apphost.ts"
478503
import { createBuilder } from './.modules/aspire.js';
@@ -484,8 +509,8 @@ const tech = await builder.addTechnology("tech");
484509
await builder.build().run();
485510
```
486511

487-
</TabItem>
488-
</Tabs>
512+
</div>
513+
</AppHostLangPivot>
489514

490515
### Configuration options
491516

@@ -508,8 +533,8 @@ Include both hosting and client sections:
508533

509534
### Add [Technology] resource
510535

511-
<Tabs syncKey="apphost-lang">
512-
<TabItem label="C#">
536+
<AppHostLangPivot>
537+
<div slot="csharp">
513538

514539
```csharp title="AppHost.cs"
515540
var builder = DistributedApplication.CreateBuilder(args);
@@ -522,8 +547,8 @@ builder.AddProject<Projects.Api>("api")
522547
builder.Build().Run();
523548
```
524549

525-
</TabItem>
526-
<TabItem label="TypeScript">
550+
</div>
551+
<div slot="typescript">
527552

528553
```typescript title="apphost.ts"
529554
import { createBuilder } from './.modules/aspire.js';
@@ -538,8 +563,8 @@ await api.withReference(tech);
538563
await builder.build().run();
539564
```
540565

541-
</TabItem>
542-
</Tabs>
566+
</div>
567+
</AppHostLangPivot>
543568

544569
### Hosting integration health checks
545570

.github/skills/update-samples/SKILL.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
---
22
name: update-samples
3-
description: Update the samples data file by fetching sample metadata from the dotnet/aspire-samples GitHub repository. Use when adding new samples, refreshing sample data, or ensuring samples.json stays in sync with the upstream repo.
3+
description: Update the samples data file by fetching sample metadata from the microsoft/aspire-samples GitHub repository. Use when adding new samples, refreshing sample data, or ensuring samples.json stays in sync with the upstream repo.
44
---
55

66
# Update Samples Data
77

8-
This skill synchronizes the samples data file with the `dotnet/aspire-samples` GitHub repository. It enumerates all sample projects in the `samples/` directory, fetches each sample's README.md, and generates a structured JSON catalog.
8+
This skill synchronizes the samples data file with the `microsoft/aspire-samples` GitHub repository. It enumerates all sample projects in the `samples/` directory, fetches each sample's README.md, and generates a structured JSON catalog.
99

1010
## Overview
1111

1212
The aspire.dev site maintains a data file for samples:
1313

1414
- **`src/frontend/src/data/samples.json`** — Sample metadata including titles, descriptions, tags, deep links, and README content extracted from the upstream repo.
1515

16-
This skill keeps that file in sync with the `dotnet/aspire-samples` repository on GitHub.
16+
This skill keeps that file in sync with the `microsoft/aspire-samples` repository on GitHub.
1717

1818
## Prerequisites
1919

@@ -32,7 +32,7 @@ Fetch the latest sample data from the GitHub API:
3232
cd src/frontend && node scripts/update-samples.js
3333
```
3434

35-
This writes updated sample metadata to `src/frontend/src/data/samples.json`. The script queries the GitHub Contents API for directories in `dotnet/aspire-samples/samples/`, fetches each sample's README.md, and extracts structured metadata.
35+
This writes updated sample metadata to `src/frontend/src/data/samples.json`. The script queries the GitHub Contents API for directories in `microsoft/aspire-samples/samples/`, fetches each sample's README.md, and extracts structured metadata.
3636

3737
### 2. What the script does
3838

@@ -46,7 +46,7 @@ For each subdirectory in `samples/`:
4646
- **`name`** — The directory name (e.g., `aspire-shop`)
4747
- **`title`** — Extracted from the first `# heading` in the README
4848
- **`description`** — The first paragraph of body text after the title (before any `##` heading)
49-
- **`href`** — Deep link to the sample on GitHub: `https://github.com/dotnet/aspire-samples/tree/main/samples/{name}`
49+
- **`href`** — Deep link to the sample on GitHub: `https://github.com/microsoft/aspire-samples/tree/main/samples/{name}`
5050
- **`readme`** — The full Markdown content of the README.md, with image paths rewritten to local assets (see below)
5151
- **`tags`** — Auto-detected tags based on technologies, languages, services, and features mentioned in the README and directory name
5252
- **`thumbnail`** — Local asset path to the first image referenced in the README (if any), or `null`
@@ -119,7 +119,7 @@ The output `samples.json` is a JSON array with entries like:
119119
"name": "aspire-shop",
120120
"title": "Aspire Shop",
121121
"description": "The app consists of four .NET services including a Blazor frontend, catalog API, catalog database manager, and basket service.",
122-
"href": "https://github.com/dotnet/aspire-samples/tree/main/samples/aspire-shop",
122+
"href": "https://github.com/microsoft/aspire-samples/tree/main/samples/aspire-shop",
123123
"readme": "# Aspire Shop\n\n![Screenshot...](~/assets/samples/aspire-shop/aspireshop-frontend-complete.png)...",
124124
"tags": ["csharp", "blazor", "postgresql", "redis", "grpc", "ef-core"],
125125
"thumbnail": "~/assets/samples/aspire-shop/aspireshop-frontend-complete.png"

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ test-results/
1919
# generated types
2020
.astro/
2121
.cache/
22-
2322
.netlify/
23+
tmp/
2424

2525
# Logs
2626
npm-debug.log*

src/frontend/config/redirects.mjs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,18 @@ export const redirects = {
7272
'/reference/cli/commands/aspire-mcp-start/': '/reference/cli/commands/aspire-agent-mcp/',
7373
'/reference/cli/commands/aspire-exec/': '/reference/cli/commands/aspire-resource/',
7474
'/get-started/configure-mcp/': '/get-started/ai-coding-agents/',
75+
'/get-started/first-app-csharp-apphost/': '/get-started/first-app/',
76+
'/get-started/first-app-typescript-apphost/': '/get-started/first-app/',
77+
'/get-started/deploy-first-app-csharp/': '/get-started/deploy-first-app/',
78+
'/get-started/deploy-first-app-typescript/': '/get-started/deploy-first-app/',
79+
'/get-started/add-aspire-existing-app-csharp-apphost/': '/get-started/add-aspire-existing-app/',
80+
'/get-started/add-aspire-existing-app-typescript-apphost/': '/get-started/add-aspire-existing-app/',
81+
'/ja/get-started/first-app-csharp-apphost/': '/ja/get-started/first-app/',
82+
'/ja/get-started/first-app-typescript-apphost/': '/ja/get-started/first-app/',
83+
'/ja/get-started/deploy-first-app-csharp/': '/ja/get-started/deploy-first-app/',
84+
'/ja/get-started/deploy-first-app-typescript/': '/ja/get-started/deploy-first-app/',
85+
'/ja/get-started/add-aspire-existing-app-csharp-apphost/': '/ja/get-started/add-aspire-existing-app/',
86+
'/ja/get-started/add-aspire-existing-app-typescript-apphost/': '/ja/get-started/add-aspire-existing-app/',
7587
'/get-started/pipelines/': '/deployment/pipelines/',
7688
'/ja/get-started/pipelines/': '/ja/deployment/pipelines/',
7789
'/deployment/manifest-format/': '/deployment/azure/manifest-format/',

0 commit comments

Comments
 (0)