Scott Hanselman

Exploring Wyam - a .NET Static Site Content Generator

December 11, '16 Comments [20] Posted in ASP.NET | Open Source
Sponsored By

It's a bit of a renaissance out there when it comes to Static Site Generators. There's Jekyll and GitBook, Hugo and Hexo. Middleman and Pelican, Brunch and Octopress. There's dozens, if not hundreds of static site content generators, and "long tail is long."

Wyam is a great .NET based open source static site generator

Static Generators a nice for sites that DO get updated with dynamic content, but just not updated every few minutes. That means a Static Site Generator can be great for documentation, blogs, your brochure-ware home page, product catalogs, resumes, and lots more. Why install WordPress when you don't need to hit a database or generate HTML on every page view? Why not generate your site only when it changes?

I recently heard about a .NET Core-based open source generator called Wyam and wanted to check it out.

Wyam is a simple to use, highly modular, and extremely configurable static content generator that can be used to generate web sites, produce documentation, create ebooks, and much more.

Wyam is a module system with a pipeline that you can configure and chain processes together however you like. You can generate HTML from Markdown, from Razor, even XSLT2 - anything you like, really. Wyam also integrates nicely into your continuous build systems like Cake and others, so you can also get the Nuget Tools package for Wyam.

There's a few ways to get Wyam but I downloaded the setup.exe from GitHub Releases. You can also just get a ZIP and download it to any folder. When I ran the setup.exe it flashed (I didn't see a dialog, but it's beta so I'll chalk it up to that) and it installed to C:\Users\scott\AppData\Local\Wyam with what looked like the Squirrel installer from GitHub and Paul Betts.

Wyam has a number of nice features that .NET Folks will find useful.

Let's see what I can do with in just a few minutes!

Scaffolding a Blog

Wyam has a similar command line syntax as dotnet.exe and it uses "recipes" so I can say --recipe Blog and I'll get:

C:\Users\scott\Desktop\wyamtest>wyam new --recipe Blog
Wyam version 0.14.1-beta

,@@@@@ /@\ @@@@@
@@@@@@ @@@@@| $@@@@@h
$@@@@@ ,@@@@@@@ g@@@@@P
]@@@@@M g@@@@@@@ g@@@@@P
$@@@@@ @@@@@@@@@ g@@@@@P
j@@@@@ g@@@@@@@@@p ,@@@@@@@
`$@@@@@@@@@@@` ]@@@@@@@@@`
$@@@@@@@P` ?$@@@@@P
`^`` *P*`
Scaffold directory C:/Users/scott/Desktop/wyamtest/input does not exist and will be created
Installing NuGet packages
NuGet packages installed in 101813 ms
Recursively loading assemblies
Assemblies loaded in 2349 ms
Cataloging classes
Classes cataloged in 277 ms

One could imagine recipes for product catalogs, little league sites, etc. You can make your own custom recipes as well.

I'll make a config.wyam file with this inside:

Settings.Host = "";
GlobalMetadata["Title"] = "Scott Hanselman";
GlobalMetadata["Description"] = "The personal wyam-made blog of Scott Hanselman";
GlobalMetadata["Intro"] = "Hi, welcome to my blog!";

Then I'll run wyam with:

C:\Users\scott\Desktop\wyamtest>wyam -r Blog
Wyam version 0.14.1-beta
Loading configuration from file:///C:/Users/scott/Desktop/wyamtest/config.wyam
Installing NuGet packages
NuGet packages installed in 30059 ms
Recursively loading assemblies
Assemblies loaded in 368 ms
Cataloging classes
Classes cataloged in 406 ms
Evaluating configuration script
Evaluated configuration script in 2594 ms
Root path:
Input path(s):
Output path:
Cleaning output path output
Cleaned output directory
Executing 7 pipelines
Executing pipeline "Pages" (1/7) with 8 child module(s)
Executed pipeline "Pages" (1/7) in 221 ms resulting in 13 output document(s)
Executing pipeline "RawPosts" (2/7) with 7 child module(s)
Executed pipeline "RawPosts" (2/7) in 18 ms resulting in 1 output document(s)
Executing pipeline "Tags" (3/7) with 10 child module(s)
Executed pipeline "Tags" (3/7) in 1578 ms resulting in 1 output document(s)
Executing pipeline "Posts" (4/7) with 6 child module(s)
Executed pipeline "Posts" (4/7) in 620 ms resulting in 1 output document(s)
Executing pipeline "Feed" (5/7) with 3 child module(s)
Executed pipeline "Feed" (5/7) in 134 ms resulting in 2 output document(s)
Executing pipeline "RenderPages" (6/7) with 3 child module(s)
Executed pipeline "RenderPages" (6/7) in 333 ms resulting in 4 output document(s)
Executing pipeline "Resources" (7/7) with 1 child module(s)
Executed pipeline "Resources" (7/7) in 19 ms resulting in 14 output document(s)
Executed 7/7 pipelines in 2936 ms

