Maintaining and developing this website
Introduction
This documentation describes how to maintain and develop this website (Borealium). The website is open source and hosted on GitHub.
The purpose of this documentation is to describe the general structure of the website, how localisation functions and can be extended, key data sources that affect the website generation, and how to add or change content.
This website uses the Lume framework. For specifics of using Lume, please read their documentation — this document will only describe the specifics of maintaining this website, not all specifics about the framework used.
Structure
The core website functionality (pages, layouts, etc) are in src/
.
Data from Pahkat (the package management service used by Divvun) is found in the data/
directory, alongside those
resources specified as external dependencies. The language and category data is also defined in this directory.
The language data specifies which languages are supported by the website, but also which languages are supported by the UI only (i.e. do not show search results for resources in those languages). The category data specifies categories that cannot be derived from Divvun's repositories.
Plugins used by Lume are found in the plugins/
directory. These plugins extend Lume to provide support for things such
as multilingualisation, Fluent translations, blog excerpts, etc.
Adding content
Quickstart
Adding a blog post
Adding a static page
Adding a new external resource
Each resource is defined in a separate file in data/resources/
. The easiest is to just
copy one of the existing files, and modify the content.
NB! Make sure the id string does not contain anything but ASCII letters and hyphen. No underscores, no nothing beyond ASCII letters and hyphen.
Adding documentation for a resource
Adding a new language
Adding a new category
Available categories are the sum of
the ones given by Pahkat,
and the ones defined in data/categories.ts
. To add new categories just extend that file.
Localisation
There are two options for localisation of content:
When creating a long prose file, such as a blog post, use an .mdx
file (Markdown extended with TypeScript) with a special naming convention that includes the language. Consider a blog post that is
translated to English, Swedish and Finnish. Your directory structure should look like this:
src/post
└── 2023-08-12_beep-boop
├── index.mdx
├── index.fi.mdx
└── index.sv.mdx
For predominantly static content, such as titles of sections reused on multiple pages, or other reusable strings, this website uses Fluent files. These files are composable based
on their position within the directory tree, so if an index.en.ftl
file exists in src/
, and an index.en.ftl
exists at src/foo/
, then all files in src/foo/
will have all
the strings defined in src/index.en.ftl
with src/foo/index.en.ftl
layered on top.
In order to create a new Fluent translation, just create a file with the same name but a different language tag, e.g. src/index.se.ftl
. The system will automatically detect it and use
it where necessary.
In order to access these translations from an .mdx
file, use the t
function which is always accessible in that scope:
{t("my-i18n-id")}
If your translation includes a variable, you can specify that like so:
{t("some-id",
{
someVar: "some value"
})
}
Within .tsx
templates, the t
function is a child of the page
variable.
It is recommended that the majority of the strings use the root definitions, and only using nested definitions when it makes sense to do so -- the goal is to promote string reuse, not clutter.
Development
Prerequisites
- Install Rust — this is needed for validating the
.ftl
files - Install Deno — this is the JavaScript engine used by Lume
Quickstart
deno task serve
That's it! Now you have a local dev environment setup.
It is recommended to use Visual Studio Code for developing this website, as it supported Deno effectively and supplies type handling and error detection.
Custom plugins
The below describes what each plugin is for, and is not of particular interest or use to those simply adding content to the website.
category-data
Provides the category data to Lume pages where required. Not particularly interesting.
excerpt
This plugin generates the single paragraph summaries for the sidebar present on most pages on the website.
fluent
This plugin implements the Fluent wrappers so that .ftl
files can be used with this website.
language-data
Provides the language data to Lume pages where required. Not particularly interesting.
multilang
This plugin implements the support for generating a separate subsite for every provided language, and implements the fallback mechanisms that allow individual pages to fallback to the next closest translated language.
outline
This plugin generates the table of contents sidebar for documentation pages.
Client-side JavaScript
This website uses as little client-side JavaScript as possible. There are limited exceptions to this:
- The search functionality only works with JavaScript enabled
Client-side JavaScript is injected using a script
helper function, which converts the provided string input into the body of a <script>
element.
Should the need for client-side JavaScript change in the future, there are techniques to embed React client-side hydration as necessary, but is currently out of scope for this document.