diff --git a/src/frontend/src/assets/whats-new/aspire-13.3/notification-center-bell.png b/src/frontend/src/assets/whats-new/aspire-13.3/notification-center-bell.png new file mode 100644 index 000000000..589fb6d19 Binary files /dev/null and b/src/frontend/src/assets/whats-new/aspire-13.3/notification-center-bell.png differ diff --git a/src/frontend/src/assets/whats-new/aspire-13.3/notification-center-open.png b/src/frontend/src/assets/whats-new/aspire-13.3/notification-center-open.png new file mode 100644 index 000000000..d1e384e29 Binary files /dev/null and b/src/frontend/src/assets/whats-new/aspire-13.3/notification-center-open.png differ diff --git a/src/frontend/src/content/docs/whats-new/aspire-13-3.mdx b/src/frontend/src/content/docs/whats-new/aspire-13-3.mdx index 65785496f..b2828ed42 100644 --- a/src/frontend/src/content/docs/whats-new/aspire-13-3.mdx +++ b/src/frontend/src/content/docs/whats-new/aspire-13-3.mdx @@ -1,6 +1,6 @@ --- title: What's new in Aspire 13.3 -description: Aspire 13.3 introduces Azure Network Security Perimeter support, enables the container tunnel by default, and more. +description: Aspire 13.3 brings the new aspire destroy command, browser console log and screenshot capture in the dashboard, end-to-end Helm-based Kubernetes deployment via aspire deploy, JavaScript publishing for Next.js/Vite/SSR frameworks, the container tunnel enabled by default, deeper TypeScript AppHost parity, and a refreshed Azure integration suite. sidebar: label: Aspire 13.3 order: 0 @@ -9,39 +9,884 @@ tableOfContents: maxHeadingLevel: 2 --- -import { Steps, Aside } from '@astrojs/starlight/components'; -import LearnMore from '@components/LearnMore.astro'; +import { Steps, Aside, Icon, Tabs, TabItem } from '@astrojs/starlight/components'; import { Image } from 'astro:assets'; +import LearnMore from '@components/LearnMore.astro'; +import OsAwareTabs from '@components/OsAwareTabs.astro'; import azureFrontDoorIcon from '@assets/icons/azure-front-door-icon.png'; +import notificationCenterBell from '@assets/whats-new/aspire-13.3/notification-center-bell.png'; +import notificationCenterOpen from '@assets/whats-new/aspire-13.3/notification-center-open.png'; + +Aspire 13.3 is here, and it's a packed release — leading with a brand-new **`aspire destroy`** command for tearing down deployments, **browser console logs, network requests, and screenshots** captured into the Aspire dashboard alongside server-side telemetry, end-to-end **`aspire deploy` to Kubernetes** with a Helm-based engine and Ingress / Gateway API routing, first-class **JavaScript publishing** for Next.js, Vite, and SSR frameworks, the **container tunnel** enabled by default across Docker Desktop, Docker Engine, and Podman, and deeper **TypeScript AppHost** parity with C#. + +We'd love to hear what you think. Drop by [ Discord](https://aka.ms/aspire-discord) to chat with the team and the community, or file feedback and issues on [ GitHub](https://github.com/microsoft/aspire/issues). -Welcome to Aspire 13.3! Whether you're a long-time Aspire user or just getting started, we're excited for you to try what's new. If you have questions, feedback, or run into issues, come say hi on [Discord](https://aka.ms/aspire-discord) or open an issue on [GitHub](https://github.com/dotnet/aspire/issues). +This release introduces: + +- A new **`aspire destroy`** command that tears down provisioned resources across Azure, Kubernetes, and Compose, plus the **`aspire dashboard`** CLI for running the dashboard standalone. The Aspire CLI is also now available as a `dotnet tool`. +- **Browser logs and screenshots** — the new `Aspire.Hosting.Browsers` integration captures frontend console logs, network requests, and screenshots and surfaces them in the dashboard next to server-side telemetry. +- **`aspire deploy` to Kubernetes** (preview) — declare an `AddKubernetesEnvironment` and Aspire generates a Helm chart and runs an end-to-end deployment pipeline. New **Ingress** and **Gateway API routing** resources describe traffic at the AppHost level. +- **JavaScript publish methods** (preview) — a unified `PublishAs*` family for static SPAs, SSR Node servers, and npm-script-based deployments, plus the new `AddNextJsApp` helper and first-class support for Bun, Yarn, and pnpm. +- The **container tunnel** is enabled by default, providing uniform host connectivity across Docker Desktop, Docker Engine, and Podman. +- Major **TypeScript AppHost** parity work that closes most of the remaining gap with C# AppHosts. +- **`aspire init`** (preview) — bootstrap an AppHost into an existing repository with the new `aspireify` agent skill. +- **Azure Front Door**, **Network Security Perimeter**, and **Azure Kubernetes Service (AKS)** hosting integrations, plus **Foundry Prompt Agent** support. +- …and much more. ## 🆙 Upgrade to Aspire 13.3
+ + + + For general purpose upgrade guidance, see [Upgrade Aspire](/whats-new/upgrade-aspire/). -The easiest way to upgrade to Aspire 13.3 is using the `aspire update` command: +The easiest way to upgrade to Aspire 13.3 is using the [`aspire update` command](/reference/cli/commands/aspire-update/): -1. Update the Aspire CLI: +1. Update the Aspire CLI itself: - ```bash - aspire update + ```bash title="Aspire CLI — Update the CLI" + aspire update --self ``` -1. Update your projects: +1. Update your projects (run from the root of your repository): - ```bash - aspire update project + ```bash title="Aspire CLI — Update all Aspire packages" + aspire update ``` -## Azure Front Door integration +Or install the CLI from scratch: + + + + + ```bash title="Aspire CLI — Install Aspire CLI" + curl -sSL https://aspire.dev/install.sh | bash + ``` + + + + + ```powershell title="Aspire CLI — Install Aspire CLI" + irm https://aspire.dev/install.ps1 | iex + ``` + + + + + + For more details on installing the Aspire CLI, see [Install the + CLI](/get-started/install-cli/). + + +## 🛠️ CLI enhancements + +### Aspire CLI as a NativeAOT dotnet tool + +Aspire 13.3 publishes the Aspire CLI as a **NativeAOT .NET global tool**. The CLI has always shipped as a `dotnet tool`, but in 13.3 it takes advantage of new .NET 10 support for distributing NativeAOT-compiled tools — meaning instant startup with no JIT or runtime warmup, and no managed runtime dependency in the tool package. If you already have .NET 10 installed, you can install the CLI without using the curl/PowerShell installer: + +```bash title="Bash — Install via dotnet tool" +dotnet tool install -g Aspire.Cli +``` + + + For more details, see [Install the Aspire CLI](/get-started/install-cli/). + + +### `aspire dashboard` for the standalone dashboard + +The new `aspire dashboard` command runs the Aspire Dashboard in standalone mode (without an AppHost), making it easy to consume telemetry from any OTLP-emitting application — your own services, third-party tools, or apps running outside the Aspire app model. + +Previously, the only way to run the dashboard outside an AppHost was to pull the [standalone container image](/dashboard/standalone/) and configure ports, certificates, and the OTLP endpoint by hand. With `aspire dashboard run`, the CLI handles all of that for you using the same dashboard binary that ships with the SDK — no Docker or container runtime required. + +```bash title="Aspire CLI — Run the standalone dashboard" +aspire dashboard run +``` + +```text frame="terminal" title="Output" + Dashboard: http://localhost:18888/login?t=a360442eeb99c38fe60954dc4f045acc + + OTLP/gRPC: http://localhost:4317 + + OTLP/HTTP: http://localhost:4318 + + Logs: ~/.aspire/logs/cli_20260506T065505_02e43b93.log +``` + +The command is interactive and blocking — it stays in the foreground while the dashboard is running. Open the **Dashboard** URL in your browser, then point any OTLP-compatible application at the **OTLP/gRPC** or **OTLP/HTTP** endpoint, and your logs, traces, and metrics show up live. The container image is still available for environments where running the CLI isn't an option. + + + Command reference: [`aspire dashboard`](/reference/cli/commands/aspire-dashboard/) and [Standalone dashboard](/dashboard/standalone/). + + +### `aspire docs api` — API reference search from the CLI + +Search and read the Aspire API reference directly from the terminal: + +```bash title="Aspire CLI — Search and view API docs" +aspire docs api list +aspire docs api search "AddAzureFrontDoor" +aspire docs api get Aspire.Hosting.AzureFrontDoorBuilderExtensions +``` + + + Command references: [`aspire docs api list`](/reference/cli/commands/aspire-docs-api-list/), [`aspire docs api search`](/reference/cli/commands/aspire-docs-api-search/), and [`aspire docs api get`](/reference/cli/commands/aspire-docs-api-get/). + + +### Connect the CLI to a standalone dashboard + +The `aspire otel logs` and `aspire otel traces` commands now accept `--dashboard-url` and `--api-key` options, so you can query telemetry from a [standalone dashboard](/dashboard/standalone/) without launching an AppHost. Start the dashboard with `aspire dashboard run`, then point the CLI at it: + +```bash title="Aspire CLI — Query a standalone dashboard" +# Stream structured logs from a standalone dashboard +aspire otel logs --dashboard-url https://localhost:18888 --api-key $ASPIRE_DASHBOARD_KEY -f + +# Search recent traces in a standalone dashboard +aspire otel traces --dashboard-url https://localhost:18888 --api-key $ASPIRE_DASHBOARD_KEY +``` + +`--dashboard-url` accepts either the dashboard's base URL or a login URL — login URLs are normalized automatically. + +### `aspire init` installs the `aspireify` agent skill + + + +`aspire init` now drops a minimal AppHost skeleton and an `aspire.config.json` file into an existing repository, and installs the **aspireify** agent skill alongside it. `aspire init` itself does not wire up resources, projects, or integrations — you complete the wiring by invoking the `aspireify` skill from your AI agent of choice (GitHub Copilot CLI, Claude Code, etc.). + + + +### Hidden resources are filtered by default + +`aspire ps`, `aspire describe`, and other CLI commands now hide resources that are marked as hidden in the AppHost (such as proxies, helper containers, and migrations). Use `--include-hidden` to include them. + +### `aspire do` improvements + +- **`--list-steps`** prints the list of pipeline steps that would run for `aspire do`, `aspire publish`, `aspire deploy`, or `aspire destroy` without actually executing them. +- **`check-container-runtime`** is a built-in pipeline step that fails fast when no container runtime is available, preventing late-stage build/publish failures. +- **Publish summary** now shows a hierarchical, timeline-style view of pipeline execution. +- **Independent steps continue on sibling failure** — a single failed step no longer blocks unrelated work in the same pipeline run. + +### CLI quality-of-life + +- **AppHost path guardrails** — the CLI's global config now validates AppHost paths to prevent accidentally pointing at the wrong project. +- **Container runtime health check** runs before `aspire deploy` to catch missing/broken Docker or Podman setups early. +- **`aspire ps`** displays the dashboard URL alongside running AppHosts. +- **Non-interactive CLI mode** has been improved with the new `PromptBinding` that surfaces required values up front. + +### Improved AI agent init + +`aspire agent init` gained a **location selection** step and now installs a refreshed standard skill set: + +- The **`aspire` skill** orchestrates Aspire apps via the CLI — starting and stopping the AppHost, inspecting resources, viewing logs and telemetry, and adding integrations. +- The **`aspireify` skill** completes the one-time AppHost wiring after `aspire init` drops a skeleton into an existing repository. +- Pair these with `playwright-cli` and `dotnet-inspect` for browser testing and .NET API discovery. + +Pick which skills to install with `--skills aspire,aspireify,...` or run `aspire agent init` interactively. + +## 🚢 Deployment improvements + +### New `aspire destroy` command + +`aspire destroy` is the inverse of `aspire deploy` — it tears down what `aspire deploy` provisioned, using the same compute environments declared in your AppHost. That means a single command works across every deployment target: + +- **Azure** — provisioned resources are deleted via Azure Resource Manager. +- **Kubernetes** — Helm releases and namespaces created during deploy are uninstalled. +- **Docker Compose** — published Compose stacks are stopped and removed. + +This is especially useful for CI environments, ephemeral preview deployments, and dev sandboxes where you want to reclaim resources cleanly without hand-tracking what was deployed. + +```bash title="Aspire CLI — Tear down a deployment" +aspire destroy +``` + + + Command reference: [`aspire destroy`](/reference/cli/commands/aspire-destroy/). + + +## 🐳 Container, Kubernetes, and Compose + +### 🔗 Container tunnel enabled by default + +Aspire 13.3 enables the **Aspire container tunnel** by default, providing uniform container-to-host connectivity regardless of your container orchestrator. + +Previously introduced as an opt-in experimental feature in Aspire 13.0, the container tunnel allows containers to reliably communicate with host-based services (such as the Aspire dashboard, OTEL collector, and other projects). Before this change, Docker Desktop users benefited from built-in host connectivity (`host.docker.internal`), while other container runtimes such as Docker Engine on Linux or Podman required manual workarounds. + +With the tunnel enabled by default, all supported container orchestrators now behave consistently without any additional configuration. + + + +#### Disabling the container tunnel + +If you need to opt out, set the `ASPIRE_ENABLE_CONTAINER_TUNNEL` environment variable to `false` before starting your AppHost: + + + + + ```bash title="Bash — Disable container tunnel" + # Set the env var only for this aspire run invocation, then start the AppHost. + ASPIRE_ENABLE_CONTAINER_TUNNEL=false aspire run + ``` + + + + + ```powershell title="PowerShell — Disable container tunnel" + # Set the env var only for this aspire run invocation, then start the AppHost. + $env:ASPIRE_ENABLE_CONTAINER_TUNNEL = "false"; aspire run + ``` + + + + +You can also disable it in `launchSettings.json` by adding the variable to your existing AppHost launch profile: + +```json title="launchSettings.json" +{ + "profiles": { + "https": { + "commandName": "Project", + "environmentVariables": { + "ASPIRE_ENABLE_CONTAINER_TUNNEL": "false" + } + } + } +} +``` + + + For more details on container networking, see [Inner-loop networking overview](/fundamentals/networking-overview/). + + +### Kubernetes deployment with Helm engine + + + +Aspire 13.3 ships a Helm-based Kubernetes deployment engine. Declare a Kubernetes environment in your AppHost, run `aspire deploy`, and Aspire generates a complete Helm chart and applies it end-to-end against your cluster — no separate `helm install`, `kustomize`, or hand-rolled manifests required. `aspire destroy` removes the Helm release and namespace cleanly. + + + + +```csharp title="C# — AppHost.cs" +// Declare a Kubernetes environment. Aspire generates a Helm chart for it. +var k8s = builder.AddKubernetesEnvironment("k8s"); + +// Bind a project to the Kubernetes environment so it deploys there. +builder.AddProject("api") + .WithComputeEnvironment(k8s); +``` + + + + +```typescript title="TypeScript — apphost.ts" +import { createBuilder } from './.modules/aspire.js'; + +const builder = await createBuilder(); + +// Declare a Kubernetes environment. Aspire generates a Helm chart for it. +const k8s = await builder.addKubernetesEnvironment('k8s'); + +// Bind a project to the Kubernetes environment so it deploys there. +const api = await builder.addProject('api', '../Api/Api.csproj'); +await api.withComputeEnvironment(k8s); + +await builder.build().run(); +``` + + + + + + For more details, see [Deploy to Kubernetes](/deployment/kubernetes/kubernetes/). + + +### Kubernetes Ingress and Gateway API routing + +New first-class **Ingress** and **Gateway API** routing resources let you declare how traffic enters your Kubernetes cluster directly from the AppHost. Aspire generates the corresponding Ingress, IngressClass, Gateway, HTTPRoute, and (where applicable) cert-manager `Certificate` resources. + + + + +```csharp title="C# — Ingress with cert-manager" +// Declare a Kubernetes environment. +var k8s = builder.AddKubernetesEnvironment("k8s"); + +// Project that will be served behind the ingress. +var api = builder.AddProject("api") + .WithComputeEnvironment(k8s); + +// Add an ingress fronted by the nginx ingress class with a TLS cert. +var ingress = k8s.AddIngress("public") + .WithIngressClass("nginx") + .WithHostname("api.example.com") + .WithTls("api-cert"); + +// Route requests at "/" to the project's HTTP endpoint. +ingress.WithRoute("/", api.GetEndpoint("http")); +``` + + + + +```typescript title="TypeScript — Ingress with cert-manager" +import { createBuilder } from './.modules/aspire.js'; + +const builder = await createBuilder(); + +// Declare a Kubernetes environment. +const k8s = await builder.addKubernetesEnvironment('k8s'); + +// Add an ingress with a TLS cert. +const ingress = await k8s.addIngress('public'); +await ingress.withHostname('api.example.com'); +await ingress.withTls('api-cert'); + +await builder.build().run(); +``` + + + + + + For more details, see [Kubernetes Ingress routing](/deployment/kubernetes-ingress/) and [AKS Gateway API routing](/deployment/kubernetes-gateway-aks/). + + +### Podman support for Docker Compose + +The Docker Compose deployment engine now supports **Podman** as a container runtime out of the box, with no manual workarounds needed. Aspire detects Podman, generates Compose files compatible with `podman-compose`, and exposes the same lifecycle commands you'd use with Docker. + +### Privileged mode for Docker Compose publishing + +You can now publish containers with the `privileged` flag enabled when targeting Docker Compose, which is required by some workloads (e.g., low-level networking utilities, nested containers). + + + + +```csharp title="C# — Privileged Docker Compose service" +// Add a netshoot diagnostics container and publish it to Docker Compose +// with privileged mode enabled (required for low-level network tooling). +builder.AddContainer("netshoot", "nicolaka/netshoot") + .PublishAsDockerComposeService((resource, service) => + { + service.Privileged = true; + }); +``` + + + + +```typescript title="TypeScript — Privileged Docker Compose service" +import { createBuilder } from './.modules/aspire.js'; + +const builder = await createBuilder(); + +// Add a netshoot diagnostics container and publish it to Docker Compose +// with privileged mode enabled (required for low-level network tooling). +await builder + .addContainer('netshoot', 'nicolaka/netshoot') + .publishAsDockerComposeService(async (resource, service) => { + await service.privileged.set(true); + }); + +await builder.build().run(); +``` + + + + +### Dockerfile builder APIs for TypeScript AppHosts + +TypeScript AppHosts can now build Dockerfiles programmatically with `WithDockerfileBuilder` / `AddDockerfileBuilder`, mirroring the C# `WithDockerfile` extension. Diagnostic [`ASPIREDOCKERFILEBUILDER001`](/diagnostics/aspiredockerfilebuilder001/) covers the experimental warning. + + + For more details, see [Customize Dockerfile builds](/app-host/withdockerfile/). + + +## 🧩 App model and AppHost + +### HTTP command result mode + +`HttpCommand` now supports a **result mode** that returns the response body to the dashboard's notification center, so HTTP-triggered commands can return structured payloads instead of just success/failure: + + + + +```csharp title="C# — HTTP command with result body" +// Expose POST /admin/sync as a dashboard command. ResultMode = Auto sends the +// HTTP response body back to the dashboard's notification center. +builder.AddProject("api") + .WithHttpCommand("/admin/sync", "Sync now", commandOptions: new() + { + ResultMode = HttpCommandResultMode.Auto + }); +``` + + + + +```typescript title="TypeScript — HTTP command with result body" +import { createBuilder } from './.modules/aspire.js'; + +const builder = await createBuilder(); + +// Expose POST /admin/sync as a dashboard command. resultMode "Auto" sends +// the HTTP response body back to the dashboard's notification center. +const api = await builder.addProject('api', '../Api/Api.csproj'); +await api.withHttpCommand('/admin/sync', 'Sync now', { resultMode: 'Auto' }); + +await builder.build().run(); +``` + + + + +`HttpCommandResultMode` accepts `None`, `Auto` (infer from the response content type), `Json`, or `Text`. + + + For more details, see [HTTP commands](/fundamentals/http-commands/). + + +### Resource commands return structured results + +Custom resource commands can now return an `ExecuteCommandResult` with a structured `Message` payload that the dashboard renders in the notification center. The new `Logger` property on `ExecuteCommandContext` lets command implementations log directly to the resource's log stream. + + + + +```csharp title="C# — Issue an access token from a resource command" +using System.Security.Cryptography; +using Aspire.Hosting.ApplicationModel; + +builder.AddProject("myservice") + .WithCommand( + name: "issue-access-token", + displayName: "Issue Access Token", + executeCommand: context => + { + var token = Convert.ToBase64String(RandomNumberGenerator.GetBytes(32)); + + return Task.FromResult(CommandResults.Success( + message: "Access token issued.", + result: token, + resultFormat: CommandResultFormat.Text)); + }); +``` + + + + +```typescript title="TypeScript — Issue an access token from a resource command" +import { + createBuilder, + CommandResultFormat, + type ExecuteCommandContext, + type ExecuteCommandResult, +} from './.modules/aspire.js'; + +const builder = await createBuilder(); + +await builder + .addNodeApp('myservice', './myservice', 'src/server.ts') + .withCommand('issue-access-token', 'Issue Access Token', + async (_context: ExecuteCommandContext): Promise => { + const token = crypto.randomUUID().replace(/-/g, ''); + + return { + success: true, + message: 'Access token issued.', + data: { + value: token, + format: CommandResultFormat.Text, + }, + }; + }); + +await builder.build().run(); +``` + + + + +The dashboard surfaces a **View response** action on the success toast, and the CLI splits status messages to `stderr` and the payload to `stdout` so it's safe to pipe (`aspire resource myservice issue-access-token | pbcopy`). + + + For more details, see [Custom resource commands](/fundamentals/custom-resource-commands/). + + +### BeforeStart pipeline steps + +A new **BeforeStart** pipeline phase replaces the bespoke eventing-subscriber classes used by the Kubernetes, Docker Compose, and AKS deployment engines. Authors of compute environments can now add ordered startup logic via standard pipeline steps rather than custom subscribers. + +### Subscribe extensions for lifecycle events + +Two new convenience extension methods on `IDistributedApplicationBuilder` make it easier to wire up lifecycle event handlers without `.Eventing.Subscribe(...)` plumbing: + + + + +```csharp title="C# — Subscribe to lifecycle events" +// Run a callback right before the AppHost begins starting resources. +builder.SubscribeBeforeStart(async e => { /* ... */ }); +// Run a callback once all resources have been created. +builder.SubscribeAfterResourcesCreated(async e => { /* ... */ }); +``` + + + + +```typescript title="TypeScript — Subscribe to lifecycle events" +import { createBuilder } from './.modules/aspire.js'; + +const builder = await createBuilder(); + +// Run a callback right before the AppHost begins starting resources. +await builder.subscribeBeforeStart(async (e) => { /* ... */ }); +// Run a callback once all resources have been created. +await builder.subscribeAfterResourcesCreated(async (e) => { /* ... */ }); + +await builder.build().run(); +``` + + + + +Thanks to community contributor [@afscrome](https://github.com/afscrome) for this addition. + + + For more details, see [Eventing](/app-host/eventing/). + + +### `WithEndpoint` updates existing endpoints + +`WithEndpoint` no longer throws when an endpoint of the same name already exists. Calling it a second time updates the existing endpoint instead — making it easier to layer endpoint configuration across extension methods. + +### Exclude management endpoints from `WithReference()` + +Endpoint annotations now have an `ExcludeReferenceEndpoint` flag. Setting it to `true` excludes the endpoint (e.g. management or health endpoints) from the default `WithReference()` injection, so consumers don't accidentally receive admin URLs: + + + + +```csharp title="C# — Exclude an endpoint from WithReference" +// Mark the "admin" endpoint so it isn't injected into consumers via WithReference(). +builder.AddProject("api") + .WithEndpoint("admin", e => e.ExcludeReferenceEndpoint = true); +``` + + + + +```typescript title="TypeScript — Exclude an endpoint from withReference" +import { createBuilder } from './.modules/aspire.js'; + +const builder = await createBuilder(); + +// Mark the "admin" endpoint so it isn't injected into consumers via withReference(). +const api = await builder.addProject('api', '../Api/Api.csproj'); +await api.withEndpoint('admin', { excludeReferenceEndpoint: true }); + +await builder.build().run(); +``` + + + + +### `ASPIRE_ENVIRONMENT` variable + +The AppHost now honors a top-level `ASPIRE_ENVIRONMENT` environment variable that selects an environment-specific configuration profile, controlling which `appsettings.{environment}.json` is loaded and which environment is reported in dashboard telemetry. + +### Aspire trusted developer certificate used everywhere + +The Aspire trusted developer certificate is now used in more places — including the Microsoft Developer Control Plane (DCP) on Windows, where it replaces the ephemeral certificate DCP previously generated. Set `ASPIRE_DCP_USE_DEVELOPER_CERTIFICATE` to opt out if needed. + +## 🌐 TypeScript AppHost parity + +Aspire 13.3 closes most of the remaining functional gap between C# AppHosts and the TypeScript AppHost SDK: + +- **Unified `withEnvironment` API** so all SDKs configure environment variables the same way. +- **Endpoint property expressions** (`endpoint.url`, `endpoint.host`, `endpoint.port`) are now usable inside TypeScript AppHost expressions. +- **Docker Compose API parity**: `PublishAsDockerComposeService`-equivalent hooks and post-processing are exposed in TypeScript. +- **Custom domain configuration** for Azure Container Apps is now exposed in the TypeScript AppHost SDK. +- **Unified YARP TS route helpers** — `addRoute(...)` and `addCatchAllRoute(...)` replace several earlier ad-hoc helpers. +- **`WithAdminDeploymentScriptSubnet`** is now exported for TypeScript AppHosts. +- **Image push options**, **endpoint mutation callbacks**, **`ConfigureEnvFile`**, and **builder pipeline** APIs all reach TypeScript parity. +- **Predefined value catalogs** — the new `[AspireValue]` attribute and predefined catalogs (e.g., `FoundryModels.OpenAI.Gpt41Mini`) make it easier to reference well-known values from TypeScript AppHosts. +- **Build-time duplicate capability ID detection** — diagnostic [`ASPIREEXPORT013`](/diagnostics/aspireexport013/) catches duplicate exported capability IDs at compile time. + + + For more details, see [Authoring multi-language integrations](/extensibility/multi-language-integration-authoring/). + + +## 🟨 JavaScript and TypeScript apps + +Aspire 13.3 brings first-class **JavaScript publishing** to both C# and TypeScript AppHosts. A new family of `PublishAs*` extension methods replaces hand-rolled `Dockerfile` plumbing for the most common JS deployment shapes: + +- **`PublishAsStaticWebsite`** (preview) — publishes a JS app as a static website served by a YARP image, with optional API reverse-proxy to a backend resource. Ideal for SPAs (Vite, plain Next.js export). +- **`PublishAsNodeServer`** — publishes a self-contained Node entry-point (e.g., `server.js`) without copying `node_modules` at runtime. Ideal for pre-bundled Node servers. +- **`PublishAsNpmScript`** — publishes a Node app that runs an npm script (`start`/`serve`) at runtime, copying `package.json` and production dependencies. Ideal for full Nitro Next.js, Remix, and Astro SSR. + +Aspire 13.3 also adds **`AddNextJsApp`** as a first-class Next.js helper alongside the existing `AddViteApp` and `AddNodeApp`, plus first-class support for **Bun, Yarn, and pnpm** in TypeScript AppHosts (npm remains the default). + + + +### Next.js + +`AddNextJsApp` runs Next.js in development and automatically configures Next.js *standalone* publishing — no explicit `PublishAs*` call is needed. Make sure your `next.config.js` sets `output: "standalone"` so the build emits the standalone server. + + + + +```csharp title="C# — AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +builder.AddNextJsApp("web", "./web"); + +builder.Build().Run(); +``` + + + + +```typescript title="TypeScript — apphost.ts" +import { createBuilder } from './.modules/aspire.js'; + +const builder = await createBuilder(); + +await builder.addNextJsApp('web', './web'); + +await builder.build().run(); +``` + + + + +### Vite + +`AddViteApp` runs Vite in development; `PublishAsStaticWebsite` ships the production build as a YARP-served static site, with an optional API reverse-proxy to a backend resource so the same `/api` path works in dev and production. + + + + +```csharp title="C# — AppHost.cs" +#pragma warning disable ASPIREEXTENSION001 +var builder = DistributedApplication.CreateBuilder(args); + +var api = builder.AddProject("api"); + +builder.AddViteApp("web", "./web") + .WithReference(api) + .PublishAsStaticWebsite(apiPath: "/api", apiTarget: api); + +builder.Build().Run(); +#pragma warning restore ASPIREEXTENSION001 +``` + + + + +```typescript title="TypeScript — apphost.ts" +import { createBuilder } from './.modules/aspire.js'; + +const builder = await createBuilder(); + +const api = await builder.addProject('api', '../Api/Api.csproj'); + +await builder + .addViteApp('web', './web') + .withReference(api) + .publishAsStaticWebsite({ apiPath: '/api', apiTarget: api }); + +await builder.build().run(); +``` + + + + +### TanStack Start (SSR) + +For SSR frameworks like [TanStack Start](https://tanstack.com/start) and SvelteKit that bundle to a Node entry-point, pair `AddViteApp` (for development) with `PublishAsNodeServer` to ship the built `.output/server/index.mjs` as a slim runtime container without copying `node_modules`. + + + + +```csharp title="C# — AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +builder.AddViteApp("web", "./web") + .PublishAsNodeServer(entryPoint: ".output/server/index.mjs", + outputPath: ".output"); + +builder.Build().Run(); +``` + + + + +```typescript title="TypeScript — apphost.ts" +import { createBuilder } from './.modules/aspire.js'; + +const builder = await createBuilder(); + +await builder + .addViteApp('web', './web') + .publishAsNodeServer('.output/server/index.mjs', { + outputPath: '.output', + }); + +await builder.build().run(); +``` + + + + + + + + For more details, see [JavaScript/TypeScript apps](/integrations/frameworks/javascript/), [Publish JavaScript apps](/deployment/javascript-apps/), and [TypeScript AppHosts](/app-host/typescript-apphost/). + + +## 📊 Dashboard improvements + +### Notification center for command results + +The dashboard now has a **notification center** that surfaces results of resource commands and lifecycle events without requiring you to scrape the logs panel. Commands return [structured results](#resource-commands-return-structured-results) which the dashboard renders inline. + +The notification center is accessible via the bell icon in the top-right corner of the header. When there are unread notifications, a badge with the unread count appears on the icon. + +The Aspire dashboard showing a notification bell icon with a badge in the top-right corner + +Selecting the bell icon opens the **Notifications** dialog, which lists all notifications. From here you can view command responses. + +The Aspire dashboard notification panel open, showing a 'Rebuild succeeded' notification with a View response button + +### Telemetry API enabled by default + +The dashboard's telemetry API is now **enabled by default**, with an automatic token exchange between the CLI/extension and the dashboard. AI tools and other consumers can subscribe to live telemetry without any extra configuration. + + + +### AI features disabled by default + +The dashboard's AI features are **disabled by default** in 13.3 (`Dashboard:AI:Disabled` defaults to `true`). The dashboard's AI surface is being phased out in favor of the Aspire CLI and the `aspire` agent skill, which provide a richer terminal-based and editor-integrated experience. Future releases will remove these dashboard features entirely. + +### Open dashboard in VS Code Simple Browser + +When you launch your Aspire app from VS Code, the dashboard now opens in **VS Code's Simple Browser** by default rather than spawning an external browser window. The behavior is controlled by the `aspire.dashboardBrowser` setting. + +## 🧰 VS Code extension + +- **AppHost CodeLens and gutter decorations** — the extension renders inline run/stop affordances and resource state right in the editor. +- **Auto-restore** — set `aspire.enableAutoRestore` to have the extension automatically run `aspire restore` when a workspace opens or its config changes. +- **Launch config** entries can now specify `env` and `args` for the AppHost, just like a regular .NET launch config. +- **Open AppHost source** from the *Running AppHosts* view. +- **Open Aspire Dashboard** from the VS Code Command Palette. +- **Right-click context menus** on resource endpoint URLs (open, copy, etc.). +- The walkthrough has been updated to cover TypeScript AppHosts. +- The extension auto-detects the Aspire CLI in default install paths even when it isn't on `PATH`. + + + For more details, see [Aspire VS Code extension](/get-started/aspire-vscode-extension/). + + +## 📦 Integration updates + +### 🔍 Browser logs and screenshots + +The new **Aspire.Hosting.Browsers** integration captures browser console logs, network requests, and screenshots from your frontend resources during development, surfacing them in the dashboard alongside server-side telemetry. Add `WithBrowserLogs()` to any frontend resource to enable it. + + + + +```csharp title="C# — AppHost.cs" +// Capture browser console logs, network requests, and screenshots from +// this Vite frontend; they show up in the dashboard alongside server telemetry. +builder.AddViteApp("frontend") + .WithBrowserLogs(); +``` + + + + +```typescript title="TypeScript — apphost.ts" +import { createBuilder } from './.modules/aspire.js'; + +const builder = await createBuilder(); + +// Capture browser console logs, network requests, and screenshots from +// this Vite frontend; they show up in the dashboard alongside server telemetry. +const frontend = await builder.addViteApp('frontend', './frontend'); +await frontend.withBrowserLogs(); + +await builder.build().run(); +``` + + + + + + + + For more details, see [Browser logs](/integrations/devtools/browser-logs/). + + +### Durable Task Scheduler for Azure Functions + +Azure Functions can now declare a **Durable Task Scheduler** dependency directly from the AppHost, with full local and Azure-deployed support. The APIs are released as experimental under [`ASPIREDURABLETASK001`](/diagnostics/aspiredurabletask001/). + + + For more details, see [Azure Functions hosting](/integrations/cloud/azure/azure-functions/azure-functions-host/). + + +### RabbitMQ v7 with publisher and subscriber tracing + +The RabbitMQ client integration has been updated to support RabbitMQ.Client v7, with OpenTelemetry tracing for both publishers and subscribers. + +### `Aspire.Microsoft.Azure.StackExchangeRedis` is stable + +The [📦 Aspire.Microsoft.Azure.StackExchangeRedis](https://www.nuget.org/packages/Aspire.Microsoft.Azure.StackExchangeRedis) package is no longer in preview. Use it for entra-authenticated Azure Cache for Redis and Azure Managed Redis access. + +### Npgsql metrics align with .NET 10 + +The Npgsql client integration emits OpenTelemetry metrics that align with the .NET 10 metric naming specification. + +## ☁️ Azure improvements + +### Azure Front Door integration — global edge in one API call -Aspire 13.3 adds a new hosting integration for [Azure Front Door](https://learn.microsoft.com/azure/frontdoor/), Microsoft's global edge network for fast, secure, and highly available web apps. Add a Front Door profile in front of your backends with `AddAzureFrontDoor` and attach origins with `WithOrigin`: +You no longer need to stitch together ARM templates or click through portal blades to get a CDN in front of your app. Aspire 13.3 adds a new hosting integration for [Azure Front Door](https://learn.microsoft.com/azure/frontdoor/), Microsoft's global edge network for fast, secure, and highly available web apps. Add a Front Door profile in front of your backends with `AddAzureFrontDoor` and attach origins with `WithOrigin`: + + + ```csharp title="C# — AppHost.cs" +// Two backend projects exposed as external HTTP endpoints. var api = builder.AddProject("api") .WithExternalHttpEndpoints(); var web = builder.AddProject("web") .WithExternalHttpEndpoints(); +// Provision an Azure Front Door profile and attach each backend as an origin. +// Each WithOrigin call creates its own endpoint, origin group, origin, and route. builder.AddAzureFrontDoor("frontdoor") .WithOrigin(api) .WithOrigin(web); ``` -Each `WithOrigin` call provisions its own Front Door endpoint, origin group, origin, and route, so every backend is independently routable through its own `*.azurefd.net` hostname. The integration provisions Front Door in the Standard SKU by default; use `ConfigureInfrastructure` to customize the Front Door, for example to change SKUs, attach a Web Application Firewall (WAF) policy, enable caching, and more. + + + +```typescript title="TypeScript — apphost.ts" +import { createBuilder } from './.modules/aspire.js'; + +const builder = await createBuilder(); + +// Two backend projects exposed as external HTTP endpoints. +const api = await builder.addProject('api', '../Api/Api.csproj'); +await api.withExternalHttpEndpoints(); + +const web = await builder.addProject('web', '../Web/Web.csproj'); +await web.withExternalHttpEndpoints(); + +// Provision an Azure Front Door profile and attach each backend as an origin. +// Each withOrigin call creates its own endpoint, origin group, origin, and route. +const frontDoor = await builder.addAzureFrontDoor('frontdoor'); +await frontDoor.withOrigin(api); +await frontDoor.withOrigin(web); + +await builder.build().run(); +``` + + + + +Each `withOrigin` call provisions its own Front Door endpoint, origin group, origin, and route,so every backend is independently routable through its own `*.azurefd.net` hostname. The integration provisions Front Door in the Standard SKU by default; use `ConfigureInfrastructure` to customize the Front Door, for example to change SKUs, attach a Web Application Firewall (WAF) policy, enable caching, and more. For more details, see [Azure Front Door integration](/integrations/cloud/azure/azure-front-door/). -## 🌐 Azure Network Security Perimeter support +### 🌐 Azure Network Security Perimeter support Aspire 13.3 adds support for [Azure Network Security Perimeters (NSPs)](https://learn.microsoft.com/azure/private-link/network-security-perimeter-concepts), which provide a logical security boundary for Azure PaaS services. NSPs complement the existing virtual network and private endpoint support by operating at the PaaS layer — grouping resources like Storage, Key Vault, Cosmos DB, and SQL so they can communicate with each other while restricting public access via access rules. -### Create a perimeter and associate resources +#### Create a perimeter and associate resources + + + ```csharp title="C# — AppHost.cs" +// Declare a Network Security Perimeter and add an inbound access rule. var nsp = builder.AddNetworkSecurityPerimeter("my-nsp") .WithAccessRule(new AzureNspAccessRule { @@ -87,57 +969,137 @@ var nsp = builder.AddNetworkSecurityPerimeter("my-nsp") AddressPrefixes = { "203.0.113.0/24" } }); +// Associate Azure resources with the perimeter — they remain reachable from each +// other but become subject to the perimeter's access rules for outside traffic. var storage = builder.AddAzureStorage("storage") .WithNetworkSecurityPerimeter(nsp); var keyVault = builder.AddAzureKeyVault("kv") .WithNetworkSecurityPerimeter(nsp); ``` + + + +```typescript title="TypeScript — apphost.ts" +import { createBuilder } from './.modules/aspire.js'; +import { NetworkSecurityPerimeterAccessRuleDirection } from './.modules/aspire.js'; + +const builder = await createBuilder(); + +// Declare a Network Security Perimeter and add an inbound access rule. +const nsp = await builder.addNetworkSecurityPerimeter('my-nsp'); +await nsp.withAccessRule({ + name: 'allow-my-ip', + direction: NetworkSecurityPerimeterAccessRuleDirection.Inbound, + addressPrefixes: ['203.0.113.0/24'], +}); + +// Associate Azure resources with the perimeter — they remain reachable from each +// other but become subject to the perimeter's access rules for outside traffic. +const storage = await builder.addAzureStorage('storage'); +await storage.withNetworkSecurityPerimeter(nsp); +const keyVault = await builder.addAzureKeyVault('kv'); +await keyVault.withNetworkSecurityPerimeter(nsp); + +await builder.build().run(); +``` + + + + NSPs support **Enforced** mode (blocks traffic that violates the rules) and **Learning** mode (logs violations without blocking), making it easy to audit traffic before locking down access. For more details, see [Azure Virtual Network integration](/integrations/cloud/azure/azure-virtual-network/#add-a-network-security-perimeter). -## 🔗 Container tunnel enabled by default +### Azure Kubernetes Service (AKS) hosting integration — Kubernetes without the YAML -Aspire 13.3 enables the **Aspire container tunnel** by default, providing uniform container-to-host connectivity regardless of your container orchestrator. + -Previously introduced as an opt-in experimental feature in Aspire 13.0, the container tunnel allows containers to reliably communicate with host-based services (such as the Aspire dashboard, OTEL collector, and other projects). Before this change, Docker Desktop users benefited from built-in host connectivity (`host.docker.internal`), while other container runtimes such as Docker Engine on Linux or Podman required manual workarounds. +If you've ever wanted to deploy to Kubernetes but dreaded writing manifests by hand, this one's for you. Aspire 13.3 adds first-class support for **provisioning and deploying to Azure Kubernetes Service**. Use `AddAzureKubernetesEnvironment` to declare an AKS environment, customize node pools, and have your AppHost generate a Bicep + Helm-based deployment pipeline — all type-safe, all from code. -With the tunnel enabled by default, all supported container orchestrators now behave consistently without any additional configuration. + + - +```csharp title="C# — AppHost.cs" +// Declare an AKS environment and customize its system node pool. +var aks = builder.AddAzureKubernetesEnvironment("aks") + .WithSystemNodePool("Standard_D2s_v5", minCount: 1, maxCount: 3); -### Disabling the container tunnel +// Bind a project to the AKS environment so it deploys there. +builder.AddProject("api") + .WithComputeEnvironment(aks); +``` -If you need to opt out, set the `ASPIRE_ENABLE_CONTAINER_TUNNEL` environment variable to `false` before starting your AppHost: + + + +```typescript title="TypeScript — apphost.ts" +import { createBuilder } from './.modules/aspire.js'; + +const builder = await createBuilder(); + +// Declare an AKS environment and customize its system node pool. +const aks = await builder.addAzureKubernetesEnvironment('aks'); +await aks.withSystemNodePool('Standard_D2s_v5', { minCount: 1, maxCount: 3 }); -```bash title="Shell — Disable container tunnel" -ASPIRE_ENABLE_CONTAINER_TUNNEL=false aspire run +// Bind a project to the AKS environment so it deploys there. +const api = await builder.addProject('api', '../Api/Api.csproj'); +await api.withComputeEnvironment(aks); + +await builder.build().run(); ``` -You can also disable it in `launchSettings.json`: + + -```json title="launchSettings.json" +`WithSystemNodePool` lets you customize the system node pool's VM size and autoscaling bounds. By default the AKS cluster uses the **Free** control-plane SKU; the `AksSkuTier` enum is no longer part of the public API. + + + For more details, see [Azure Kubernetes Service integration](/integrations/cloud/azure/aks/) and [Deploy an Aspire app to AKS](/deployment/kubernetes/aks/). + + +### Private endpoint support for Azure Container Registry, OpenAI, and Foundry + +`WithPrivateEndpoint` is now supported on additional Azure resources, allowing you to provision and connect to Azure Container Registry, Azure OpenAI, and Azure AI Foundry resources over a virtual network without exposing them publicly. + +### Azure AI Foundry Prompt Agent + +Aspire 13.3 ships a new working implementation of **Azure AI Foundry Prompt Agent** support via `AddPromptAgent`. The previous `AddAndPublishPromptAgent` API and the original shape of `AzurePromptAgentResource` (which never functioned end-to-end) have been replaced — `AddPromptAgent` now returns a working `AzurePromptAgentResource`. + +The Foundry model catalog also gained two new models: **GPT-5.4** and **Qwen3 VL**. + + + For more details, see [Azure AI Foundry integration](/integrations/cloud/azure/azure-ai-foundry/). + + +### Automatic HTTPS upgrade for Azure App Service + +Endpoints deployed to Azure App Service environments are now automatically upgraded to HTTPS, eliminating the need to manually configure HTTP-to-HTTPS redirects in your services. + +### Configurable Azure credential process timeout + +The new `Azure:CredentialProcessTimeoutSeconds` configuration value lets you tune the timeout for Azure credential acquisition during deployments — useful for environments where authentication round-trips can take longer than the default. + +```json title="appsettings.json" { - "profiles": { - "MyApp.AppHost": { - "environmentVariables": { - "ASPIRE_ENABLE_CONTAINER_TUNNEL": "false" - } - } + "Azure": { + "CredentialProcessTimeoutSeconds": 60 } } ``` - - For more details on container networking, see [Inner-loop networking overview](/fundamentals/networking-overview/). - +### Azure deployment quality-of-life + +- Deployment summaries now include **clickable links to the Azure Portal** for resources that were just provisioned. +- Multi-environment deployments now **enforce explicit compute environment binding**: every resource must specify which environment it deploys to, preventing accidental cross-environment leakage. + +## 🏗️ Templates -## 🐍 Python starter template migrated to TypeScript AppHost +### 🐍 Python starter migrated to TypeScript AppHost The `aspire-py-starter` template (Starter App with FastAPI and React) has moved from the `dotnet new` template system to the Aspire CLI template system and now uses a **TypeScript AppHost** instead of a C# AppHost. This aligns it with the same pattern as the `aspire-ts-starter` template. @@ -163,3 +1125,45 @@ aspire new aspire-py-starter --use-redis-cache true For details on the `aspire new` command and all available templates, see [aspire new command](/reference/cli/commands/aspire-new/). + +## 🐛 Bug fixes and full changelog + +For the complete list of bug fixes and smaller changes in this release, see the [Aspire 13.3 release notes on GitHub](https://github.com/microsoft/aspire/releases/tag/v13.3.0). + +## 🙏 Community contributions + +Aspire is built in the open, and this release wouldn't be what it is without you. A huge thank you to all community contributors who helped make Aspire 13.3 possible — including [@afscrome](https://github.com/afscrome) for the lifecycle Subscribe extension methods, [@spboyer](https://github.com/spboyer) for documentation and template polish, [@holystix04](https://github.com/holystix04), and [@tranhoangtu-it](https://github.com/tranhoangtu-it). We're always excited to [see community contributions](/community/contributors/)! If you'd like to get involved, check out our [contributing guide](/community/contributor-guide/). + +## ⚠️ Breaking changes + +| Change | Migration | +|---|---| +| `--log-level` renamed to `--pipeline-log-level` on `aspire publish` and `aspire deploy` | Update scripts/CI to use `--pipeline-log-level`. | +| `package.json` `engines.node` is no longer used to select Node images for generated Dockerfiles | Specify the Node version explicitly via `WithDockerfile` or your project's Dockerfile base image. | +| `NameOutput` renamed to `NameOutputReference` in Azure Network resources | Replace any usage of `*.NameOutput` with `*.NameOutputReference`. | +| `OtlpEndpointEnvironmentVariableName` property removed | Remove references; the OTLP endpoint env var is now managed automatically. | +| **Dashboard MCP server removed** (along with `ASPIRE_DASHBOARD_MCP_ENDPOINT_URL`) | Use the AppHost-level MCP server with `aspire agent init`. | +| `AksSkuTier` enum is no longer part of the public AKS API | The AKS control-plane SKU tier now defaults to **Free**; remove any references to `AksSkuTier`. | +| `ASPIREEXTENSION001` JavaScript diagnostic ID renamed | Use [`ASPIREJAVASCRIPT001`](/diagnostics/aspirejavascript001/). | +| Docker Swarm `UpdateConfig` property types changed | Update generated/hand-written Compose overrides accordingly. | +| The non-functional `AddAndPublishPromptAgent` API and the original `AzurePromptAgentResource` shape were removed | Use the new `AddPromptAgent` API (which returns a working `AzurePromptAgentResource`). | +| CLI telemetry JSON output schema aligned with the MCP tool format | Update any consumers of `--format json` from telemetry-related CLI commands. | +| `aspire init` no longer fully wires up your AppHost on its own | Run the `aspireify` agent skill (e.g. via Copilot CLI) to complete wiring after `aspire init`. | +| Kubernetes Ingress and Gateway routing types moved namespaces | Update `using` directives if you reference them directly. | +| `dotnet new aspire-py-starter` removed | Use `aspire new aspire-py-starter` from the Aspire CLI. | + +### Migration from Aspire 13.2 to 13.3 + + + +1. **Update the CLI** — run `aspire update --self`. +2. **Update your projects** — run `aspire update` from the root of your repository. +3. **Audit `--log-level` usage** in CI/CD pipelines and rename to `--pipeline-log-level`. +4. **Search for `NameOutput`, `AddAndPublishPromptAgent`, and `AksSkuTier`** in your AppHost code and update them per the table above. +5. **Replace `dotnet new aspire-py-starter`** with `aspire new aspire-py-starter` for any new Python starter projects. +6. **Rerun `aspire agent init`** if you previously relied on the dashboard MCP server. +7. **Re-pin Node versions** in your Dockerfiles if you were relying on `package.json` `engines.node` for image selection. + + + +**Go build something amazing.** We'd love to hear about your experience with Aspire 13.3 — share what you're building on [GitHub](https://github.com/microsoft/aspire/issues) or come hang out with us on [Discord](https://aka.ms/aspire-discord).