I can also run it with -t for different themes, like "wyam -r Blog -t Phantom":

Wyam supports themes

As with most Static Site Generators I can start with a markdown file like "" and included name value pairs of metadata at the top:

Title: First Post
Published: 2016-01-01
Tags: Introduction
This is my first post!

If I'm working on my site a lot, I could run Wyam with the -w (WATCH) switch and then edit my posts in Visual Studio Code and Wyam will WATCH the input folder and automatically run over and over, regenerating the site each time I change the inputs! A nice little touch, indeed.

There's a lot of cool examples at that show you how to generate RSS, do pagination, use Razor but still generate statically, as well as mixing Razor for layouts and Markdown for posts.

The AdventureTime sample is fairly sophisticated (be sure to read the comments in the config.wyam for gotcha) example that includes a custom Pipeline, use of Yaml for front matter, and mixes markdown and Razor.

There's also a ton of modules you can use to extend the build however you like. For example, you could have source images be large and then auto-generate thumbnails like this:

ReadFiles("*").Where(x => x.Contains("images\\") && new[] { ".jpg", ".jpeg", ".gif", ".png"}.Contains(Path.GetExtension(x))),

There's a TON of options. You could even use Excel as the source data for your site, generate CSVs from the Excel OOXML and then generate your site from those CSVs. Sounds crazy, but if you run a small business or non-profit you could quickly make a nice workflow for someone to take control of their own site!

GOTCHA: When generating a site locally your initial reaction may be to open the /output folder and open the index.html in your local browser. You MAY be disappointed with you use a static site generator. Often they generate absolute paths for CSS and Javascript so you'll see a lousy version of your website locally. Either change your templates to generate relative paths OR use a staging site and look at your sites live online. Even better, use the Wyam "preview web server" and run Wyam with a "-p" argument and then visit http://localhost:5080 to see your actual site as it will show up online.

Wyam looks like a really interesting start to a great open source project. It's got a lot of code, good docs, and it's easy to get started. It also has a bunch of advanced features that would enable me to easily embed static site generation in a dynamic app. From the comments, it seems that Dave Glick is doing most of the work himself. I'm sure he'd appreciate you reaching out and helping with some issues.

As always, don't just send a PR without talking and working with the maintainers of your favorite open source projects. Also, ask if they have issues that are friendly to

Sponsor: Big thanks to Redgate! Help your team write better, shareable SQL faster. Discover how your whole team can write better, shareable SQL faster with a free trial of SQL Prompt. Write, refactor and share SQL effortlessly, try it now!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb
Sunday, 11 December 2016 00:59:52 UTC
Thanks for the write-up! For anyone who's interested in checking Wyam out, I'm happy to lend a hand and answer any questions you have here or over at the Wyam Gitter chat.
Sunday, 11 December 2016 01:07:51 UTC
Been using Jekyll and Hexo for quite some time and always thought it would be nice to have something more in the .NET space. Especially for piping data into these static systems. Thanks for the post, will investigate.
Robert Sweeney
Sunday, 11 December 2016 08:39:49 UTC
I was just looking at hugo yesterday but will check this out today. Have a smally community site to do so will try it out
Sunday, 11 December 2016 13:25:06 UTC
I've loved Wyam since I found it last year. I had quite a bit of code included in one of the releases, in fact. There's literally nothing you can't do with it.

Plus, Dave Glick is a hell of a nice guy. Had lunch with him in DC this summer.
Sunday, 11 December 2016 14:48:01 UTC
Thanks for this good piece of read. Just because I see .NET next to a static site content generator, it reminded me of the once open sourced Live Writer. I wonder whether they would be a nice company to each other.
Zafer Balkan
Monday, 12 December 2016 00:26:17 UTC
I moved to a static site a few years ago. I've used Pretzel, PieCrust and am currently using Jekyll with GitHub Pages. I love the simplicity and performance. Glad to see there is a .Net option.

