© oliverelliott.org, 2025.
All Rights Reserved.
Build Your Own Website From Scratch ᕦ(ò_óˇ)ᕤ

Want to build your own website?

Check out the free tool SimpleSiteGenerator on GitHub.

SimpleSiteGenerator generates a static website based on content input files. With it, you can create and customize your own site from scratch. The website is structured as a simple blog—either image-based, article-based, or both. But you can just as easily make a non-blog website. SimpleSiteGenerator is written in Python, HTML, and CSS, and you will need some familiarity with these languages to use it.

Pictures

image
image
Mobile view:
image
(photos borrowed from Wikipedia)

On Static Websites

Static websites have many advantages:
  • They're hard to hack. After all, they're just marked up text—no admin panel!
  • They're the cheapest way to host a website: you can save hundreds of dollars compared to, say, buying a Squarespace or Wix website
  • They're fast
  • There's an elegance to their simplicity
If your website doesn't required anything fancy, and is mainly about posting content, then you should consider using a static website. A good—though not entirely rigid—litmus test is whether you need user accounts: if you don't need them, this is another hint you should go static.

Problems The SimpleSiteGenerator Solves

The SimpleSiteGenerator aims to address and simplify common website-building needs. These include:
  • a way to stay DRY and avoid rewriting your common header, footer, and navigation bar for every page
  • a way to convert page objects in a JSON file into actual pages
  • a way to create new posts without writing HTML (at least for visual posts)
  • a way to group posts by category
  • a way to click to the next or previous post in a category
  • an easy way to decide which page, among the many in your site, will serve as your homepage
  • a way to create a Feed page, with your most recent posts
  • a way to create a Latest page, with your latest post
  • a way to create a "Cover page" (aka a splash page) to greet users before they get into your proper website
  • a way to assign specific CSS or JS to a specific page or page type
  • a way to assign a specific template to a specific page or page type
  • an easy way to add or remove things from your navigation bar
  • a way to add common social media SVG icons
  • a way of logging build information
  • a default mobile-friendly website whose layout changes based on viewport width

Page Objects

Page objects are at the heart of SimpleSiteGenerator. What is a page object? A page object is simply an object—i.e., something in a JSON file with keys and values—representing the page's metadata. Let's look at an example page object for a visual-flavor post—the picture of Paris shown above:

{
    "name": "Paris",
    "showname": 1,
    "shownamesection": 1,
    "subtitle": "",
    "showsubtitle": 1,
    "type": "img",
    "border": 1,
    "files": "La_Tour_Eiffel_vue_de_la_Tour_Saint-Jacques.jpg",
    "thumbnail": "La_Tour_Eiffel_vue_de_la_Tour_Saint-Jacques_thumb.jpg",
    "url": "paris",
    "urlexternal": "",
    "publishedexternal": "",
    "publish": 1,
    "specialpage": 0,
    "selected": 1,
    "author": "Name",
    "showauthor": 0,
    "category": "france",
    "series": "",
    "keywords": "",
    "date": "2024-01-01",
    "showdate": 1,
    "blurb": "This is a blurb about Paris.",
    "showblurb": 1,
    "paywall": 0,
    "ispreview": 0,
    "description": "",
    "notes": "Image from Wikipedia"
}

A quick explanation: the files attribute is the name of our image file. The thumbnail attribute is the name of our thumbnail file. The url attribute, in SimpleSiteGenerator jargon, is a globally unique key associated with the page object. It's related (but not identical) to the URL path where the page will end up being published. Many of the other attributes you see turn various options on or off (the 0s and 1s are "boolean intergers"). You can find the full descriptions of the fields in the README.

SimpleSiteGenerator's job is to translate these page objects into actual pages on your website.

An Overview

The SimpleSiteGenerator reads data from a user-specified data directory and then creates a static website in a user-specified output directory. Here's a rough diagram:
image

TL;DR

Here's the TL;DR version of how to use SimpleSiteGenerator:
  • Add an entry for your post in content.visual.json (for an image post)
  • Put the content for your post into the data directory
  • Choose various options in dataconfig.py
  • Build your website locally with build.sh
  • Optionally, upload this folder to a hosting service to make your static website live on the internet

