Skip to content
Back to skills

Project Structure

ASecurity

.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".

  • 229 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added June 6, 2026
businessgosqltestinggitapi

Works with

  • api

Security analysis

A100/100

Scanned June 6, 2026

npx -y skills add Resgrid/Core --skill project-structure --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Project Structure?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Project Structure
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/resgrid-project-structure/badge)](https://www.skillsdirectory.com/skills/resgrid-project-structure)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
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>
    <!-- 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.0" />
    <PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />

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

    <!-- Testing -->
    <PackageVersion Include="xunit.v3" Version="1.0.0" />
    <PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.0" />
    <PackageVersion Include="Testcontainers.PostgreSql" Version="4.0.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` |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.