Deployment
A ShellDocs site is a Blazor Web App. You can run it on a .NET host, or export it to static files with shelldocs build and serve those from any static host. This site runs on a .NET host, as a Docker image.
Choosing
| Prop | Type | Default | Description |
|---|---|---|---|
Static export |
shelldocs build |
— | Plain HTML, CSS and JS. Free or cheap hosting, nothing to keep running. Search works. Demos with event handlers render but do not respond. |
A .NET host |
dotnet publish |
— | Everything works, including demos with event handlers. Needs a server or container that runs ASP.NET Core. |
What works on a static export
shelldocs build prerenders every page. The chrome is written so its initial state comes from the server and shelldocs.js handles the clicks, which means most of it needs no Blazor runtime.
| Prop | Type | Default | Description |
|---|---|---|---|
Page content and navigation |
works |
— | Every page is a real HTML file. Links are ordinary links. |
Sidebar sections |
works |
— | Expand and collapse. The section holding the current page starts open. |
Package and version selectors |
works |
— | Menus open and close, options are links. |
Table of contents |
works |
— | Highlights the heading in view. |
Theme toggle |
works |
— | Remembers the choice in localStorage. |
Tabs and CodeGroup |
works |
— | Including sync groups. |
Preview frames |
works |
— | Preview and Code tabs, copy, the actions menu. |
Mobile navigation |
works |
— | The drawer opens, closes on a link, the backdrop or Escape. |
Redirects |
works |
— | Written as redirect pages. |
Search |
works |
— | The index is a file in the export and is ranked in the browser. See below. |
Collapsing the whole sidebar |
works |
— | The desktop collapse button. The choice is remembered across pages. |
Not-found page |
works |
— | Written as 404.html, which most static hosts serve for unknown URLs. It names the address the reader asked for. |
llms.txt and agent files |
works |
— | Written into the export as files, with the page actions menu working. See AI agents (llms.txt). |
Demos with event handlers |
needs a server |
— | A demo that reacts to clicks renders in its initial state and does not respond. |
Search
The app serves its search index at /_shelldocs/search.json, and shelldocs build copies that file into the export. shelldocs.js fetches it the first time a reader opens search and ranks it in the browser, with the same scoring on a static host as on a .NET host. Nothing is sent to a server, and there is no external service to set up. More in Search.
The site and the CLI both need to be on 0.1.15-alpha or later. shelldocs build warns when the site's ShellDocs.Components is too old to serve an index.
What still needs a server
A demo with @onclick handlers, or any other Blazor event handler, needs a running app. On a static export it renders in its initial state and does not respond. If your docs depend on live demos like that, run the site on a .NET host.
Building the static site
dotnet tool install -g ShellDocs.CLI --prerelease
shelldocs build --site-url https://docs.example.com
The output goes to ./publish. Every flag is covered in shelldocs build. Two matter for hosting:
--site-urladdssitemap.xml,robots.txtand social-preview meta tags.--base-hrefis needed only when the site is served from a subpath, such as a GitHub project page at/my-repo/.
GitHub Pages
This workflow builds on every push to main and can be run by hand.
name: Deploy to GitHub Pages
on:
push:
branches: [main]
workflow_dispatch:
concurrency:
group: pages
cancel-in-progress: true
permissions:
pages: write
id-token: write
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
global-json-file: global.json
- run: dotnet tool install -g ShellDocs.CLI --version 0.1.17-alpha
- run: shelldocs build --site-url https://docs.example.com
- run: echo "docs.example.com" > publish/CNAME
- run: touch publish/.nojekyll
- uses: actions/upload-pages-artifact@v3
with:
path: publish
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
Three lines are easy to miss:
.nojekyll: GitHub Pages runs Jekyll by default, and Jekyll drops folders that start with an underscore. Blazor's assets live in_frameworkand_content, so without this file the site loads with no styles or scripts.CNAME: keeps a custom domain attached across deploys. Leave the step out if you use the defaultgithub.ioaddress.- Pin the CLI version to the version of the ShellDocs packages your project references, so a new prerelease can't change the build under you.
One-time setup
- Set the Pages source
In the repository, open Settings, then Pages, and set Source to GitHub Actions. Until this is done the deploy job fails with a 404 from the Pages API.
- Add the custom domain
On the same page enter the domain under Custom domain and save.
- Point DNS at GitHub
At your DNS provider add a
CNAMErecord for the subdomain with the valueyour-org.github.io. If the provider proxies traffic, turn the proxy off for this record until the certificate is issued. - Wait for the certificate, then enforce HTTPS
GitHub requests a certificate once the DNS check passes. When it arrives the Enforce HTTPS box becomes available.
GitHub Pages certificates come from Let's Encrypt. A CAA record on the parent domain that names only another authority blocks it, with no error shown. This happens when another platform manages the apex domain and added its own record. Add a second record, 0 issue "letsencrypt.org", next to the existing one, then remove and re-add the custom domain in the Pages settings to restart the request.
Project pages
For a site served at https://your-org.github.io/my-repo/, drop the CNAME step and pass the subpath:
shelldocs build --base-href /my-repo/
Other static hosts
Any host that serves a folder works: point it at publish. Many hosts' own build environments don't include the .NET SDK, so the dependable setup is to run shelldocs build in CI and upload the output, as the workflow above does.
Running on a .NET host
Publish and run it like any ASP.NET Core app.
dotnet publish -c Release -o out
dotnet out/MyDocs.Docs.dll
The content folder must be in the publish output. shelldocs init adds the project items that copy it:
<ItemGroup>
<Content Include="content/**/*.md" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" />
<Content Update="content/**/meta.json" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" />
</ItemGroup>
Any platform that runs ASP.NET Core works: a container, a virtual machine, or a managed app service.