# Program.cs Setup Checklist (Blazor Server)

> **Scope:** blazor-azure
> **Layer:** 2 (on keyword)
> **Keywords:** program.cs, startup, configuration, blazor, setup
> **Load When:** blazor project setup

## Template

```csharp
var builder = WebApplication.CreateBuilder(args);

// === SERVICES ===
builder.Services.AddRazorComponents().AddInteractiveServerComponents();
builder.Services.AddHttpClient();
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped(sp =>
{
    var client = sp.GetRequiredService<IHttpClientFactory>().CreateClient();
    var ctx = sp.GetRequiredService<IHttpContextAccessor>().HttpContext;
    if (ctx != null) client.BaseAddress = new Uri($"{ctx.Request.Scheme}://{ctx.Request.Host}");
    return client;
});
builder.Services.AddDbContext<AppDbContext>(o =>
    o.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
// builder.Services.AddFluentUIComponents();  // or AddMudServices()
// builder.Services.AddHangfire(...); builder.Services.AddHangfireServer();

var app = builder.Build();

// === MIDDLEWARE (ORDER CRITICAL!) ===
if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); app.UseHsts(); }
app.UseHttpsRedirection();
app.UseStaticFiles();       // MUST be before UseAntiforgery!
app.UseAntiforgery();
app.MapRazorComponents<App>().AddInteractiveServerRenderMode();
// app.MapControllers();
// app.MapHangfireDashboard("/hangfire");
app.Run();
```

## Services Checklist

| Service | Required | Error if Missing |
|---------|----------|------------------|
| `AddRazorComponents()` + `AddInteractiveServerComponents()` | Yes | Components don't render / static only |
| `AddHttpClient()` + `AddHttpContextAccessor()` + BaseAddress | **Critical** | DI fails / "Invalid URI" errors |
| `AddDbContext()` | If EF Core | Can't inject DbContext |
| `AddFluentUIComponents()` / `AddMudServices()` | If UI lib | Components unstyled |
| `AddHangfire()` + `AddHangfireServer()` | If background jobs | Can't enqueue jobs |

## Middleware Order

| # | Middleware | Required | Error if Wrong |
|---|-----------|----------|----------------|
| 1 | `UseExceptionHandler()` | Prod only | Unhandled exceptions crash |
| 2 | `UseHsts()` | Prod only | HTTP allowed in prod |
| 3 | `UseHttpsRedirection()` | Yes | Security risk |
| 4 | **`UseStaticFiles()`** | **Critical** | Static files 404 |
| 5 | `UseAntiforgery()` | Yes | Form submissions fail |
| 6 | `MapRazorComponents()` | Yes | App doesn't load |
| 7 | `MapControllers()` | If API | API 404 |

## Common Mistakes

| Mistake | Symptom | Fix |
|---------|---------|-----|
| Missing `UseStaticFiles()` | CSS/JS don't apply | Add before `UseAntiforgery()` |
| HttpClient without BaseAddress | `InvalidOperationException: Invalid URI` | Set via `IHttpContextAccessor` (see template) |
| Wrong middleware order | Static 404, forms fail | Follow order above exactly |

## UI Library Setup

**Fluent UI:** `builder.Services.AddFluentUIComponents()` → wrap in `<FluentProvider Theme="@theme">`
**MudBlazor:** `builder.Services.AddMudServices()` → add `<MudThemeProvider/>` + `<MudDialogProvider/>` + `<MudSnackbarProvider/>`
**Hangfire:** `AddHangfire(c => c.UseSqlServerStorage(...))` + `AddHangfireServer()` → `MapHangfireDashboard("/hangfire")`

## Quick Checklist

- [ ] `AddRazorComponents()` + `AddInteractiveServerComponents()`
- [ ] `AddHttpClient()` + `AddHttpContextAccessor()` + BaseAddress
- [ ] `AddDbContext()` (if EF Core)
- [ ] UI library registered
- [ ] `UseStaticFiles()` BEFORE `UseAntiforgery()`
- [ ] Middleware in correct order
- [ ] `MapRazorComponents<App>().AddInteractiveServerRenderMode()`

> **Ref:** [blazor-pitfalls.md](./blazor-pitfalls.md) | [blazor-lifecycle.md](./blazor-lifecycle.md) | [dotnet10-compatibility.md](./dotnet10-compatibility.md)

---

*MORPH-SPEC by Polymorphism Tech*
