How to deploy ASP.NET Blazor WebAssembly to GitHub Pages
Tags: blazor, dotnet, aspnet, github
Published: 2020-09-02 21:04:14

---
title: How to deploy ASP.NET Blazor WebAssembly to GitHub Pages
published: true
date: 2020-08-31 00:00:00 UTC
description: With ASP.NET Blazor WebAssembly you can create .NET applications that run completely inside of the browser. The output of a Blazor WASM project are all static files. You can deploy these applications to various static site hosts like GitHub Pages.
tags: blazor, dotnet, aspnet, github
cover_image: https://swimburger.net/media/zl3ltmv4/blazor-github-social.png?anchor=center&mode=crop&width=1000&height=420&rnd=132433606500300000
canonical_url: https://swimburger.net/blog/dotnet/how-to-deploy-aspnet-blazor-webassembly-to-github-pages
---

With ASP.NET Blazor WebAssembly (WASM) you can create .NET web applications that run completely inside of the browser sandbox. The publish output of a Blazor WASM project are **all static files**. Now that you can run .NET web applications without server-side code, you can deploy these applications to various **static site hosts, such as Azure Static Web Apps and GitHub Pages**.

Check out this walkthrough to learn [how to deploy Blazor WASM to Azure Static Web Apps](https://swimburger.net/blog/dotnet/how-to-deploy-aspnet-blazor-webassembly-to-azure-static-web-apps "How to deploy ASPNET Blazor WebAssembly to Azure Static Web Apps").

This walkthrough will show you how to deploy Blazor WASM to GitHub Pages using GitHub Actions. GitHub pages provides you with free hosting for static websites.

This how-to will walk you through these high-level steps:

1.  Create Blazor WebAssembly project
2.  Commit the project to a Git repository
3.  Create a new GitHub project and push the Git repository to GitHub
4.  Create a GitHub Actions Workflow
5.  Run GitHub Actions Workflow

**Prerequisites**:

*   .NET Core 3.1
*   Git
*   GitHub account

**You can refer to the code used throughout this walkthrough in [this GitHub repository](https://github.com/Swimburger/BlazorGitHubPagesDemo).**

# Create ASP.NET Core Blazor WebAssembly project

Run the following commands to create a new Blazor WASM project:

```
mkdir BlazorGitHubPagesDemo
cd BlazorGitHubPagesDemo
dotnet new blazorwasm
```

To give your application a try, run `dotnet run` and browse to the URL in the output (probably https://localhost:5001):
```
dotnet run
# info: Microsoft.Hosting.Lifetime[0]
#       Now listening on: https://localhost:5001
# info: Microsoft.Hosting.Lifetime[0]
#       Now listening on: http://localhost:5000
# info: Microsoft.Hosting.Lifetime[0]
#       Application started. Press Ctrl+C to shut down.
# info: Microsoft.Hosting.Lifetime[0]
#       Hosting environment: Development
# info: Microsoft.Hosting.Lifetime[0]
#       Content root path: C:\Users\niels\source\repos\BlazorGitHubPagesDemo
```

Optional: You can use the `dotnet publish` command to publish the project and verify the output:
```
dotnet publish -c Release
# Microsoft (R) Build Engine version 16.7.0+b89cb5fde for .NET
# Copyright (C) Microsoft Corporation. All rights reserved.
# 
#   Determining projects to restore...
#   All projects are up-to-date for restore.
#   BlazorGitHubPagesDemo -> C:\Users\niels\source\repos\BlazorGitHubPagesDemo\bin\Release\netstandard2.1\BlazorGitHubPagesDemo.dll
#   BlazorGitHubPagesDemo (Blazor output) -> C:\Users\niels\source\repos\BlazorGitHubPagesDemo\bin\Release\netstandard2.1\wwwroot
#   BlazorGitHubPagesDemo -> C:\Users\niels\source\repos\BlazorGitHubPagesDemo\bin\Release\netstandard2.1\publish\
```

In the publish directory, you will find a web.config file and a wwwroot folder. The config file helps you host your application in IIS, but you don't need that file for static site hosts. **Everything you need will be inside of the wwwroot folder. The wwwroot folder contains the index.html, CSS, JS, and DLL files necessary to run the Blazor application**.

# Push Blazor project to GitHub

For this walkthrough, your application source code must be inside of a GitHub repository.  
First, you need to create a local Git repository and commit your source code to the repository using these commands:
```
# add the gitignore file tailored for dotnet applications, this will ignore bin/obj and many other non-source code files
dotnet new gitignore
# create the git repository
git init
# track all files that are not ignore by .gitignore
git add --all
# commit all changes to the repostiroy
git commit -m "Initial commit"
```

Create a new GitHub repository ([instructions](https://docs.github.com/en/github/getting-started-with-github/create-a-repo)) and copy the commands to "push an existing repository from the command line" from the empty GitHub repository page, here's what it should looks like but with a different URL:

```
git remote add origin https://github.com/Swimburger/BlazorGitHubPagesDemo.git
git push -u origin master
```

# Create a GitHub Actions Workflow

Now that your source code has been pushed to GitHub, you'll need to create a **GitHub Actions Workflow** that builds your project, commits the output and pushes the code to a separate GitHub branch. GitHub Pages will use this separate branch (usually named '**gh-pages**') as the static files for your site.

Start by navigating to the **Actions** tab in your GitHub repository and click on the link '**set up a workflow yourself**':

![Screenshot of GitHub repository with Actions tab selected and a highlighted link set up a workflow yourself](https://swimburger.net/media/d4sniipo/2-github-repository-actions-page.png) 

Clicking that link will take you to the 'Edit new file' page. The file that you are about to create will instruct GitHub Actions how to build and deploy your project using YAML.  
These Workflow YAML files will be stored under the folder '.github/workflows/'.

Check out [the GitHub Actions documentation to learn more about creating workflows](https://docs.github.com/en/actions).

On the right side you can browse the GitHub Actions marketplace and read documentation. The GitHub Actions marketplace already has a ton of pre-made actions so you don't have reinvent the wheel. For example, when you search for '.NET', the first result is 'Setup .NET Core SDK' which is an action provided by the GitHub organization. You'll be using this action in the next steps.

![Screenshot of the GitHub Actions Workflow editor while searching for .NET in the marketplace pane](https://swimburger.net/media/debfp5ti/4-github-repository-actions-add-net-core-sdk.png) 

Delete all code in this file so you can build your workflow from scratch.  
The first line you'll need to add is the 'name' property. Give a meaningful name for your workflow:

```
name: Deploy to GitHub Pages
```

Next, you need to specify what will trigger the workflow. Add the following lines:

```
# Run workflow on every push to the master branch
on:
  push:
    branches: [ master ]
```

These lines instruct GitHub Actions to run your workflow on every `git push` to the master-branch.

Now, you must configure your jobs, and which image each job will run on. Give your job a meaningful name following the kebab-case naming convention such as `deploy-to-github-pages`.  
Configure your job to run on Ubuntu by adding `runs-on: ubuntu-lates`, and add an empty steps property.
```
jobs:
  deploy-to-github-pages:
    # use ubuntu-latest image to run steps on
    runs-on: ubuntu-latest
    steps:
```
The first step to add will be using the `checkout` action provided by GitHub. Without passing any parameters to the action, the `checkout` action will by default perform a `git checkout` against your master branch.
```
    # uses GitHub's checkout action to checkout code form the master branch
    - uses: actions/checkout@v2
```
Once this action is performed, your code will be available to work with.

To build and publish the Blazor application, you'll also need to have the .NET Core SDK which doesn't come pre-installed with the Ubuntu machine. Using the `setup-dotnet` action provided by GitHub, you can easily install the .NET SDK on top of the Ubuntu machine:
```
    # sets up .NET Core SDK 3.1
    - name: Setup .NET Core SDK
      uses: actions/setup-dotnet@v1.6.0
      with:
        dotnet-version: 3.1
```
By passing in the `dotnet-version` parameter, you can specify which version of the .NET SDK you want to install.

Now that the .NET Core SDK is installed, you can run the `dotnet publish` command to build and deploy your Blazor app. Using the `run` property, you can specify which commands to execute. Add a `run` property with value of your `dotnet publish` command.
```
    # publishes Blazor project to the release-folder
    - name: Publish .NET Core Project
      run: dotnet publish BlazorGitHubPagesDemo.csproj -c Release -o release --nologo
```
*   Using the `-c` (--configuration) argument, you can tell to build the project using the `Release` configuration.
*   Using the `-o` (--output) argument, you can specify where to put the published files. **Tell dotnet to publish the project to the `release` folder**.
*   The `--nologo` argument will prevent some unnecessary lines from being output to the console.

Now that you have successfully published the project to the 'release' folder, you can use another very helpful action from the [marketplace called 'github-pages-deploy-action'](https://github.com/marketplace/actions/deploy-to-github-pages). This action will make it easy to publish your static files to GitHub Pages.
```
    - name: Commit wwwroot to GitHub Pages
      uses: JamesIves/github-pages-deploy-action@3.5.9
      with:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        BRANCH: gh-pages
        FOLDER: release/wwwroot
```
*   The `${{ secrets.GITHUB_TOKEN }}` resolves to a **token used for securely communicating with GitHub on your behalf**. This token is available by default in all workflows and permissions are limited to the repository that contains your workflow. **By passing it into the `GITHUB_TOKEN` property, the action can use it to create and push to the 'gh-pages' branch.**
*   The `BRANCH` property will configure which branch the action will create and push to. **Set this to 'gh-pages'.**
*   The `FOLDER` property will configure which folder and files will be pushed to the 'gh-pages' branch. **Set this to 'release/wwwroot'.** This is where the project will be published, and all the static resources are in the wwwroot-subfolder.

Now that all steps are in place, commit the file:

![Screenshot of committing GitHub Action Workflow file](https://swimburger.net/media/vxllchwp/5-github-repository-actions-commit-workflow.png) 

Navigate back to the GitHub Actions overview page by pressing the "Actions" tab.

![Screenshot of GitHub Actions landing page with workflow run](https://swimburger.net/media/ya5bnaux/6-github-repository-actions-workflow-result-overview.png) 

You can now find your GitHub Action Workflow and the workflow runs on this page. Click on your first run which was automatically created when you committed the workflow, and watch it publish your project to the 'gh-pages' branch:

![Screenshot of GitHub Actions Workflow run output](https://swimburger.net/media/hnwjlcv5/7-github-repository-actions-workflow-run-results.png) 

Once completed, you can see the result by navigating to the 'gh-pages' branch in your repository:

![Screenshot of GitHub repository gh-pages branch](https://swimburger.net/media/ivwbmlvu/8-github-repository-gh-pages-branch.png) 

The last step is to **enable GitHub pages in the repository settings**. Navigate to the settings by clicking on the **'Settings' tab**. Scroll down to the '**GitHub Pages**' section and **select the 'gh-pages' branch in the 'Source' dropdown**.

![Screenshot of the &#x27;GitHub Pages&#x27; section in the GitHub Repository Settings](https://swimburger.net/media/4deldpqu/9-github-repository-configure-github-pages.png) 

After a few seconds to a minute, the GitHub Pages site should be available at **'\[YOUR\_USERNAME\].github.io/\[YOUR\_REPOSITORY\_NAME\]'**.  
But you'll notice that your Blazor application isn't working as expected. You'll be greeted with this:

![Screenshot of broken Blazor application](https://swimburger.net/media/stvhzcu2/10-broken-blazor-site.png) 

If you look at the console output, you'll find 404 errors for multiple files:

![Broken Blazor Application Console with 404 errors](https://swimburger.net/media/1hwgwc2u/11-broken-blazor-site-console-output.png) 

The problem is that the application is trying to fetch the resources at the root of the website (**username.github.io/**), not the GitHub Pages subfolder (**username.github.io/repo_name**).  
This is because of the **base-tag in the HTML head** which tells the browser to **resolve files relatively to the root of the server address**:
```
<!DOCTYPE html>
<html>
<head>
    ...
    <base href="/" />
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/app.css" rel="stylesheet" />
</head>
<body>
    ...
    <script src="_framework/blazor.webassembly.js"></script>
</body>
</html>
```
To solve this, you need to update the base-tag to `<base href="https://swimburger.net/your_repo_name/" />`.  
**If you were to do this directly inside of the master-branch, that would break the application for local development**. So instead of that, you can run a **command inside of your workflow to automatically replace the base tag**.
Navigate to the workflow YAML file in the master-branch and add the following section right after the `dotnet publish` action:
```
    # changes the base-tag in index.html from '/' to 'BlazorGitHubPagesDemo' to match GitHub Pages repository subdirectory
    - name: Change base-tag in index.html from / to BlazorGitHubPagesDemo
      run: sed -i 's/<base href="\/" \/>/<base href="\/BlazorGitHubPagesDemo\/" \/>/g' release/wwwroot/index.html
```
Make sure to replace 'BlazorGitHubPagesDemo' with your repository name. This command will update the file in place, **replacing the default base-tag with the subfolder-version**. Commit this change and verify the result.  
The favicon.ico and CSS-files are now loading successfully, but unfortunately as you solved one issue, another popped up:

![Screenshot of the broken Blazor app failing to load JavaScript](https://swimburger.net/media/s5ahh1b2/12-broken-blazor-site-console-output-post-base-fix.png) 

GitHub Pages by default expects you to use the Jekyll static site generator. As part of this default, GitHub pages will **not serve any files or folder starting with and underscore**. As it happens, Blazor does use underscores in the '**\_framework**' folder. Without these files, the Blazor application will not function.  
Luckily, **GitHub Pages will turn off this behavior** if you add an empty '**.nojekyll**' file at the root of the 'gh-pages' branch.  
You could create an empty '.nojekyll' file in the 'wwwroot' folder in the master branch or you could add another command to the workflow to create this file for you. This how-to will do the latter.  
Navigate back to the workflow YAML file and add the following step before the GitHub Pages deploy step:
```
    # changes the base-tag in index.html from '/' to 'BlazorGitHubPagesDemo' to match GitHub Pages repository subdirectory
    - name: Change base-tag in index.html from / to BlazorGitHubPagesDemo
      run: sed -i 's/<base href="\/" \/>/<base href="\/BlazorGitHubPagesDemo\/" \/>/g' release/wwwroot/index.html
```
Commit your changes and once the workflow run finishes, your Blazor application is finally fully functional:

![Screenshot of working Blazor app on GitHub Pages](https://swimburger.net/media/lxpheoi5/13-working-github-pages-blazor-site.png) 

Here's the entire workflow YAML file:
```
name: Deploy to GitHub Pages

# Run workflow on every push to the master branch
on:
  push:
    branches: [ master ]

jobs:
  deploy-to-github-pages:
    # use ubuntu-latest image to run steps on
    runs-on: ubuntu-latest
    steps:
    # uses GitHub's checkout action to checkout code form the master branch
    - uses: actions/checkout@v2
    
    # sets up .NET Core SDK 3.1
    - name: Setup .NET Core SDK
      uses: actions/setup-dotnet@v1.6.0
      with:
        dotnet-version: 3.1

    # publishes Blazor project to the release-folder
    - name: Publish .NET Core Project
      run: dotnet publish BlazorGitHubPagesDemo.csproj -c Release -o release --nologo
    
    # changes the base-tag in index.html from '/' to 'BlazorGitHubPagesDemo' to match GitHub Pages repository subdirectory
    - name: Change base-tag in index.html from / to BlazorGitHubPagesDemo
      run: sed -i 's/<base href="\/" \/>/<base href="\/BlazorGitHubPagesDemo\/" \/>/g' release/wwwroot/index.html

    # add .nojekyll file to tell GitHub pages to not treat this as a Jekyll project. (Allow files and folders starting with an underscore)
    - name: Add .nojekyll file
      run: touch release/wwwroot/.nojekyll
      
    - name: Commit wwwroot to GitHub Pages
      uses: JamesIves/github-pages-deploy-action@3.5.9
      with:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        BRANCH: gh-pages
        FOLDER: release/wwwroot
```

# Summary

Blazor WebAssembly can be served as static files. These files can be hosted in static hosting sites such as GitHub Pages. Using GitHub Actions you can create a workflow to automatically deploy the Blazor application to GitHub pages. Before publishing the files to GitHub pages, you must update the base-tag to point to the correct subfolder. You also must add a '.nojekyll' file to ensure files and folders starting with an underscore will be served by GitHub Pages successfully.