Contentful ❤️️ Wyam == true
At Contentful, we love static site generators. They offer a beautiful combination of speed and simplicity, and they become even more powerful when combined with a dynamic content store to add the one thing a static site lacks, dynamism.
We already have numerous integrations and extension for many popular static site generators, with Jekyll, Middleman, and Roots being some. Today I'm happy to announce that we now have an official module for the .Net-based static site generator Wyam! Wyam is a highly modular and extremely configurable static content generator and toolkit. It is built by .Net MVP and all-around awesome guy Dave Glick, as well as by numerous Github contributors.
The concept of Wyam differs slightly from many other open source static site generators. In Wyam you craft your own pipeline of modules that work together to create your final static output. You configure your pipelines and modules yourself (even though there are a few pre-configured "recipes") using the config.wyam
file, which can be extremely powerful as it's actually evaluated as C# code. This means that you can write C# and take full advantage of the entire .Net ecosystem. An example configuration file could look something like this:
The first two lines are preprocessor directives pulling in NuGet packages which contain some of the modules that we then use in our pipeline. This simple pipeline consists of reading any files with a .md
extension, reading any front matter in YAML and adding that as metadata to the documents, then parsing the markdown content to HTML and finally writing the files to disk with an .html
extension. More information about writing your configuration file can be found at wyam.io.
How does Contentful fit into the Wyam family? With our official module you can now fetch any content from Contentful, and use that as the basis of your generated static content in Wyam.
The first thing you need to do is to add a reference to the NuGet package in your config.wyam
.
Then we can now reference the module in our pipeline like this.
This would now fetch all of our entries from Contentful and add them to the pipeline. Every field of the entry will be made available as metadata to the document. There are a number of fluent methods available to configure which content the module will fetch and to add other configuration options.
Here we fetch all entries of a specific content type and we also specify which field of the content type should be used as the content of the documents created in the Wyam pipeline.
By adding a few more modules we can create some really powerful pipelines. In the next example we are using Razor templates with a layout that is then compiled into static HTML files.
In this example we're setting the body
field of the content fetched from Contentful as the content of our documents. We're also specifying to only fetch entries of the blogPost
content type. We then parse the markdown content of each document into HTML. The next module, Excerpt
, pulls the first paragraph out of our HTML and adds it as metadata to our documents; this can be useful if we for example want to show a list of all blog posts and include a small excerpt of each. We then add the content of our document into a metadata property called Body
so that we can access it later in our Razor file. After that we merge each document with a Razor template post.cshtml
and using the Razor()
module we then compile that into HTML and finally write the files to our posts output directory. Note how we name each HTML after the slug
metadata property of the document. This is the slug field in Contentful!
The Razor template we're using is then accessing the metadata from the documents that were fetched from Contentful.
The Model
for each document is a Wyam IDocument
, which is the central class in a Wyam pipeline. Each document has any number of metadata objects in a simple key/value store that you can access using the Get<T>
method. This method will then intelligently cast the value into T
, and you can use the result in your code. As you can see we're getting the title, the body and images from our metadata, all of which are of course fields in our entry in Contentful. The Contentful.Wyam package also provides a couple of handy extension methods, and we can see that we're using the ImageTagForAsset
one here. It simply takes a JToken
or asset id and generates an img
tag leveraging the image API of Contentful in the background. That means that you can do things like use facial recognition, resize images, set the border radius, set the background color and much more, directly in your static site.
You can also configure multiple pipelines for different parts of your content. For example, it's possible to have one pipeline that fetches content from Contentful and another that just reads ordinary Markdown files off of disk. Or even have two pipelines that read two different content types off of Contentful and put them in separate directories as in the next example:
Localization
By default, Contentful only fetches the configured default locale for the entries, but this can be easily configured in your pipeline.
If you want to fetch all entries in all configured locales, simply pass *
as your argument.
Please note that this will result in one document per entry per locale. If our entries were localized in three locales, every entry would be split into three separate documents in your pipeline. You can then use the metadata property ContentfulKeys.EntryLocale
to see which locale a specific entry belongs to.
Note how we put each document in a subdirectory with the same name as the documents locale by using @doc["ContetnfulKeys.EntryLocale"]
.
Handling included entries and assets
If you're familiar with our Content Delivery API, you know that you can save quite a few API calls by making sure you leverage the includes.Entry
and includes.Asset
arrays, which include entries and assets that are referenced from the those returned in your initial query. This is also possible in the Wyam module: there are two separate collections available in the metadata with the keys ContentfulKeys.IncludedAssets
and ContentfulKeys.IncludedEntries
. There are also extension methods available directly on IDocument
to get an entry or asset directly from the collections. Below are a few examples in a Razor template.
Naturally you can configure how many levels of referenced content you want to include.
This would include up to seven levels of referenced entries and assets.
Eager to start building something?
Go checkout the Wyam GitHub repository, the Wyam website, and the Contentful.Wyam GitHub repository. We can't wait to see what you will create!