#+TITLE: Hello, world! #+DATE: 2022-08-29 #+AUTHOR: Alexandre Jesus #+PANDOC_METADATA: slug:hello-world #+PANDOC_METADATA: updated:2023-08-01 #+PANDOC_EXTENSIONS: commonmark+yaml_metadata_block #+PANDOC_OPTIONS: standalone:t #+PANDOC_OPTIONS: shift-heading-level-by:2 #+SPDX-FileCopyrightText: 2022 Alexandre Jesus #+SPDX-License-Identifier: CC-BY-SA-4.0 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. You can find the source code for the website at https://git.adbjesus.com/adbjesus.com. * Static Site Generator Since this site will contain static content, I've decided to go with a static site generator. In particular, I chose [[https://getzola.org][Zola]]. 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 [[https://github.com/getzola/zola/issues/1787][open issue]] 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 [[https://orgmode.org][Org]] for writing content (see this [[https://github.com/getzola/zola/issues/909][issue]]). 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 [[https://orgmode.org/worg/org-contrib/babel/][Org 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 [[https://commonmark.org/][CommonMark]] spec) using [[https://pandoc.org][pandoc]], and the [[https://github.com/emacsorphanage/ox-pandoc][ox-pandoc]] package for Emacs. To setup ox-pandoc to export =.org= files to CommonMark I have the following in my Emacs configuration: #+begin_src elisp :eval no (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)))) #+end_src Then, I put the =index.org= for a blog post inside a dedicated folder for that post: #+begin_example content └── blog └── 01-hello-world ├── index.org └── ... // other files #+end_example 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: #+begin_src org :eval no #+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 #+end_src 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.: #+begin_example content └── blog └── 01-hello-world ├── index.org ├── index.md └── ... // other files #+end_example You can find the Org source for this post [[file:index.org][here]]. * Deploying with Nix I deploy this site to my [[https://nixos.org][NixOS]] server using the declarative NixOS configuration capabilities. For this I have a =flake.nix= in the repository of this site (edit: as of 2023-08-01 the flake no longer uses flake-utils but the idea is the same, you can check the latest version on the repository): #+begin_src 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; } ); } #+end_src Then I add this repository to the inputs section of the NixOS =flake.nix= configuration file. #+begin_src nix inputs.website = { url = "git+https://git.adbjesus.com/website"; inputs.nixpkgs.follows = "nixpkgs"; }; #+end_src and use the =nginx.virtualHosts= option to deploy it: #+begin_src nix services.nginx.virtualHosts = { "adbjesus.com" = { default = true; forceSSL = true; enableACME = true; locations."/" = { root = "${website.packages.x86_64-linux.website}/public"; }; }; }; #+end_src In the future, I will write more about my NixOS configuration using flakes, which I use to manage my personal computers and server. * Edits - 2023-01-08: Updated the link to the website, added note stating that I no longer use flake-utils.