Building a Custom Static Site Generator for Technical Documentation
Introduction
What is a Static Site Generator (SSG)?
A Static Site Generator (SSG) is a tool that converts plain text files (like Markdown) into a complete static website. The output is a set of static HTML pages, which are fast to load and easy to host. Static sites are great for technical documentation because they don’t need a server to run, and they can be easily deployed anywhere, like on GitHub Pages or Netlify.
Why Build a Custom SSG?
While there are many great SSGs available like Jekyll, Hugo, and Next.js, building a custom one offers several advantages:
Flexibility: You control all the features and can tailor them to your documentation needs.
Simplicity: A custom SSG can be much simpler, focusing only on what you need, avoiding unnecessary features.
Learning: Building your own SSG helps you understand how documentation websites work behind the scenes.
Prerequisites
Before you start, you should be familiar with:
Basic JavaScript (or Python if you prefer that language)
How to write Markdown (a simple syntax for writing formatted text)
Basic HTML for creating web pages
Project Setup
Choosing a Language
We’ll use JavaScript (Node.js) for this tutorial because of its flexibility and popularity. If you prefer Python, you can follow similar steps using Python’s tools.
Setting Up Your Development Environment
Install Node.js:
- Download and install Node.js from the official website nodejs.org.
Set up the project folder:
Create a new folder for your project. Open your terminal and run:
mkdir custom-ssg cd custom-ssg
Initialize the project:
Run the following command to create a
package.json
file:npm init -y
Installing Required Tools
For this project, you will need a couple of npm packages:
marked: A library to convert Markdown to HTML
fs-extra: A library for working with files and directories
Install them by running:
npm install marked fs-extra
Core Components of the SSG
Markdown to HTML Conversion
We’ll use marked to convert our Markdown files into HTML.
Create a sample Markdown file: Inside your project folder, create a
content
folder and add aindex.md
file:├── content │ └── index.md
Add some Markdown content to the
index.md
file:# Welcome to My Documentation Site This is an example of technical documentation.
Write the conversion script: Create a
build.js
file in the project root. This script will read the Markdown file, convert it to HTML, and save the result:const fs = require('fs-extra'); const marked = require('marked'); async function build() { // Read the Markdown file const markdown = await fs.readFile('./content/index.md', 'utf-8'); // Convert Markdown to HTML const html = marked(markdown); // Create the output directory if it doesn't exist await fs.ensureDir('./dist'); // Write the HTML file to the output directory await fs.writeFile('./dist/index.html', html); console.log('Site built successfully!'); } build();
Run the build:
Run the following command in your terminal to generate the HTML:
node build.js
You should now have an
index.html
file inside adist
folder.
Template Engine
Instead of generating plain HTML, we want a consistent layout for all pages (e.g., with a header and footer). To achieve this, we’ll add a simple template system.
Create a basic HTML template: Add a new file
template.html
:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>My Documentation Site</title> <link rel="stylesheet" href="style.css"> </head> <body> <header> <h1>Documentation Site</h1> </header> <main> {{ content }} </main> <footer> <p>© 2024 My Documentation</p> </footer> </body> </html>
Modify the build script: Update
build.js
to insert the converted HTML into the template:async function build() { // Read the Markdown file const markdown = await fs.readFile('./content/index.md', 'utf-8'); // Convert Markdown to HTML const content = marked(markdown); // Read the HTML template const template = await fs.readFile('./template.html', 'utf-8'); // Insert the content into the template const finalHtml = template.replace('{{ content }}', content); // Write the HTML file to the output directory await fs.ensureDir('./dist'); await fs.writeFile('./dist/index.html', finalHtml); console.log('Site built successfully!'); } build();
Automating Build Process
Creating a Build Script
Our build.js
script is already converting Markdown to HTML, but let’s improve it by processing multiple files.
Add multiple Markdown files: Create a few more Markdown files in the
content
folder.├── content │ └── index.md │ └── guide.md
Modify the script to handle multiple files:
async function build() { const files = await fs.readdir('./content'); for (const file of files) { const markdown = await fs.readFile(`./content/${file}`, 'utf-8'); const content = marked(markdown); const template = await fs.readFile('./template.html', 'utf-8'); const finalHtml = template.replace('{{ content }}', content); const outputFileName = file.replace('.md', '.html'); await fs.writeFile(`./dist/${outputFileName}`, finalHtml); } console.log('Site built successfully!'); } build();
Handling Navigation
You can now add links between pages by manually adding them to your Markdown files.
Advanced Features
Search Functionality
For simple static search, you can use Lunr.js or Algolia to index the content. However, this requires some extra coding, which we can add later as an enhancement.
Syntax Highlighting for Code Blocks
To highlight code snippets, use Prism.js or highlight.js in your template’s <head>
section.
Deployment and Hosting
Generating the Final Build
Now that your static site is ready, let’s deploy it!
Hosting Options
GitHub Pages: You can host your static site for free on GitHub Pages. Simply push your
dist
folder to your GitHub repository’sgh-pages
branch.Netlify or Vercel: These platforms allow for continuous deployment with just a few clicks. Once you connect your GitHub repository, it will automatically deploy the latest changes.
Conclusion
Review of the SSG Workflow
We’ve built a basic custom Static Site Generator using Node.js. You now have a working system that converts Markdown files into a static website with a consistent layout.
Potential Enhancements
You could extend this project by adding:
A search bar
Automatic navigation menus
Plugin support for additional features
Subscribe to my newsletter
Read articles from Victor Uzoagba directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Victor Uzoagba
Victor Uzoagba
I'm a seasoned technical writer specializing in Python programming. With a keen understanding of both the technical and creative aspects of technology, I write compelling and informative content that bridges the gap between complex programming concepts and readers of all levels. Passionate about coding and communication, I deliver insightful articles, tutorials, and documentation that empower developers to harness the full potential of technology.