Site creation
Follow the steps taken to create this Docusaurus blog. Learn about using essential plugins like search, sitemap, image zoom, and adding the Giscus comment system.
This article is over a year old but was reviewed on July 30, 2026 — the content is still accurate.

This article documents how this blog was built: bootstrapping Docusaurus in blog-only mode entirely through the official Docker node image (no local Node.js install), configuring docusaurus.config.js, and adding plugins for local search, sitemap, image zoom, and Giscus comments. It ends with building the static site via yarn build and deploying it over FTP with WinSCP, plus injecting a GDPR-compliant analytics script from withcabin.com.
Here are the steps I followed to create this blog.
Using Docusaurus
Since I really like the simplicity of Docker, I will not install Node.js on my machine but use the official Docker image. This article shows the raw docker run approach; if you prefer a ready-made Dockerfile and a compose.yaml, jump to Running Docusaurus with Docker.
The instruction above will download Node.js (the latest version) on my machine if it is not already present and create a running instance (called a container of it). The flag --user $UID:$GID is used to start the container using the same credentials as my local one (i.e., reuse my local Unix christophe user so files/folders created in the container will be owned by my local user).
The -v ${PWD}/:/project command line argument will share my current folder on my computer with the container that is, the /project folder in the container will be my current folder on my computer.
And finally, I run an interactive shell since I have mentioned /bin/bash as the entry point.
Now that I have a prompt in the container, I will create my blog using Docusaurus (as explained in the official documentation).
After a long time, the blog folder is created and I can take a look at its content:
The installation step is now finished; I will exit the container and return to my computer, and to do this, from the Docker console, I just type exit.
Run the website
Back to my computer, I will now go inside my blog folder (cd blog) and run the Docker command again but this time with the -p 3000:3000 extra parameter. This parameter will expose the port 3000 from the container to my machine so I can see the website by surfing to http://localhost:3000.
Instead of running an interactive shell session I prefer to run /bin/bash -c "npx docusaurus start" to run the Docusaurus watcher and serve my files:
After a few seconds, the container is ready to use and I surf to my site by going to http://localhost:3000.

The --host 0.0.0.0 flag
It is really crucial to use the --host 0.0.0.0 flag when calling npx docusaurus start. This will allow external access to the website. If missing, browsing to http://localhost:3000 (or running curl http://127.0.0.1:3000) will display an error Empty reply from server.
Some settings
By default (using the standard installation), Docusaurus will create a skeleton of a website having two main entries: a blog and a tutorial.
To keep things manageable, I will only keep the blog and remove the tutorial part. For this, I have followed this official article: https://docusaurus.io/docs/blog#blog-only-mode.
Now, I can remove the /docs folder from my blog directory:
I will also make some changes to files like docusaurus.config.js or blog/authors.yml to fit my needs.
File docusaurus.config.js
By setting hideOnScroll to true, the navigation bar will be hidden when the user scrolls down but will be displayed back as soon as they scroll up. Idea is to give more space on the screen for the content.
export default { themeConfig: { navbar: { // auto-hide the navbar when the user will scroll down, show again when scroll up hideOnScroll: true, }, },};This exports a configuration object that sets up the theme for a documentation or website framework, specifically enabling the navbar to automatically hide when users scroll down and reappear when they scroll back up.
Define the default image for social media:
export default { themeConfig: { // Default image when sharing a post on social media image: 'img/social-card.jpg', },};This file exports a configuration object that sets up theme-related settings. Specifically, it defines a default image that will be used when someone shares a post from this site on social media platforms like Twitter or Facebook.
Make my first article
With my preferred editor (vscode) I open my blog's website (I just type code . in my Linux console to open my blog project).
Now, in the /blog directory, I create a new folder called 2023-11-02-site-creation and there I create the index.md file.
Note
When my blog post contains only text and no images or linked files, I can just create a .md file like /blog/2023-11-02-this-is-a-test.md. The creation of a folder is therefore not mandatory at all.
In the previous chapter, npx was executed using the docker run --rm -it --name blog --user $UID:$GID -v ${PWD}/:/project -w /project -p 3000:3000 node /bin/bash -c "npx docusaurus start --host 0.0.0.0" command so, any changes made to the blog will be immediately synchronized with Docker meaning, I just need to save my article and npx will reload my site; very easy and convenient.
Using some layouts
Docusaurus supports some Markdown special tags called admonition (see https://docusaurus.io/docs/markdown-features/admonitions).
For instance, to display a paragraph as a tip, like below, just use the following syntax:
:::tip
Some **content** with _Markdown_ `syntax`.
:::
Information
Some content with Markdown syntax.
To get the entire list of supported features, see Markdown Features.
Adding plugins
Search engine
The search engine feature has been added by following this blog article: https://yoandev.co/une-documentation-avec-docusaurus-et-gitlab-pages/#bonus--ajoutons-un-moteur-de-recherche
Added by running yarn add @cmfcmf/docusaurus-search-local in the Docker container (opened using make bash).
Support for PHP and bash in prism
Added by running yarn swizzle @docusaurus/theme-classic prism-include-languages in the Docker container (opened using make bash). Read more at Supported Languages.
Sitemap generator
https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-sitemap
Added by running yarn add @docusaurus/plugin-sitemap in the Docker container (opened using make bash).
When added, I have also manually created the static/robots.txt file with this content:
User-Agent: *Sitemap: https://www.avonture.be/sitemap.xmlDisallow: /*index.xml$Disallow: /index.jsonDisallow: /search/index.jsonThis is a robots.txt file that tells search engine crawlers (like Google's bot) what they're allowed to access on the avonture.be website. It allows all crawlers to visit the site, points them to the sitemap for better indexing, but blocks them from accessing a few specific XML and JSON files that are probably internal or administrative resources.
Image plugins
https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-ideal-image
Added by running yarn add @docusaurus/plugin-ideal-image in the Docker container (opened using make bash). Read more at Supported Languages.
Added by running yarn add docusaurus-plugin-image-zoom in the Docker container (opened using make bash).
Adding a comment area
Adding Giscus to allow comments and feedback.
Push to Github
On Github.com, I have created a new repository called blog (https://github.com/cavo789/blog). Once this is done, back to my console and I run a few git commands:
Once this was done, I have thus pushed my files to Github as foreseen by Docusaurus that is, for instance, the /node_modules is not part of my repo; which is fine since we will create that folder later by running some npx command on the web server where the site will be hosted.
Build static version of the blog
In order to build static pages, I run docker run --rm -it --user $UID:$GID -v ${PWD}/:/project -w /project node /bin/bash -c "yarn build".
This will create/update the /build folder with a fresh version of the site.
The next step is to start my FTP client (which is WinSCP) and copy my local /blog/build folder to my remote website. To only send the files that really changed, see WinSCP - Synchronize host and remote.
Nowadays, I no longer do this by hand: the site is deployed automatically, as explained in GitHub - Use Actions to deploy this blog.
Adding withcabin for GDPR compliant stats
By adding the lines below to the docusaurus.config.js as child node of const config, I'm injecting a script into the body part. This will then allow GDPR compliant stats on https://withcabin.com/.
scripts: [ { src: 'https://scripts.withcabin.com/hello.js', async: true, defer: true, },],This configuration defines a single external script to be loaded on a webpage. The script comes from an external URL and is configured to load asynchronously and deferred, meaning it won't block the page from rendering while it's being fetched.
Note: the script is only injected to pages after a yarn build that is when the static site is rendered; not during a yarn watch.





