---
author: A.D.B. Jesus
date: 2022-08-29
slug: hello-world
title: Hello, world!
---
I have been thinking of starting a blog for a while, mostly to write
about stuff that makes no sense to publish academically, but also to
improve my writing skills. I expect to mostly write about Programming,
Emacs, Linux, and other tech topics. But we will see where it goes.
In this first post I will quickly go over the implementation and
deployment of this site. Note that, you can find the code for this site
at <https://git.adbjesus.com/website>.
### Static Site Generator
Since this site will contain static content, I've decided to go with a
static site generator. In particular, I chose
[Zola](https://getzola.org). The main reason for using Zola and not
something else is that I am familiar with its implementation language
(Rust). This can allow me to easily contribute to the project to fix any
issue or scratch any itch.
In terms of styling, I'm using simple templates and CSS I implemented
myself, which match the light/dark system theme option set by the user.
Something I am not yet doing, is using syntax highlighting for code in
blog posts. Although Zola supports this, it does not support some of the
languages that I want, such as Emacs Lisp and Nix, and it is using old
and buggy Sublime syntaxes. There is currently an [open
issue](https://github.com/getzola/zola/issues/1787) to replace the
current system. Another option, would be to use a javascript based
syntax highlighter. However, I would rather keep my site
javascript-free. As a result, since I don't consider it to be a critical
feature for now, I will not implement any syntax highlighting for the
time being.
### Using Org
One issue I had with Zola is that it does not suppor
[Org](https://orgmode.org) for writing content (see this
[issue](https://github.com/getzola/zola/issues/909)). However, I would
prefer to use it instead of markdown because I prefer and am more
comfortable with its syntax, but also because I want to be able to use
[Org Babel](https://orgmode.org/worg/org-contrib/babel/) to execute code
within the `.org` file directly when writing posts for which executing
code is useful.
Nonetheless, this proved not to be an issue for my simple use case
because I can automatically convert `.org` files to `.md` files
(following the [CommonMark](https://commonmark.org/) spec) using
[pandoc](https://pandoc.org), and the
[ox-pandoc](https://github.com/emacsorphanage/ox-pandoc) package for
Emacs. To setup ox-pandoc to export `.org` files to CommonMark I have
the following in my Emacs configuration:
``` elisp
(use-package ox-pandoc
:ensure t
:after org
:custom
(org-pandoc-menu-entry
'((?c "to cmk." org-pandoc-export-to-commonmark)
(?C "to cmk and open." org-pandoc-export-to-commonmark-and-open))))
```
Then, I put the `index.org` for a blog post inside a dedicated folder
for that post:
``` example
content
└── blog
└── 01-hello-world
├── index.org
└── ... // other files
```
The `index.org` file includes some metadata in its header for both Zola
and ox-pandoc. For example, for this post I'm using the following
header:
``` org
#+TITLE: Hello, world!
#+DATE: 2022-08-25
#+PANDOC_METADATA: slug:hello-world
#+PANDOC_EXTENSIONS: commonmark+yaml_metadata_block
#+PANDOC_OPTIONS: standalone:t
#+PANDOC_OPTIONS: shift-heading-level-by:2
```
The `TITLE`, `DATE`, and `PANDOC_METADATA` fields are added to the
exported markdown metadata block. To add the metadata block to the
generated markdown file we set the `yaml_metadata_block` pandoc
extension in `PANDOC_EXTENSIONS`, and the `standalone:t` option in
`PANDOC_OPTIONS`. The last line is used to start the generated headings'
levels at 3 for styling purposes.
Finally, I use the `C-c C-e p c` shortcut to generate the markdown file,
which goes into the same folder, i.e.:
``` example
content
└── blog
└── 01-hello-world
├── index.org
├── index.md
└── ... // other files
```
You can find the Org source for this post [here](index.org).
### Deploying with Nix
I deploy this site to my [NixOS](https://nixos.org) server using the
declarative NixOS configuration capabilities. For this I have a
`flake.nix` in the repository of this site:
``` nix
{
description = "My personal website";
inputs = {
nixpkgs = {
url = "github:nixos/nixpkgs/nixos-22.05";
};
flake-utils = {
url = "github:numtide/flake-utils";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; };
in rec {
packages.website =
pkgs.stdenv.mkDerivation {
name = "website";
src = self;
buildInputs = [ pkgs.zola ];
buildPhase = ''
zola build
'';
installPhase = ''
mkdir -p $out cp -Tr public $out/public
'';
};
packages.default = self.packages.${system}.website;
}
);
}
```
Then I add this repository to the inputs section of the NixOS
`flake.nix` configuration file.
``` nix
inputs.website = {
url = "git+https://git.adbjesus.com/website";
inputs.nixpkgs.follows = "nixpkgs";
};
```
and use the `nginx.virtualHosts` option to deploy it:
``` nix
nginx.virtualHosts = {
"adbjesus.com" = {
default = true;
forceSSL = true;
enableACME = true;
locations = {
"/" = {
root = "${inputs.website.packages.${system}.website}/public";
extraConfig = ''
add_header Last-Modified "${toDateTime inputs.website.lastModified}";
add_header Cache-Control max-age="${toString (60 * 60 * 24)}";
'';
};
};
};
};
```
In the future, I will write more about my NixOS configuration using
flakes, which I use to manage my personal computers and server.