Quickstart: How to Create a Post

To create a post (after cloning the repository), first create a datafolder/ directory for your website. The easiest way to do this is to copy the example folder, example/test.site.org.data/, then modify it.

Visual Post

To create a post, you need to add the content and metadata for the post into the data directory. If your post is a picture or video, add an entry for your page object in content.visual.json. In your page object, choose a unique url attribute and set the publish attribute to 1. Set the type attribute to one of the following:
  • img
  • video
If your post is an image, drop the picture(s) into published/img/. Put the thumbnail there, too. If your post is a video, put the video into the published/video/ folder. Add the names of these files in the files and thumbnail attributes of your page object. If you have a multiple pictures, use a comma-delimited string with no spaces. E.g.:

"files": "picture1.jpg,picture2.jpg,picture3.jpg",
"thumbnail": "picture_thumbnail.jpg"

Article Post

If your post is an article, add an entry for the page object in content.article.json in the data directory. As before, be sure to set the url and publish attributes. Set the type attribute to "article". In this case, there's no need to set the files and thumbnail attributes.

In the directory published/article/, create a folder whose name is the url key of your page object. Write the content of your post in a file called content.html. If, for example, the url attribute of your page object is "testarticle1", put the content.html file here:

published/article/testarticle1/html/content.html

Any images or videos for the article go in:

published/article/testarticle1/img/
published/article/testarticle1/video/

Now the bare-bones data directory looks like this:

datafolder
├── content.article.json
├── content.sections.json
├── content.visual.json
├── dataconfig.py
└── published
    ├── article
    │   └── testarticle1
    │       ├── html
    │       │   └── content.html
    │       ├── img
    │       └── video
    ├── img
    │   ├── picture1.jpg
    │   ├── picture2.jpg
    │   ├── picture3.jpg
    │   └── picture_thumbnail.jpg
    └── video

Build the website with the command:

mkdir sitefolder
./scripts/build.sh x datafolder sitefolder log.txt x x x

Host it locally (on port 8000):

cd sitefolder
python -m http.server 8000

How Does SimpleSiteGenerator Compare to Other Frameworks?

There are a lot of perfectly good static web frameworks out there. The other frameworks are more mature, have better docs, and have teams behind them. So why this one? No reason, other than that I wanted to do it my own way.

The first selling point of SimpleSiteGenerator is that it's written in Python. I'm a Python partisan. No need to learn Ruby (as with Jekyll) or download a binary (as with HUGO).

The second selling point is, it's simple. At its core, it's just one Python script! While there are many options and configuration choices, it's not such a complicated problem that you need a huge codebase. Among the current static site generators out there, SimpleSiteGenerator is spirtually closest to Pelican. However, SimpleSiteGenerator is more minimalist.

The third selling point is, SimpleSiteGenerator uses JinJa for templating. JinJa's homepage states: "Special placeholders in the template allow writing code similar to Python syntax". Say no more! It's also similar to Django's templating language. I like JinJa better than HUGO's Go templates or Jekyll's Liquid templates.

The fourth is, it supports two post types out of the box: visual-flavor and article-flavor. Thus, it's as easy to make a blog with long-winded rants about politics—that will embarrass your family and lose you friends—as it is to make a low-rent Instagram clone.

Finally, it's direct. If you want to make an article post, there's no writing of markdown then letting the program translate your markdown into HTML (an approach favored by many of the other frameworks). You write HTML directly and that's exactly what goes into your website—no mysteries.

Reasons not to use SimpleSiteGenerator:

The SimpleSiteGenerator is a DIY project and, as such, it's not completely polished. A classic line on StackExchange states:

Remember that everyone else's code always sucks

SimpleSiteGenerator is meant to be modified—because your site will probably have different needs than mine. You may want a different aesthetic, different attributes for the posts, etc. This will involve adding your own CSS and templates and—for big changes—modifying the Python code.
© oliverelliott.org, 2025.
All Rights Reserved.