After reviewing the key concepts in the previous section, it is time to put them into practice by building, step by step, a fully functional, statically generated blog that includes:
- articles (of course) converted from Markdown to HTML
- pages (also written in Markdown and converted to HTML)
- an ATOM syndication feed
- a development server
The blog will have its own stylesheet and templates, using the Jingoo template engine (inspired by Jinja2).
Disclaimer
The first thing to note is that this guide is a tutorial on using YOCaml, not on using Jingoo, HTML, CSS or even OCaml. So feel free to use an existing template or create your own if you are a designer and this guide also assumes that you have at least a superficial knowledge of OCaml.
About Code Organization
For simplicity, most of the code for our generator will be written in
a single module, blog.ml
(no mli
is needed thanks to the
(executables_implicit_empty_intf)
directive in our
dune-project
). However, as mentioned several times, YOCaml is just a
collection of regular packages, so you are free to organize your
code however you like.
Starting point
The entire tutorial assumes that the Setup
section has been completed, and we will be building upon the blog
project we created earlier. We assume the directory is organized as
follows:
├── _opam
├── _build
├── bin
│ ├── blog.ml
│ └── dune
├── blog.opam
├── .ocamlformat
├── dune-project
└── README.md
Data Organization
Before we start writing code, let's organize our directory. To do this, we will create several folders to hold the files needed to build our site.
mkdir -p assets/css
mkdir assets/images
mkdir assets/templates
mkdir -p content/articles
mkdir content/pages
This should structure our directory as follows:
├── _opam
├── _build
+ ├── assets
+ ├── css
+ ├── images
+ └── templates
├── bin
│ ├── blog.ml
│ └── dune
+ ├── content
+ ├── articles
+ └── pages
├── blog.opam
├── .ocamlformat
├── dune-project
└── README.md
The content of our site (mainly Markdown files) will go in
content/
. We create two subdirectories to store pages and articles,
respectively. Our assets will be stored in the assets/
directory,
which will contain our CSS files, images, and templates.
Our goal is to generate the complete site in the _www
directory,
which we should not create ourselves, as YOCaml will handle it!
Git Repository
It is recommended to use a Git repository to track the progress of your development and, potentially, to take advantage of services like GitHub or GitLab for CI and static page hosting to automate deployment.
If you choose to use a repository, don’t forget to update the
dune-project
file accordingly (and run dune build
to rebuild your
OPAM file). You can also add a
.gitignore
file tailored for OCaml, including the _www
directory to ignore the
generated output.
Setting Up the Cache
As we saw earlier, YOCaml uses a cache to track dynamic
dependencies. We can clear the contents of blog.ml
and replace it
with the following code:
open Yocaml
let www = Path.rel [ "_www" ]
let program () =
let open Eff in
let cache = Path.(www / ".cache") in
Action.restore_cache cache
>>= Action.store_cache cache
let () = Yocaml_unix.run ~level:`Debug program
-
We start by describing a path that will be the directory where we create/move all our files, here
www
. -
We create various shortcuts to quickly reference the different directories we just created (to get familiar with the Path API).
-
Since no actions are written yet, we simply read the cache and then save it. Later, our Actions will be placed between the cache restoration and storage steps.
Here is an example of adding some action in the code:
open Yocaml
let www = Path.rel [ "_www" ]
let program () =
let open Eff in
let cache = Path.(www / ".cache") in
Action.restore_cache cache
+ >>= a_first_action
+ >>= a_second_action (* etc. *)
>>= Action.store_cache cache
let () = Yocaml_unix.run ~level:`Debug program
Let’s move on to the next step!