- Python 43.5%
- Shell 21.2%
- CSS 14.3%
- Go Template 11.9%
- JavaScript 9.1%
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013Yf2W9HEmzJtGN9DRtT7WH |
||
|---|---|---|
| brand | ||
| custom | ||
| staging | ||
| tools | ||
| .gitignore | ||
| deploy.sh | ||
| README.md | ||
forgejo-custom
The customisation of git.zatto.pl: Forgejo with
Codeberg's page layout (logo in the navbar, full-height page, large
multi-column footer), Zatto branding and our own zatto-dark colours.
No fork and no custom build. Everything lives in Forgejo's
CUSTOM_PATH
(/data/gitea in the container):
| Path | What it does |
|---|---|
custom/templates/base/footer_content.tmpl |
The footer. Overrides an upstream template, see Upgrading Forgejo |
custom/templates/custom/header.tmpl |
Loads zatto-layout.css (official hook, after the theme CSS) |
custom/templates/custom/extra_links.tmpl |
"About" in the navbar for visitors (official hook) |
custom/public/assets/css/zatto-layout.css |
Layout only, colours come from theme variables, so it works with every theme |
custom/public/assets/css/theme-zatto-dark.css |
Our default theme ([ui] DEFAULT_THEME = zatto-dark) |
custom/public/assets/img/ |
logo.svg/.png, favicon.*, apple-touch-icon.png (app icon), zatto/glyph.svg (navbar mask) |
The navbar template is deliberately not overridden: logo.svg is the app
icon (dark tile), and zatto-layout.css paints the bare glyph over it as a
CSS mask in the theme's text colour. Upgrades can't break the navbar.
Brand assets
brand/ holds the vector logo, reconstructed from the brand raster images by
measurement rather than auto-tracing:
src=brand/source # the brand rasters (wordmark, icon)
tools/measure_brand.py $src/wordmark.png $src/icon.png # raw edge measurements (JSON)
tools/build_brand.py $src/wordmark.png $src/icon.png brand/
tools/verify_brand.py brand/geometry.json $src/wordmark.png $src/icon.png /tmp/verify --built brand/
tools/export_assets.sh # brand/ -> custom/public/assets/img (rsvg-convert)
tools/sync_inline.py # brand/ -> inline SVGs in the footer template
Checked against the rasters: mean edge offset 0.22 px on a 112 px cap height
(wordmark) and 0.13 px on a 424 px icon. Needs numpy, pillow, scipy.
Test, then deploy
staging/up.sh [--theme forgejo-light] # throw-away Forgejo 15.0.0 on 127.0.0.1:3300 (CT101 sandbox)
node tools/shoot.mjs staging/shots.json # screenshots through a containerised Chrome (see header)
./deploy.sh # git.zatto.pl: backup, install, restart, smoke test
./deploy.sh --list # backups on the host
./deploy.sh --restore backup-YYYYMMDD-HHMMSS.tgz
Caching. Forgejo serves /assets with a 6 h browser cache. It links
theme-*.css, logo.svg and favicon.* with its own version string (or none),
which our deploys don't change. Anything that must show up right after a
deploy therefore goes into zatto-layout.css, whose URL carries a content
hash. That is why the zatto-dark footer tone lives there and not in the theme
file.
tools/assemble.sh builds the tree that staging mounts and deploy.sh ships,
so staging tests exactly what goes live. It stamps a content hash into the
stylesheet URL (browsers cache /assets for 6 h) and refuses a footer
template that is out of sync with brand/.
Testing deploy.sh
tools/test_deploy.sh sources deploy.sh and runs it against a throw-away
container that looks like production (old theme, no templates). It breaks
things on purpose: truncated upload, tampered file, a restart that never gets
healthy, failing smoke tests. Each time it checks that the live tree is
untouched or rolled back. It refuses the container name forgejo.
docker run -d --name forgejo-deploytest -p 127.0.0.1:3301:3000 -v deploytest-data:/data \
-e FORGEJO__database__DB_TYPE=sqlite3 -e FORGEJO__security__INSTALL_LOCK=true \
codeberg.org/forgejo/forgejo:15.0.0 # on the sandbox host
ssh -f -N -L 13301:127.0.0.1:3301 zatto@<sandbox> # "public" URL for the smoke test
HOST=zatto@<sandbox> CONTAINER=forgejo-deploytest LOCAL_URL=http://127.0.0.1:3301 \
PUBLIC_URL=http://127.0.0.1:13301 PRODLIKE_THEME=<copy of our theme css on the sandbox> tools/test_deploy.sh
deploy.sh only ships committed state. A deploy replaces
/data/gitea/templates and /data/gitea/public completely, so nothing can be
changed there by hand. The container restart takes about 10 s. A failed upload
leaves the live site untouched. A failed swap, an unhealthy restart or a failed
smoke test restores the backup automatically.
Upgrading Forgejo
Before bumping the image tag:
- Diff upstream
templates/base/footer_content.tmplof the new version against the previous one. Carry any change over into ours (newctx.Localekeys, language menu markup, helpers). - Run the staging with the new tag (
FORGEJO_TAG=16.0.0 staging/up.sh). Then screenshot it, desktop and mobile, dark and light. - Deploy the image bump. If a template breaks after the upgrade, delete
/data/gitea/templates/base/footer_content.tmpland restart. Forgejo falls back to its built-in footer.
Credits
- Layout follows Codeberg's Forgejo customisation
(Codeberg-Infrastructure/forgejo,
branch
codeberg-15). - Forgejo wordmark (
brand/forgejo-wordmark-mono.svg, from the same repository): the Forgejo logo by Caesar Schinas, CC BY-SA 4.0.