- JavaScript 70.3%
- HTML 17.2%
- Python 5.5%
- CSS 4.8%
- Shell 1.4%
- Other 0.8%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| .claude | ||
| .githooks | ||
| .github/workflows | ||
| .vscode | ||
| archetypes | ||
| assets | ||
| content | ||
| layouts | ||
| scripts | ||
| static | ||
| .gitignore | ||
| AGENTS.md | ||
| biome.json | ||
| CLAUDE.md | ||
| flake.lock | ||
| flake.nix | ||
| hugo.toml | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
blog.lvmbdv.dev
Ata Kuyumcu's personal blog. A Hugo (extended) static site styled with Tailwind CSS v4, leaning on structured data (JSON-LD) and IndieWeb microformats (h-card / h-entry).
Requirements
- Hugo extended (bundles Dart Sass / the Tailwind binary). Pinned version
lives in
.github/workflows/ci.yml(HUGO_VERSION). - Node for Biome. Pinned via
NODE_VERSIONin.github/workflows/ci.yml. - Python 3 (stdlib only) for the helper scripts.
Development
hugo server -D # local dev server, drafts included, live reload
hugo --gc --minify # production build into public/ (gitignored)
npx @biomejs/biome check # lint + format CSS/JS/JSON (--write to fix)
Helper scripts (scripts/, stdlib Python only):
python3 scripts/reflow-markdown.py [file...] # reflow prose to 80 cols
python3 scripts/validate-linked-data.py public # validate JSON-LD in a build
Writing posts
- Posts live in
content/posts/*.mdwith YAML front matter (title,date,tags, optionalcover,draft,description). - Set
description(~150 chars max) — without it the meta/og/twitter descriptions fall back to the whole first paragraph and get truncated everywhere. - Covers are 1200×630 (the single-post template hardcodes those
dimensions), live in
static/images/, and are referenced ascover: "images/<name>.jpg". Crop to that aspect before adding. If the image needs attribution (CC BY etc.), setcover_credit(markdown, e.g.cover_credit: "[Photo](url) by Author, CC BY 2.0") — it renders as a caption under the cover. - When undrafting, bump
dateto the publish day — posts sort by it. - Prose wraps at 80 columns — use
reflow-markdown.pyrather than hand-wrapping. - Tag pages (
content/tags/<tag>/_index.md) are hand-authored; prune orphans manually. draft: truehides a post from the built site but the source and anystatic/images remain reachable in the repo.- Unpublish a post by setting
draft: true(don't delete).
Layout
content/posts/*.md— posts. Front matter is YAML (---).content/tags/<tag>/_index.md— tag pages are hand-authored.layouts/— custom templates.partials/head/holdsmeta,css,jsonld,indieweb.assets/css/main.css— Tailwind v4 entry.scripts/— standalone Python 3, stdlib only.
Credits
static/dungeon/tilemap.png is three Kenney packs stacked into one 12-column
sheet, 16×16 tiles throughout. Each pack is exactly 11 rows, so each band starts
at a round multiple of 132:
- Tiny Dungeon by Kenney, rows 0-10 (sprite indices 0-131).
- Tiny Town by
Kenney, rows 11-21, addressed in code as
TOWN + nwhereTOWN = 132. - Tiny Farm by
Kenney, rows 22-32, addressed in code as
FARM + nwhereFARM = 264.
The packs ship separate palettes; they are merged into one 62-colour table when stacked, so the sheet stays 8-bit indexed rather than becoming truecolour.
Both are released under CC0 1.0, which asks for nothing, so this section is courtesy rather than obligation.
Deploy
The live site is served by Caddy from /srv/blog.lvmbdv.dev on the same
server that hosts forge.lvmbdv.dev. Forgejo Actions
(.github/workflows/ci.yml) runs on every push to main: build (Hugo with
Pagefind indexing) → validate:linked-data → rsync public/ to the webroot.
The rsync runs as the deploy user over an rrsync-restricted SSH key stored as
the DEPLOY_SSH_KEY Actions secret; the key can only write to the webroot.
There is no manual deploy step: pushing to main deploys.
The Codeberg repo is a push mirror kept for backup; it no longer serves the site.