This post is part of the Azure Static Web Apps with Blazor series.
A complete working example is available here: mongeon/code-examples · azure-swa-blazor/01-getting-started.
When you have a Blazor WebAssembly project to deploy, the first reflex is often Azure App Service. It works, sure, but it’s a bit like renting a truck to deliver an envelope. Blazor WASM, once compiled, is just static files. You don’t need a .NET server behind it.
Azure Static Web Apps (SWA) exists for exactly that. The service hosts your static files on a global CDN, handles HTTPS automatically, and integrates with GitHub for continuous deployment. The free tier is generous enough for most personal projects or prototypes.
How is it different from App Service?
App Service is a full application server. Your code runs in a process on a VM somewhere. You pay for compute, even if your app is doing nothing.
Static Web Apps is static file hosting distributed on a CDN. There is no .NET server running. Your Blazor WASM is served as HTML, CSS and WebAssembly directly to the browser. If you need a backend, SWA can hook up Azure Functions, but we’ll cover that in a later article.
For a standalone Blazor WASM project, SWA is simpler, cheaper, and often faster thanks to the CDN.
Creating the Blazor WASM project
We start with a standalone project. No hosted template, because SWA handles the backend separately with Azure Functions.
dotnet new blazorwasm -n Client -o Client
This gives us a basic Blazor WASM project with the Counter and Weather pages. Nothing fancy, but it’s all we need to test the deployment.
The project structure looks like this:
Client/
Pages/
Counter.razor
Home.razor
wwwroot/
Program.cs
Client.csproj
Before going further, make sure it runs locally:
cd Client
dotnet run
You should see the app on https://localhost:5001 (or whatever port shows up in your terminal).
The staticwebapp.config.json file
Blazor WASM is a single-page application (SPA). When a user navigates to /counter, there is no counter.html file on the server. All requests need to fall back to index.html so that Blazor’s router can take over.
Add a staticwebapp.config.json file in your project’s wwwroot folder:
{
"navigationFallback": {
"rewrite": "/index.html"
}
}
Without this file, a refresh on /counter will return a 404. We’ll explore this config file in detail in the next article in the series, but for now this is all we need.
Deploying to Azure from GitHub
Push your code to a GitHub repo if you haven’t already. Then, in the Azure portal:
Create the resource by searching for “Static Web Apps” in the marketplace. Pick the Free tier to start.
Connect your GitHub repo in the deployment section. Azure will ask for the organization, repo and branch.
Configure the build by selecting the “Blazor” preset in the Build Details. The important values:
- App location: the path to your Blazor project (for example
Clientif your .csproj is in aClientsubfolder) - Output location:
wwwroot
Azure will automatically create a GitHub Actions workflow in your repo. This workflow will build and deploy your app on every push to the configured branch.
The GitHub Actions workflow
After creating the resource, check your GitHub repo. There’s a new file in .github/workflows/. The generated workflow looks like this (simplified):
name: Azure Static Web Apps CI/CD
on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened, closed]
branches:
- main
jobs:
build_and_deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build And Deploy
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
repo_token: ${{ secrets.GITHUB_TOKEN }}
action: "upload"
app_location: "Client"
output_location: "wwwroot"
The AZURE_STATIC_WEB_APPS_API_TOKEN secret is added automatically to your repo by Azure when you create the resource. You don’t have to configure anything manually.
Once the workflow runs, your app is available at a URL like https://lively-moss-123456.azurestaticapps.net. No DNS configuration, no SSL certificate to manage.
Checking that it works
Go to the URL provided by Azure. You should see your Blazor app. Click on Counter, increment the counter, then refresh the page. If you set up the staticwebapp.config.json correctly, the page reloads properly instead of showing a 404.
If you get a 404 on refresh, check that the staticwebapp.config.json file is in wwwroot and that it’s included in the publish output.
In the next article, we’ll explore the staticwebapp.config.json file in depth: routes, redirects, security headers, and how to protect specific pages.
Articles in this series
- What is an Azure Static Web App? (This article)
- The staticwebapp.config.json file
- Adding an Azure Functions API
- SWA’s built-in authentication
- Local development with the swa CLI
- PR preview environments
Happy deploying, and enjoy it, the free tier is pretty generous.
This post was written with AI assistance and edited by me.