Most developers create a new Web API and immediately start writing controllers, entities, and endpoints.
That works until the project grows.
Then formatting becomes inconsistent, NuGet versions start drifting, and your AI coding assistant keeps making decisions that do not match your architecture.
Before writing the first endpoint, I recommend setting up these three things:
.editorconfigCentral NuGet Package Management
CLAUDE.md
They take a few minutes to configure and save hours of cleanup later.
The .editorconfig file defines how code should look across the entire solution.
It can control:
Indentation and spacing
File-scoped namespaces
Brace placement
Use of
varNaming conventions
Unused imports
Code-analysis severity
Special rules for migrations and tests
For example:
root = true
[*.cs]
indent_size = 4
indent_style = space
csharp_style_namespace_declarations = file_scoped
dotnet_style_readonly_field = true
dotnet_diagnostic.IDE0005.severity = warning
Without an.editorconfig, every developer’s IDE can format code differently.
One person uses var. Another writes explicit types. One removes braces. Another adds them back.
Soon, your pull requests contain more formatting changes than actual business logic.
A shared .editorconfig gives the whole team one coding standard. Your existing configuration can also enforce interface naming, PascalCase members, analyzer rules, migration exclusions, and test-specific exceptions.
The goal is simple:
Stop debating formatting during code reviews.
Let the configuration handle it.
In a solution with multiple projects, package versions can quickly become inconsistent.
Your API project might use one version of Entity Framework Core while your Persistence project uses another.
That is how strange restore errors and dependency conflicts begin.
Create a Directory.Packages.props file at the solution root:
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>
true
</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
<ItemGroup>
<PackageVersion
Include="Microsoft.EntityFrameworkCore"
Version="9.0.4" />
<PackageVersion
Include="Npgsql.EntityFrameworkCore.PostgreSQL"
Version="9.0.4" />
<PackageVersion
Include="Serilog.AspNetCore"
Version="9.0.0" />
<PackageVersion
Include="OpenTelemetry.Extensions.Hosting"
Version="1.15.3" />
</ItemGroup>
</Project>
Your individual project files can then reference packages without specifying versions:
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" />
<PackageReference Include="Serilog.AspNetCore" />
</ItemGroup>
Now every project gets its package versions from one place.
This gives you:
One place to update packages
Consistent versions across projects
Easier security upgrades
Fewer dependency conflicts
Cleaner
.csprojfiles
CentralPackageTransitivePinningEnabled also lets NuGet promote and pin a transitive dependency when a centrally defined version needs to be enforced.
You can combine this with a Directory.Build.props file for solution-wide settings:
<Project>
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<AnalysisLevel>latest</AnalysisLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>
</Project>
A good rule is:
Package versions belong in
Directory.Packages.props. Shared build rules belong inDirectory.Build.props.
Also, do not copy a hundred packages into a new project just because you might need them someday.
Add packages when the project actually needs them. NuGet packages are dependencies, not Pokémon.
If you use Claude Code or another AI coding assistant, create a CLAUDE.md file at the repository root.
This file acts as the project’s instruction manual.
It should explain:
What the application does
Which technologies it uses
How the solution is structured
Where new features should go
Which commands should be used
How migrations should be created
How tests should be organized
Which architectural rules must never be broken
Which actions require explicit approval
For example:
# Project Guidelines
This project is a .NET 9 Web API using Clean Architecture,
EF Core, PostgreSQL, Wolverine, and OpenTelemetry.
## Architecture
- Domain contains entities and domain events.
- Application contains business logic and abstractions.
- Persistence contains EF Core and service implementations.
- Infrastructure contains external integrations.
- API contains controllers and dependency injection.
## Important Rules
- Never use DbContext directly in the Application layer.
- Never create EF Core migrations manually.
- Every new feature must include tests.
- Never run git push unless explicitly requested.
- Use fluent LINQ syntax instead of query syntax.
Without project instructions, the AI has to guess.
It may place database code inside the Application layer, create migrations manually, skip tests, introduce a different folder structure, or push code when you only asked it to make a local change.
A detailed CLAUDE.md can document commands, architecture, feature workflows, security rules, testing expectations, deployment constraints, and even instructions such as never running git push without permission.
The AI does not know your unwritten rules.
Write them down once, and you will not need to repeat them in every prompt.
When starting a new Web API, I now follow this order:
Create the solution and projects.
Add
.editorconfig.Add
Directory.Build.props.Add
Directory.Packages.props.Add
CLAUDE.md.Configure analyzers and warnings.
Run
dotnet build.Only then start building features.
These files are not exciting.
They will not appear in your product demo, and your client will never ask about them.
But they create the foundation for consistent code, predictable builds, controlled dependencies, and safer AI-assisted development.
A clean project does not begin with the first controller.
It begins with the rules that every controller must follow.
Boost your .NET skills by subscribing to my YouTube Channel
Promote yourself to 10,000+ subscribers by sponsoring this newsletter

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.