- HTML 62.1%
- Python 21.2%
- CSS 16.7%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
The instance's canonical hostname moved off git.zephyrftp.com. FORGEJO_URL in build.py, README's deploy section, and both blog posts' prose links all updated; rebuilt to regenerate every page. |
||
| assets | ||
| blog | ||
| contact | ||
| posts | ||
| build.py | ||
| index.html | ||
| README.md | ||
| styles.css | ||
badcluster.dev
Source for the Bad Cluster site. Static HTML/CSS, no JS framework, no build tooling beyond a small Python script that generates the blog pages from Markdown.
Structure
index.html Generated - home page (don't hand-edit, see build.py)
styles.css Shared stylesheet for every page
assets/ Images
blog/ Generated - blog index + one folder per post
contact/ Generated - contact page
posts/ Source - Markdown files, one per blog post
build.py Regenerates index.html, blog/, and contact/ from
the content below and posts/*.md
Anything under blog/ or contact/, plus index.html itself, is build
output. Hand-editing those will work until the next python3 build.py,
which overwrites them. Edit posts/*.md for blog content, or build.py
itself for the home page, header/footer, or page templates.
Adding a blog post
Create a new file in posts/, named however you like (the date in the
filename is just for sorting convenience - the real date comes from
frontmatter). Format:
---
title: Your Post Title
date: 2026-07-04
summary: One sentence, shown on the blog index page.
---
Body in Markdown from here on. Headings, links, lists, `inline code`,
and fenced code blocks all work.
Then rebuild:
python3 build.py
Requires the markdown package: pip install markdown.
Editing the home page or templates
The home page content, header, footer, and page shell are all defined as
Python strings in build.py (see build_home(), render_header(),
render_footer(), page_shell()). Edit those, then rerun the build.
Contact form
The contact form posts to Formspree. To make it actually deliver messages to you:
- Create a free account at formspree.io and add a new form.
- Copy the form endpoint URL it gives you (looks like
https://formspree.io/f/abcd1234). - In
build.py, replace theFORM_ACTIONplaceholder with that URL. - Rerun
python3 build.pyand redeploy.
Until that's done, the form is wired up correctly but has nowhere real to
send to - build.py will print a reminder every time you build if the
placeholder is still in place.
Local preview
Browser security blocks the page's absolute paths (/styles.css, etc.)
when opened directly as a file:// URL. Serve it locally instead:
python3 -m http.server 8000
Then open http://localhost:8000/.
Deploying
Hosted on linveo1, git-based: /var/www/badcluster.dev on the server
is a clone of this repo (origin = git.badcluster.dev/arelas/badcluster-site).
To publish a change: push here, then on the server
cd /var/www/badcluster.dev && git pull. No GitHub Pages, no CNAME
file, no separate build/deploy step beyond that.