6 Steps for Setting Up a New .NET Project the Right Way
A friendly, step-by-step guide to starting a clean .NET 10 project with the right folder layout, central packages, analyzers, EditorConfig, and CI.
A small story before we start
Imagine your mother is setting up a new kitchen. Before she cooks even one meal, she does some quiet, boring work first. She decides where the spices go. She labels the jars. She keeps the rice on one shelf and the dal on another. She puts a dustbin in the corner.
None of this is cooking. But because she spent ten minutes organising, every meal after that is faster and calmer. She never hunts for the salt. Guests can find a glass of water by themselves.
Setting up a new .NET project is exactly the same. The first thirty minutes feel boring. You are not building the real feature yet. But if you set up the "kitchen" properly, every day after that is smoother. Your code stays tidy. Your teammates know where things live. Mistakes get caught early.
This guide gives you 6 simple steps to set up a new .NET project the right way. We will use .NET 10, which is the current LTS (Long Term Support) version in 2026, with C# 14. You can follow along even if you are new.
Why bother doing this at all?
You might think: "I just want to write code. Why all this setup?"
Here is the honest answer. A messy start does not hurt you on day one. It hurts you on day sixty, when you have ten projects, three teammates, and nobody remembers which version of a library to use. The setup work is cheap now and very expensive later.
Here is a quick comparison of the two paths.
| Without setup | With setup |
|---|---|
| Versions differ across projects | One version, listed once |
Every .csproj repeats the same settings | Settings live in one shared file |
| Bugs found late, in production | Bugs caught at build time |
| New teammate is confused for days | New teammate runs one command |
| "Works on my machine" problems | Same rules for everyone |
Let us walk through the steps one by one.
Step 1 — Create the solution and your first project
A solution is a box that holds one or more projects. Think of the solution as a school bag and each project as a notebook inside it.
Open a terminal in an empty folder and run these commands. Each one does a small, clear job.
// These are shell commands, shown here so they are easy to copy.
// dotnet new sln -n MyShop
// dotnet new web -n MyShop.Api -o src/MyShop.Api
// dotnet sln add src/MyShop.Api/MyShop.Api.csprojThe first command makes the solution file. In .NET 10 with Visual Studio 2026 you can use the newer .slnx format, which is a much cleaner XML file than the old, bloated .sln. To get it, add --format slnx when you create the solution.
The second command makes a small web project inside a src folder. The third command adds that project to the solution so they know about each other.
From empty folder to first run
Steps
Solution
dotnet new sln
Project
dotnet new web
Add to sln
dotnet sln add
Run
dotnet run
After this, type dotnet run --project src/MyShop.Api and you should see your app start. That is your "hello world" moment. Now we make it tidy.
Step 2 — Pick a clear folder layout
Where you put files matters more than people think. A good rule, recommended in the Microsoft docs and used by many real teams, is to split your code into two top-level folders:
src/holds your real application code.tests/holds your test projects.
This separation is simple but powerful. Anyone who opens your repository instantly knows where the product is and where the tests are. Build scripts can target one folder. New people are not lost.
A common beginner mistake is to dump every project in the root folder. It works for one project. It becomes a mess at ten. So set up src and tests from day one, even if each has only one project for now. It is the labelled spice jar idea again.
Here is a small table of what each project type usually means, so the names are not scary.
| Project | What it holds | Example name |
|---|---|---|
| Api / Web | The entry point users talk to | MyShop.Api |
| Domain | Your core business rules | MyShop.Domain |
| Infrastructure | Database, email, outside systems | MyShop.Infrastructure |
| Tests | Code that checks your code | MyShop.UnitTests |
You do not need all of these on day one. Start small. But knowing the pattern helps you grow without chaos.
Step 3 — Use Central Package Management
This is the step that surprises people the most, because it solves a pain you may not have noticed yet.
Normally, each project lists its own NuGet packages with version numbers inside the .csproj file. With three projects, you might accidentally use version 9.0.1 of a library in one and 9.0.3 in another. These tiny differences cause real, confusing bugs.
Central Package Management (CPM) fixes this. You list every version once, in a single file at the repository root called Directory.Packages.props. Then your project files only say which package they want, not which version.
Create Directory.Packages.props at the root:
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageVersion Include="xunit" Version="2.9.2" />
</ItemGroup>
</Project>Now in each project's .csproj, you reference the package without a version:
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" />
</ItemGroup>The version is gone from the project file. There is exactly one place to change a version, and every project follows it. This feature is built into NuGet (6.2 and later) and is the standard way to manage versions in modern .NET.
How CPM resolves a version
Steps
Project asks
No version in csproj
Central file
Find PackageVersion
Apply
Use that version
Restore
Same for all projects
One tip for safety: a couple of well-known libraries like MediatR and MassTransit are now under a commercial license for many uses. They are still good tools, but check the license before adding them to a paid product. With CPM you at least have one clear place to see and review every dependency you pull in.
Step 4 — Share build rules with Directory.Build.props
You have centralised versions. Now centralise settings.
Every .csproj usually repeats the same lines: which .NET version to target, whether to turn on nullable warnings, and so on. Copying these everywhere is tiring and easy to get wrong.
Directory.Build.props is a special MSBuild file. When you build, MSBuild automatically looks up your folders, finds this file, and applies it to every project below it. You write the settings once, and all projects inherit them, just like house rules everyone in the family follows.
<Project>
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>14.0</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
</Project>Let me explain the important ones in plain words.
Nullableenable turns on warnings when a value might benull. This catches one of the most common crashes in C# before it ever runs.TreatWarningsAsErrorsmakes the build fail on warnings. This sounds harsh, but it keeps small problems from piling up. A warning ignored today becomes a bug next month.ImplicitUsingsremoves the need to write the most commonusinglines in every file. Less noise, cleaner code.
Now adding a new project is almost free. It picks up all the rules automatically. No copy-paste, no drift.
Step 5 — Add analyzers and an EditorConfig
So far we have set up structure. Now we add a helper that reads your code and gently corrects you, like a kind teacher checking homework.
Analyzers are small tools that run during the build and spot problems: unused variables, risky patterns, things that look like bugs. Popular free ones include Meziantou.Analyzer, Roslynator, and SonarAnalyzer.CSharp. You add them like any package (and with CPM, you list the version once).
<ItemGroup>
<PackageReference Include="Meziantou.Analyzer">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Roslynator.Analyzers">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>The PrivateAssets>all part just means "use this while building, but do not ship it to people who use my library."
The second helper is .editorconfig. This is a plain text file that describes your code style: how many spaces to indent, whether to use var, how to name things. The wonderful part is that almost every editor (Visual Studio, VS Code, Rider) reads it automatically. So everyone on the team writes code the same way, even if they have different settings on their own machine.
A tiny example:
// .editorconfig (shown as text)
// root = true
//
// [*.cs]
// indent_style = space
// indent_size = 4
// dotnet_diagnostic.CA1822.severity = warningThat last line shows something powerful: you can set how serious each analyzer rule is. You can make some rules just suggestions and others hard errors. You tune the strictness to fit your team.
What happens when you build with analyzers
Steps
Write
Save your file
Build
dotnet build
Analyzers
Find risky code
Style
Apply editorconfig
Feedback
Fix before runtime
The goal here is simple: catch mistakes at build time, not in front of a user. The earlier you catch a problem, the cheaper it is to fix.
Step 6 — Set up Git and a simple CI pipeline
Your project is now clean and consistent. The last step is to protect it.
First, Git. Run git init and add a .gitignore file so you do not accidentally commit junk like the bin/ and obj/ build folders. The easy way is dotnet new gitignore, which creates a ready-made file tuned for .NET.
Second, CI (Continuous Integration). CI means a robot on the internet that builds and tests your code every time you push. If something is broken, you find out in minutes, not when a user complains. GitHub Actions is a popular, free choice.
Here is the idea of a basic pipeline in plain steps:
| Stage | What it does |
|---|---|
| Restore | Downloads the packages |
| Build | Compiles with all your strict rules |
| Test | Runs everything in tests/ |
| Publish | Optionally packages the app |
Because of the earlier steps, this pipeline is strict and trustworthy. Your TreatWarningsAsErrors setting means a sloppy warning fails CI. Your analyzers run in CI too. Your central versions mean the CI machine builds exactly what you build. Everything connects.
A small but important habit: commit your Directory.Build.props, Directory.Packages.props, and .editorconfig to Git. They are the rules of the kitchen, and everyone who clones the repo should get them automatically.
Putting it all together
Let us zoom out and see how the six pieces support each other. Each step makes the next one stronger.
None of these steps is hard on its own. Together they turn a random pile of files into a project that is pleasant to work in for years. A new teammate can clone it, run dotnet build, and trust that the rules are already in place.
Remember the kitchen. Ten quiet minutes of labelling jars makes every future meal easier. Thirty quiet minutes of project setup makes every future feature easier. That is the whole idea.
Quick recap
- Step 1: Make a solution and your first project. Use
.slnxin .NET 10 if you can. - Step 2: Split code into
src/andtests/. Decide the layout early. - Step 3: Use Central Package Management so every version lives in one file.
- Step 4: Put shared settings in Directory.Build.props (nullable, target framework, warnings as errors).
- Step 5: Add analyzers and an .editorconfig to catch bugs and keep one style.
- Step 6: Set up Git with a
.gitignore, and a simple CI pipeline to build and test on every push. - Target .NET 10 (LTS) with C# 14 for new projects in 2026.
- Watch licenses: tools like MediatR and MassTransit are now commercially licensed for many uses.
- The setup is cheap now and saves a lot of pain later. Treat it like labelling your kitchen jars.
References and further reading
- Central Package Management — Microsoft Learn
- Organize projects for .NET — Microsoft Learn
- Introducing Central Package Management — .NET Blog
- How to Start a New .NET Project in 2026 — Anton Dev Tips
- Central Package Management in .NET — Milan Jovanović
- David Fowler's .NET project structure notes — GitHub Gist
Related Posts
SOLID Principles in C# and .NET: A Beginner-Friendly Guide
Learn the 5 SOLID principles in C# and .NET with simple words, real-life examples, diagrams, and clean code you can copy and try yourself today.
What Rewriting a 40-Year-Old Project Taught Me About Software Development
Honest lessons from rewriting a 40-year-old legacy app to .NET 10. Why big-bang rewrites fail, the strangler pattern, tests, and respecting old code.
The Urge to Build Something: Turn That Spark Into a Real .NET App
Got the itch to build something? Learn how to turn that urge into a real, finished .NET 10 app with small steps, a tiny first project, and zero fear.
40 Lessons I Learned in 12 Years as a .NET Developer
Forty honest, beginner-friendly lessons from 12 years of .NET work, covering C#, EF Core, testing, deployment, teamwork, and a calm career.
8 Tips to Write Clean Code in C# and .NET
Learn 8 simple, beginner-friendly tips to write clean C# and .NET code with clear names, small methods, good error handling, and easy-to-read structure.
Building Semantic Search With Amazon S3 Vectors and Semantic Kernel
A beginner-friendly guide to building semantic search in .NET using Amazon S3 Vectors for cheap storage and Semantic Kernel for embeddings.