Approach
My approach is largely manual, where it's interesting, and automated where it isn't. By automated, I mean triggering human-authored scripts to perform repetitive task (like deploying, or updating text).
This approach is based largely out of a desire to, I guess, be seen in some limited capacity. But while you might witness some flourishes, my style is still sadly pretty corpo-brained; perhaps because that's where I've spent most of my computer-life, or maybe I'm just that self-domesticated.
Dev Setup
Because I'm kind of corpo brained, I have a fairly formal setup. I've got a README.md
, and a Dockerfile, and an example nginx.conf
--lol, yup.
Kind of pathetic, I admit. But it does make for smooth for when I come in trying to make some changes after months on hiatus elsewheres.
Some more specifics: I use the NPM package live-server to get live-reloading as I save.
I'm trying to keep the architecture/framework/tooling ((I'm sorry I can't help how I talk)) relatively low-impact (at least compared to what I'd be forced to make for work). So that means no ReactJS, no express, no "sythetics" (lol), and not even a webserver. It's just a plain old nginx container listening behind a reverse proxy.
Dockerfile
FROM nginx:latest
WORKDIR /etc/nginx
COPY ./config/nginx.conf ./
COPY ./config/derelict.ink ./
RUN mkdir html
COPY ./static ./html/static
COPY ./stubs ./html/stubs
COPY ./pages ./html/pages
RUN nginx -t
And a docker compose
file for easy deploys. Which lets me do like DOCKER_HOST="ssh://${REMOTE_HOST}" docker compose up -d
to redeploy to whatever remote(s) I want with minimal fuss.
compose.yml
name: derelict.ink services: web: build: . container_name: derelict.ink ports: - 127.0.0.1:1234:1234
I did this so I could take advantage of Server-Side Includes (SSI), because I wanted to follow the
Example SSIs
Note these are inside special "SSI Command" HTML comments (<--# -->
), but wrapping them here would cause the command to be executed!
# set var="browser-title" value="Colophon"
# set var="page-title" value="🕳️🔍️"
# include file="/stubs/header.shtml"
Git hooks
I use this post-commit
hook to make the changelog on the left.
#!/bin/sh
# Append breaks so we can source file directly
git log --format='%ad %s' --date=short \
| sed 's/$/
/' \
> static/text/changelog.txt
echo changelog.txt updated
exit 0
Okay, I've actually since updated this to an incredibly hideous sed
one-liner that I'm not going to paste here. Shoot me an email if you want it, and I'll gladly share, though.
Version Control
I use git.
Specifically, I have several repositories. Local (obviously), one corp instance (you know the place), Codeberg, and backup on another VPS that I run.
Actually it's so easy to set up your own private git server. Cross-reference with any missing pieces here, but once you've got your git user set up, you can just do the following to add a backup for an existing repository:
From your git user's home dir (on the remote)
# Easiest to just scp a copy of the repo to the remote # and use it, rather than faffing about with permissions # pulling down a repo from some secondary remote... git clone --bare /home/user/repo-name repo-name # If you get this error when pushing: # fatal: detected dubious ownership in repository at # make sure file ownership is set to git user chown -R git:git repo-name
Then from your working repository (on your local)
# Add an additional push target (fetch source (AKA source of truth) # will still live at whatever you have before git remote set-url --add --push origin git@example.com:repo-name # Verify remotes git remote show origin
Changelog
Here's a list of the dates and subjects of the git commits that have gone into making this website. See Git hooks under Dev setup on the right here, for details on how its made.
2025-09-10 chore:
2025-09-10 content(colophon):
2025-09-10 content(home):
2025-09-05 content(home):
2025-09-05 content:
2025-09-05 style:
2025-08-30 content(colophon):
2025-08-30 content(colophon):
2025-08-30 chore:
2025-08-30 style(changelog):
2025-08-30 style:
2025-08-30 style:
2025-08-29 content(home):
2025-08-29 style:
2025-08-29 content(colophon):
2025-08-29 content:
2025-08-27 chore:
2025-08-27 chore:
2025-08-27 chore:
2025-08-27 chore:
2025-08-27 content:
2025-08-27 chore:
2025-08-27 content:
2025-08-27 refactor:
2025-08-27 chore:
2025-08-27 chore:
2025-08-27 chore:
2025-08-27 doc:
2025-08-27 chore:
2025-08-22 chore:
2025-08-22 content:
2025-08-21 chore:
2025-08-21 content:
2025-08-21 content:
2025-08-21 content:
2025-08-21 doc:
2025-08-21 content:
2025-08-21 chore:
2025-07-25 chore:
2025-07-25 chore:
2025-07-25 content:
2025-07-25 content:
2025-07-25 revert:
2025-06-02 chore:
2025-03-30 content:
2025-03-30 chore:
2025-03-30 content:
2025-03-30 content:
2025-03-30 content:
2025-03-30 doc:
2025-03-30 chore:
2025-03-30 feat:
2025-03-30 chore:
2025-03-30 doc:
2025-03-30 chore:
2025-03-30 content:
2025-03-29 style:
2025-03-29 content:
2025-03-29 content:
2025-03-29 content:
2025-03-29 chore:
2025-03-29 content:
2025-03-29 fix:
2025-03-29 content:
2025-03-29 content:
2025-03-21 content:
2025-03-21 chore:
2025-03-21 content:
2025-03-17 content:
2025-03-17 content:
2025-03-13 content:
2025-03-13 content:
2025-03-13 fix:
2025-03-13 content:
2025-03-13 content:
2025-03-12 content:
2025-03-12 content:
2025-03-12 fix:
2025-03-12 chore:
2025-03-12 chore:
2025-03-12 refactor:
2025-03-12 chore:
2025-03-12 content:
2025-03-12 content:
2025-03-12 refactor:
2025-03-12 refactor:
2025-03-12 content:
2025-03-12 chore:
2025-02-26 content:
2025-02-26 content:
2025-02-26 style:
2025-02-26 fix:
2025-02-26 style:
2025-02-26 content:
2025-02-26 style:
2025-02-26 content:
2025-02-26 style:
2025-02-25 style:
2025-02-25 style:
2025-02-25 doc:
2025-02-25 fix:
2025-02-25 style:
2025-02-25 content:
2025-02-25 style:
2025-02-24 style:
2025-02-23 content:
2025-02-23 style:
2025-02-23 init