Source for Ryan Workman's personal blog at workman.tech. Posts are authored in markdown, rendered to static HTML by a small Node build script, and served by GitHub Pages from the repo root.
- Node.js build script (
markdown-it+gray-matter), withprettierformatting the generated HTML andhtml-validatelinting it - Vanilla HTML and CSS
- GitHub Pages for hosting
- No frameworks or bundler. A GitHub Actions workflow validates each pull request (build freshness + HTML lint)
- Install Node.js 22.17 or newer (required by the
html-validatelint tooling; CI runs Node 24). npm install.- To preview the site, run
npm run devand visit http://localhost:3000. This is a thin wrapper aroundpython3 -m http.server 3000— it serves the repo root over HTTP so absolute paths like/css/style.cssand/images/...resolve correctly. Requires Python 3 on yourPATH.
-
Create
_posts/<theme>/YYYY-MM-DD-slug.md. The parent folder name is the theme and becomes part of the URL. -
Add frontmatter at the top of the file:
--- title: rails perf wins from a 3-month audit date: 2026-06-01 description: short blurb used for the meta description and OG tags tags: [ruby, rails, performance] ---
titleanddateare required.descriptionandtagsare optional. -
Run
npm run build. -
Review the diff — both the source
.mdand the generated HTML. -
Commit everything: the markdown source and the generated HTML inside
<theme>/. -
Push. GitHub Pages will redeploy automatically.
The published URL pattern is https://workman.tech/<theme>/YYYY-MM-DD-slug.html.
Note: The build runs locally; CI does not build the site for you. Instead, a GitHub Actions workflow re-runs the build on every pull request and fails if the committed HTML doesn't match a fresh build (it also lints the HTML). So if you commit a post's source
.mdwithout runningnpm run build, CI will catch it. Always runnpm run buildand commit the generated HTML alongside the source.
npm run dev— start a local static server on port 3000 for previewing the site.npm run build— render all posts and regenerate the homepage post list. Every generated file is formatted with Prettier.npm run lint:html— validateindex.htmland the generated theme HTML withhtml-validate.npm run lint:fix— auto-format source files with Prettier. (html-validate has no autofix, so HTML problems must be fixed by hand.)npm run clean— remove generated theme directories and reset the homepage post-list region to its empty state. Only touches files that start with the<!-- generated by build.js -->marker, so hand-edited content is safe.
GitHub Pages serves the repo root. Any push to main triggers a redeploy and is usually live within a minute. The custom domain is configured via the CNAME file.
See CLAUDE.md for the architecture details and the list of deferred follow-ups (RSS, sitemap, per-tag pages, syntax highlighting, OG images).