diff --git a/src/frontend/src/content/docs/architecture/resource-api-patterns.mdx b/src/frontend/src/content/docs/architecture/resource-api-patterns.mdx
index f1cb1745d..5a71d18c7 100644
--- a/src/frontend/src/content/docs/architecture/resource-api-patterns.mdx
+++ b/src/frontend/src/content/docs/architecture/resource-api-patterns.mdx
@@ -3,7 +3,7 @@ title: Resource API Patterns
description: Discover common API resource patterns in Aspire, including how to add and configure resources, use annotations, and implement custom value objects.
---
-import { Aside, Steps } from '@astrojs/starlight/components';
+import { Aside, Steps, Tabs, TabItem } from '@astrojs/starlight/components';
Aspire's resource model allows you to define and configure resources in a structured way, enabling seamless integration and management of your application's components. This guide provides details the common patterns for adding and configuring resources in Aspire.
@@ -30,6 +30,9 @@ An `AddX(...)` method executes:
### Signature pattern
+
+
+
```csharp
public static IResourceBuilder AddX(
this IDistributedApplicationBuilder builder,
@@ -49,46 +52,150 @@ public static IResourceBuilder AddX(
}
```
+
+
+
+```typescript
+// Resources are added via async builder methods:
+const resource = await builder.addRedis("name" /*, optional params */);
+
+// The builder handles validation, instantiation,
+// and registration internally. Optional wiring:
+// .withEndpoint(...)
+// .withHealthCheck(...)
+// .withImage(...)
+// .withEnvironment(...)
+// .withArgs(...)
+// builder.addEventingSubscriber(...)
+```
+
+
+
+
### Optional wiring examples
**Endpoints**:
+
+
+
```csharp
.WithEndpoint(port: hostPort, targetPort: containerPort, name: endpointName)
```
+
+
+
+```typescript
+resource.withEndpoint({ port: hostPort, targetPort: containerPort, name: endpointName });
+```
+
+
+
+
**Health checks**:
+
+
+
```csharp
.WithHealthCheck(healthCheckKey)
```
+
+
+
+```typescript
+resource.withHealthCheck(healthCheckKey);
+```
+
+
+
+
**Container images / registries**:
+
+
+
```csharp
.WithImage(imageName, imageTag)
.WithImageRegistry(registryUrl)
```
+
+
+
+```typescript
+resource.withImage(imageName, imageTag);
+resource.withImageRegistry(registryUrl);
+```
+
+
+
+
**Entrypoint and args**:
+
+
+
```csharp
.WithEntrypoint("/bin/sh")
.WithArgs(context => { /* build args */ return Task.CompletedTask; })
```
+
+
+
+```typescript
+resource.withEntrypoint("/bin/sh");
+resource.withArgs(["--flag", "value"]);
+```
+
+
+
+
**Environment variables**:
+
+
+
```csharp
.WithEnvironment(context => new("ENV_VAR", valueProvider))
```
+
+
+
+```typescript
+resource.withEnvironment("ENV_VAR", value);
+```
+
+
+
+
**Event subscriptions**:
+
+
+
```csharp
builder.Eventing.Subscribe(resource, handler);
```
+
+
+
+```typescript
+builder.addEventingSubscriber(async (context) => {
+ context.onBeforeStart(async (event) => {
+ // Handle event
+ });
+});
+```
+
+
+
+
### Summary table
| Step | Call/Method | Purpose |
@@ -104,6 +211,9 @@ builder.Eventing.Subscribe(resource, handler);
### Signature pattern
+
+
+
```csharp
public static IResourceBuilder WithX(
this IResourceBuilder builder,
@@ -111,6 +221,16 @@ public static IResourceBuilder WithX(
builder.WithAnnotation(new FooAnnotation(options));
```
+
+
+
+:::note
+The TypeScript SDK doesn't expose `withAnnotation(...)` directly. Configuration methods like `withEndpoint(...)` and `withEnvironment(...)` handle annotation attachment internally.
+:::
+
+
+
+
- **Target**: `IResourceBuilder`.
- **Action**: `WithAnnotation(...)`.
- **Returns**: `IResourceBuilder`.
@@ -128,6 +248,9 @@ Annotations are **public** metadata types implementing `IResourceAnnotation`. Th
### Definition and attachment
+
+
+
```csharp
public sealed record PersistenceAnnotation(
TimeSpan? Interval,
@@ -138,6 +261,16 @@ builder.WithAnnotation(new PersistenceAnnotation(
100));
```
+
+
+
+:::note
+The TypeScript SDK doesn't expose annotations as a user-facing pattern. Resource metadata is managed internally by the SDK's configuration methods.
+:::
+
+
+
+
### Summary table
| Concept | Pattern | Notes |
@@ -165,11 +298,27 @@ Custom value objects defer evaluation and allow the framework to discover depend
### Attaching to resources
+
+
+
```csharp
builder.WithEnvironment(context =>
new("REDIS_CONNECTION_STRING", redis.GetConnectionStringAsync));
```
+
+
+
+```typescript
+resource.withEnvironment("REDIS_CONNECTION_STRING", redis);
+```
+
+
+
+
+
+
+
```csharp title="Example: BicepOutputReference"
public sealed partial class BicepOutputReference :
IManifestExpressionProvider,
@@ -182,6 +331,19 @@ public sealed partial class BicepOutputReference :
}
```
+
+
+
+:::note
+In the TypeScript SDK, `BicepOutputReference` and the value provider interfaces exist as read-only types. Users consume these types (e.g., via `resource.getOutput("name")`) but don't implement custom value objects.
+:::
+
+
+
+
+
+
+
```csharp
public static IResourceBuilder WithEnvironment(
this IResourceBuilder builder,
@@ -194,6 +356,16 @@ public static IResourceBuilder WithEnvironment(
}
```
+
+
+
+:::note
+In the TypeScript SDK, `withEnvironment()` handles value binding directly without requiring custom annotation types.
+:::
+
+
+
+
### Summary table
| Concept | Pattern | Purpose |
diff --git a/src/frontend/src/content/docs/dashboard/security-considerations.mdx b/src/frontend/src/content/docs/dashboard/security-considerations.mdx
index 46e9937b5..626b798f2 100644
--- a/src/frontend/src/content/docs/dashboard/security-considerations.mdx
+++ b/src/frontend/src/content/docs/dashboard/security-considerations.mdx
@@ -3,6 +3,7 @@ title: Aspire dashboard security considerations
description: Security considerations for running the Aspire dashboard
---
+import { Tabs, TabItem } from '@astrojs/starlight/components';
import OsAwareTabs from '@components/OsAwareTabs.astro';
The [Aspire dashboard](/dashboard/overview/) offers powerful insights to your apps. The dashboard displays information about resources, including their configuration, console logs and in-depth telemetry.
@@ -82,14 +83,67 @@ The preceding Docker command:
- Configures the OTLP endpoint to use `ApiKey` authentication. This requires that incoming telemetry has a valid `x-otlp-api-key` header value.
- Configures the expected API key. `{MY_APIKEY}` in the example value should be replaced with a real API key. The API key can be any text, but a value with at least 128 bits of entropy is recommended.
-When API key authentication is configured, the dashboard validates incoming telemetry has a required API key. Apps that send the dashboard telemetry must be configured to send the API key. This can be configured in .NET with `OtlpExporterOptions.Headers`:
+When API key authentication is configured, the dashboard validates incoming telemetry has a required API key. Apps that send the dashboard telemetry must be configured to send the API key. The following examples show how to configure the API key header in each language:
-```csharp
+
+
+
+Configure the header using `OtlpExporterOptions.Headers`:
+
+```csharp title="C# — Program.cs"
builder.Services.Configure(
o => o.Headers = $"x-otlp-api-key={MY_APIKEY}");
```
-Other languages have different OpenTelemetry APIs. Passing the [`OTEL_EXPORTER_OTLP_HEADERS` environment variable](https://opentelemetry.io/docs/specs/otel/protocol/exporter/) to apps is a universal way to configure the header.
+
+
+
+Set the `OTEL_EXPORTER_OTLP_HEADERS` environment variable, or configure the header on the OTLP exporter directly:
+
+```go title="Go — main.go"
+import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
+
+client := otlptracegrpc.NewClient(
+ otlptracegrpc.WithHeaders(map[string]string{
+ "x-otlp-api-key": apiKey,
+ }),
+)
+```
+
+
+
+
+Set the `OTEL_EXPORTER_OTLP_HEADERS` environment variable, or configure the header in code:
+
+```python title="Python — app.py"
+from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
+ OTLPSpanExporter,
+)
+
+exporter = OTLPSpanExporter(
+ headers={"x-otlp-api-key": api_key},
+)
+```
+
+
+
+
+Set the `OTEL_EXPORTER_OTLP_HEADERS` environment variable, or configure the header in code:
+
+```typescript title="TypeScript — tracing.ts"
+import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
+
+const exporter = new OTLPTraceExporter({
+ headers: {
+ 'x-otlp-api-key': apiKey,
+ },
+});
+```
+
+
+
+
+Passing the [`OTEL_EXPORTER_OTLP_HEADERS` environment variable](https://opentelemetry.io/docs/specs/otel/protocol/exporter/) to apps is a universal way to configure the header across all languages.
### Telemetry API endpoint
diff --git a/src/frontend/src/content/docs/extensibility/interaction-service.mdx b/src/frontend/src/content/docs/extensibility/interaction-service.mdx
index 37e53fba8..af1100f08 100644
--- a/src/frontend/src/content/docs/extensibility/interaction-service.mdx
+++ b/src/frontend/src/content/docs/extensibility/interaction-service.mdx
@@ -19,6 +19,10 @@ The interaction service (`Aspire.Hosting.IInteractionService`) allows you to pro
This is useful for scenarios where you need to gather information from the user or provide feedback on the status of operations, regardless of how the application is being launched or deployed.
+
+
## The `IInteractionService` API
The `IInteractionService` interface is retrieved from the `DistributedApplication` dependency injection container. `IInteractionService` can be injected into types created from DI or resolved from `IServiceProvider`, which is usually available on a context argument passed to events.
diff --git a/src/frontend/src/content/docs/fundamentals/external-parameters.mdx b/src/frontend/src/content/docs/fundamentals/external-parameters.mdx
index 3ea783d04..e829177d4 100644
--- a/src/frontend/src/content/docs/fundamentals/external-parameters.mdx
+++ b/src/frontend/src/content/docs/fundamentals/external-parameters.mdx
@@ -3,7 +3,7 @@ title: External parameters
description: Learn how to express parameters such as secrets, connection strings, and other configuration values that might vary between environments.
---
-import { Aside, Steps } from '@astrojs/starlight/components';
+import { Aside, Steps, Tabs, TabItem } from '@astrojs/starlight/components';
import { Image } from 'astro:assets';
import dashboardUnresolvedParams from '@assets/fundamentals/dashboard-unresolved-parameters-message.png';
import customizedParameterUi from '@assets/fundamentals/customized-parameter-ui.png';
@@ -16,6 +16,9 @@ Parameter values are read from the `Parameters` section of the AppHost's configu
Consider the following example AppHost _AppHost.cs_ file:
+
+
+
```csharp title="AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);
@@ -26,6 +29,26 @@ builder.AddProject("api")
.WithEnvironment("ENVIRONMENT_VARIABLE_NAME", parameter);
```
+
+
+
+```typescript title="TypeScript — apphost.ts" twoslash
+import { createBuilder } from './.modules/aspire.js';
+
+const builder = await createBuilder();
+
+// Add a parameter named "example-parameter-name"
+const parameter = await builder.addParameter("example-parameter-name");
+
+await builder.addProject("api", "./ApiService/ApiService.csproj")
+ .withEnvironment("ENVIRONMENT_VARIABLE_NAME", parameter);
+
+await builder.build().run();
+```
+
+
+
+
The preceding code adds a parameter named `example-parameter-name` to the AppHost. The parameter is then passed to the `Projects.ApiService` project as an environment variable named `ENVIRONMENT_VARIABLE_NAME`.
### Configure parameter values
@@ -44,6 +67,9 @@ Consider the following AppHost configuration file _appsettings.json_:
The preceding JSON configures a parameter in the `Parameters` section of the AppHost configuration. In other words, that AppHost is able to find the parameter as it's configured. For example, you could walk up to the `IDistributedApplicationBuilder.Configuration` and access the value using the `Parameters:example-parameter-name` key:
+
+
+
```csharp
var builder = DistributedApplication.CreateBuilder(args);
@@ -51,6 +77,21 @@ var key = $"Parameters:example-parameter-name";
var value = builder.Configuration[key]; // value = "local-value"
```
+
+
+
+```typescript title="TypeScript — apphost.ts" twoslash
+import { createBuilder } from './.modules/aspire.js';
+
+const builder = await createBuilder();
+
+const key = "Parameters:example-parameter-name";
+// Configuration access is handled internally by the Aspire runtime
+```
+
+
+
+
-
-