Using BlazorStatic from scratch
This guide will show you how to create static site using BlazorStatic. It is good for understanding how it works, but you can also use the BlazorStaticMinimalBlog where everything is already set up for you.
Create Blazor app
Start by creating new Blazor project.
Interactivity
is set toNone
since that is not something we need for static site.dotnet new blazor --name BlazorStaticMinimalBlog --output BlazorStaticMinimalBlog --interactivity None --empty
Remove
blazor.web.js
fromApp.razor
(we don't need it for static site).Make necessary changes to your layout. I am using tailwindcss, so everything is accommodated to that.
When you run
dotnet watch
your app should be running.(if you are also using tailwind, you need to run
tailwindcss -i .\wwwroot\app.css -o .\wwwroot\app.min.css -w
or npm command )
Add content
Add you markdown files following this structure:
├───Content └───Blog │ first-post.md │ second-post.md └───media programming_bug.jpg
The directory structure can be customized (by
BlazorStaticOptions
), but for simplicity we will use the default one.The post start with yaml front matter metadata.
--- title: First post lead: Sample post so you can see how it works published: 2024-06-20 tags: [tag-001, another-sample-tag] authors: - name: "Jan TesaÅ™" gitHubUserName: "tesar-tech" xUserName: "tesar_tech" ---
These metadata has to match C# class (
BlazorStatic.BlogFrontMatter
) that we will use now. You can use your own class, but it has to implementIFrontMatter
interface. You can also use multipleIFrontMatter
classes in one web app, see projects for more info (and its usage inProgram.cs
).Mark Content folder to copy to the output:
<ItemGroup> <None Update="Content/**/*"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup>
You can also use
dotnet publish
to copy the content folder to the output.
BlazorStatic nuget
dotnet add package BlazorStatic --prerelease
Turn on
StaticWebAssets
. This will ensure wwwroot and RLCs assets are copied to the output folder.builder.WebHost.UseStaticWebAssets();
Register services in
Program.cs
builder.Services.AddBlazorStaticService(opt => { opt.IgnoredPathsOnContentCopy.Add("app.css");//pre-build version for tailwind } ).AddBlazorStaticContentService<BlogFrontMatter>();
BlogFrontMatter
is the class that will be used to parse the metadata from markdown files. This is part of the BlazorStatic package. It exactly matches the metadata infirst-post.md
andsecond-post.md
. Nothing stops you from creating your own class that will match your own metadata. It just needs to implement interfaceIFrontMatter
, which has just one propertyList<string> Tags { get; set; }
.As you can see
BlazorStaticService
has options you can change. For example you can change the directory structure ( where your md files are located), or you can ignore some files (likeapp.css
in this case (we haveapp.min.css
)).Use
BlazorStatic
Before running the app we need to tell the service to actually do something:app.UseBlazorStaticGenerator(shutdownApp: !app.Environment.IsDevelopment());
UseBlazorStaticGenerator
will parse the markdown files and expose them to the app as Postthrough BlazorStaticContentService
and will generate the static files a put them into theoutput
folder (also customizable). It will shut down the app outside of development environment. This is meant for CI/CD pipelines, otherwise the app would run "forever" in particular job.
Scaffold the UI for blog posts
When you run the app right now, it will output the non-parametrized pages (e.g. @page "/"
into index.html
) and will
copy content of wwwroot
into the output
. You can set where to look for non-parametrized pages by
opt.RazorPagesPaths
(default is Components/Pages
folder).
File generation is done by using
HttpClient
and saving the result into.html
file.
We need to scaffold the UI for blog posts. BlazorStatic doesn't force you to use any particular UI, but it will help you
by providing BlazorStaticContentService<BlogFrontMatter>.Posts
collection where your processed posts live.
You get get some inspiration for th UI. These pages are important:
Blog.razor page which either displays the list of posts or the post itself. It starts with these page directives:
@page "/blog" @page "/blog/{fileName}"
First will display the list of posts, second will display the post itself. The list of post is in
PostList.razor
component.PostsList.razor component, which is used in Blog.razor and Tags.razor pages to display the list of posts.
Tags.razor page, which either displays the tags cloud or the list of posts with particular tag. It have these page directives:
@page "/tags" @page "/tags/{tagName}"
For posts and tags generation, the directives must match the options, default value are:
builder.Services.AddBlazorStaticContentService<BlogFrontMatter>(opt => {
opt.PageUrl = "blog";
opt.TagsPageUrl = "tags";
});
Run and see
Now, when you run the app it outputs the static website into the output
folder. When you open them the links and
images will not work. But it is fine. For debugging purposes you just run the app and don't care about the output. You
can even suppress the output by opt.SuppressFileGeneration = true;
(default is false
) and turn it on only for CI/CD
pipeline.