Bootstrapping This Site
I've been meaning to put something up at this domain for a while. Not a blog in the "please subscribe and smash that like button" sense. Just a place to write about stuff I'm actually doing. Tech, music, tools, the occasional rant. The usual.
The question was always what to build it on. The obvious answer is WordPress because it's the obvious answer, and that's exactly why I didn't want it. I already manage too much infrastructure at work. I'm not spending my free time chasing plugin updates and PHP vulnerabilities for a personal site. Ghost was the next candidate, cleaner than WordPress, decent API, but it's still a server you have to babysit. I wanted something I could git push and walk away from.
So: Hugo. Static site generator, posts as Markdown files, Claude Code as the CMS. No database, no runtime, nothing to patch. The whole thing deploys via rsync to DreamHost. This post is being written in a terminal.
The aesthetic was the other thing. I wanted it to look like it came out of the early 90s underground: ICE and ACiD ANSI pack energy, hacker zine aesthetic, not startup landing page. Electric blues and purples on near-black. Monospace everything. If it could pass for a BBS login screen in the right light, we're close.
What You Need Before You Start
Two prereqs that this post assumes you already have:
GitHub account (free). You need a private repo to store the site source. If you already have a personal access token set up, you're good. If not, create one at github.com → Settings → Developer settings → Personal access tokens.
DreamHost account, or any shared host that gives you SSH access and lets you point a domain at a directory. DreamHost runs about $3-5/month on a shared plan. The important thing is shell access. Without it, rsync won't work and you're stuck with FTP like it's 2002.
Installing Hugo
On WSL2 (Ubuntu/Debian):
sudo apt update && sudo apt install hugo
Verify:
hugo version
You want 0.110+ for current template behavior. If your distro's package is ancient, install via the Hugo releases page or snap:
snap install hugo
Creating the Site
cd ~/projects
hugo new site conspicuoustechnologist
cd conspicuoustechnologist
git init
Hugo scaffolds the directory structure. The important ones:
content/ ← your posts go here
themes/ ← your theme goes here
hugo.toml ← site config
static/ ← files served as-is (images, etc.)
public/ ← built output, gitignored
The Theme
No theme was downloaded or modified. This one was built from scratch inside themes/conspicuous/. The minimum Hugo theme needs:
themes/conspicuous/
layouts/
_default/
baseof.html ← base template everything extends
list.html ← category/tag listing pages
single.html ← individual post template
index.html ← homepage
partials/
header.html
footer.html
shortcodes/
jd303.html ← the jd303 voice block
claude.html ← the claude voice block
static/
css/
main.css
theme.toml
The color palette: near-black background (#050510), electric blue (#00aaff), cyan (#00d4ff), purple (#cc44ff). Two fonts pulled from Google Fonts: VT323 for display text (headers, title), Share Tech Mono for body copy. Everything monospace.
The two-voice shortcodes are the structural piece. In any post, jd303 and Claude sections are wrapped like this:
[ jd303 ]
...jd303 writes here...
[ claude ]
...claude writes here...
Each renders as a styled block with a [ jd303 ] or [ claude ] label. jd303 gets purple (#cc44ff), Claude gets cyan (#00d4ff). Different border treatment, different color accent. Two terminals talking to each other.
Site Config
hugo.toml at the root:
baseURL = "https://conspicuoustechnologist.com/"
languageCode = "en-us"
title = "CONSPICUOUS TECHNOLOGIST"
theme = "conspicuous"
[params]
description = "Tech, music, and other noise from a GenX systems guy in Denver."
author = "jd303"
tagline = "// signal over noise //"
[markup]
[markup.highlight]
style = "monokai"
lineNos = true
[[menus.main]]
name = "home"
url = "/"
weight = 1
[[menus.main]]
name = "posts"
url = "/posts/"
weight = 2
[[menus.main]]
name = "about"
url = "/about/"
weight = 3
DreamHost Setup
In the DreamHost panel, point your domain at a directory. The default is usually /home/[username]/[domain.com]. Note your actual shell username. It is not the same as your panel login. This matters. More on this in a second.
Enable SSH access in the panel under Users → Manage Users. Once it's active:
# In a new terminal, proves it actually works
ssh your-shell-username@conspicuoustechnologist.com
If that connects, you're good.
The Deploy Script
deploy.sh in the project root:
#!/bin/bash
export PATH="$HOME/.local/bin:$PATH"
DREAMHOST_USER="your-shell-username"
DREAMHOST_HOST="conspicuoustechnologist.com"
DREAMHOST_PATH="/home/your-shell-username/conspicuoustechnologist.com"
set -e
for cmd in hugo rsync ssh; do
if ! command -v $cmd &>/dev/null; then
echo "ERROR: $cmd not found."
exit 1
fi
done
echo "// building site //"
hugo --minify
echo "// deploying to DreamHost //"
rsync -avz --delete public/ "${DREAMHOST_USER}@${DREAMHOST_HOST}:${DREAMHOST_PATH}/"
echo "// deployed //"
Make it executable:
chmod +x deploy.sh
To deploy:
./deploy.sh
That builds the site into public/ and rsyncs it to DreamHost. The --delete flag removes files from the server that no longer exist locally. First run will ask for your DreamHost SSH password. Set up SSH key auth if you want passwordless deploys.
GitHub
git add .
git commit -m "initial commit"
gh repo create conspicuoustechnologist --private --source=. --push
That's it. The repo is the source of truth. Posts are Markdown files. ./deploy.sh ships it.
The build itself took one session. Most of it was writing the theme CSS, getting the glow effects right, the ANSI-adjacent border treatments on the voice blocks, the nav style. The .-{link}-. nav format was the first thing I locked in and everything else followed from it.
One thing that bit us: DreamHost has two usernames. There's the one you log into the panel with, and there's the actual shell user that your domain runs under. They are not the same. I was rsyncing to the wrong one for a few minutes wondering why nothing was showing up. Once we pointed DREAMHOST_USER at the right account (doetech, not jdoe) it deployed clean on the first try.
That was honestly the only friction. Hugo's fast, rsync is rsync, and having Claude Code in the loop for the theme scaffolding meant I wasn't starting from a blank file.
The result is what you're looking at. One evening, one session, zero plugin hell.
Shipped on my birthday, which was either intentional or a happy accident depending on when you ask me.