website-htmx-rustelo-code/site/guide/site-operations.md

251 lines
8.9 KiB
Markdown
Raw Normal View History

2026-07-10 03:44:13 +01:00
# Site Operations
Operational guide for managing an htmx-ssr consumer site (L3 instance).
All recipes run from the **site root** — the directory that contains `site/`.
## Runtime boundary
The htmx-ssr binary separates what is compiled-in from what is read at runtime.
This determines whether a change requires a restart, a rebuild, or nothing.
| What you change | Binary effect | Action needed |
|------------------------------------------|---------------|---------------------------------------|
| Markdown content, NCL metadata | None | `just content` — no restart |
| JSON content indexes (`site/r/`) | None | Already written by `just content` |
| Knowledge graph (`content_graph.json`) | None | `just graph` — no restart |
| Static assets (CSS, images) | None | Copy to `site/public/` — no restart |
| Jinja templates (`.j2`) | None | `just templates` + server restart |
| FTL strings (`site/i18n/locales/`) | None | Server restart only |
| RBAC (`site/rbac.ncl`) | None | **Automatic hot-reload** — nothing |
| Routes or menus (`site/config/routes.ncl`) | **Baked** | Binary rebuild (see §Routes & menus) |
| New language (routes.ncl + site.ncl) | **Baked** | Binary rebuild (see §New language) |
---
## 1. Update content — preview locally
Content = markdown posts, NCL metadata, and project/blog/recipe pages.
```sh
# Edit markdown files:
# site/content/{type}/{lang}/{category}/{slug}/index.md
# site/content/{type}/{lang}/{category}/{slug}/index.ncl (metadata)
# Regenerate JSON indexes:
just content # all types, all langs
just content type=blog # single type
just content type=blog lang=en # single type + lang
just content type=blog lang=en category=rust # single category (uses --category)
# Watch mode (auto-regenerate on save):
just content-watch
just content-watch type=blog lang=en
# Start server and open browser:
just dev # http://localhost:3030
```
Changes in `site/content/` are served directly — no server restart.
The JSON indexes in `site/r/` are what the server reads; always run `just content` after editing NCL metadata or adding new files.
---
## 2. Update content including the knowledge graph
The knowledge graph connects posts to ontology nodes and to each other.
Requires `ONTOREF_NICKEL_IMPORT_PATH` and `CONTENT_GRAPH_IMPL_ONTOLOGY` in `.env`.
```sh
just content # rebuild JSON indexes first
just graph # rebuild content_graph.json
just dev # preview
```
The graph is pre-built: `gen-content-graph --site .` writes `site/r/content_graph.json`.
The server reads it as a static file — no restart after regeneration.
---
## 3. Publish content to production (no binary rebuild)
Content changes do not need a new container image. Update the PV directly.
**Kubernetes / docker-compose (PVC):**
```sh
# Sync the JSON indexes to the running pod's PVC:
kubectl cp site/r/ <pod-name>:/var/www/site/r/
# Sync source content (if the server reads markdown directly):
kubectl cp site/content/ <pod-name>:/var/www/site/content/
# No rollout restart needed — server reads these on next request.
```
**Full PV resync (after template or FTL changes too):**
```sh
kubectl cp site/ <pod-name>:/var/www/site/
kubectl rollout restart deployment/<deployment-name>
```
**New container image (when binary was rebuilt):**
Run `just build-push-remote` from `website-htmx-rustelo/code/`.
This builds a new image via lian-build and pushes it to the registry.
Deployment manifests reference the new tag.
---
## 4. Update templates — preview locally and publish
Templates are Jinja2 (`.j2`) files loaded at server startup from `HTMX_TEMPLATE_PATH`.
```sh
# Edit source templates in the L2 project:
# website-htmx-rustelo/code/crates/pages_htmx/templates/pages/{slug}.j2
# website-htmx-rustelo/code/crates/pages_htmx/templates/partials/{name}.j2
# Reassemble htmx-templates in the consumer site:
just templates # copies framework + project templates to htmx-templates/
# Restart server (templates loaded at startup):
just dev # kills old server, starts fresh
# Publish: sync htmx-templates to PV + rollout restart
kubectl cp htmx-templates/ <pod-name>:/var/www/htmx-templates/
kubectl rollout restart deployment/<deployment-name>
```
`just templates` runs `assemble-htmx-templates.nu` — it overlays framework defaults
with the L2 project's templates. Project templates always win over framework defaults.
If `just local-install` was run (binary rebuild), the installed share templates at
`~/.local/share/rustelo-htmx-server/htmx-templates/` are also updated. The site's
`htmx-templates/` directory takes precedence over the installed share.
---
## 5. Change menus or routes
Routes and menus are **compiled into the binary** from `site/config/routes.ncl` at
build time. Changing them requires rebuilding the binary.
```sh
# 1. Edit in the consumer site (jpl/site, etc.):
# site/site/config/routes.ncl — add/change URL paths and menu entries
# site/site/config/site.ncl — confirm language list is current
# 2. Copy to the L2 source project (website-htmx-rustelo/code):
# cp site/site/config/routes.ncl website-htmx-rustelo/code/site/config/routes.ncl
# 3. Rebuild the binary from website-htmx-rustelo/code:
cd /path/to/website-htmx-rustelo/code
just local-install # builds release binary + installs wrapper
# 4. Restart the consumer site server:
cd /path/to/jpl/site
just dev
```
`just local-install` takes ~2 min on first build, incremental afterward (sccache).
The new binary at `~/.local/libexec/rustelo-htmx-server` is picked up immediately
on next `just dev` — no path changes needed.
**Route component name convention:**
```
URL: /my-tool → Component: "MyToolPage"
URL: /lian-build → Component: "LianBuildPage"
```
---
## 6. Update FTL strings (i18n text)
FTL files are loaded at **server startup** from `site/i18n/locales/{lang}/`.
No rebuild needed; restart applies the changes.
```sh
# Edit FTL files:
# site/i18n/locales/en/pages/{slug}.ftl
# site/i18n/locales/es/pages/{slug}.ftl
# site/i18n/locales/en/common.ftl (shared UI strings)
# Apply changes (restart server):
just dev # kills existing server, starts with fresh FTL
# Publish: sync i18n to PV + rollout restart
kubectl cp site/i18n/ <pod-name>:/var/www/site/i18n/
kubectl rollout restart deployment/<deployment-name>
```
FTL is fail-open: missing keys render as empty string, never crash.
Both languages (`en` and `es`) must be kept in sync — add every key to both.
---
## 7. Add a new language
Adding a language requires both FTL files (runtime) and route paths (compile-time).
```sh
# Step 1 — Create FTL translations (runtime, no rebuild):
mkdir -p site/i18n/locales/{lang}/pages
cp site/i18n/locales/en/*.ftl site/i18n/locales/{lang}/
# Translate all strings in the copied files
# Step 2 — Register the language (requires rebuild):
# In site/config/site.ncl — add to the languages list
# In site/config/routes.ncl — add "{lang} = /{path}" to every route
# Step 3 — Rebuild binary:
cd /path/to/website-htmx-rustelo/code
just local-install
# Step 4 — Restart:
cd /path/to/consumer-site
just dev
```
If the new language shares URL paths with English (e.g., language detection via
`Accept-Language` header only), steps 2 and 3 may be skipped — only FTL is needed.
Verify with `just htmx-smoke` after starting the server.
---
## 8. Change RBAC permissions
RBAC is hot-reloaded automatically. The server watches `site/rbac.ncl` for changes
and applies them without restart.
```sh
# Edit:
# site/rbac.ncl — roles, groups, protected paths, anonymous deny paths
# No action needed — the running server picks up changes within ~1s.
# Confirm in server logs: "rbac hot-reload: N groups, M overrides"
```
If the server is not running, changes take effect on next `just dev`.
**For deployment**: sync `site/rbac.ncl` to the PVC — no rollout restart needed.
```sh
kubectl cp site/rbac.ncl <pod-name>:/var/www/site/rbac.ncl
```
---
## Quick reference
```sh
just dev # start local server
just content [type] [lang] # regenerate content indexes
just content-watch [type] [lang] # watch + auto-regenerate
just graph # rebuild content_graph.json
just templates # rebuild htmx-templates from source
just sync # templates + content (no graph)
just sync-full # templates + content + graph
```
**When to rebuild the binary** (`just local-install` in `website-htmx-rustelo/code`):
- Routes or menu structure changed
- New language with distinct URL paths
- New page component type added