A profanity filter, on tap, in your AppHost.
The
ProfanityFilter.Hosting
package wraps the Potty Mouth API as a first-class
ContainerResource.
Add it to your distributed application, reference it from any project, and you have a fast,
local-first profanity-filter HTTP service alongside the rest of your services — no infra to spin up.
Containerized
Backed by the official ghcr.io/ievangelist/profanity-filter-api image. Same engine as the GitHub Action, served over HTTPS with a sensible default port.
Multi-language
Annotated with the new [AspireExport] attribute, so the same NuGet package powers both C# and TypeScript AppHosts.
Just works
Implements IResourceWithConnectionString. Reference the resource from any project and the HTTPS endpoint flows in automatically.
Install
From your AppHost directory, run the
aspire add
command. The CLI installs the NuGet package for C# AppHosts and additionally generates the typed
.modules
SDK for TypeScript AppHosts — same command, both languages.
aspire add ProfanityFilter.Hosting C# AppHost
Call AddProfanityFilter
on your IDistributedApplicationBuilder,
then wire any project that needs to call the filter with
.WithReference(...) and
.WaitFor(...).
// apphost.cs
#:sdk Aspire.AppHost.Sdk@13.3.0
#:package Aspire.Hosting
#:package ProfanityFilter.Hosting
#:project ../src/MyApi/MyApi.csproj
var builder = DistributedApplication.CreateBuilder(args);
var profanityFilter = builder.AddProfanityFilter("profanity-filter")
.WithCustomDataBindMount("./CustomData");
builder.AddProject<Projects.MyApi>("api")
.WithReference(profanityFilter)
.WaitFor(profanityFilter);
builder.Build().Run(); TypeScript AppHost
Thanks to Aspire’s multi-language authoring, the same package generates a typed TypeScript SDK at AppHost build time. The C# implementation runs as-is — the SDK is a thin client that calls into it over JSON-RPC.
// apphost.ts
import { createBuilder } from "./.modules/aspire.js";
import { addProfanityFilter } from "./.modules/profanityfilter.hosting.js";
const builder = await createBuilder();
const filter = await addProfanityFilter(builder, "profanity-filter")
.withCustomDataBindMount("./CustomData");
const api = await builder.addProject("api", { project: "../src/MyApi/MyApi.csproj" })
.withReference(filter)
.waitFor(filter);
const app = await builder.build();
await app.run(); Reference it from your code
The resource implements
IResourceWithConnectionString,
so referencing it from a project flows the HTTPS endpoint through as a connection string under the resource name.
Pair that with
ProfanityFilter.Client
and a single
AddProfanityFilterClient(...)
call — it reads the connection string, registers a typed
HttpClient,
and exposes a strongly-typed
ProfanityFilterClient
with REST and SignalR-backed real-time clients ready to inject.
// In your API project (MyApi.csproj) — install ProfanityFilter.Client, then:
builder.AddProfanityFilterClient("profanity-filter");
// Now inject ProfanityFilterClient anywhere — it's a typed
// HTTP client wired to the resource's connection string, with
// .Rest for REST calls and .Realtime for the SignalR hub.
app.MapPost("/scrub", async (
string text,
ProfanityFilterClient profanity) =>
{
var response = await profanity.Rest.ApplyFilterAsync(
new ProfanityFilterRequest(text, ReplacementStrategy.Emoji));
return response.Match(
onValue: r => Results.Ok(r.FilteredText),
onAbsent: () => Results.NotFound());
});
Need keyed services?
AddKeyedProfanityFilterClient("name")
registers the same dependencies under a service key — useful when you reference more than one filter.
Custom word lists
Ship project-specific terms with
WithCustomDataBindMount.
Drop one or more newline-delimited
*.txt
files into the folder you point at — they’re merged with the built-in 4,900+ word dictionary at startup.
// Optional: ship a folder of newline-delimited *.txt files with
// project-specific words and phrases that should also be filtered.
// They are merged with the built-in 4,900+ word dictionary at runtime.
var profanityFilter = builder.AddProfanityFilter("profanity-filter")
.WithCustomDataBindMount("./CustomData"); API surface
| Member | Description |
|---|---|
| AddProfanityFilter(name) | Adds the profanity filter container to the distributed application. Returns an IResourceBuilder<ProfanityFilterResource>. |
| WithCustomDataBindMount(source) | Bind-mounts a host folder of *.txt word lists into /app/CustomData inside the container. |
| ProfanityFilterResource.HttpsEndpoint | The HTTPS endpoint reference. Implements IResourceWithConnectionString, so referencing the resource flows the URL through automatically. |