diff --git a/CommunityToolkit.Aspire.slnx b/CommunityToolkit.Aspire.slnx
index a58bb4ef6..0032f5caf 100644
--- a/CommunityToolkit.Aspire.slnx
+++ b/CommunityToolkit.Aspire.slnx
@@ -51,6 +51,10 @@
+
+
+
+
@@ -251,6 +255,7 @@
+
@@ -327,6 +332,7 @@
+
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 2afb0fc61..05eb84018 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -76,6 +76,8 @@
+
+
+
diff --git a/README.md b/README.md
index 7d3a49d85..96be6d01f 100644
--- a/README.md
+++ b/README.md
@@ -62,6 +62,7 @@ This repository contains the source code for the Aspire Community Toolkit, a col
| - **Learn More**: [`Hosting.Umami`][umami-integration-docs]
- Stable 📦: [![CommunityToolkit.Aspire.Hosting.Umami][umami-shields]][umami-nuget]
- Preview 📦: [![CommunityToolkit.Aspire.Hosting.Umami][umami-shields-preview]][umami-nuget-preview] | An Aspire hosting integration leveraging the [Umami](https://umami.is/) container. |
| - **Learn More**: [`Hosting.Azure.Extensions`][azure-ext-integration-docs]
- Stable 📦: [![CommunityToolkit.Aspire.Azure.Extensions][azure-ext-shields]][azure-ext-nuget]
- Preview 📦: [![CommunityToolkit.Aspire.Hosting.Azure.Extensions][azure-ext-shields-preview]][azure-ext-nuget-preview] | An integration that contains some additional extensions for hosting Azure container. |
| - **Learn More**: [`Hosting.Squad`][squad-integration-docs]
- Stable 📦: [![CommunityToolkit.Aspire.Hosting.Squad][squad-shields]][squad-nuget]
- Preview 📦: [![CommunityToolkit.Aspire.Hosting.Squad][squad-shields-preview]][squad-nuget-preview] | An Aspire hosting integration that models a [Squad](https://github.com/bradygaster/squad) AI-agent team as a first-class resource. |
+| - **Learn More**: [`Hosting.Floci`][floci-integration-docs]
- Stable 📦: [![CommunityToolkit.Aspire.Hosting.Floci][floci-shields]][floci-nuget]
- Preview 📦: [![CommunityToolkit.Aspire.Hosting.Floci][floci-shields-preview]][floci-nuget-preview] | An Aspire hosting integration leveraging the [Floci](https://floci.io) AWS emulator container. |
## 🙌 Getting Started
@@ -333,3 +334,8 @@ This project is supported by the [.NET Foundation](https://dotnetfoundation.org)
[squad-nuget]: https://nuget.org/packages/CommunityToolkit.Aspire.Hosting.Squad/
[squad-shields-preview]: https://img.shields.io/nuget/vpre/CommunityToolkit.Aspire.Hosting.Squad?label=nuget%20(preview)
[squad-nuget-preview]: https://nuget.org/packages/CommunityToolkit.Aspire.Hosting.Squad/absoluteLatest
+[floci-integration-docs]: https://learn.microsoft.com/dotnet/aspire/community-toolkit/hosting-floci
+[floci-shields]: https://img.shields.io/nuget/v/CommunityToolkit.Aspire.Hosting.Floci
+[floci-nuget]: https://nuget.org/packages/CommunityToolkit.Aspire.Hosting.Floci/
+[floci-shields-preview]: https://img.shields.io/nuget/vpre/CommunityToolkit.Aspire.Hosting.Floci?label=nuget%20(preview)
+[floci-nuget-preview]: https://nuget.org/packages/CommunityToolkit.Aspire.Hosting.Floci/absoluteLatest
diff --git a/examples/floci/CommunityToolkit.Aspire.Hosting.Floci.ApiService/CommunityToolkit.Aspire.Hosting.Floci.ApiService.csproj b/examples/floci/CommunityToolkit.Aspire.Hosting.Floci.ApiService/CommunityToolkit.Aspire.Hosting.Floci.ApiService.csproj
new file mode 100644
index 000000000..630ecb85b
--- /dev/null
+++ b/examples/floci/CommunityToolkit.Aspire.Hosting.Floci.ApiService/CommunityToolkit.Aspire.Hosting.Floci.ApiService.csproj
@@ -0,0 +1,14 @@
+
+
+
+ enable
+ enable
+
+
+
+
+
+
+
+
+
diff --git a/examples/floci/CommunityToolkit.Aspire.Hosting.Floci.ApiService/Program.cs b/examples/floci/CommunityToolkit.Aspire.Hosting.Floci.ApiService/Program.cs
new file mode 100644
index 000000000..35e805d8c
--- /dev/null
+++ b/examples/floci/CommunityToolkit.Aspire.Hosting.Floci.ApiService/Program.cs
@@ -0,0 +1,351 @@
+using Amazon.Runtime;
+using Amazon.S3;
+using Amazon.S3.Model;
+using Azure;
+using Azure.Storage.Blobs;
+using Google.Api.Gax;
+using Google.Cloud.Storage.V1;
+using Microsoft.Extensions.Diagnostics.HealthChecks;
+
+var builder = WebApplication.CreateBuilder(args);
+
+// --- AWS (S3) --------------------------------------------------------------
+// Read AWS config from env vars injected by Aspire's WithReference(floci).
+// RegionEndpoint is intentionally omitted — the SDK resolves it from AWS_DEFAULT_REGION
+// automatically, and combining ServiceURL + RegionEndpoint in SDK v4 triggers a NPE in
+// the endpoint rule engine.
+var awsEndpointUrl = Environment.GetEnvironmentVariable("AWS_ENDPOINT_URL")!;
+var awsRegion = Environment.GetEnvironmentVariable("AWS_DEFAULT_REGION")!;
+var awsAccessKey = Environment.GetEnvironmentVariable("AWS_ACCESS_KEY_ID")!;
+var awsSecretKey = Environment.GetEnvironmentVariable("AWS_SECRET_ACCESS_KEY")!;
+
+var s3 = new AmazonS3Client(
+ new BasicAWSCredentials(awsAccessKey, awsSecretKey),
+ new AmazonS3Config
+ {
+ ServiceURL = awsEndpointUrl,
+ ForcePathStyle = true
+ });
+
+builder.Services.AddSingleton(s3);
+
+// --- Azure (Blob Storage) ----------------------------------------------------
+// AZURE_STORAGE_CONNECTION_STRING is injected by Aspire's WithReference(flociAzure) —
+// it already points BlobEndpoint at the Floci Azure emulator with the well-known
+// devstoreaccount1 dev credentials.
+var azureConnectionString = Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING")!;
+
+var blobServiceClient = new BlobServiceClient(azureConnectionString);
+
+builder.Services.AddSingleton(blobServiceClient);
+
+// --- GCP (Cloud Storage) ------------------------------------------------------
+// STORAGE_EMULATOR_HOST / GOOGLE_CLOUD_PROJECT are injected by Aspire's WithReference(flociGcp).
+// EmulatorDetection.EmulatorOnly makes the client library read STORAGE_EMULATOR_HOST and skip
+// real GCP credential resolution entirely.
+var gcpProjectId = Environment.GetEnvironmentVariable("GOOGLE_CLOUD_PROJECT")!;
+
+var gcpStorageClient = await new StorageClientBuilder
+{
+ EmulatorDetection = EmulatorDetection.EmulatorOnly
+}.BuildAsync();
+
+builder.Services.AddSingleton(gcpStorageClient);
+
+// Creates the demo bucket/container once each Floci emulator is reachable; logs a warning if
+// still starting. Runs concurrently with the health checks — failures here are non-fatal.
+builder.Services.AddHostedService();
+builder.Services.AddHostedService();
+builder.Services.AddHostedService();
+
+builder.Services.AddHealthChecks()
+ .AddAsyncCheck("floci-s3", async ct =>
+ {
+ try
+ {
+ var response = await s3.ListBucketsAsync(ct);
+ if (response?.Buckets == null)
+ {
+ return HealthCheckResult.Unhealthy("Floci S3 returned null buckets list");
+ }
+ return HealthCheckResult.Healthy($"Floci S3 reachable — {response.Buckets.Count} bucket(s)");
+ }
+ catch (Exception ex)
+ {
+ return HealthCheckResult.Unhealthy("Floci S3 unreachable", ex);
+ }
+ })
+ .AddAsyncCheck("floci-azure-blob", async ct =>
+ {
+ try
+ {
+ var count = 0;
+ await foreach (var _ in blobServiceClient.GetBlobContainersAsync(cancellationToken: ct))
+ {
+ count++;
+ }
+ return HealthCheckResult.Healthy($"Floci Azure Blob reachable — {count} container(s)");
+ }
+ catch (Exception ex)
+ {
+ return HealthCheckResult.Unhealthy("Floci Azure Blob unreachable", ex);
+ }
+ })
+ .AddAsyncCheck("floci-gcp-storage", async ct =>
+ {
+ try
+ {
+ var count = 0;
+ await foreach (var _ in gcpStorageClient.ListBucketsAsync(gcpProjectId).WithCancellation(ct))
+ {
+ count++;
+ }
+ return HealthCheckResult.Healthy($"Floci GCP Storage reachable — {count} bucket(s)");
+ }
+ catch (Exception ex)
+ {
+ return HealthCheckResult.Unhealthy("Floci GCP Storage unreachable", ex);
+ }
+ });
+
+var app = builder.Build();
+
+app.Logger.LogInformation(
+ "AWS endpoint={AwsEndpoint} region={AwsRegion} | Azure blob endpoint present={HasAzureConn} | GCP project={GcpProject}",
+ awsEndpointUrl, awsRegion, !string.IsNullOrEmpty(azureConnectionString), gcpProjectId);
+
+// /alive — liveness probe (process is up, no dependency checks)
+// /health — readiness probe (checks S3/Blob/GCS connectivity)
+app.MapGet("/alive", () => Results.Ok());
+app.MapHealthChecks("/health");
+
+// --- S3 demo endpoints -------------------------------------------------------
+
+// List all buckets currently in Floci
+app.MapGet("/s3/buckets", async (IAmazonS3 s3) =>
+{
+ var response = await s3.ListBucketsAsync();
+ return (response?.Buckets ?? []).Select(b => new { b.BucketName, b.CreationDate });
+});
+
+// Create a new bucket
+app.MapPost("/s3/{bucket}", async (string bucket, IAmazonS3 s3) =>
+{
+ await s3.PutBucketAsync(new PutBucketRequest { BucketName = bucket });
+ return Results.Created($"/s3/{bucket}", new { bucket });
+});
+
+// Store a text value at bucket/key
+app.MapPut("/s3/{bucket}/{*key}", async (string bucket, string key, HttpRequest request, IAmazonS3 s3) =>
+{
+ using var reader = new StreamReader(request.Body);
+ var body = await reader.ReadToEndAsync();
+ await s3.PutObjectAsync(new PutObjectRequest { BucketName = bucket, Key = key, ContentBody = body });
+ return Results.Created($"/s3/{bucket}/{key}", new { bucket, key, size = body.Length });
+});
+
+// Retrieve a value previously stored at bucket/key
+app.MapGet("/s3/{bucket}/{*key}", async (string bucket, string key, IAmazonS3 s3) =>
+{
+ try
+ {
+ var response = await s3.GetObjectAsync(new GetObjectRequest { BucketName = bucket, Key = key });
+ using var reader = new StreamReader(response.ResponseStream);
+ return Results.Ok(await reader.ReadToEndAsync());
+ }
+ catch (AmazonS3Exception ex) when (ex.ErrorCode is "NoSuchKey" or "NoSuchBucket")
+ {
+ return Results.NotFound(new { bucket, key });
+ }
+});
+
+// --- Azure Blob demo endpoints ------------------------------------------------
+
+// List all containers currently in Floci Azure
+app.MapGet("/azure/containers", async (BlobServiceClient blobServiceClient) =>
+{
+ var containers = new List