Skip to main content
skill CX Codex

project-structure · codewithmukesh — Claude Code skill for .NET solution layout

A skill that tells your agent how to lay out a .NET solution: central package versions, shared build properties, .slnx format and naming rules.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add codewithmukesh/dotnet-claude-kit --skill project-structure -a claude-code
Open on GitHub

What project-structure does

The skill spells out how a .NET solution is organised: where source and test projects live, how projects and namespaces are named, which files control the build. Your agent reads those rules and places new code accordingly instead of guessing.

Inside are four principles plus file examples. Directory.Packages.props keeps NuGet versions in one place, so individual .csproj files carry no Version attribute. Directory.Build.props holds shared settings such as the target framework, Nullable and ImplicitUsings. The solution uses the .slnx format, source sits in src/, tests in tests/.

There is a naming table (solution, project, namespace, feature folder) and a walk through anti-patterns: versions scattered across projects, build properties repeated in every .csproj, test projects mixed into src/. The package versions in the examples are marked as illustrative, and the author advises resolving current ones with dotnet add package without the --version flag. The skill installs into Claude, Codex, Cursor, GitHub Copilot, Gemini CLI and OpenCode, so the layout stays the same whichever editor you switch to.

What it helps with

  • lay out a new .NET project across src and tests folders
  • pull NuGet versions into one file instead of a dozen .csproj files
  • move shared build settings into Directory.Build.props
  • migrate a solution from .sln to .slnx
  • pick names for projects, namespaces and feature folders

Example prompts for the agent

  • Scaffold a new .NET project using the project-structure skill conventions
  • Move the package versions into Directory.Packages.props
  • Check the solution layout — test projects belong in tests/, not src/

How to install project-structure

1Skills CLI (Vercel)

npx skills add codewithmukesh/dotnet-claude-kit --skill project-structure -a claude-code

2Manually: put the files in place

~/.claude/skills/project-structure/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/project-structure/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about project-structure

How do I install project-structure in Claude?

Run npx skills add codewithmukesh/dotnet-claude-kit --skill project-structure -a claude-code. The skill lands in ~/.claude/skills/project-structure/SKILL.md.

What does the project-structure skill do?

It documents .NET solution conventions: the .slnx format, central package management, shared build properties, global usings and naming rules. The agent applies them when you set up a solution or add a project.

Does this skill require .NET 10?

The Directory.Build.props example uses net10.0 and LangVersion 14, and global.json pins SDK 10.0.100. Those are example values, not a hard requirement — swap in your own target framework.

Source text

SKILL.md · MIT
---
name: project-structure
description: >
  .NET solution and project structure conventions. Covers .slnx format,
  Directory.Build.props, Directory.Packages.props for central package management,
  global usings, and naming conventions.
  Load this skill when setting up a new solution, adding projects, configuring
  build properties, or when the user mentions "solution structure", ".slnx",
  "Directory.Build.props", "central package management", "Directory.Packages.props",
  "global usings", ".editorconfig", "project layout", or "naming conventions".
---

# Project Structure

## Core Principles

1. **Central package management** — Use `Directory.Packages.props` to manage NuGet package versions in one place. No version numbers in individual `.csproj` files.
2. **Shared build properties** — Use `Directory.Build.props` for common settings (target framework, nullable, implicit usings). Don't repeat in every project.
3. **.slnx for solutions** — The new XML-based solution format is cleaner and more merge-friendly than the legacy `.sln` format.
4. **src/tests separation** — Source projects in `src/`, test projects in `tests/`. Clear boundary.

## Patterns

### Solution Layout

```
MyApp/
├── MyApp.slnx                       # Solution file
├── Directory.Build.props             # Shared MSBuild properties
├── Directory.Packages.props          # Central package management
├── .editorconfig                     # Code style rules
├── .gitignore
├── global.json                       # SDK version pinning
├── src/
│   ├── MyApp.Api/                    # Web API (entry point)
│   │   ├── MyApp.Api.csproj
│   │   ├── Program.cs
│   │   └── Features/
│   ├── MyApp.Domain/                 # Domain entities, value objects (optional)
│   │   └── MyApp.Domain.csproj
│   └── MyApp.Infrastructure/         # EF Core, external services (optional)
│       └── MyApp.Infrastructure.csproj
└── tests/
    └── MyApp.Api.Tests/
        └── MyApp.Api.Tests.csproj
```

### Directory.Build.props

```xml
<Project>
  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <LangVersion>14</LangVersion>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
  </PropertyGroup>
</Project>
```

### Directory.Packages.props (Central Package Management)

