diff --git a/src/frontend/config/sidebar/integrations.topics.ts b/src/frontend/config/sidebar/integrations.topics.ts
index 9003ee9e4..2c8ec07c0 100644
--- a/src/frontend/config/sidebar/integrations.topics.ts
+++ b/src/frontend/config/sidebar/integrations.topics.ts
@@ -1386,7 +1386,10 @@ export const integrationTopics: StarlightSidebarTopicsUserConfig = {
{ label: 'Bun', slug: 'integrations/frameworks/bun-apps' },
{ label: 'Deno', slug: 'integrations/frameworks/deno-apps' },
{ label: 'JavaScript', slug: 'integrations/frameworks/javascript' },
- { label: 'Node.js extensions', slug: 'integrations/frameworks/nodejs-extensions' },
+ {
+ label: 'JavaScript monorepo extensions',
+ slug: 'integrations/frameworks/nodejs-extensions',
+ },
],
},
{ label: 'Perl', slug: 'integrations/frameworks/perl' },
diff --git a/src/frontend/src/content/docs/deployment/javascript-apps.mdx b/src/frontend/src/content/docs/deployment/javascript-apps.mdx
index a016d9bea..70446c878 100644
--- a/src/frontend/src/content/docs/deployment/javascript-apps.mdx
+++ b/src/frontend/src/content/docs/deployment/javascript-apps.mdx
@@ -1315,4 +1315,4 @@ Using the implicit default `runScriptName` (`"dev"`) without any custom argument
- [Deploy your first Aspire app](/get-started/deploy-first-app/)
- [JavaScript integration](/integrations/frameworks/javascript/)
- [Publishing and deployment overview](/deployment/deploy-with-aspire/)
-- [Node.js hosting extensions](/integrations/frameworks/nodejs-extensions/)
+- [JavaScript monorepo hosting extensions](/integrations/frameworks/nodejs-extensions/)
diff --git a/src/frontend/src/content/docs/integrations/caching/redis-extensions.mdx b/src/frontend/src/content/docs/integrations/caching/redis-extensions.mdx
index aaecdfc97..63ab629f7 100644
--- a/src/frontend/src/content/docs/integrations/caching/redis-extensions.mdx
+++ b/src/frontend/src/content/docs/integrations/caching/redis-extensions.mdx
@@ -16,6 +16,7 @@ import redisIcon from '@assets/icons/redis-icon.png';
alt="Redis logo"
width={100}
height={100}
+ fit="contain"
class:list={'float-inline-left icon'}
data-zoom-off
/>
@@ -25,6 +26,7 @@ The Aspire Community Toolkit Redis hosting extensions package provides extra fun
This package provides the following features:
- [DbGate](https://dbgate.org/) management UI
+- dbx management UI
## Hosting integration
@@ -59,7 +61,7 @@ This updates your `aspire.config.json` with the Redis extensions package:
### DbGate management UI
-To add the DbGate management UI to your Redis resource, call the `WithDbGate` method on the `RedisResource` instance:
+To add the DbGate management UI, decorate the official Redis resource with `WithDbGate` / `withDbGate`:
@@ -68,31 +70,32 @@ To add the DbGate management UI to your Redis resource, call the `WithDbGate` me
var builder = DistributedApplication.CreateBuilder(args);
var redis = builder.AddRedis("redis")
- .WithDbGate();
+ .WithDbGate();
-builder.AddProject()
- .WithReference(redis);
+builder.AddProject("example-project")
+ .WithReference(redis);
-// After adding all resources, run the app...
+builder.Build().Run();
```
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const redis = await builder.addRedis("redis");
+const redis = await builder.addRedis('redis');
await redis.withDbGate();
const exampleProject = await builder.addProject(
- "example-project",
- "../ExampleProject/ExampleProject.csproj");
+ 'example-project',
+ '../ExampleProject/ExampleProject.csproj'
+);
await exampleProject.withReference(redis);
-// After adding all resources, run the app...
+await builder.build().run();
```
@@ -100,6 +103,44 @@ await exampleProject.withReference(redis);
This adds a new DbGate resource to the app host which is available from the Aspire dashboard. DbGate is a comprehensive database management tool that provides a web-based interface for managing your Redis databases.
+### dbx management UI
+
+[dbx](https://github.com/t8y2/dbx) is a lightweight, web-based database client and an alternative management UI to DbGate and Adminer. Decorate the Redis resource with `WithDbx` / `withDbx` to add it:
+
+
+
+
+```csharp title="AppHost.cs"
+var builder = DistributedApplication.CreateBuilder(args);
+
+var redis = builder.AddRedis("redis")
+ .WithDbx();
+
+builder.Build().Run();
+```
+
+
+
+
+```typescript title="apphost.mts"
+import { createBuilder } from './.aspire/modules/aspire.mjs';
+
+const builder = await createBuilder();
+
+const redis = await builder.addRedis('redis');
+await redis.withDbx({
+ containerName: 'redis-dbx',
+ imageTag: '0.5.33',
+});
+
+await builder.build().run();
+```
+
+
+
+
+The C# overload accepts an optional container configuration callback and `containerName`. The TypeScript binding accepts optional `containerName` and `imageTag` values.
+
## See also
- [DbGate documentation](https://dbgate.org/)
diff --git a/src/frontend/src/content/docs/integrations/databases/mongodb/mongodb-extensions.mdx b/src/frontend/src/content/docs/integrations/databases/mongodb/mongodb-extensions.mdx
index ec3ab32ef..f7dec1a9d 100644
--- a/src/frontend/src/content/docs/integrations/databases/mongodb/mongodb-extensions.mdx
+++ b/src/frontend/src/content/docs/integrations/databases/mongodb/mongodb-extensions.mdx
@@ -1,6 +1,6 @@
---
title: Use community extensions for MongoDB hosting
-description: Extend the functionality of your MongoDB hosting with the Aspire Community Toolkit, including the DbGate management UI.
+description: Decorate official Aspire MongoDB resources with Community Toolkit DbGate and dbx management interfaces for local development.
---
import { Badge, Tabs, TabItem } from '@astrojs/starlight/components';
@@ -15,6 +15,7 @@ import mongodbIcon from '@assets/icons/mongodb-icon.png';
alt="MongoDB logo"
width={100}
height={100}
+ fit="contain"
class:list={'float-inline-left icon'}
data-zoom-off
/>
@@ -24,6 +25,7 @@ The Aspire Community Toolkit MongoDB hosting extensions package provides extra f
This package provides the following features:
- [DbGate](https://dbgate.org/) management UI
+- dbx management UI
## Hosting integration
@@ -45,7 +47,7 @@ For TypeScript AppHosts, add the Community Toolkit MongoDB extensions package to
### DbGate management UI
-To add the [DbGate](https://dbgate.org/) management UI to your MongoDB resource, call the `WithDbGate` method on the `MongoDBResourceBuilder` instance:
+To add the [DbGate](https://dbgate.org/) management UI, decorate the official `MongoDBServerResource` builder with `WithDbGate` / `withDbGate`:
@@ -66,14 +68,14 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const mongodb = await builder.addMongoDB("mongodb");
+const mongodb = await builder.addMongoDB('mongodb');
await mongodb.withDbGate();
-const api = await builder.addProject("api", "../Api/Api.csproj");
+const api = await builder.addProject('api', '../Api/Api.csproj');
await api.withReference(mongodb);
await builder.build().run();
@@ -84,6 +86,44 @@ await builder.build().run();
This adds a new DbGate resource to the AppHost which is available from the Aspire dashboard. DbGate is a comprehensive database management tool that provides a web-based interface for managing your MongoDB databases.
+### dbx management UI
+
+[dbx](https://github.com/t8y2/dbx) is a lightweight, web-based database client and an alternative management UI to DbGate and Adminer. Use `WithDbx` / `withDbx` to add a dbx child resource configured for the MongoDB server:
+
+
+
+
+```csharp title="AppHost.cs"
+var builder = DistributedApplication.CreateBuilder(args);
+
+var mongodb = builder.AddMongoDB("mongodb")
+ .WithDbx();
+
+builder.Build().Run();
+```
+
+
+
+
+```typescript title="apphost.mts"
+import { createBuilder } from './.aspire/modules/aspire.mjs';
+
+const builder = await createBuilder();
+
+const mongodb = await builder.addMongoDB('mongodb');
+await mongodb.withDbx({
+ containerName: 'mongodb-dbx',
+ imageTag: '0.5.33',
+});
+
+await builder.build().run();
+```
+
+
+
+
+The C# overload accepts an optional container configuration callback and `containerName`. The TypeScript binding accepts optional `containerName` and `imageTag` values.
+
## See also
- [DbGate documentation](https://dbgate.org/)
diff --git a/src/frontend/src/content/docs/integrations/databases/mysql/mysql-extensions.mdx b/src/frontend/src/content/docs/integrations/databases/mysql/mysql-extensions.mdx
index 53e41e896..6e82fc84c 100644
--- a/src/frontend/src/content/docs/integrations/databases/mysql/mysql-extensions.mdx
+++ b/src/frontend/src/content/docs/integrations/databases/mysql/mysql-extensions.mdx
@@ -1,6 +1,6 @@
---
title: Use community extensions for MySQL hosting
-description: Extend the functionality of your MySQL hosting with the Aspire Community Toolkit, including management UIs like Adminer and DbGate.
+description: Decorate official Aspire MySQL resources with Community Toolkit Adminer, DbGate, and dbx management interfaces.
---
import { Badge, Tabs, TabItem } from '@astrojs/starlight/components';
@@ -15,6 +15,7 @@ import mysqlIcon from '@assets/icons/mysqlconnector-icon.png';
alt="MySQL logo"
width={100}
height={100}
+ fit="contain"
class:list={'float-inline-left icon'}
data-zoom-off
/>
@@ -25,6 +26,7 @@ This package provides the following features:
- [Adminer](https://adminer.org/) management UI
- [DbGate](https://dbgate.org/) management UI
+- dbx management UI
## Hosting integration
@@ -46,7 +48,7 @@ For TypeScript AppHosts, add the Community Toolkit MySQL extensions package to `
### DbGate management UI
-To add the [DbGate](https://dbgate.org/) management UI to your MySQL resource, call the `WithDbGate` method on the `MySqlServerResourceBuilder` instance:
+To add the [DbGate](https://dbgate.org/) management UI, decorate the official `MySqlServerResource` builder with `WithDbGate` / `withDbGate`:
@@ -67,14 +69,14 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const mysql = await builder.addMySql("mysql");
+const mysql = await builder.addMySql('mysql');
await mysql.withDbGate();
-const api = await builder.addProject("api", "../Api/Api.csproj");
+const api = await builder.addProject('api', '../Api/Api.csproj');
await api.withReference(mysql);
await builder.build().run();
@@ -87,7 +89,7 @@ This adds a new DbGate resource to the AppHost which is available from the Aspir
### Adminer management UI
-To add the [Adminer](https://adminer.org/) management UI to your MySQL resource, call the `WithAdminer` method on the `MySqlServerResourceBuilder` instance:
+To add the [Adminer](https://adminer.org/) management UI, decorate the official `MySqlServerResource` builder with `WithAdminer` / `withAdminer`:
@@ -108,14 +110,14 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const mysql = await builder.addMySql("mysql");
+const mysql = await builder.addMySql('mysql');
await mysql.withAdminer();
-const api = await builder.addProject("api", "../Api/Api.csproj");
+const api = await builder.addProject('api', '../Api/Api.csproj');
await api.withReference(mysql);
await builder.build().run();
@@ -150,15 +152,15 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const mysql = await builder.addMySql("mysql");
+const mysql = await builder.addMySql('mysql');
await mysql.withDbGate();
await mysql.withAdminer();
-const api = await builder.addProject("api", "../Api/Api.csproj");
+const api = await builder.addProject('api', '../Api/Api.csproj');
await api.withReference(mysql);
await builder.build().run();
@@ -167,6 +169,44 @@ await builder.build().run();
+### dbx management UI
+
+[dbx](https://github.com/t8y2/dbx) is a lightweight, web-based database client and an alternative management UI to DbGate and Adminer. Use `WithDbx` / `withDbx` to add a dbx child resource configured for the MySQL server:
+
+
+
+
+```csharp title="AppHost.cs"
+var builder = DistributedApplication.CreateBuilder(args);
+
+var mysql = builder.AddMySql("mysql")
+ .WithDbx();
+
+builder.Build().Run();
+```
+
+
+
+
+```typescript title="apphost.mts"
+import { createBuilder } from './.aspire/modules/aspire.mjs';
+
+const builder = await createBuilder();
+
+const mysql = await builder.addMySql('mysql');
+await mysql.withDbx({
+ containerName: 'mysql-dbx',
+ imageTag: '0.5.33',
+});
+
+await builder.build().run();
+```
+
+
+
+
+The C# overload accepts an optional container configuration callback and `containerName`. The TypeScript binding accepts optional `containerName` and `imageTag` values.
+
## See also
- [Adminer documentation](https://www.adminer.org/)
diff --git a/src/frontend/src/content/docs/integrations/databases/postgres/postgresql-extensions.mdx b/src/frontend/src/content/docs/integrations/databases/postgres/postgresql-extensions.mdx
index 3fd9013e3..6f2e802f8 100644
--- a/src/frontend/src/content/docs/integrations/databases/postgres/postgresql-extensions.mdx
+++ b/src/frontend/src/content/docs/integrations/databases/postgres/postgresql-extensions.mdx
@@ -1,6 +1,6 @@
---
title: Use community extensions for PostgreSQL hosting
-description: Extend the functionality of your PostgreSQL hosting with community-built extensions, including management UIs like Adminer and DbGate.
+description: Decorate official Aspire PostgreSQL resources with Community Toolkit management interfaces and Flyway migration commands.
---
import { Badge, Tabs, TabItem } from '@astrojs/starlight/components';
@@ -15,6 +15,7 @@ import postgresqlIcon from '@assets/icons/postgresql-icon.png';
alt="PostgreSQL logo"
width={100}
height={100}
+ fit="contain"
class:list={'float-inline-left icon'}
data-zoom-off
/>
@@ -25,6 +26,8 @@ This package provides the following features:
- [Adminer](https://adminer.org/) management UI
- [DbGate](https://dbgate.org/) management UI
+- dbx management UI
+- [Flyway](https://documentation.red-gate.com/fd) migration and repair commands
## Hosting integration
@@ -46,7 +49,7 @@ For TypeScript AppHosts, add the Community Toolkit PostgreSQL extensions package
### DbGate management UI
-To add the DbGate management UI to your PostgreSQL resource, call the `WithDbGate` method on the `PostgresServerResource` instance:
+To add the DbGate management UI, decorate the official `PostgresServerResource` builder with `WithDbGate` / `withDbGate`:
@@ -67,16 +70,17 @@ builder.AddProject()
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const postgres = await builder.addPostgres("postgres");
+const postgres = await builder.addPostgres('postgres');
await postgres.withDbGate();
const exampleProject = await builder.addProject(
- "example-project",
- "../ExampleProject/ExampleProject.csproj");
+ 'example-project',
+ '../ExampleProject/ExampleProject.csproj'
+);
await exampleProject.withReference(postgres);
// After adding all resources, run the app...
@@ -89,7 +93,7 @@ This adds a new DbGate resource to the app host which is available from the Aspi
### Adminer management UI
-To add the Adminer management UI to your PostgreSQL resource, call the `WithAdminer` method on the `PostgresServerResource` instance:
+To add the Adminer management UI, decorate the official `PostgresServerResource` builder with `WithAdminer` / `withAdminer`:
@@ -110,16 +114,17 @@ builder.AddProject()
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const postgres = await builder.addPostgres("postgres");
+const postgres = await builder.addPostgres('postgres');
await postgres.withAdminer();
const exampleProject = await builder.addProject(
- "example-project",
- "../ExampleProject/ExampleProject.csproj");
+ 'example-project',
+ '../ExampleProject/ExampleProject.csproj'
+);
await exampleProject.withReference(postgres);
// After adding all resources, run the app...
@@ -154,17 +159,18 @@ builder.AddProject()
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const postgres = await builder.addPostgres("postgres");
+const postgres = await builder.addPostgres('postgres');
await postgres.withDbGate();
await postgres.withAdminer();
const exampleProject = await builder.addProject(
- "example-project",
- "../ExampleProject/ExampleProject.csproj");
+ 'example-project',
+ '../ExampleProject/ExampleProject.csproj'
+);
await exampleProject.withReference(postgres);
// After adding all resources, run the app...
@@ -173,10 +179,104 @@ await exampleProject.withReference(postgres);
+### dbx management UI
+
+[dbx](https://github.com/t8y2/dbx) is a lightweight, web-based database client and an alternative management UI to DbGate and Adminer. Use `WithDbx` / `withDbx` to add a dbx child resource configured for the PostgreSQL server:
+
+
+
+
+```csharp title="AppHost.cs"
+var builder = DistributedApplication.CreateBuilder(args);
+
+var postgres = builder.AddPostgres("postgres")
+ .WithDbx();
+
+builder.Build().Run();
+```
+
+
+
+
+```typescript title="apphost.mts"
+import { createBuilder } from './.aspire/modules/aspire.mjs';
+
+const builder = await createBuilder();
+
+const postgres = await builder.addPostgres('postgres');
+await postgres.withDbx({
+ containerName: 'postgres-dbx',
+ imageTag: '0.5.33',
+});
+
+await builder.build().run();
+```
+
+
+
+
+The C# overload accepts an optional container configuration callback and `containerName`. The TypeScript binding accepts optional `containerName` and `imageTag` values.
+
+## Run Flyway commands
+
+Flyway decorators apply to an official `PostgresDatabaseResource`, not the PostgreSQL server resource.
+
+### Run migrations
+
+In C#, add a Flyway resource and pass it to `WithFlywayMigration`. In TypeScript, `withFlywayMigration` creates the Flyway resource from its name and migration scripts path.
+
+Place versioned SQL files such as `V1__init.sql` in `./migrations`; Flyway discovers them by its versioned migration naming convention.
+
+
+
+
+```csharp title="AppHost.cs"
+var builder = DistributedApplication.CreateBuilder(args);
+
+var migrations = builder.AddFlyway("migrations", "./migrations");
+var postgres = builder.AddPostgres("postgres");
+var database = postgres.AddDatabase("appdb")
+ .WithFlywayMigration(migrations);
+
+migrations.WaitFor(database);
+
+var api = builder.AddProject("api")
+ .WithReference(database)
+ .WaitFor(database)
+ .WaitForCompletion(migrations);
+
+builder.Build().Run();
+```
+
+
+
+
+```typescript title="apphost.mts"
+import { createBuilder } from './.aspire/modules/aspire.mjs';
+
+const builder = await createBuilder();
+
+const postgres = await builder.addPostgres('postgres');
+const database = await postgres.addDatabase('appdb');
+await database.withFlywayMigration('flyway-migration', './migrations');
+
+await builder.build().run();
+```
+
+
+
+
+`WithFlywayMigration` configures the Flyway connection arguments and `migrate` command; it doesn't add resource ordering. In the C# example, `migrations.WaitFor(database)` starts Flyway after PostgreSQL is ready, and `api.WaitForCompletion(migrations)` gates the API on the migration resource's completion.
+
+The TypeScript overload creates and configures the Flyway resource internally, but it doesn't add a `waitFor` relationship or return the Flyway resource builder. The TypeScript binding therefore can't express the C# example's startup and completion dependencies for that internally created resource.
+
+Use `WithFlywayRepair(migrations)` in C# or `withFlywayRepair("flyway-repair", "./migrations")` in TypeScript when you need Flyway's `repair` command instead of `migrate`. The same ordering behavior and TypeScript limitation apply.
+
## See also
- [Adminer documentation](https://www.adminer.org/)
- [DbGate documentation](https://dbgate.org/)
+- [Flyway documentation](https://documentation.red-gate.com/fd)
- [PostgreSQL integration](/integrations/databases/postgres/postgres-host/)
- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire)
- [Aspire integrations overview](/integrations/overview/)
diff --git a/src/frontend/src/content/docs/integrations/databases/sql-server/sql-server-extensions.mdx b/src/frontend/src/content/docs/integrations/databases/sql-server/sql-server-extensions.mdx
index 5e2e0e478..3d7e32cd7 100644
--- a/src/frontend/src/content/docs/integrations/databases/sql-server/sql-server-extensions.mdx
+++ b/src/frontend/src/content/docs/integrations/databases/sql-server/sql-server-extensions.mdx
@@ -1,6 +1,6 @@
---
title: Use community extensions for SQL Server hosting
-description: Extend the functionality of your SQL Server hosting with the Aspire Community Toolkit, including management UIs like Adminer and DbGate.
+description: Decorate official Aspire SQL Server resources with Community Toolkit Adminer, DbGate, and dbx management interfaces.
---
import { Badge, Tabs, TabItem } from '@astrojs/starlight/components';
@@ -15,6 +15,7 @@ import sqlIcon from '@assets/icons/sql-icon.png';
alt="SQL Server logo"
width={100}
height={100}
+ fit="contain"
class:list={'float-inline-left icon'}
data-zoom-off
/>
@@ -25,6 +26,7 @@ This package provides the following features:
- [Adminer](https://adminer.org/) management UI
- [DbGate](https://dbgate.org/) management UI
+- dbx management UI
## Hosting integration
@@ -46,7 +48,7 @@ For TypeScript AppHosts, add the Community Toolkit SQL Server extensions package
### DbGate management UI
-To add the [DbGate](https://dbgate.org/) management UI to your SQL Server resource, call the `WithDbGate` method on the `SqlServerResourceBuilder` instance:
+To add the [DbGate](https://dbgate.org/) management UI, decorate the official `SqlServerServerResource` builder with `WithDbGate` / `withDbGate`:
@@ -67,14 +69,14 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const sqlserver = await builder.addSqlServer("sqlserver");
+const sqlserver = await builder.addSqlServer('sqlserver');
await sqlserver.withDbGate();
-const api = await builder.addProject("api", "../Api/Api.csproj");
+const api = await builder.addProject('api', '../Api/Api.csproj');
await api.withReference(sqlserver);
await builder.build().run();
@@ -87,7 +89,7 @@ This adds a new DbGate resource to the AppHost which is available from the Aspir
### Adminer management UI
-To add the [Adminer](https://adminer.org/) management UI to your SQL Server resource, call the `WithAdminer` method on the `SqlServerResourceBuilder` instance:
+To add the [Adminer](https://adminer.org/) management UI, decorate the official `SqlServerServerResource` builder with `WithAdminer` / `withAdminer`:
@@ -108,14 +110,14 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const sqlserver = await builder.addSqlServer("sqlserver");
+const sqlserver = await builder.addSqlServer('sqlserver');
await sqlserver.withAdminer();
-const api = await builder.addProject("api", "../Api/Api.csproj");
+const api = await builder.addProject('api', '../Api/Api.csproj');
await api.withReference(sqlserver);
await builder.build().run();
@@ -150,15 +152,15 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const sqlserver = await builder.addSqlServer("sqlserver");
+const sqlserver = await builder.addSqlServer('sqlserver');
await sqlserver.withDbGate();
await sqlserver.withAdminer();
-const api = await builder.addProject("api", "../Api/Api.csproj");
+const api = await builder.addProject('api', '../Api/Api.csproj');
await api.withReference(sqlserver);
await builder.build().run();
@@ -167,6 +169,44 @@ await builder.build().run();
+### dbx management UI
+
+[dbx](https://github.com/t8y2/dbx) is a lightweight, web-based database client and an alternative management UI to DbGate and Adminer. Use `WithDbx` / `withDbx` to add a dbx child resource configured for the SQL Server resource:
+
+
+
+
+```csharp title="AppHost.cs"
+var builder = DistributedApplication.CreateBuilder(args);
+
+var sqlserver = builder.AddSqlServer("sqlserver")
+ .WithDbx();
+
+builder.Build().Run();
+```
+
+
+
+
+```typescript title="apphost.mts"
+import { createBuilder } from './.aspire/modules/aspire.mjs';
+
+const builder = await createBuilder();
+
+const sqlserver = await builder.addSqlServer('sqlserver');
+await sqlserver.withDbx({
+ containerName: 'sqlserver-dbx',
+ imageTag: '0.5.33',
+});
+
+await builder.build().run();
+```
+
+
+
+
+The C# overload accepts an optional container configuration callback and `containerName`. The TypeScript binding accepts optional `containerName` and `imageTag` values.
+
## See also
- [Adminer documentation](https://www.adminer.org/)
diff --git a/src/frontend/src/content/docs/integrations/frameworks/bun-apps.mdx b/src/frontend/src/content/docs/integrations/frameworks/bun-apps.mdx
index 6d609e651..3f92c750d 100644
--- a/src/frontend/src/content/docs/integrations/frameworks/bun-apps.mdx
+++ b/src/frontend/src/content/docs/integrations/frameworks/bun-apps.mdx
@@ -5,6 +5,7 @@ description: Learn how to use the Aspire.Hosting.JavaScript Bun hosting APIs to
---
import { Image } from 'astro:assets';
+import { Tabs, TabItem } from '@astrojs/starlight/components';
import InstallPackage from '@components/InstallPackage.astro';
import bunIcon from '@assets/icons/bun-icon.png';
@@ -13,14 +14,15 @@ import bunIcon from '@assets/icons/bun-icon.png';
alt="Bun logo"
width={100}
height={100}
+ fit="contain"
class:list={'float-inline-left icon'}
data-zoom-off
/>
The Aspire Bun hosting integration enables you to run [Bun](https://bun.sh/) applications alongside your other Aspire resources in the app host. Bun apps participate in the same service discovery, health checks, OpenTelemetry export, and Aspire dashboard support as the rest of your solution.
-:::note
-The `AddBunApp(...)` integration was previously implemented as part of the [📦 CommunityToolkit.Aspire.Hosting.Bun](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.Bun) package but is now built in to `Aspire.Hosting.JavaScript`.
+:::caution[Community Toolkit package deprecated]
+The [📦 CommunityToolkit.Aspire.Hosting.Bun](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.Bun) package is deprecated. Bun support has graduated to the official `Aspire.Hosting.JavaScript` package.
:::
## Hosting integration
@@ -29,9 +31,59 @@ To access the Bun hosting APIs in your [`AppHost`](/get-started/app-host/) proje
+### Migrate from the Community Toolkit package
+
+Remove `CommunityToolkit.Aspire.Hosting.Bun` and install `Aspire.Hosting.JavaScript`. The official API requires the app directory and script path separately:
+
+
+
+
+```csharp title="AppHost.cs"
+var builder = DistributedApplication.CreateBuilder(args);
+
+// Deprecated Toolkit API:
+// builder.AddBunApp(
+// "bun-api",
+// workingDirectory: "../bun-app",
+// entryPoint: "server.ts");
+
+// Official Aspire.Hosting.JavaScript API:
+builder.AddBunApp("bun-api", "../bun-app", "server.ts");
+
+builder.Build().Run();
+```
+
+
+
+
+```typescript title="apphost.mts" twoslash
+import { createBuilder } from './.aspire/modules/aspire.mjs';
+
+const builder = await createBuilder();
+
+// Deprecated Toolkit API:
+// await builder.addBunApp('bun-api', {
+// workingDirectory: '../bun-app',
+// entryPoint: 'server.ts',
+// });
+
+// Official Aspire.Hosting.JavaScript API:
+await builder.addBunApp('bun-api', '../bun-app', 'server.ts');
+
+await builder.build().run();
+```
+
+
+
+
+The official package requires both paths. In TypeScript, replace the Toolkit options object with the official `appDirectory` and `scriptPath` arguments.
+
### Add Bun app
-Add a Bun application to your app host using the `AddBunApp` extension method:
+Add a Bun application to your AppHost using `AddBunApp` / `addBunApp`:
+
+
+
```csharp title="AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);
@@ -45,6 +97,23 @@ builder.AddProject("apiservice")
builder.Build().Run();
```
+
+
+
+```typescript title="apphost.mts"
+import { createBuilder } from './.aspire/modules/aspire.mjs';
+
+const builder = await createBuilder();
+
+const bunApp = await builder.addBunApp('bun-api', '../bun-app', 'server.ts');
+await bunApp.withHttpEndpoint({ port: 3000, env: 'PORT' });
+
+await builder.build().run();
+```
+
+
+
+
`AddBunApp` requires:
- **name**: The name of the resource in the Aspire dashboard.
@@ -55,6 +124,9 @@ builder.Build().Run();
Pass a different `scriptPath` to run a different script:
+
+
+
```csharp title="AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);
@@ -64,6 +136,27 @@ var bunApp = builder.AddBunApp("bun-api", "../bun-app", "src/http/server.ts")
builder.Build().Run();
```
+
+
+
+```typescript title="apphost.mts" twoslash
+import { createBuilder } from './.aspire/modules/aspire.mjs';
+
+const builder = await createBuilder();
+
+const bunApp = await builder.addBunApp(
+ 'bun-api',
+ '../bun-app',
+ 'src/http/server.ts'
+);
+await bunApp.withHttpEndpoint({ port: 3000, env: 'PORT' });
+
+await builder.build().run();
+```
+
+
+
+
### Install packages before startup
When your Bun app includes a `package.json` file, Aspire uses Bun as the package manager and installs packages automatically before the application starts.
@@ -72,6 +165,9 @@ When your Bun app includes a `package.json` file, Aspire uses Bun as the package
Bun applications typically read the port from an environment variable. Use `WithHttpEndpoint` to declare the HTTP endpoint and bind it to a named environment variable:
+
+
+
```csharp title="AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);
@@ -81,14 +177,31 @@ var bunApp = builder.AddBunApp("bun-api", "../bun-app", "server.ts")
builder.Build().Run();
```
+
+
+
+```typescript title="apphost.mts" twoslash
+import { createBuilder } from './.aspire/modules/aspire.mjs';
+
+const builder = await createBuilder();
+
+const bunApp = await builder.addBunApp('bun-api', '../bun-app', 'server.ts');
+await bunApp.withHttpEndpoint({ port: 3000, env: 'PORT' });
+
+await builder.build().run();
+```
+
+
+
+
Your Bun application reads the `PORT` variable at startup:
```typescript title="server.ts"
const server = Bun.serve({
- port: process.env.PORT || 3000,
- fetch(request) {
- return new Response("Hello from Bun!");
- },
+ port: process.env.PORT || 3000,
+ fetch(request) {
+ return new Response('Hello from Bun!');
+ },
});
console.log(`Server listening on port ${server.port}`);
diff --git a/src/frontend/src/content/docs/integrations/frameworks/go/go-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/go/go-host.mdx
index a72a3d2b8..df3c038f6 100644
--- a/src/frontend/src/content/docs/integrations/frameworks/go/go-host.mdx
+++ b/src/frontend/src/content/docs/integrations/frameworks/go/go-host.mdx
@@ -1,6 +1,6 @@
---
title: Set up Go apps in the AppHost
-seoTitle: "Set up Go apps in the Aspire AppHost: hosting integration"
+seoTitle: 'Set up Go apps in the Aspire AppHost: hosting integration'
description: Learn how to use the Aspire Go hosting integration to orchestrate and configure Go applications in an Aspire solution.
---
@@ -83,6 +83,16 @@ This updates your `aspire.config.json` with the Go hosting integration package:
+### Migrate from the Community Toolkit package
+
+For Aspire 13.4 and later, use the official package as the Go hosting golden path:
+
+1. Remove `CommunityToolkit.Aspire.Hosting.Golang` from the AppHost.
+2. Add `Aspire.Hosting.Go`.
+3. Keep Go resources on `AddGoApp` / `addGoApp` and review the official parameters for `appDirectory`, `packagePath`, build tags, linker flags, compiler flags, and the race detector.
+
+The deprecated Toolkit package shouldn't be added to new AppHosts. The examples in this article use only the official `Aspire.Hosting.Go` APIs.
+
## Add Go app
Use `AddGoApp` / `addGoApp` to add a Go application to your AppHost. By default, Aspire runs `go run .` from the application directory.
diff --git a/src/frontend/src/content/docs/integrations/frameworks/javascript.mdx b/src/frontend/src/content/docs/integrations/frameworks/javascript.mdx
index 142a75e00..930a1008b 100644
--- a/src/frontend/src/content/docs/integrations/frameworks/javascript.mdx
+++ b/src/frontend/src/content/docs/integrations/frameworks/javascript.mdx
@@ -14,6 +14,7 @@ import jsIcon from '@assets/icons/javascript.svg';
alt="JavaScript logo"
width={100}
height={100}
+ fit="contain"
class:list={'float-inline-left icon'}
data-zoom-off
/>
@@ -1427,7 +1428,7 @@ configuration, configure the production-serving resource separately.
## See also
- [External parameters](/fundamentals/external-parameters/) - Learn how to use parameters in Aspire
-- [Node.js hosting extensions](/integrations/frameworks/nodejs-extensions/) - Community Toolkit extensions for Vite, Yarn, and pnpm
+- [JavaScript monorepo hosting extensions](/integrations/frameworks/nodejs-extensions/) - Community Toolkit extensions for Nx and Turborepo workspaces
- [Deploy JavaScript apps](/deployment/javascript-apps/) - Production deployment patterns including `PublishAsStaticWebsite`, `PublishAsNodeServer`, and `PublishAsPackageScript`
- [What's new in Aspire 13](/whats-new/aspire-13/) - Learn about first-class JavaScript support
- [Aspire integrations overview](/integrations/overview/)
diff --git a/src/frontend/src/content/docs/integrations/frameworks/nodejs-extensions.mdx b/src/frontend/src/content/docs/integrations/frameworks/nodejs-extensions.mdx
index d089e4f61..e507b2f68 100644
--- a/src/frontend/src/content/docs/integrations/frameworks/nodejs-extensions.mdx
+++ b/src/frontend/src/content/docs/integrations/frameworks/nodejs-extensions.mdx
@@ -1,9 +1,9 @@
---
-title: Node.js hosting extensions
-description: Learn how to use the Aspire Community Toolkit Node.js hosting extensions to run Vite apps and use Yarn or pnpm as the package manager.
+title: JavaScript monorepo hosting extensions
+description: Add Nx and Turborepo workspaces to Aspire with Community Toolkit decorators for package managers, child apps, and mapped ports.
---
-import { Badge } from '@astrojs/starlight/components';
+import { Badge, Tabs, TabItem } from '@astrojs/starlight/components';
import InstallPackage from '@components/InstallPackage.astro';
import ThemeImage from '@components/ThemeImage.astro';
import nodejsIcon from '@assets/icons/nodejs-icon.png';
@@ -21,148 +21,136 @@ import nodejsLightIcon from '@assets/icons/nodejs-light-icon.png';
classOverride="float-inline-left icon"
/>
-:::note
-TypeScript AppHost support for this integration is not yet available. The examples on this page show C# AppHost code only. The `withVite`, `withYarnPackageInstaller`, `withPnpmPackageInstaller`, and `withNpmPackageInstaller` APIs are absent from the generated `.aspire/modules/aspire.mjs` module.
-:::
-
-The Aspire Community Toolkit Node.js hosting extensions package provides extra functionality to the [Aspire.Hosting.JavaScript](https://www.nuget.org/packages/Aspire.Hosting.JavaScript) hosting package.
+The [📦 CommunityToolkit.Aspire.Hosting.JavaScript.Extensions](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions) package adds Nx and Turborepo monorepo support to the official [📦 Aspire.Hosting.JavaScript](https://www.nuget.org/packages/Aspire.Hosting.JavaScript) integration. Use the official package for individual Node.js, Vite, Next.js, and Bun apps; use this Community Toolkit package when an app belongs to an Nx or Turborepo workspace.
-:::caution[Package rename]
-In Aspire 13.0, `Aspire.Hosting.NodeJs` was renamed to
-[`Aspire.Hosting.JavaScript`](/integrations/frameworks/javascript/).
+Start with an existing Nx or Turborepo workspace. Pass the workspace root as `workingDirectory`, then pass the Nx project name or Turborepo package name to `AddApp` / `addApp`. For Turborepo, the optional `filter` selects the package to run.
-Use `Aspire.Hosting.JavaScript` for Aspire 13+ applications.
-`Aspire.Hosting.NodeJs` is the old package name.
-:::
+The extensions add:
-This package provides the following features:
-
-- Running [Vite](https://vitejs.dev/) applications
-- Running Node.js applications using [Yarn](https://yarnpkg.com/) and [pnpm](https://pnpm.io/)
-- Ensuring that packages are installed before running the application (using the specified package manager)
+- `AddNxApp` / `addNxApp` for an Nx workspace.
+- `AddTurborepoApp` / `addTurborepoApp` for a Turborepo workspace.
+- `AddApp` / `addApp` for apps within those workspaces.
+- `WithNpm`, `WithYarn`, `WithPnpm`, and `WithBun` to select the workspace package manager.
+- `WithPackageManagerLaunch` / `withPackageManagerLaunch` to launch the workspace through the selected package manager.
+- `WithMappedEndpointPort` / `withMappedEndpointPort` to pass an Aspire endpoint's allocated port to a JavaScript app.
## Hosting integration
-To get started with the Aspire Community Toolkit Node.js hosting extensions, install the [📦 CommunityToolkit.Aspire.Hosting.NodeJS.Extensions](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.NodeJS.Extensions) NuGet package in the app host project.
-
-
+
+
-## Run specific package managers
+
-This integration extension adds support for running Node.js applications using Yarn or pnpm as the package manager.
+
+
-### Yarn
-
-To add a Node.js application using Yarn, use the `AddYarnApp` extension method:
-
-```csharp title="AppHost.cs"
-var builder = DistributedApplication.CreateBuilder(args);
+```bash title="Terminal"
+aspire add CommunityToolkit.Aspire.Hosting.JavaScript.Extensions
+```
-var yarnApp = builder.AddYarnApp("yarn-demo")
- .WithExternalHttpEndpoints();
+This command adds the package to `aspire.config.json` so Aspire can generate its TypeScript bindings.
-builder.AddProject("example")
- .WithReference(yarnApp);
+
+
-builder.Build().Run();
-```
+## Add an Nx workspace app
-### pnpm
+`AddNxApp` / `addNxApp` models the workspace. Add each runnable project with `AddApp` / `addApp`, then decorate that child app with the official JavaScript resource APIs it needs.
-To add a Node.js application using pnpm, use the `AddPnpmApp` extension method:
+
+
```csharp title="AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);
-var pnpmApp = builder.AddPnpmApp("pnpm-demo")
- .WithExternalHttpEndpoints();
+var nx = builder.AddNxApp("nx-workspace", "../nx-demo")
+ .WithNpm(install: true)
+ .WithPackageManagerLaunch();
-builder.AddProject("example")
- .WithReference(pnpmApp);
+nx.AddApp("blog")
+ .WithHttpEndpoint(env: "PORT")
+ .WithMappedEndpointPort();
builder.Build().Run();
```
-## Run Vite apps
+
+
-This integration extension adds support for running the development server for Vite applications. By default, it uses the `npm` package manager to launch, but this can be overridden with the `packageManager` argument.
+```typescript title="apphost.mts" twoslash
+import { createBuilder } from './.aspire/modules/aspire.mjs';
-### Using npm (default)
+const builder = await createBuilder();
-```csharp title="AppHost.cs"
-var builder = DistributedApplication.CreateBuilder(args);
+const nx = await builder.addNxApp('nx-workspace', {
+ workingDirectory: '../nx-demo',
+});
+await nx.withNpm(true);
+await nx.withPackageManagerLaunch();
-var viteApp = builder.AddViteApp("vite-demo")
- .WithExternalHttpEndpoints();
+const blog = await nx.addApp('blog');
+await blog.withHttpEndpoint({ env: 'PORT' });
+await blog.withMappedEndpointPort();
-builder.Build().Run();
+await builder.build().run();
```
-### Using Yarn
+
+
-```csharp title="AppHost.cs"
-var builder = DistributedApplication.CreateBuilder(args);
-
-var viteApp = builder.AddViteApp("yarn-demo", packageManager: "yarn")
- .WithExternalHttpEndpoints();
+## Add a Turborepo workspace app
-builder.Build().Run();
-```
+Use `AddTurborepoApp` / `addTurborepoApp` for a Turborepo workspace. The optional `filter` selects the workspace package to run.
-### Using pnpm
+
+
```csharp title="AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);
-var viteApp = builder.AddViteApp("pnpm-demo", packageManager: "pnpm")
- .WithExternalHttpEndpoints();
+var turbo = builder.AddTurborepoApp("turborepo", "../turborepo-demo")
+ .WithPnpm(install: true)
+ .WithPackageManagerLaunch();
-builder.Build().Run();
-```
-
-## Install packages
-
-When using the `WithNpmPackageInstallation`, `WithYarnPackageInstallation`, or `WithPnpmPackageInstallation` methods, the package manager is used to install the packages before starting the application. These methods are useful to ensure that packages are installed before the application starts, similar to how a C# application would restore NuGet packages before running.
-
-### npm
-
-```csharp title="AppHost.cs"
-var builder = DistributedApplication.CreateBuilder(args);
-
-var nodeApp = builder.AddNodeApp("node-demo", "server.js")
- .WithNpmPackageInstallation();
+turbo.AddApp("web", filter: "web")
+ .WithHttpEndpoint(env: "PORT")
+ .WithMappedEndpointPort();
builder.Build().Run();
```
-### Yarn
+
+
-```csharp title="AppHost.cs"
-var builder = DistributedApplication.CreateBuilder(args);
+```typescript title="apphost.mts" twoslash
+import { createBuilder } from './.aspire/modules/aspire.mjs';
-var yarnApp = builder.AddYarnApp("yarn-demo")
- .WithYarnPackageInstallation();
+const builder = await createBuilder();
-builder.Build().Run();
-```
+const turbo = await builder.addTurborepoApp('turborepo', {
+ workingDirectory: '../turborepo-demo',
+});
+await turbo.withPnpm(true);
+await turbo.withPackageManagerLaunch();
-### pnpm
+const web = await turbo.addApp('web', { filter: 'web' });
+await web.withHttpEndpoint({ env: 'PORT' });
+await web.withMappedEndpointPort();
-```csharp title="AppHost.cs"
-var builder = DistributedApplication.CreateBuilder(args);
+await builder.build().run();
+```
-var pnpmApp = builder.AddPnpmApp("pnpm-demo")
- .WithPnpmPackageInstallation();
+
+
-builder.Build().Run();
-```
+:::note[Use the official package for individual apps]
+`AddNodeApp`, `AddViteApp`, `AddNextJsApp`, and `AddBunApp`, together with the generic `WithNpm`, `WithYarn`, `WithPnpm`, and `WithBun` decorators for individual JavaScript resources, are provided by `Aspire.Hosting.JavaScript`. They aren't APIs from this Community Toolkit package.
+:::
## See also
-- [Node.js integration](/integrations/frameworks/javascript/)
-- [Vite documentation](https://vitejs.dev/)
-- [Yarn documentation](https://yarnpkg.com/)
-- [pnpm documentation](https://pnpm.io/)
+- [JavaScript integration](/integrations/frameworks/javascript/)
+- [Nx documentation](https://nx.dev/)
+- [Turborepo documentation](https://turbo.build/repo/docs)
- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire)
- [Aspire integrations overview](/integrations/overview/)
-- [Aspire GitHub repo](https://github.com/microsoft/aspire)
diff --git a/src/frontend/src/content/docs/integrations/frameworks/python.mdx b/src/frontend/src/content/docs/integrations/frameworks/python.mdx
index ad3b9fa97..b1f5dfac4 100644
--- a/src/frontend/src/content/docs/integrations/frameworks/python.mdx
+++ b/src/frontend/src/content/docs/integrations/frameworks/python.mdx
@@ -4,7 +4,7 @@ seoTitle: Python integration for Aspire AppHost and apps
description: Add Python apps, modules, and ASGI services to an Aspire AppHost and orchestrate them alongside your other resources with full service discovery, environment injection, and debugging support.
---
-import { Tabs, TabItem } from '@astrojs/starlight/components';
+import { Aside, Tabs, TabItem } from '@astrojs/starlight/components';
import InstallPackage from '@components/InstallPackage.astro';
import { Image } from 'astro:assets';
import pythonIcon from '@assets/icons/python.svg';
@@ -14,20 +14,32 @@ import pythonIcon from '@assets/icons/python.svg';
alt="Python logo"
width={100}
height={100}
+ fit="contain"
class:list={'float-inline-left icon'}
data-zoom-off
/>
The Aspire Python hosting integration lets you model Python scripts, modules, executables, and ASGI web apps as first-class resources in your [`AppHost`](/get-started/app-host/) project. Aspire manages virtual environment setup, injects connection strings and service URLs into the Python process, and wires up service discovery and observability automatically.
-:::tip[First-class Python support]
-As of Aspire 13, Python is a first-class workload with the `Aspire.Hosting.Python` package. The previous `CommunityToolkit.Aspire.Hosting.Python.Extensions` package is deprecated, and its functionality has been integrated into the official package with full support for debugging, service discovery, and deployment alongside .NET and JavaScript applications.
+:::caution[Community Toolkit package deprecated]
+As of Aspire 13, the official `Aspire.Hosting.Python` package is the Python hosting golden path. The previous `CommunityToolkit.Aspire.Hosting.Python.Extensions` package is deprecated.
:::
## Hosting integration
+### Migrate from the Community Toolkit package
+
+Remove the deprecated `CommunityToolkit.Aspire.Hosting.Python.Extensions` package reference, then install `Aspire.Hosting.Python`. Replace Toolkit-specific helpers with the official APIs that match the process you run:
+
+- Use `AddUvicornApp` / `addUvicornApp` for ASGI apps.
+- Replace `AddUvApp` with `AddPythonApp` / `addPythonApp` and `WithUv` / `withUv`.
+- Use `AddPythonExecutable` / `addPythonExecutable` for an executable installed in the Python environment.
+- Pass application arguments with `WithArgs` / `withArgs` instead of the deprecated `AddPythonApp` overloads that accept script arguments.
+
+The examples in this article use only `Aspire.Hosting.Python`.
+
## Add Python app
Use `AddPythonApp` to run a Python script directly:
@@ -40,7 +52,7 @@ var builder = DistributedApplication.CreateBuilder(args);
var python = builder.AddPythonApp(
name: "python-api",
- projectDirectory: "../python-app",
+ appDirectory: "../python-app",
scriptPath: "main.py")
.WithHttpEndpoint(port: 8000, env: "PORT");
@@ -54,14 +66,21 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const python = await builder.addPythonApp("python-api", "../python-app", "main.py");
-await python.withHttpEndpoint({ port: 8000, env: "PORT" });
-
-const example = await builder.addProject("example", "../ExampleProject/ExampleProject.csproj");
+const python = await builder.addPythonApp(
+ 'python-api',
+ '../python-app',
+ 'main.py'
+);
+await python.withHttpEndpoint({ port: 8000, env: 'PORT' });
+
+const example = await builder.addProject(
+ 'example',
+ '../ExampleProject/ExampleProject.csproj'
+);
await example.withReference(python);
await builder.build().run();
@@ -71,9 +90,10 @@ await builder.build().run();
`AddPythonApp` / `addPythonApp` requires:
+
- **name** — the resource name shown in the Aspire dashboard
-- **projectDirectory** / **appDirectory** — path to the directory containing your Python application
-- **scriptPath** — the Python script to run, relative to the project directory
+- **appDirectory** — path to the directory containing your Python application
+- **scriptPath** — the Python script to run, relative to `appDirectory`
## Add Python module
@@ -87,7 +107,7 @@ var builder = DistributedApplication.CreateBuilder(args);
var python = builder.AddPythonModule(
name: "python-module",
- projectDirectory: "../python-app",
+ appDirectory: "../python-app",
moduleName: "mymodule")
.WithHttpEndpoint(port: 8000, env: "PORT");
@@ -98,12 +118,16 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const python = await builder.addPythonModule("python-module", "../python-app", "mymodule");
-await python.withHttpEndpoint({ port: 8000, env: "PORT" });
+const python = await builder.addPythonModule(
+ 'python-module',
+ '../python-app',
+ 'mymodule'
+);
+await python.withHttpEndpoint({ port: 8000, env: 'PORT' });
await builder.build().run();
```
@@ -112,8 +136,9 @@ await builder.build().run();
`AddPythonModule` / `addPythonModule` requires:
+
- **name** — the resource name shown in the Aspire dashboard
-- **projectDirectory** / **appDirectory** — path to the directory containing your Python application
+- **appDirectory** — path to the directory containing your Python application
- **moduleName** — the Python module to run
## Add Python executable
@@ -127,10 +152,10 @@ Use `AddPythonExecutable` to run a CLI tool installed in the virtual environment
var builder = DistributedApplication.CreateBuilder(args);
var python = builder.AddPythonExecutable(
- name: "python-tool",
- projectDirectory: "../python-app",
- executable: "uvicorn",
- args: ["main:app", "--host", "0.0.0.0", "--port", "8000"]);
+ name: "python-tool",
+ appDirectory: "../python-app",
+ executableName: "uvicorn")
+ .WithArgs("main:app", "--host", "0.0.0.0", "--port", "8000");
builder.Build().Run();
```
@@ -139,13 +164,17 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
// TypeScript: pass additional arguments via withArgs after creation
-const python = await builder.addPythonExecutable("python-tool", "../python-app", "uvicorn");
-await python.withArgs(["main:app", "--host", "0.0.0.0", "--port", "8000"]);
+const python = await builder.addPythonExecutable(
+ 'python-tool',
+ '../python-app',
+ 'uvicorn'
+);
+await python.withArgs(['main:app', '--host', '0.0.0.0', '--port', '8000']);
await builder.build().run();
```
@@ -169,8 +198,8 @@ var builder = DistributedApplication.CreateBuilder(args);
var python = builder.AddUvicornApp(
name: "python-api",
- projectDirectory: "../python-app",
- appName: "main:app")
+ appDirectory: "../python-app",
+ app: "main:app")
.WithHttpEndpoint(port: 8000, env: "PORT");
builder.AddProject("example")
@@ -183,14 +212,21 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const python = await builder.addUvicornApp("python-api", "../python-app", "main:app");
-await python.withHttpEndpoint({ port: 8000, env: "PORT" });
-
-const example = await builder.addProject("example", "../ExampleProject/ExampleProject.csproj");
+const python = await builder.addUvicornApp(
+ 'python-api',
+ '../python-app',
+ 'main:app'
+);
+await python.withHttpEndpoint({ port: 8000, env: 'PORT' });
+
+const example = await builder.addProject(
+ 'example',
+ '../ExampleProject/ExampleProject.csproj'
+);
await example.withReference(python);
await builder.build().run();
@@ -200,9 +236,10 @@ await builder.build().run();
`AddUvicornApp` / `addUvicornApp` requires:
+
- **name** — the resource name shown in the Aspire dashboard
-- **projectDirectory** / **appDirectory** — path to the directory containing your Python application
-- **appName** / **app** — the ASGI application in `module:variable` format (for example, `main:app` for an `app` variable in `main.py`)
+- **appDirectory** — path to the directory containing your Python application
+- **app** — the ASGI application in `module:variable` format (for example, `main:app` for an `app` variable in `main.py`)
### Uvicorn configuration
@@ -226,14 +263,18 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const python = await builder.addUvicornApp("python-api", "../python-app", "main:app");
-await python.withHttpEndpoint({ port: 8000, env: "PORT" });
-await python.withEnvironment("UVICORN_WORKERS", "4");
-await python.withEnvironment("UVICORN_LOG_LEVEL", "info");
+const python = await builder.addUvicornApp(
+ 'python-api',
+ '../python-app',
+ 'main:app'
+);
+await python.withHttpEndpoint({ port: 8000, env: 'PORT' });
+await python.withEnvironment('UVICORN_WORKERS', '4');
+await python.withEnvironment('UVICORN_LOG_LEVEL', 'info');
await builder.build().run();
```
@@ -242,6 +283,7 @@ await builder.build().run();
Common Uvicorn environment variables:
+
- **UVICORN_PORT** — port to listen on
- **UVICORN_HOST** — host to bind to (default: `127.0.0.1`)
- **UVICORN_WORKERS** — number of worker processes
@@ -251,6 +293,8 @@ Common Uvicorn environment variables:
The Python hosting integration automatically detects and uses a virtual environment in the project directory. By default, if a `requirements.txt` or `pyproject.toml` is found, Aspire creates and activates a virtual environment before starting the app.
+The official integration doesn't expose a C# or TypeScript API to disable virtual environment management. Use the default `.venv` location or specify a different path.
+
### Custom virtual environment
To specify a custom virtual environment path, use `WithVirtualEnvironment`:
@@ -271,12 +315,16 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const python = await builder.addPythonApp("python-api", "../python-app", "main.py");
-await python.withVirtualEnvironment("../python-app/.venv");
+const python = await builder.addPythonApp(
+ 'python-api',
+ '../python-app',
+ 'main.py'
+);
+await python.withVirtualEnvironment('../python-app/.venv');
await builder.build().run();
```
@@ -284,23 +332,6 @@ await builder.build().run();
-### Disable virtual environment
-
-To opt out of automatic virtual environment management, call `WithoutVirtualEnvironment` in C#:
-
-```csharp title="AppHost.cs"
-var builder = DistributedApplication.CreateBuilder(args);
-
-var python = builder.AddPythonApp("python-api", "../python-app", "main.py")
- .WithoutVirtualEnvironment();
-
-builder.Build().Run();
-```
-
-:::note
-`WithoutVirtualEnvironment` is not yet available in the TypeScript AppHost. To achieve the same effect from a TypeScript AppHost, omit `withVirtualEnvironment` and ensure the Python executable is on `PATH`.
-:::
-
## Package management
### uv package manager
@@ -324,13 +355,17 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const python = await builder.addUvicornApp("python-api", "../python-app", "main:app");
+const python = await builder.addUvicornApp(
+ 'python-api',
+ '../python-app',
+ 'main:app'
+);
await python.withUv();
-await python.withHttpEndpoint({ port: 8000, env: "PORT" });
+await python.withHttpEndpoint({ port: 8000, env: 'PORT' });
await builder.build().run();
```
@@ -359,13 +394,17 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const python = await builder.addPythonApp("python-api", "../python-app", "main.py");
+const python = await builder.addPythonApp(
+ 'python-api',
+ '../python-app',
+ 'main.py'
+);
await python.withPip();
-await python.withHttpEndpoint({ port: 8000, env: "PORT" });
+await python.withHttpEndpoint({ port: 8000, env: 'PORT' });
await builder.build().run();
```
@@ -397,12 +436,16 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const python = await builder.addUvicornApp("python-api", "../python-app", "main:app");
-await python.withHttpEndpoint({ port: 8000, env: "PORT" });
+const python = await builder.addUvicornApp(
+ 'python-api',
+ '../python-app',
+ 'main:app'
+);
+await python.withHttpEndpoint({ port: 8000, env: 'PORT' });
await builder.build().run();
```
@@ -431,13 +474,17 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const python = await builder.addPythonApp("python-api", "../python-app", "main.py");
-await python.withHttpEndpoint({ port: 8000, env: "HTTP_PORT", name: "http" });
-await python.withHttpEndpoint({ port: 8443, env: "HTTPS_PORT", name: "https" });
+const python = await builder.addPythonApp(
+ 'python-api',
+ '../python-app',
+ 'main.py'
+);
+await python.withHttpEndpoint({ port: 8000, env: 'HTTP_PORT', name: 'http' });
+await python.withHttpEndpoint({ port: 8443, env: 'HTTPS_PORT', name: 'https' });
await builder.build().run();
```
@@ -466,13 +513,17 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const python = await builder.addUvicornApp("python-api", "../python-app", "main:app");
-await python.withHttpEndpoint({ port: 8000, env: "PORT" });
-await python.withHttpHealthCheck("/health");
+const python = await builder.addUvicornApp(
+ 'python-api',
+ '../python-app',
+ 'main:app'
+);
+await python.withHttpEndpoint({ port: 8000, env: 'PORT' });
+await python.withHttpHealthCheck('/health');
await builder.build().run();
```
@@ -501,13 +552,17 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const python = await builder.addPythonApp("python-api", "../python-app", "main.py");
-await python.withEnvironment("DEBUG", "true");
-await python.withEnvironment("LOG_LEVEL", "debug");
+const python = await builder.addPythonApp(
+ 'python-api',
+ '../python-app',
+ 'main.py'
+);
+await python.withEnvironment('DEBUG', 'true');
+await python.withEnvironment('LOG_LEVEL', 'debug');
await builder.build().run();
```
@@ -538,14 +593,18 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const postgres = await builder.addPostgres("postgres");
-const db = await postgres.addDatabase("mydb");
+const postgres = await builder.addPostgres('postgres');
+const db = await postgres.addDatabase('mydb');
-const python = await builder.addPythonApp("python-api", "../python-app", "main.py");
+const python = await builder.addPythonApp(
+ 'python-api',
+ '../python-app',
+ 'main.py'
+);
await python.withReference(db);
await builder.build().run();
@@ -583,12 +642,16 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const python = await builder.addUvicornApp("python-api", "../python-app", "main:app");
-await python.withHttpsEndpoint({ port: 8443, env: "PORT" });
+const python = await builder.addUvicornApp(
+ 'python-api',
+ '../python-app',
+ 'main:app'
+);
+await python.withHttpsEndpoint({ port: 8443, env: 'PORT' });
await python.withHttpsDeveloperCertificate();
await builder.build().run();
@@ -650,20 +713,31 @@ builder.Build().Run();
```typescript title="apphost.mts"
-import { createBuilder } from "./.aspire/modules/aspire.mjs";
+import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const internalApi = await builder.addUvicornApp("internal-api", "../internal-api", "main:app");
-await internalApi.withHttpEndpoint({ port: 8001, env: "PORT" });
+const internalApi = await builder.addUvicornApp(
+ 'internal-api',
+ '../internal-api',
+ 'main:app'
+);
+await internalApi.withHttpEndpoint({ port: 8001, env: 'PORT' });
// internalApi is NOT exposed publicly — only reachable by other Aspire resources
-const publicApi = await builder.addUvicornApp("public-api", "../public-api", "main:app");
-await publicApi.withHttpEndpoint({ port: 8000, env: "PORT" });
+const publicApi = await builder.addUvicornApp(
+ 'public-api',
+ '../public-api',
+ 'main:app'
+);
+await publicApi.withHttpEndpoint({ port: 8000, env: 'PORT' });
await publicApi.withExternalHttpEndpoints();
// publicApi IS exposed publicly
-const frontend = await builder.addProject("frontend", "../WebFrontend/WebFrontend.csproj");
+const frontend = await builder.addProject(
+ 'frontend',
+ '../WebFrontend/WebFrontend.csproj'
+);
await frontend.withReference(internalApi);
await frontend.withReference(publicApi);
diff --git a/src/frontend/src/content/docs/integrations/messaging/rabbitmq/rabbitmq-connect.mdx b/src/frontend/src/content/docs/integrations/messaging/rabbitmq/rabbitmq-connect.mdx
index 119c3779d..7cf49f605 100644
--- a/src/frontend/src/content/docs/integrations/messaging/rabbitmq/rabbitmq-connect.mdx
+++ b/src/frontend/src/content/docs/integrations/messaging/rabbitmq/rabbitmq-connect.mdx
@@ -1,11 +1,11 @@
---
title: Connect to RabbitMQ
-seoTitle: "Connect to RabbitMQ from Aspire apps (C# and TypeScript)"
+seoTitle: 'Connect to RabbitMQ from Aspire apps (C# and TypeScript)'
description: Learn how to connect to RabbitMQ from C#, Go, Python, and TypeScript consuming apps in an Aspire solution.
---
import { Image } from 'astro:assets';
-import { Aside, Tabs, TabItem } from '@astrojs/starlight/components';
+import { Aside, Badge, Tabs, TabItem } from '@astrojs/starlight/components';
import InstallDotNetPackage from '@components/InstallDotNetPackage.astro';
import rabbitmqIcon from '@assets/icons/rabbitmq-icon.svg';
@@ -14,15 +14,16 @@ import rabbitmqIcon from '@assets/icons/rabbitmq-icon.svg';
alt="RabbitMQ logo"
width={100}
height={100}
+ fit="contain"
class:list={'float-inline-left icon'}
data-zoom-off
/>
-This page describes how consuming apps connect to a RabbitMQ resource that's already modeled in your AppHost. For the AppHost API surface — adding a RabbitMQ server, data volumes, management plugin, parameters, and more — see [RabbitMQ Hosting integration](../rabbitmq-host/).
+This page describes how consuming apps connect to a RabbitMQ resource that's already modeled in your AppHost. For the AppHost API surface — adding a RabbitMQ server, data volumes, management plugin, parameters, and more — see [RabbitMQ Hosting integration](/integrations/messaging/rabbitmq/rabbitmq-host/).
-When you reference a RabbitMQ resource from your AppHost, Aspire injects the connection information into the consuming app as environment variables. Your app can either read those environment variables directly — the pattern works the same from any language — or, in C#, use the Aspire RabbitMQ client integration for automatic dependency injection, health checks, and telemetry.
+When you reference a RabbitMQ resource from your AppHost, Aspire injects the connection information into the consuming app as configuration and environment variables. Your app can either read that information directly — the pattern works the same from any language — or, in C#, use an Aspire client integration.
-These connection properties are available when the AppHost models a typed RabbitMQ resource (for example, `AddRabbitMQ("messaging")`) and references it from a consuming app. If the AppHost uses `AddConnectionString("messaging")` or `addConnectionString("messaging")`, consuming apps receive a single `ConnectionStrings` value (`ConnectionStrings:messaging` / `ConnectionStrings__messaging`) instead of deconstructed resource variables such as `MESSAGING_URI`, `MESSAGING_HOST`, and `MESSAGING_PORT`.
+When the AppHost models a typed RabbitMQ resource (for example, `AddRabbitMQ("messaging")`) and references it from a consuming app, the app receives `ConnectionStrings:messaging` plus deconstructed resource variables such as `MESSAGING_URI`, `MESSAGING_HOST`, and `MESSAGING_PORT`. If the AppHost uses `AddConnectionString("messaging")` or `addConnectionString("messaging")`, consuming apps receive only the `ConnectionStrings` value.
## Connection properties
@@ -30,14 +31,14 @@ Aspire exposes each property as an environment variable named `[RESOURCE]_[PROPE
The RabbitMQ server resource exposes the following connection properties:
-| Property Name | Description |
-| ------------- | ----------- |
-| `Host` | The hostname or IP address of the RabbitMQ server |
-| `Port` | The port number the RabbitMQ server is listening on |
-| `Username` | The username for authentication |
-| `Password` | The password for authentication |
+| Property Name | Description |
+| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
+| `Host` | The hostname or IP address of the RabbitMQ server |
+| `Port` | The port number the RabbitMQ server is listening on |
+| `Username` | The username for authentication |
+| `Password` | The password for authentication |
| `VirtualHost` | The virtual host path. Defaults to `/` (the default virtual host). Embedded as the path component of the connection URI when non-default. |
-| `Uri` | The connection URI, with the format `amqp://{Username}:{Password}@{Host}:{Port}` |
+| `Uri` | The connection URI, with the format `amqp://{Username}:{Password}@{Host}:{Port}` |
**Example connection string:**
@@ -57,8 +58,8 @@ When your AppHost adds a typed RabbitMQ resource with `builder.AddRabbitMQ("mess
- `MESSAGING_PORT` = port number
- `MESSAGING_USERNAME` = username
- `MESSAGING_PASSWORD` = password
-- `MESSAGING_VIRTUALHOST` = virtual host path (if set)
- `MESSAGING_URI` = full connection URI
+- `ConnectionStrings__messaging` = full connection string
This is the **recommended approach** because Aspire manages the resource lifecycle, configuration, and provides typed client integrations.
@@ -86,7 +87,13 @@ Install the [📦 Aspire.RabbitMQ.Client](https://www.nuget.org/packages/Aspire.
#### Add the RabbitMQ client
@@ -98,7 +105,9 @@ builder.AddRabbitMQClient(connectionName: "messaging");
```
Resolve the connection through dependency injection:
@@ -201,7 +210,9 @@ builder.AddRabbitMQClient("messaging", o => o.DisableAutoActivation = false);
```
#### Client integration health checks
@@ -225,6 +236,42 @@ The Aspire RabbitMQ client integration automatically configures logging, tracing
**Metrics**: The RabbitMQ client integration doesn't currently support metrics by default.
+#### Use MassTransit
+
+
+
+For apps that use MassTransit, install the [📦 CommunityToolkit.Aspire.MassTransit.RabbitMQ](https://www.nuget.org/packages/CommunityToolkit.Aspire.MassTransit.RabbitMQ) package in the consuming project:
+
+
+
+Register MassTransit against the same resource name used in the AppHost:
+
+```csharp title="Program.cs"
+using MassTransit;
+
+var builder = WebApplication.CreateBuilder(args);
+
+builder.AddMassTransitRabbitMq(
+ "messaging",
+ massTransitConfiguration: registration =>
+ registration.AddConsumer());
+
+var app = builder.Build();
+app.Run();
+
+public sealed record OrderSubmitted(Guid OrderId);
+
+public sealed class OrderSubmittedConsumer : IConsumer
+{
+ public Task Consume(ConsumeContext context) =>
+ Task.CompletedTask;
+}
+```
+
+`AddMassTransitRabbitMq` reads `ConnectionStrings:messaging` directly from the consuming app's configuration. The name must match the referenced RabbitMQ resource, and registration throws an `InvalidOperationException` when that connection string is missing or empty. It doesn't read `MESSAGING_URI` or bind an `Aspire:RabbitMQ` settings section.
+
+The optional `configureOptions` delegate configures `MassTransitRabbitMqSettings`; set `DisableTelemetry` to `true` only when you don't want the integration to register its OpenTelemetry instrumentation. Use `AddMassTransitRabbitMq` for an additional MassTransit bus type.
+
#### Read environment variables in C\#
If you prefer not to use the Aspire client integration, you can read the Aspire-injected connection URI from the environment and pass it directly to the [📦 RabbitMQ.Client](https://www.nuget.org/packages/RabbitMQ.Client/) library:
@@ -331,11 +378,10 @@ Or, build the connection options from individual properties:
import amqp from 'amqplib';
const connection = await amqp.connect({
- hostname: process.env.MESSAGING_HOST,
- port: Number(process.env.MESSAGING_PORT),
- username: process.env.MESSAGING_USERNAME,
- password: process.env.MESSAGING_PASSWORD,
- vhost: process.env.MESSAGING_VIRTUALHOST ?? '/',
+ hostname: process.env.MESSAGING_HOST,
+ port: Number(process.env.MESSAGING_PORT),
+ username: process.env.MESSAGING_USERNAME,
+ password: process.env.MESSAGING_PASSWORD,
});
```
@@ -343,5 +389,9 @@ const connection = await amqp.connect({
diff --git a/src/frontend/src/content/docs/integrations/security/keycloak.mdx b/src/frontend/src/content/docs/integrations/security/keycloak.mdx
index 8aa13c768..0e9dd06e1 100644
--- a/src/frontend/src/content/docs/integrations/security/keycloak.mdx
+++ b/src/frontend/src/content/docs/integrations/security/keycloak.mdx
@@ -17,6 +17,7 @@ import keycloakIcon from '@assets/icons/keycloak-icon.svg';
alt="Keycloak logo"
width={100}
height={100}
+ fit="contain"
class:list={'float-inline-left icon'}
data-zoom-off
/>
@@ -63,7 +64,7 @@ import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const keycloak = await builder.addKeycloak("keycloak", 8080);
+const keycloak = await builder.addKeycloak("keycloak", { port: 8080 });
const apiService = await builder.addProject("apiservice", "../ApiService/ApiService.csproj");
await apiService.withReference(keycloak);
@@ -131,7 +132,7 @@ import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const keycloak = await builder.addKeycloak("keycloak", 8080);
+const keycloak = await builder.addKeycloak("keycloak", { port: 8080 });
await keycloak.withDataVolume();
const apiService = await builder.addProject("apiservice", "../ApiService/ApiService.csproj");
@@ -175,7 +176,7 @@ import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const keycloak = await builder.addKeycloak("keycloak", 8080);
+const keycloak = await builder.addKeycloak("keycloak", { port: 8080 });
await keycloak.withDataBindMount("/path/to/keycloak/data");
const apiService = await builder.addProject("apiservice", "../ApiService/ApiService.csproj");
@@ -223,7 +224,11 @@ const builder = await createBuilder();
const username = await builder.addParameter("username");
const password = await builder.addParameter("password", { secret: true });
-const keycloak = await builder.addKeycloak("keycloak", 8080, username, password);
+const keycloak = await builder.addKeycloak("keycloak", {
+ port: 8080,
+ adminUsername: username,
+ adminPassword: password,
+});
const apiService = await builder.addProject("apiservice", "../ApiService/ApiService.csproj");
await apiService.withReference(keycloak);
@@ -261,7 +266,7 @@ import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const keycloak = await builder.addKeycloak("keycloak", 8080);
+const keycloak = await builder.addKeycloak("keycloak", { port: 8080 });
await keycloak.withRealmImport("./Realms");
const apiService = await builder.addProject("apiservice", "../ApiService/ApiService.csproj");
@@ -321,7 +326,7 @@ import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const keycloak = await builder.addKeycloak("keycloak", 8080);
+const keycloak = await builder.addKeycloak("keycloak", { port: 8080 });
await keycloak.withDockerfile("./keycloak");
const apiService = await builder.addProject("apiservice", "../ApiService/ApiService.csproj");
@@ -399,7 +404,7 @@ import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
-const keycloak = await builder.addKeycloak("keycloak", 8080);
+const keycloak = await builder.addKeycloak("keycloak", { port: 8080 });
await keycloak.withOtlpExporter();
const apiService = await builder.addProject("apiservice", "../ApiService/ApiService.csproj");
@@ -413,6 +418,54 @@ await builder.build().run();
This enables Keycloak to send traces, metrics, and logs to the Aspire dashboard, providing better observability for your authentication flows.
+### Use PostgreSQL with the Community Toolkit extension
+
+
+
+The [📦 CommunityToolkit.Aspire.Hosting.Keycloak.Extensions](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.Keycloak.Extensions) package decorates the official `KeycloakResource` with `WithPostgres` / `withPostgres`. It configures Keycloak to use an official `PostgresDatabaseResource`, supplies the JDBC URL and credentials, and makes Keycloak wait for the database.
+
+
+
+
+
+
+```csharp title="AppHost.cs"
+var builder = DistributedApplication.CreateBuilder(args);
+
+var postgres = builder.AddPostgres("keycloak-postgres");
+var database = postgres.AddDatabase("keycloakdb");
+
+var keycloak = builder.AddKeycloak("keycloak", 8080)
+ .WithPostgres(database);
+
+builder.Build().Run();
+```
+
+
+
+
+```typescript title="apphost.mts"
+import { createBuilder } from './.aspire/modules/aspire.mjs';
+
+const builder = await createBuilder();
+
+const postgres = await builder.addPostgres('keycloak-postgres');
+const database = await postgres.addDatabase('keycloakdb');
+
+const keycloak = await builder.addKeycloak('keycloak', { port: 8080 });
+await keycloak.withPostgres(database);
+
+await builder.build().run();
+```
+
+
+
+
+By default, `WithPostgres` uses the PostgreSQL server's username and password parameters. Its optional arguments let you supply different `username` and `password` parameter resources and set `xaEnabled` when Keycloak needs XA transactions.
+
### Hosting integration health checks
The Keycloak hosting integration automatically adds an HTTP health check
@@ -507,10 +560,35 @@ builder.Services.AddAuthentication()
For production deployments, consider using connection strings:
+
+
+
```csharp title="AppHost.cs"
+var builder = DistributedApplication.CreateBuilder(args);
+
builder.AddConnectionString("keycloak", "https://your-keycloak-server.com");
+
+builder.Build().Run();
+```
+
+
+
+
+```typescript title="apphost.mts" twoslash
+import { createBuilder, refExpr } from './.aspire/modules/aspire.mjs';
+
+const builder = await createBuilder();
+
+await builder.addConnectionString('keycloak', {
+ environmentVariableNameOrExpression: refExpr`https://your-keycloak-server.com`,
+});
+
+await builder.build().run();
```
+
+
+
### Security best practices
- Always use `RequireHttpsMetadata = true` in production environments
diff --git a/src/frontend/src/data/integration-docs.json b/src/frontend/src/data/integration-docs.json
index e7c67f277..57f00fc02 100644
--- a/src/frontend/src/data/integration-docs.json
+++ b/src/frontend/src/data/integration-docs.json
@@ -441,11 +441,11 @@
},
{
"match": "CommunityToolkit.Aspire.Hosting.MongoDB.Extensions",
- "href": "/integrations/databases/mongodb/mongodb-get-started/"
+ "href": "/integrations/databases/mongodb/mongodb-extensions/"
},
{
"match": "CommunityToolkit.Aspire.Hosting.MySql.Extensions",
- "href": "/integrations/databases/mysql/mysql-get-started/"
+ "href": "/integrations/databases/mysql/mysql-extensions/"
},
{
"match": "CommunityToolkit.Aspire.Hosting.Ollama",
@@ -457,7 +457,7 @@
},
{
"match": "CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions",
- "href": "/integrations/databases/postgres/postgres-get-started/"
+ "href": "/integrations/databases/postgres/postgresql-extensions/"
},
{
"match": "CommunityToolkit.Aspire.Hosting.PowerShell",
@@ -489,7 +489,7 @@
},
{
"match": "CommunityToolkit.Aspire.Hosting.SqlServer.Extensions",
- "href": "/integrations/databases/sql-server/sql-server-get-started/"
+ "href": "/integrations/databases/sql-server/sql-server-extensions/"
},
{
"match": "CommunityToolkit.Aspire.Hosting.SurrealDb",
@@ -501,7 +501,7 @@
},
{
"match": "CommunityToolkit.Aspire.MassTransit.RabbitMQ",
- "href": "/integrations/messaging/rabbitmq/rabbitmq-get-started/"
+ "href": "/integrations/messaging/rabbitmq/rabbitmq-connect/"
},
{
"match": "CommunityToolkit.Aspire.Meilisearch",