Files
alkgen/docs/architecture/decisions/006-ssr-library-posture.md
glm-5.3-flash a91ea2ec89 docs(architecture): phase 1 base: text-generation core specs, ADRs 001-010, OQ tracker
- overview.md, core.md, emit.md, targets.md: modular spec set for the
  generalized engine (contexts + templates + partials -> text), with
  the three targets (ssr-html, bast-rust-codecs, call-handlers,
  wgsl-jit) as template sets plus emit postures
- ADRs 001-010: one core/template-set split, handlebars 6.4 strict
  substrate, sync/wasm/deterministic posture, typed contexts with
  builders, per-registry escaper, SSR library posture, typed direct
  codecs output contract, template-set ownership, feature gating,
  library-only v1
- open-questions.md: OQ-01..OQ-08 centralized tracker carrying phase-0
  residue (GN-01/02/07/09) with three deferred(scope) entries plus a
  resolved disposition for phase-0 OQ-GN-04
- tasks/architecture/: external-trigger tracker tasks paired with the
  deferred OQs (taskgraph validate passes)
- phase-0.md checklist dispositioned for OQ-GN-04; AGENTS.md lifecycle
  updated to phase 1

Verification: taskgraph validate (4 tasks OK), cargo fmt --check,
cargo test, em-dash grep clean; architecture-reviewer pass returned
zero critical issues
2026-11-06 08:18:43 +00:00

3.0 KiB

ADR-006: SSR: alkgen is an in-process rendering library for alkforge

Status

Accepted

Context

alkforge (family ADR-002, the gitea replacement) needs server-side HTML generation before the codegen branches matter to it. Its no-deformation rule routes the ask into alkgen's design rather than around it. During the unpause discussion three candidate postures existed for SSR rendering, and the choice shapes alkgen's public API and dependency weight inside alkforge:

  1. pre-rendered static assets (the dev-tool posture reused);
  2. in-process library rendering, render-per-request;
  3. in-process library rendering with consumer-side caching.

A separate quickjs-based SSR route (preact) was floated and rejected: pure Rust rendering is faster and removes an interpreter from the attack surface, which matters for a git-serving web product.

Decision

  1. In-process library rendering (posture B in emit.md): alkforge links alkgen and renders HTML on demand. Static pre-rendering remains possible later (same machinery, posture A), but the design-time posture is in-process.
  2. Render-per-request vs cached rendering is alkforge's choice. alkgen guarantees pure, synchronous, deterministic rendering (ADR-003), which is the property that makes consumer-side caching and content hashing safe to build; alkgen provides no cache.
  3. Output units are fragments and full pages. Partials make fragments natural; pages compose fragments. The phase-0 fragment exclusion was scoped to the code branches and does not apply here (phase-0 OQ-GN-09).
  4. Render failures are typed errors mapped by alkforge to its error surface; no panics; no silently-blank regions (strict mode, ADR-002).
  5. No DO-NOT-EDIT banner on rendered HTML: it is the served product, not a checked-in generated artifact. Determinism still applies, and golden render tests pin pages in alkforge.

Consequences

  • Positive: no filesystem, no build step, and no staleness discipline needed for SSR content; templates can change with alkforge's builds safely against live data.
  • Positive: the same API shape (build registry, render template) is the dev-tool integration shape, so posture A and posture B share the core's surface rather than forking it.
  • Negative: rendering cost sits in the request path when uncached; consumers who need zero request-path cost can still pre-render (posture A) with the same sets.
  • Negative: alkgen gains an always-deployed dependency weight in alkforge; ADR-009 keeps that weight to the core by keeping alktype out of SSR builds.

References

  • emit.md (posture B)
  • targets.md (ssr-html)
  • ADR-001, ADR-005, ADR-008, ADR-009
  • Phase-0 OQ-GN-09 (docs/research/phase-0.md); family ADR-002 (/workspace/@alkdev/alkfamily/docs/architecture/decisions/002-alkforge-gitea-replacement.md)