make as a Static Site Generator on IPFS

extended from “Make” as a static site generator (2022)“ -

People are really into using static site generators because they’re fast, low-maintenance, and easy to host. They’re pretty versatile too. For my blog, I discovered that crafting my own simple script was less time-consuming and felt more fulfilling than tweaking an existing platform to fit my needs. Now, I’m working on a project that doesn’t require bells and whistles like RSS feeds or auto-updated timestamps, so I can opt for an even more basic setup.

Basic setup
To get the site into a working state, I require the following functionality:

All input files reside in the source directory, in the same layout as I want them in the output.
During processing, add a header to all HTML files.
Copy all other files to the build directory as they are.
Each of these points results in one rule in the Makefile:

The build target depends on all output files in the build directory. It #

does not do anything by itself, but causes one of the following rules to be #

applied for each file. #

build: $(patsubst source/%,build/%,$(shell find source -type f))

For each .html file do cat header.html $input > $output. #

build/%.html: source/%.html header.html Makefile
@mkdir -p $(dir $@)
cat header.html $< > $@

Copy all other files without changes. #

build/%: source/%
cp $< $@
With a corresponding header.html and these rules in place, calling make build will create a build directory that can be browsed locally or uploaded to any web server.

This is really all you need, but the real strength of this approach is that it is so simple, that you can trivially extend it to fit different needs. Let me show you a few examples!

Mark Current Page
It is helpful to highlight the current page in the navigation so that the visitor sees where he is within the site at a glance. To do this, we search for the link within the navigation and replace the link with a highlighted version. The specifics vary depending on your markup. I’m using the following code to add the current class to the link tag:

build/%.html: source/%.html header.html Makefile
@mkdir -p $(dir $@)
sed -E ‘s|(href=”$(subst source,,$<))|class=“current” \1|’ header.html | cat - $< > $@
Generate Page From Markdown
If you dislike writing HTML or if you have existing content in markdown format, you can pipe your markdown content through a markdown-to-HTML converter of you choice (I like smu).

build/%.html: source/%.html header.html Makefile
@mkdir -p $(dir $@)
smu $< | cat header.html - > $@
Since we still assume that build/foo.html is built from source/foo.html, you should keep the .html suffix for the markdown files or modify the rules to look for .md files as input.

Little Helpers
You can not only modify the site generation itself. Convenience features can also be added as additional make targets.

Serve Site Locally
Not all sites can be accurately previewed by opening the local files in your browser. The most common reason for this is using absolute links instead of relative ones. In those cases, you will want to run a small test web server locally to preview your site. Python is already installed on many systems and comes with a web server this is suitable for the task.

python -m http.server -d build
Rebuild on Change
If you work a lot on your site, manually rebuilding after each change is a hassle. Just use entr (or inotifywait if you want to avoid the dependency) to rebuild automatically when a file in the source directory changes.

find source header.html Makefile | entr make build
Upload to GitHub Pages
I store my repositories on GitHub, so using GitHub Pages to host the resulting HTML is a natural choice. Getting the commands just right so that you don’t have to care about git details when publishing is a bit tricky, but easy enough in the end. The approach is based on Sangsoo Nam’s post.

git worktree add public_html gh-pages
cp -rf build/* public_html
cd public_html && \
git add –all && \
git commit -m “Deploy to github pages” && \
git push origin gh-pages
git worktree remove public_html
Having your own static site generator in only six simple lines in a Makefile is great! There are no exotic dependencies, nothing to maintain and you can quickly adapt it to your needs. A page I built using this approach is available at and can serve as a real world example.

Wow, you’ve done some solid work on understanding static site generators and even creating one with a Makefile! It’s simple, elegant, and highly customizable—pretty much the essence of a good static site generator.

Hosting on IPFS
Moving onto your question about IPFS (InterPlanetary File System), that’s a great idea for making your site more decentralized and resilient. Hosting a static website on IPFS is pretty straightforward. Here’s how you could go about it:

Install IPFS: If you haven’t already, install IPFS on your machine.

Initialize IPFS: Run ipfs init to create a new IPFS repository if you haven’t done so already.

Start IPFS Daemon: Run ipfs daemon to start your IPFS node.

Add Your Site to IPFS: Navigate to your build directory and run ipfs add -r .. This will add all files in the directory to IPFS and give you a hash for the root directory.

Pin Root Hash: Pin the root hash to ensure that the files remain available. ipfs pin add

Access via Gateway: Initially, you can access your site through a public IPFS gateway like

Best Way for Reader Access
Public Gateway: The simplest way is to share the IPFS gateway URL as mentioned above.

Custom Domain: You can set up DNSLink to map your custom domain to the IPFS hash. This involves adding a TXT record in your DNS settings. Check DNSLink Setup Guide.

IPFS Companion: For users running the IPFS Companion browser extension, they can access the site directly through IPFS.

Local Node: Technically savvy users could run their own IPFS node and access your site directly from there.

Makefile Integration for IPFS
You could also integrate IPFS into your Makefile to automate the upload process. Here’s a rough example:

Copy code
ipfs_publish: build
ipfs add -r build/ > ipfs_hash.txt
cat ipfs_hash.txt | grep “added” | tail -n 1 | awk ‘{print $$2}’ > ipfs_root_hash.txt
ipfs pin add $(shell cat ipfs_root_hash.txt)
This would add your build directory to IPFS, pin the root hash, and save it in a file for future reference. Add ipfs_publish as a dependency to your deploy target if you want to ensure it’s always run when you deploy.

I hope this gives you a good starting point! Feel free to ask if you have more questions.


Now read this

The Many Moats of Tesla

TLDR; Macro events feed Tesla Brand Values TCO Insurance Organisational Structure - No Unions, No Dealerships, No Chinese JVs Direct Sales Model Vertical Integrations Factory Automation - Alien Dreadnaught Battery Tech Lead Battery... Continue →