```xml
<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>

  <ItemGroup>
    <!-- Versions below are illustrative — resolve the current stable versions
         with `dotnet add package <name>` (no --version flag); see the packages rule -->
    <!-- ASP.NET Core -->
    <PackageVersion Include="Mediator.Abstractions" Version="3.0.0" />
    <PackageVersion Include="Mediator.SourceGenerator" Version="3.0.0" />
    <PackageVersion Include="FluentValidation.DependencyInjectionExtensions" Version="12.0.0" />

    <!-- Data -->
    <PackageVersion Include="Microsoft.EntityFrameworkCore" Version="10.0.10" />
    <PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.10" />

    <!-- Observability -->
    <PackageVersion Include="Serilog.AspNetCore" Version="10.0.0" />
    <PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.17.0" />

    <!-- Testing -->
    <PackageVersion Include="xunit.v3" Version="3.2.2" />
    <PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.10" />
    <PackageVersion Include="Testcontainers.PostgreSql" Version="4.13.0" />
  </ItemGroup>
</Project>
```

### Project File (.csproj) with Central Package Management

```xml
<Project Sdk="Microsoft.NET.Sdk.Web">
  <!-- No TargetFramework here — inherited from Directory.Build.props -->

  <ItemGroup>
    <!-- No Version attribute — managed centrally -->
    <PackageReference Include="Mediator.Abstractions" />
    <PackageReference Include="Mediator.SourceGenerator" />
    <PackageReference Include="FluentValidation.DependencyInjectionExtensions" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" />
    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
    <PackageReference Include="Serilog.AspNetCore" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\MyApp.Domain\MyApp.Domain.csproj" />
    <ProjectReference Include="..\MyApp.Infrastructure\MyApp.Infrastructure.csproj" />
  </ItemGroup>
</Project>
```

### global.json (SDK Pinning)

```json
{
  "sdk": {
    "version": "10.0.100",
    "rollForward": "latestFeature"
  }
}
```

### .slnx Solution Format

```xml
<Solution>
  <Folder Name="/src/">
    <Project Path="src/MyApp.Api/MyApp.Api.csproj" />
    <Project Path="src/MyApp.Domain/MyApp.Domain.csproj" />
    <Project Path="src/MyApp.Infrastructure/MyApp.Infrastructure.csproj" />
  </Folder>
  <Folder Name="/tests/">
    <Project Path="tests/MyApp.Api.Tests/MyApp.Api.Tests.csproj" />
  </Folder>
</Solution>
```

### Naming Conventions

| Element | Convention | Example |
|---------|-----------|---------|
| Solution | `CompanyName.AppName` or `AppName` | `MyApp.slnx` |
| Project | `AppName.Layer` | `MyApp.Api`, `MyApp.Domain` |
| Namespace | Matches folder path | `MyApp.Api.Features.Orders` |
| Feature folder | PascalCase, plural | `Features/Orders/` |
| Test project | `ProjectName.Tests` | `MyApp.Api.Tests` |

## Anti-patterns

### Don't Scatter Package Versions

```xml
<!-- BAD — version in every .csproj, version drift -->
<PackageReference Include="Mediator.Abstractions" Version="2.0.0" />  <!-- in Project A -->
<PackageReference Include="Mediator.Abstractions" Version="3.0.0" />  <!-- in Project B -->

<!-- GOOD — central management, one version -->
<!-- Directory.Packages.props: <PackageVersion Include="Mediator.Abstractions" Version="3.0.0" /> -->
<!-- .csproj: <PackageReference Include="Mediator.Abstractions" /> -->
```

### Don't Repeat Build Properties

```xml
<!-- BAD — same properties in every .csproj -->
<PropertyGroup>
  <TargetFramework>net10.0</TargetFramework>
  <Nullable>enable</Nullable>
  <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<!-- GOOD — once in Directory.Build.props, inherited everywhere -->
```

### Don't Mix Source and Test Projects

```
# BAD — tests mixed with source
src/
  MyApp.Api/
  MyApp.Api.Tests/    # test project in src/

# GOOD — clear separation
src/
  MyApp.Api/
tests/
  MyApp.Api.Tests/
```

## Decision Guide

| Scenario | Recommendation |
|----------|---------------|
| New solution | `.slnx` format |
| Package version management | `Directory.Packages.props` (central) |
| Shared build settings | `Directory.Build.props` |
| SDK version pinning | `global.json` |
| Common using directives | Global usings in `Directory.Build.props` |
| Small API (1-2 devs) | Single project (`MyApp.Api`) |
| Medium API (3-5 devs) | 2-3 projects (`Api`, `Domain`, `Infrastructure`) |
| Large / modular app | Module-per-project with shared `Contracts` |

© codewithmukesh · MIT · codewithmukesh/dotnet-claude-kit

Similar skills

Everything for Backend and APIs →

project-structure by other authors comes first.

From the same set46

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor