This is my obligatory post explaining how to use the blog engine I created in Chicken Scheme. You should know this blog uses wing.
You can see the repo here.
There are a number of static site generators out there and just about every language has one. Chicken Scheme even had one that existed already but I found it to not have been updated, and not as easy to use as I would've liked. So I made wing.
It takes inspiration from a few different lisp static site generators. The first is hyde which is the preexisting Chicken Scheme blog engine. wing uses a lot of the same libraries, and I learned how to use the atom library by looking at hyde source code.
The second is haunt. I liked how haunt setup the meta information in the markdown post itself.
There are few unique features about wing that I would like to emphasize before I go into how to use it.
The first unique feature compared to other static site generators is that it makes use of scheme files for configuration and even a poor man's database. The basic data structure is a combination of lists and associated lists.
The posts.scm that functions as a database looks like this:
(((title "Yunohost Review Initial Impressions")
(summary "Review of Yunohost a Great Self Hosting Solution")
(tags "yunohost selfhost")
(path "yunohost-review-initial-impressions.md")
(id "37e04f75-24f8-4dbe-8434-1589bc82af2f")
(md5 "77710b201d194a520da809c6e7e7eaf9")
(published "2020-03-29T15:02:07Z")
(updated "2020-03-29T15:02:07Z"))
...)
The beauty of this is that I don't need to use any special libraries to read these files or install databases. The Chicken Scheme interpreter can read these in with the read
function and will deserialize them into Scheme objects.
The second feature is automatic dates. The thing I noticed about all the other static site generators is they leave the time tracking to the author. For me, I hate keeping track of dates. One of these days I will write my rant about how much I hate the Gregorian calendar. Anyways, there are two date fields in the posts.scm file: published and updated. So instead of keeping track of this manually, I created a mechanism to keep track of dates and changes.
When the publish command is run, the published field is set as well as the updated field to the current date and time. Then when the build command is run it will compare md5 hashes that exist in the posts.scm file to the hashes of the files in /posts. If there are any changes it will update the updated field. Easy enough!
wing uses a scheme file to control the layout of the homepage and the posts. The layout file has two functions and they both are basically just sxml files with parameters. sxml files being a way to represent xml in scheme that can also be translated into html. The benefit of this is that users can use Scheme as a scripting language to customize their blog in really cool ways. You will notice that I have added my own personal touch to my blog, and I did this entirely through editing the layouts.scm file. wing comes with a default file that will be generated upon creating the blog. It is quite plain and simple so make sure to customize it to your hearts content!
You can follow the installation instructions in the project README. At the end of the process you will have a wing binary.
Create a new directory with your desired name. Then run this command inside that directory:
wing init
This will prompt you with a few questions that will help setup the configuration file as well as create a couple of directories and files.
The hierarchy should like this:
.
+-- config.scm
+-- layouts.scm
+-- posts
| +-- diy-internet-radio-with-debian.md
+-- posts.scm
+-- static
The only Scheme file that you will ever want to edit is the layouts file. And that is to customize your blog.
One thing I would recommend is to setup this directory as a git repository. That way you can version control your blog.
To start a new post you simply run:
wing new
Just like init
this will prompt a few questions for metadata related things. The most important thing to notice is the title field.
Once you fill in the prompts you will see a markdown file in the posts directory. Go ahead and write your post there. Once you are happy with the markdown file you will want to publish it.
Having a separate publishing step helps decouple posts that might be a work in progress (drafts) from actual public posts. It also helps the system figure out the time fields. You publish a post by running:
wing publish *post-title*
For example:
wing publish diy-internet-radio-with-debian
You only need to run publish once for a post, and wing actually prevents you from running it twice. The reason this is important is that when you run the publish command it adds a single entry into the posts.scm file. This is how it works a bit like a database. If you make updates to a post it is okay. The final build step will keep track of this.
In order to convert the markdown files into viewable html files you run the build step. This also has the effect of generating an atom.xml file to be used for readers who want to subscribe to your blog via RSS/Atom.
These files will be in the static directory.
wing build
There will be an index.html with a list of the posts entries and then separate html pages for each blog post.
wing comes with an http server that can serve static files. I find this useful if I want to test out changes locally. For the final version I recommend using something like nginx or apache to serve the static files. I personally use a symbolic link to the static directory to acheive this.
Chicken Scheme is quite fast (it gets transpiled to C!) so you could even put the server behind a reverse proxy as well and it should work just fine.
wing serve
That is it! My intent was to make a simple and practical blog that had a training wheels like experience. It is sort of a milestone for every hacker to make their own blog, so this was my go at it. Hopefully others find it useful and fun to use. I personally enjoyed the process and plan to use it for my future posts.
Content for this site is CC-BY-SA.