How I Made This Site (This Time)
Someone on the Fediverse was curious how I made this site, since I mentioned using Emacs org-mode, and their own site is built using org-roam and Hugo.
It's not that much different from the more complicated process I was using before, on GitHub Pages. This one is simpler in one respect: I'm deploying directly to my own host, so I don't have to use the more complicated nikola deploy_github
configuration, which requires separate source and deployment Git branches.
For reference, here's my original post on how to get Nikola and nikola.el
working with GitHub Pages:
This time, I'm going to take the reader through the setup, step-by-step.
Requirements
Here are the things you'll need for this tutorial. I'll show you some steps.
- Emacs: Obviously. With Org Mode.
- Git: Git and a private Git repository.
-
Nikola: Nikola is a static site generator, with an
orgmode
plugin. - nikola.el: nikola.el is an Emacs package that wraps Nikola functions.
- Webserver: This setup assumes you have your own private webserver for deployment, but Nikola has a test server.
Install and Configure Nikola
From Nikola's installation instructions, slightly tweaked to use v8.2.4:
python3 -m venv nikola-env
cd nikola-env
bin/python -m pip install -U pip setuptools wheel
bin/python -m pip install 'Nikola[extras]==8.2.4'
You can now use Nikola by launching the script directly:
bin/nikola
Or you can activate the environment before working with Nikola and use the nikola command:
source bin/activate
nikola
Install Nikola add-ons
Now you need the Nikola orgmode
plugin.
nikola plugin -i orgmode
And you need to install a Nikola theme. I chose the hack theme, but you can pick another.
nikola theme -i hack
Init Local Blog
Nikola sites require a particular directory and file structure, and it has a command to create that for us. Let's use that method, rather than more complicated options.
See Nikola's instructions, here. Here's what I recommend:
nikola init --demo <directory_name>
cd <directory_name>
git init
This creates the Blog structure, and also initializes the directory as a Git repository. You should continue and connect it to your Git repository, and push an initial commit.
The --demo
option will fill in some blanks in your configuration file, and is recommended the first time.
Configure Nikola
Nikola settings live in the conf.py
file that was created when you initialized your blog.
You can view the demo conf.py online, here.
Most of the settings are self-explanatory, and many of them have defaults. However, we do need to change a few things for our theme and the orgmode
plugin.
Configure orgmode
At the bottom of conf.py
, add the following:
# Add orgmode to compilers dict
COMPILERS["orgmode"] = [".org"]
# Add org files to posts and pages
POSTS = POSTS + (("posts/*.org", "posts", "post.tmpl"),)
PAGES = PAGES + (("stories/*.org", "stories", "story.tmpl"),)
This will allow you to write posts and pages for your blog in org-mode, with everything that comes with that.
Configure theme
Each theme may have particular settings to configure, but here are the ones for the "hack" theme.
Uncomment GLOBAL_CONTEXT
, and set:
THEME = "hack"
# ...snip...
GLOBAL_CONTEXT = {}
GLOBAL_CONTEXT['HACK_VARIANT'] = 'dark'
I also have these additional settings:
DATE_FANCINESS = 2
# For Hack theme
NAVIGATION_LINKS = {
DEFAULT_LANG: (
('/index.html', 'Home'),
('/archive.html', 'Archives'),
('/categories/index.html', 'Tags'),
('/stories/about-me', 'About Me'),
('/rss.xml', 'RSS'),
),
}
Configure deployment
You will probably want to configure this after you've successfully built and deployed manually by your usual methods, so that you get the command right, but here's what mine looks like:
DEPLOY_COMMANDS = {
'default': [
"rsync -rav --delete output/ root@notroot:/var/www/blog.notroot.online",
]
}
I have my host notroot
configured in my .ssh/config
.
Install and Configure nikola.el
It's a bit outdated, and I can't get M-x nikola-deploy
to work, but otherwise we want this.
Simplest thing is to use use-package
. Here's my config:
;; Nikola.el config
(use-package nikola
:config
(setq nikola-output-root-directory "~/Dev/mine/notroot-blog/")
(setq nikola-verbose t)
(setq nikola-webserver-auto t)
(setq nikola-new-post-extension "org")
(setq nikola-new-page-extension "org"))
Then from inside your init.el
buffer, do M-x load-file RET RET
to install and configure nikola.el
.
Write a Blog Post in Emacs
Now we can write a blog post, like this one, in Emacs org-mode. Super easy!
Just do M-x nikola-new-post
to create a new posts, or M-x nikola-new-page
to create a new page, like my "About Us" page.
Emacs will give you an *.org
file, but will also create a *.meta
file. Most things will be preset, but you will probably want to add tags. Here's the meta file for this blog post:
.. title: How I Made This Site (This Time) .. slug: how-i-made-this-site-(this-time) .. date: 2024-04-07 18:29:06 .. tags: nikola,emacs,org-mode,blogging,tutorial
And here's a screenshot of me writing this post! Talk about "meta" heheh:
Preview and Build
You can also preview your work.
Do M-x nikola-webserver-start
and navigate to the URL shown in the mini-buffer.
To see changes in the blog post, you will need to stop it with M-x nikola-webserver-stop
, and restart it. Nikola does not rebuild on save.
Run M-x nikola-build
. You can watch the progress in the *Nikola*
buffer.
How Nikola Builds
One of the nice things about Nikola is that it builds using Emacs org-mode export to HTML directly, rather than translating to another markdown format, first. No pandoc
is involved. No intermediary *.md
files.
The benefit is obvious: the HTML will exported from your org files pretty much how you expect.
The one exception I've found is that inter-org file links like [[file:another-blog-post.org]]
will be turned into <img>
tags, not <a>
tags, which is too bad. That's because the slugs Nikola uses don't match org-mode's own. I'm sure there's an elisp workaround, but I haven't played with it, yet.
Fortunately, this is org-mode! If you need to link from one blog post to another, just do something like:
#+begin_export html <a href="/posts/publishing-with-nikola-in-emacs/">Publishing with Nikola in Emacs</a> #+end_export
Deploy Your Blog
The nikola-deploy
command is, unfortunately, not working for me. I have forked this old project, and at some point I'll try to fix it, but for now, I just use the shell command in Emacs.
Do M-! nikola deploy
to upload your site to your webserver.
Then browse to your new blog. If everything is working, you should be live!
Conclusion
Once you get Nikola and nikola.el
working, this is a very easy way to blog, if you're an Emacs person. It's intuitive and highly configurable.
For example, Nikola does it's own syntax highlighting, but I'll be adding something like highlight.js
down the road. I can add comments sections, and I've barely touched the possible Nikola add-ons.
If you're an Emacs person, I think this is one of the more flexible, but robust, SSG integrations out there. I, too, love the idea of publishing natively using only Emacs, but one of the great features of Emacs is also its ability to compose cleanly with other commandline tools.
Comments
With an account on the Fediverse or Mastodon, you can respond to this post. Since Mastodon is decentralized, you can use your existing account hosted by another Mastodon server or compatible platform if you don't have an account on this one. Known non-private replies are displayed below.