The only thing I missed from my WordPress days was the ability to search my posts. Finally cracked that problem using Azure Search, Azure Functions and a touch of JavaScript. Anyone interested I blogged about it, and shared all my code.
Monday, 12 December 2016 08:21:03 UTC
Pretzel is another .Net project I have used in the path although I don't think any of the current offerings have the polish of Jekyll or Middleman.
Monday, 12 December 2016 08:45:31 UTC
"Low ceremony"...

For whom have ever tried to setup a local generation of github pages (jekyll) on Windows, this is very good point :)
Monday, 12 December 2016 10:39:29 UTC
Wyam has actually been around for a while. I wanted to use it for my blog but it didn't run on Linux so I went with Jekyll and put Wyam on my 'watch' list in case the situation changed. I'm pretty happy with Jekyll but I'm not a Rubyist and hit paint points whenever I want to make alterations (I'd also started using Jekyll for customer site requests and found the initial productivity dipped whenever I had a request for something extra). With Wyam running on .NET Core I shall certainly give this a revisit :-)
Monday, 12 December 2016 12:00:35 UTC
I've been looking at these for a while. How do people do form processing for contact and feedback forms on static sites? Thanks.
Monday, 12 December 2016 12:42:51 UTC
@Jeremy Hutchinson That very cool, thanks for sharing. Wyam has a module for building and using search indexes with a JavaScript library called Lunr for local static searching, but it's not that powerful and doesn't work great for a large amount of content since the entire index has to be delivered to the client. I'll be taking a look at your work to see there's something we could do with the Azure search service.

@Matthew Blott Unfrotunatly, not .NET Core quite yet. It's certainly headed that direction, probably once netstandard 2.0 bits are in preview since a lot of AppDomain stuff is in use. Wyam will go Core sometime next year though (hopefully earlier in the year)

@Keith There's a number of services that help with forms processing for static sites. A number of them are listed here. There's also a new service called Staticman that will submit PRs on form submission. And Netlify (a static site host) has forms processing services as well.
Monday, 12 December 2016 12:52:32 UTC
@Dave Glick - thanks great list.
Monday, 12 December 2016 13:02:10 UTC
@Keith, there's plenty of solutions, such as
Monday, 12 December 2016 14:14:23 UTC
@Dave Glick Most of the work is in Azure, all that needs to be done in the static site is a page to build a JSON representation of the searchable posts and pages, and a bit of javascript to kick off the search and convert the results to HTML.

I'm planning to put together samples of how to do that for a few static sites, and would be happy to contribute to your /examples.

Oh, and there is the issue of when to kick off the Indexing. With GitHub Pages I can kick it off with their Page Build webhook, but for others it would probably need to be handled in the build sometime after the deploy.

I'll be in touch
Tuesday, 13 December 2016 19:37:56 UTC
It's been awhile since I last looked at it, but can embedding Google search into a static site solve the site search problem? If you're OK with using Google I guess :-P
Wednesday, 14 December 2016 01:12:16 UTC
I've used Pretzel, PieCrust and am currently using Jekyll with GitHub Pages. Snapback Caps I love the simplicity and performance. Glad to see there is a .Net option.
Friday, 16 December 2016 14:55:22 UTC
@Pete Yes, embedding google is a workable option, and was very easy to setup.

I didn't like it for 2 reasons:
1. The ux was a little harsh. User types in the search box, hits enter, gets taken to a results page, then when they click on a result they get taken back to my blog.
2. I was dependent on Google's indexing, so new blog posts wouldn't be searchable for an indeterminate amount of time.

But really, I'd be lying if I said I did the Azure Search/Azure Function integration for any reason other than to see if I could.

Saturday, 17 December 2016 05:34:32 UTC
yeah, Wyam does great job, its a great platform for programming and infact most of the static sites does Wyam as cms.
Wayne Moore
Thursday, 22 December 2016 19:17:30 UTC
Nice writeup, I will definitely have to look into it further. I'm moving a few sites to something like this, and this seems a little more what I'm looking for.

I used Pretzel on two sites so far and like it, but the project feels a little abandoned/neglected. This gives me a better alternative than wrestling with Jekyll on Windows...
Friday, 23 December 2016 09:08:33 UTC
Once the application is launched, give it a few minutes to update the catalogue, so do not worry if the movie you want to see at the moment is not available. Each day new servers are added and new titles become available. Not bad for an app that is completely free of charge! ShowBox
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.