Previously, in Part 1, we created ClinicApp with the Blazor Web App template, ran it, and clicked a counter button powered entirely by C#.

Today we slow down and look around. When you open the ClinicApp folder, you're greeted by a dozen files you didn't write. It's tempting to shrug and say "template stuff" — but that's how projects start feeling like magic, and magic is exactly what we're here to remove. By the end of this tour, every file will have a job you can name. Here's the map:

ClinicApp — project files
ClinicApp/ ├── Program.cs ← startup: services + pipeline ├── ClinicApp.csproj ← the project file ├── Components/ │ ├── App.razor ← the HTML shell │ ├── Routes.razor ← the router │ ├── _Imports.razor ← shared usings │ ├── Layout/ │ │ ├── MainLayout.razor ← frame around every page │ │ └── ReconnectModal.razor ← reconnection UI │ └── Pages/ │ ├── Home.razor ← a page (route: /) │ └── Counter.razor ← a page (route: /counter) └── wwwroot/ ← css, images, static files
The Blazor Web App template, at a glance — every file has one clear job.

Think of the app as a theater production. Someone turns on the lights, someone builds the stage, someone decides which scene plays. Let's meet the crew.

Program.cs — the ignition

Every .NET app starts here. Program.cs builds the app, registers the services it will need (we'll add our own PatientService here later in the series), wires up Blazor, and finally starts the web server. It runs once, at startup — like turning the key in a car. You'll edit it occasionally; you'll rarely need to stare at it.

Components/App.razor — the HTML shell

View the source of any page in your running app and you'll see a normal HTML document: <html>, <head>, <body>, stylesheet links. That skeleton lives in App.razor. It's the outermost wrapper around everything else — the theater building itself.

Components/Routes.razor — the router

When you visit /counter, how does Blazor know which page to show? That's the router's job. Routes.razor looks at the URL, finds the component whose address matches, and renders it. No match? It shows a "not found" message instead. It's the box office, checking your ticket and pointing you to the right seat.

_Imports.razor — shared usings

In C#, you write using statements at the top of each file. Components need those too — but repeating them in every single .razor file would get old fast. _Imports.razor collects the common ones once, and every component in the project gets them automatically. Quietly convenient, and it will do us a favor in Part 3.

Components/Layout/MainLayout.razor — the frame

Notice how every page in ClinicApp shares the same sidebar and top row? Pages don't repeat that markup — it lives in the layout. MainLayout.razor is the picture frame; each page is the picture slotted inside it. Change the frame once, and every page changes with it. Next to it you'll also find ReconnectModal.razor, a recent addition to the template: the built-in reconnection UI that appears automatically if the app's live connection to the server drops.

Components/Pages/ — the pages themselves

Here's a secret that simplifies everything: Home.razor and Counter.razor are not special "page files." They are ordinary components that happen to have an address, declared with a @page directive at the top. Give any component an address and it becomes a page — that's the whole trick. Our own Patients.razor and PatientDetails.razor pages will join this folder later in the series.

wwwroot/ — static files

Anything the browser should fetch as-is — stylesheets, images, favicons — lives in wwwroot. If it's a plain file with no C# in it, this is its home.

ClinicApp.csproj — the project file

One sentence, as promised: this small file tells the .NET SDK what kind of project this is and which packages it depends on.

Reading Counter.razor like a local

Let's put the tour to work and read a real file. Open Components/Pages/Counter.razor:

@page "/counter"
@rendermode InteractiveServer

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

Every component you'll ever write has up to three zones, and here they all are:

  • Directives at the top — lines starting with @. @page "/counter" gives the component its address, and @rendermode InteractiveServer is what makes the page respond to clicks. For now, just know that interactive pages need that line under @page — the full story of render modes is Part 12's job.
  • Markup in the middle — HTML, with C# values dropped in wherever you see an @, like @currentCount.
  • Code at the bottom — a @code block holding plain C#: fields, methods, whatever the component needs. @onclick="IncrementCount" is the bridge between zones: a click in the markup runs a method in the code.

Note: Did you notice how often the word component came up? The shell is a component. The router is a component. The layout, the pages — components all the way down. "Everything is a component" is the single most useful idea in Blazor, and it's the theme of this entire series.

What's next

You now know the whole cast — nothing in ClinicApp should feel like magic anymore. So let's start writing components of our own. In Part 3, we'll build PatientCard.razor, our first reusable piece of UI, and use it to put our first patients on screen. See you there!