… …
ReviewOS

stacks/stx

buildApp SSG: no per-page <title>/meta — @section('title') silently dropped, @head not wired into the app-shell path, page-authored head tags stripped

#1756
Closed glennmichael123 opened this 10 days ago ·
10 days ago

Summary

Apps built with buildApp() ship the identical <title> and meta description on every generated page. The document shell resolves the title as options.title || configTitle (src/document-shell.ts:78), and the SSG path in src/build.ts never derives a per-page title from the view — there is no per-page head mechanism wired in at all:

  • @section('title', ...) in a view extending a body-fragment layout has no @yield target in the shell model, so it is silently dropped.
  • The directive exists (processHeadDirective in src/head.ts), but it is only invoked from the full-document template processor (src/process.ts), not from the app-shell/SSG build path.
  • If a page does author its own <head>, stripDocumentWrapper() (src/app-shell.ts) explicitly strips <meta>, <title>, and <link> tags, preserving only <style> — so per-page titles are actively discarded, then replaced with the global config title.

Impact

SEO is effectively blocked for any stx SSG app: crawlers and link scrapers see one site-wide title/description. Real-world case: bench-review has ~30 views authoring @section('title', ...), yet every page in dist/ carries the same stx.config.ts title verbatim; per-page titles only apply via client JS after hydration, which social scrapers and the first indexing wave never execute.

Suggested fix

During buildApp() page generation, extract per-view head content and pass it into the document shell:

  1. Honor by running processHeadDirective in the app-shell path and feeding the result into the shell's head composition (alongside options.title).
  2. Map @section('title', ...) to options.title as a convenience (it is the idiom users already reach for).
  3. Alternatively (or additionally), stop stripping <title>/<meta> in stripDocumentWrapper() and hoist them into the shell head, letting page-authored head tags win over config defaults.

Sign in to comment on this issue.