The Goal
A low effort way to publish new content and keep maintenance to a minimum.
I wanted to:
- Edit markdown files
- Push files to git
- Website is updated
I did not want to:
- Host a database for posts
- Manage an admin login
- Manage comments
- Manage security updates
Statiq.Web
I found a neat static site generator called Statiq.Web (formerly Wyam). It converts markdown and razor markup to static HTML.
Create your first post
First, follow the setup instructions.
Then, create a new markdown file at /input/posts/my-post.md
Title: My Post
Lead: It's a good post
Published: 2021-02-15
Tags: ASP.NET
Image: posts\2021-02-15-bg.png
---
<your markdown here>
Make sure your local Statiq.Web site is running
dotnet run -- preview
You can view your site at http://localhost:5080 and as you make changes, the site will reload.
Deploy to Azure
You can use Statiq.Web's built-in Azure deployment
Add the DeployToAzureAppService()
method to your Program.cs
.
static async Task Main(string[] args)
{
await Bootstrapper
.Factory
.CreateWeb(args)
.DeployToAzureAppService(
Config.FromSetting<string>("AzureAppServiceSiteName"),
Config.FromSetting<string>("AzureAppServiceUsername"),
Config.FromSetting<string>("AzureAppServicePassword")
)
.RunAsync();
}
Add an appsettings.json
to your project with the following:
{
"AzureAppServiceSiteName": "<your site name>",
"AzureAppServiceUsername": "<username>",
"AzureAppServicePassword": "<password>"
}
You can get your Azure App Service publish username and password by opening your App Service in http://portal.azure.com and clicking the "Get publish profile" link.
Open the <yoursitename>.PublishSettings
file. There are a few different profiles but the important one looks like
<publishProfile
profileName="<yoursitename> - Zip Deploy"
publishMethod="ZipDeploy"
userName="$<yoursitename>"
userPWD="<a long random string>" />
Replace the settings in appsettings.json
with the values from the .PublishSettings
file. Note your username will include the $
.
Your appsettings.json
should now look something like this:
{
"AzureAppServiceSiteName": "mysite",
"AzureAppServiceUsername": "$mysite",
"AzureAppServicePassword": "rinfj9f9sv29l1add4ahkz0kb4m9dlv9evi9amjtybbwicfx71oe"
}
Now deploy your application using the built-in Statiq deploy command:
dotnet run -- deploy
Navigate to your new site.
You may notice there's a problem if you try to navigate to any of the links.
We need to tell IIS how to serve our static content.
IIS Static Site Hosting
If you choose to host your site in Azure App Service, you'll need to supply a web.config
to tell IIS how to serve your static content.
Add a web.config
to the /input
directory of your project.
I adapted my web.config
slightly from this example. The author explains each section of the web.config
and why it exists.
I encountered a problem where navigating to /posts
or /tags
was not resolving to posts.html
and tags.html
respectively. I had to add the following explicit routes in order to get /posts
and /tags
working.
<rewrite>
<rules>
<rule name="PostsRewrite" stopProcessing="true">
<match url="^posts$" />
<action type="Rewrite" url="/posts.html" />
</rule>
<rule name="TagsRewrite" stopProcessing="true">
<match url="^tags$" />
<action type="Rewrite" url="/tags.html" />
</rule>
<rule name="RewriteHtml">
<match url="^(.*)$" />
<conditions logicalGrouping="MatchAll">
<add input="{REMOTE_PORT}" pattern=".*" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="{R:1}.html" />
</rule>
</rules>
</rewrite>
Deploy your site again.
dotnet run -- deploy
If you encounter any problems, you can use Kudu to inspect (and even edit) the web.config
right in Azure. It might be quicker than editing the web.config
locally and re-deploying.
Setup YAML Pipeline
The last step is to setup an Azure pipeline so that the website is automatically updated after pushing markdown to git.
Note: You can skip this step if you are comfortable manually deploying your site using
dotnet run -- deploy
The pipeline does the following:
- Runs the pipeline whenever a commit is pushed to
master
- Restores NuGet packages
- Builds the app
- Deploys your site using Statiq's built-in Azure App Service deploy:
dotnet run -- deploy
- Publishes site output to an artifact attached to the build. This step isn't necessary but it could be helpful if you ever need to troubleshoot.
trigger:
- master
stages:
- stage: Build
variables:
- name: BuildConfiguration
value: 'Release'
- name: Parameters.RestoreBuildProjects
value: '**/*.csproj'
jobs:
- job: 'Build'
pool:
name: Azure Pipelines
vmImage: windows-2019
demands:
- msbuild
steps:
- task: DotNetCoreCLI@2
displayName: Restore
inputs:
command: restore
projects: '$(Parameters.RestoreBuildProjects)'
includeNuGetOrg: true
- task: DotNetCoreCLI@2
displayName: Build
inputs:
projects: '$(Parameters.RestoreBuildProjects)'
arguments: '--configuration $(BuildConfiguration)'
- task: DotNetCoreCLI@2
displayName: Run Statiq
inputs:
command: run
projects: 'MySite.csproj'
arguments: '--configuration Release --verbosity normal -- deploy'
- task: PublishBuildArtifacts@1
displayName: 'Publish /output'
inputs:
pathToPublish: 'output'
ArtifactName: '$(Build.BuildNumber)'
Conclusion
With this setup your workflow is simple:
- Write posts using markdown
- Push changes to git
- View the changes on your site