Migrate Vite SPA to Hugo (hugo-coder, dark) with WebGPU background

- Hugo static site at root: config, content (home/about/resume/blog + 5 projects),
  data/resume.yaml, custom layouts (gpu background, resume renderer, projects list),
  dark theme with canvas behind content
- gpu-bg/: extracted WebGPU/WebGL2 spiral engine as a Vite sub-package; slim bootstrap
  drops router/overlay/text renderer; fixed uniforms (scene0/dim0); self-contained engine.js
- archive/: retired Vite SPA preserved (router, overlay, data, engine/text orphaned)
- 3-stage Dockerfile (node -> hugo extended/dart-sass -> nginx), static nginx config
- DEPLOYMENT.md handover + README rewrite; pre-hugo rollback tag
This commit is contained in:
2026-08-21 03:39:42 +02:00
parent 3ad5cf55e3
commit 9ea85db5ce
74 changed files with 3170 additions and 75 deletions

89
DEPLOYMENT.md Normal file
View File

@@ -0,0 +1,89 @@
# Deployment Handover
How the migrated Hugo site is served, and how to adjust the server-side deploy workflow (Gitea Actions + webhook) for the new two-stage build.
## Serving topology (unchanged)
The site is served as before. The host's system nginx (Certbot-managed TLS at `djosen.one`) proxies `location /` → `127.0.0.1:8080`, where the Docker `web` container listens. **Nothing changed** in the system nginx (`nginx/system-default.conf` / `nginx/reverse.conf`) or the Certbot/DNS setup during this migration.
What changed is **what's inside the container**: instead of a Vite SPA (a single `index.html` plus JavaScript), the container now serves a Hugo static site — `public/` with one real `.html` page per path.
## What changed in the build
The build is now **two steps**:
1. **Engine** — `gpu-bg/` Vite/Typescript build → a static JS bundle (`gpu-bg/dist/`).
2. **Site** — `hugo --minify` → `public/`.
The Dockerfile runs both in stages (`node` → `hugo` → `nginx`).
Key details for the server build:
- **Hugo image:** the `site` stage uses `hugomods/hugo:debian-dart-sass-go-0.165.0` — an **extended Hugo** build including dart-sass. This is required because hugo-coder compiles the theme's SCSS via Hugo Pipes (`toCSS`), and Hugo 0.129+ dropped libsass in favor of dart-sass. This replaced the deprecated `klakegg/hugo` image.
- **Theme submodule:** hugo-coder lives as a **git submodule** at `themes/hugo-coder`.
- **Static serving only:** the container nginx no longer does SPA fallback (`try_files ... /index.html`). It serves plain static files — each page is a real `.html`, and a 404 for a missing path is legitimate and intentional.
## Mandatory server-side change (the #1 gotcha)
**Your clone/checkout must initialize submodules before building.** The `themes/hugo-coder` submodule must be pulled in before `docker build`; otherwise `hugo` fails with `theme not found` and the build breaks.
- **Gitea Actions `deploy.yml`:** make the checkout recursive. With `actions/checkout`, set:
```yaml
- uses: actions/checkout@v3
with:
submodules: recursive
```
- **Plain webhook / shell:** use a recursive clone, or run the update before building:
```bash
git clone --recursive ...
# or, on an existing clone:
git pull
git submodule update --init --recursive
```
Nothing else changes server-side: registry credentials, the SSH/webhook target, and the `docker compose up -d` deploy command are all the same. The image is slightly larger to build (node and Hugo-extended layers are discarded; the final nginx stage stays small).
## Testing
### Local (before pushing)
```bash
git submodule update --init --recursive
cd gpu-bg && npm install && npm run build && cd ..
hugo # builds public/
docker compose build # 3-stage build
docker compose up -d # maps 127.0.0.1:8080:8080
```
### Smoke test (after `up -d`)
```bash
curl -sf http://127.0.0.1:8080/ | grep -q 'id="gpu"' && echo "canvas OK"
curl -sf http://127.0.0.1:8080/gpu/engine.js -o /dev/null && echo "engine bundle OK"
curl -sf http://127.0.0.1:8080/about/ -o /dev/null && echo "about OK"
curl -sf http://127.0.0.1:8080/projects/ -o /dev/null && echo "projects OK"
curl -sf http://127.0.0.1:8080/resume/ -o /dev/null && echo "resume OK"
curl -sf http://127.0.0.1:8080/posts/ -o /dev/null && echo "posts OK"
curl -s http://127.0.0.1:8080/nonexistent -o /dev/null -w "%{http_code}\n" # expect 404
```
### Browser check (manual — WebGPU is a real-GPU feature)
- Homepage: emerald spiral animates behind the dark glass panel; text readable.
- With WebGPU disabled, the WebGL2 fallback still animates.
- With no WebGL at all, the page still shows its content; the canvas simply doesn't render.
### After deploy (remote)
- `curl -s https://djosen.one/health` → `ok` (system nginx health endpoint, unchanged).
- Verify `/`, `/about/`, `/projects/`, `/resume/`, `/posts/` over HTTPS.
- Confirm the spiral actually renders in a real browser — the one thing `curl` cannot check.
## Rollback
The previous site is preserved in the git tag `pre-hugo` and the `archive/` folder. To roll back: `git checkout pre-hugo` and redeploy with the old single-stage Dockerfile (also recoverable from git history).
No system nginx or DNS changes were made in this migration, so rollback is purely a container-image swap.