website-htmx-rustelo-code/site/guide/site-operations.md
2026-07-10 03:44:13 +01:00

8.9 KiB

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.

# 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.

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):

# 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):

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.

# 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.

# 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.

# 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).

# 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.

# 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.

kubectl cp site/rbac.ncl <pod-name>:/var/www/site/rbac.ncl

Quick reference

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