add-aspire-worker-project
Create a new .NET Aspire worker project with Kafka, RavenDB, and MinIO integration (project)
Best use case
add-aspire-worker-project is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Create a new .NET Aspire worker project with Kafka, RavenDB, and MinIO integration (project)
Teams using add-aspire-worker-project should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/add-aspire-worker-project/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How add-aspire-worker-project Compares
| Feature / Agent | add-aspire-worker-project | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Create a new .NET Aspire worker project with Kafka, RavenDB, and MinIO integration (project)
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Add Aspire Worker Project Skill
Create a new .NET Aspire worker project with messaging, database, and storage integration for NovaTune.
## Project Context
- Workers location: `src/NovaTuneApp/NovaTuneApp.Workers.{Name}/`
- AppHost: `src/NovaTuneApp/NovaTuneApp.AppHost/`
- Solution: `src/NovaTuneApp/NovaTuneApp.sln`
- Naming convention: `NovaTuneApp.Workers.{PurposeName}`
## Steps
### 1. Create Project Directory
```bash
mkdir -p src/NovaTuneApp/NovaTuneApp.Workers.Lifecycle
```
### 2. Create Project File
Location: `src/NovaTuneApp/NovaTuneApp.Workers.Lifecycle/NovaTuneApp.Workers.Lifecycle.csproj`
```xml
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>dotnet-NovaTuneApp.Workers.Lifecycle</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\NovaTuneApp.ServiceDefaults\NovaTuneApp.ServiceDefaults.csproj" />
<ProjectReference Include="..\NovaTuneApp.ApiService\NovaTuneApp.ApiService.csproj" />
</ItemGroup>
<ItemGroup>
<!-- KafkaFlow for Kafka/Redpanda messaging -->
<PackageReference Include="KafkaFlow" Version="3.1.0" />
<PackageReference Include="KafkaFlow.Microsoft.DependencyInjection" Version="3.1.0" />
<PackageReference Include="KafkaFlow.Serializer.JsonCore" Version="3.1.0" />
<PackageReference Include="KafkaFlow.Admin" Version="3.1.0" />
<!-- RavenDB -->
<PackageReference Include="RavenDB.Client" Version="7.0.2" />
<!-- MinIO -->
<PackageReference Include="Minio" Version="6.0.3" />
<!-- Health Checks -->
<PackageReference Include="AspNetCore.HealthChecks.Kafka" Version="9.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.RavenDB" Version="9.0.0" />
<!-- Serilog -->
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="3.0.1" />
<PackageReference Include="Serilog.Formatting.Compact" Version="3.0.0" />
</ItemGroup>
</Project>
```
### 3. Create Program.cs
Location: `src/NovaTuneApp/NovaTuneApp.Workers.Lifecycle/Program.cs`
```csharp
using Confluent.Kafka;
using KafkaFlow;
using KafkaFlow.Serializer;
using Microsoft.Extensions.Options;
using Minio;
using NovaTuneApp.ApiService.Infrastructure.Configuration;
using NovaTuneApp.Workers.Lifecycle.Handlers;
using NovaTuneApp.Workers.Lifecycle.Services;
using Raven.Client.Documents;
using Serilog;
using Serilog.Events;
using Serilog.Formatting.Compact;
// Bootstrap logging
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.Console(new RenderedCompactJsonFormatter())
.CreateBootstrapLogger();
try
{
var builder = Host.CreateApplicationBuilder(args);
// Add service defaults (OpenTelemetry, health checks, etc.)
builder.AddServiceDefaults();
// Serilog
builder.Services.AddSerilog((services, configuration) => configuration
.ReadFrom.Configuration(builder.Configuration)
.ReadFrom.Services(services)
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("KafkaFlow", LogEventLevel.Information)
.Enrich.FromLogContext()
.Enrich.WithEnvironmentName()
.Enrich.WithMachineName()
.WriteTo.Console(new RenderedCompactJsonFormatter()));
// Configuration
builder.Services.Configure<NovaTuneOptions>(
builder.Configuration.GetSection(NovaTuneOptions.SectionName));
builder.Services.Configure<LifecycleOptions>(
builder.Configuration.GetSection(LifecycleOptions.SectionName));
var topicPrefix = builder.Configuration["NovaTune:TopicPrefix"] ?? "dev";
var bootstrapServers = builder.Configuration.GetConnectionString("messaging")
?? "localhost:9092";
// RavenDB
var ravenConnectionString = builder.Configuration.GetConnectionString("novatune");
string ravenDbUrl;
string ravenDbDatabase;
if (ravenConnectionString != null && ravenConnectionString.Contains(';'))
{
var parts = ravenConnectionString.Split(';')
.Select(p => p.Split('=', 2))
.Where(p => p.Length == 2)
.ToDictionary(p => p[0], p => p[1]);
ravenDbUrl = parts.GetValueOrDefault("URL") ?? "http://localhost:8080";
ravenDbDatabase = parts.GetValueOrDefault("Database") ?? "NovaTune";
}
else
{
ravenDbUrl = ravenConnectionString ?? "http://localhost:8080";
ravenDbDatabase = builder.Configuration["RavenDb:Database"] ?? "NovaTune";
}
builder.Services.AddSingleton<IDocumentStore>(sp =>
{
var store = new DocumentStore
{
Urls = [ravenDbUrl],
Database = ravenDbDatabase
};
store.Initialize();
return store;
});
// MinIO
var minioEndpoint = builder.Configuration.GetConnectionString("storage")
?? "http://localhost:9000";
var minioAccessKey = builder.Configuration["MinIO:AccessKey"] ?? "minioadmin";
var minioSecretKey = builder.Configuration["MinIO:SecretKey"] ?? "minioadmin";
var minioHost = minioEndpoint.Replace("http://", "").Replace("https://", "");
var useSSL = minioEndpoint.StartsWith("https://");
builder.Services.AddSingleton<IMinioClient>(_ =>
new MinioClient()
.WithEndpoint(minioHost)
.WithCredentials(minioAccessKey, minioSecretKey)
.WithSSL(useSSL)
.Build());
// Health Checks
builder.Services.AddHealthChecks()
.AddRavenDB(
setup => setup.Urls = [ravenDbUrl],
name: "ravendb",
timeout: TimeSpan.FromSeconds(5))
.AddKafka(
new ProducerConfig { BootstrapServers = bootstrapServers },
name: "kafka",
timeout: TimeSpan.FromSeconds(5))
.AddUrlGroup(
new Uri($"{minioEndpoint}/minio/health/live"),
name: "minio",
timeout: TimeSpan.FromSeconds(5));
// KafkaFlow Consumer (track deletions)
builder.Services.AddKafka(kafka => kafka
.UseMicrosoftLog()
.AddCluster(cluster =>
{
cluster.WithBrokers([bootstrapServers]);
cluster.AddConsumer(consumer => consumer
.Topic($"{topicPrefix}-track-deletions")
.WithGroupId($"{topicPrefix}-lifecycle-worker")
.WithBufferSize(100)
.WithWorkersCount(2)
.WithAutoOffsetReset(KafkaFlow.AutoOffsetReset.Earliest)
.AddMiddlewares(m => m
.AddDeserializer<JsonCoreDeserializer>()
.AddTypedHandlers(h => h.AddHandler<TrackDeletedHandler>())
)
);
})
);
// Services
builder.Services.AddTransient<TrackDeletedHandler>();
builder.Services.AddScoped<IPhysicalDeletionService, PhysicalDeletionService>();
// Background Services
builder.Services.AddHostedService<KafkaFlowHostedService>();
builder.Services.AddHostedService<PhysicalDeletionBackgroundService>();
var host = builder.Build();
await host.RunAsync();
}
catch (Exception ex)
{
Log.Fatal(ex, "Lifecycle worker terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
```
### 4. Add to Solution
```bash
cd src/NovaTuneApp
dotnet sln add NovaTuneApp.Workers.Lifecycle/NovaTuneApp.Workers.Lifecycle.csproj
```
### 5. Register in AppHost
Location: `src/NovaTuneApp/NovaTuneApp.AppHost/AppHost.cs`
Add project reference to `NovaTuneApp.AppHost.csproj`:
```xml
<ProjectReference Include="..\NovaTuneApp.Workers.Lifecycle\NovaTuneApp.Workers.Lifecycle.csproj"/>
```
Add to AppHost.cs (in the non-testing block):
```csharp
// Lifecycle Worker - handles physical deletion of soft-deleted tracks
builder.AddProject<Projects.NovaTuneApp_Workers_Lifecycle>("lifecycle-worker")
.WithReference(messaging)
.WaitFor(messaging)
.WithReference(database)
.WaitFor(database)
.WithReference(storage.GetEndpoint("api"))
.WaitFor(storage)
.WithEnvironment("NovaTune__TopicPrefix", "dev");
```
### 6. Create Configuration Class
Location: `src/NovaTuneApp/NovaTuneApp.Workers.Lifecycle/Configuration/LifecycleOptions.cs`
```csharp
namespace NovaTuneApp.Workers.Lifecycle.Configuration;
public class LifecycleOptions
{
public const string SectionName = "Lifecycle";
/// <summary>
/// Interval between physical deletion polling.
/// Default: 5 minutes.
/// </summary>
public TimeSpan PollingInterval { get; set; } = TimeSpan.FromMinutes(5);
/// <summary>
/// Maximum tracks to process per cycle.
/// Default: 50.
/// </summary>
public int BatchSize { get; set; } = 50;
/// <summary>
/// Whether physical deletion is enabled.
/// Default: true.
/// </summary>
public bool Enabled { get; set; } = true;
}
```
### 7. Create appsettings.json
Location: `src/NovaTuneApp/NovaTuneApp.Workers.Lifecycle/appsettings.json`
```json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"NovaTune": {
"TopicPrefix": "dev"
},
"Lifecycle": {
"PollingInterval": "00:05:00",
"BatchSize": 50,
"Enabled": true
}
}
```
## Project Structure
```
NovaTuneApp.Workers.Lifecycle/
├── Configuration/
│ └── LifecycleOptions.cs
├── Handlers/
│ └── TrackDeletedHandler.cs
├── Services/
│ ├── IPhysicalDeletionService.cs
│ └── PhysicalDeletionService.cs
├── Program.cs
├── appsettings.json
├── appsettings.Development.json
└── NovaTuneApp.Workers.Lifecycle.csproj
```
## Dependencies Pattern
Workers typically depend on:
| Dependency | Purpose |
|------------|---------|
| `NovaTuneApp.ServiceDefaults` | OpenTelemetry, health checks, service discovery |
| `NovaTuneApp.ApiService` | Shared models, configuration, services |
| `KafkaFlow` | Kafka/Redpanda messaging |
| `RavenDB.Client` | Document database |
| `Minio` | Object storage |
| `Serilog` | Structured logging |
## Verification
After creating the project:
```bash
# Build solution
dotnet build src/NovaTuneApp/NovaTuneApp.sln
# Run the worker standalone
dotnet run --project src/NovaTuneApp/NovaTuneApp.Workers.Lifecycle
# Run with Aspire orchestration
dotnet run --project src/NovaTuneApp/NovaTuneApp.AppHost
```Related Skills
ado-multi-project
Organize specs and tasks across multiple Azure DevOps projects with intelligent content-based mapping. Use when working with project-per-team, area-path-based, or team-based ADO architectures. Handles cross-project coordination and folder structure organization.
add-project
새 프로젝트를 STAR+I로 추가할 때
lets-go-rss
A lightweight, full-platform RSS subscription manager that aggregates content from YouTube, Vimeo, Behance, Twitter/X, and Chinese platforms like Bilibili, Weibo, and Douyin, featuring deduplication and AI smart classification.
thor-skills
An entry point and router for AI agents to manage various THOR-related cybersecurity tasks, including running scans, analyzing logs, troubleshooting, and maintenance.
grail-miner
This skill assists in setting up, managing, and optimizing Grail miners on Bittensor Subnet 81, handling tasks like environment configuration, R2 storage, model checkpoint management, and performance tuning.
ux
This AI agent skill provides comprehensive guidance for creating professional and insightful User Experience (UX) designs, covering user research, information architecture, interaction design, visual guidance, and usability evaluation. It aims to produce actionable, user-centered solutions that avoid generic AI aesthetics.
whisper-transcribe
Transcribes audio and video files to text using OpenAI's Whisper CLI, enhanced with contextual grounding from local markdown files for improved accuracy.
chrome-debug
This skill empowers AI agents to debug web applications and inspect browser behavior using the Chrome DevTools Protocol (CDP), offering both collaborative (headful) and automated (headless) modes.
ontopo
An AI agent skill to search for Israeli restaurants, check table availability, view menus, and retrieve booking links via the Ontopo platform, acting as an unofficial interface to its data.
vly-money
Generate crypto payment links for supported tokens and networks, manage access to X402 payment-protected content, and provide direct access to the vly.money wallet interface.
astro
This skill provides essential Astro framework patterns, focusing on server-side rendering (SSR), static site generation (SSG), middleware, and TypeScript best practices. It helps AI agents implement secure authentication, manage API routes, and debug rendering behaviors within Astro projects.
tech-blog
Generates comprehensive technical blog posts, offering detailed explanations of system internals, architecture, and implementation, either through source code analysis or document-driven research.