Files
tibi-svelte-starter/api/hooks/ssr/AGENTS.md
T
apairon 4020ad62c5 feat: enhance medialib image handling and add asset URL resolution
- Implemented `resolveApiAssetUrl` function to normalize asset URLs based on API base.
- Updated `MedialibImage` component to utilize new asset URL resolution and added support for alt text and class properties.
- Enhanced image loading behavior with improved width measurement and focal point handling.
- Added placeholder image handling and improved accessibility with alt text.
- Introduced new test script for auditing broken links in skill documentation.
- Expanded seeded test content to include medialib entries and updated related tests for pagebuilder previews.
- Improved global setup and teardown logging for clarity on seeded content management.
2026-05-17 00:52:41 +00:00

3.1 KiB

SSR and Caching

Server-side rendering via goja (Go JS runtime) with HTML caching.

For the full workflow, prefer the tibi-ssr-caching skill.

  • frontend-architecture when SSR changes interact with route loading, i18n, or App.svelte data flow.
  • media-seo-publishing when SSR output includes image URLs, SEO metadata, or publication timing.
  • tibi-hook-authoring when SSR changes depend on neighboring hook behavior such as public filtering or cache invalidation.

Request flow

  1. get_read.js receives the request and calls lib/ssr-server.js.
  2. get_read.js loads lib/app.server.js and calls app.default.render({ url }).
  3. frontend/src/ssr.ts stays thin and only initializes locale state before rendering App.svelte.
  4. frontend/src/App.svelte is responsible for actual page data loading for both browser and SSR.
  5. During SSR, App.svelte calls the same loadContent(...) path directly inside typeof window === "undefined".
  6. Rendered HTML is stored in the ssr collection together with dependency tracking strings.

Keep browser and SSR content loading on the same application path whenever possible. Do not fork a second data-loading model for SSR unless the current architecture explicitly requires it.

Build

  • SSR bundle is built via yarn build:server and outputs to lib/app.server.js.
  • The project no longer uses Babel for SSR.
  • goja-compatible transforms are configured in esbuild.config.server.js via supported.
  • The server build must remove frontend-only splitting/outdir options inherited from the shared esbuild config.

Cache invalidation

  • clear_cache.js hook invalidates SSR cache entries based on collection dependencies.
  • Dependencies are stored as strings like content:<id> or content:*.
  • DELETE invalidation must be robust even when context.data.id is missing.

Route validation

  • SSR route validation is active in config.js.
  • Public page URLs are language-prefixed (/de/..., /en/...), while content.path in the DB is stored without that prefix.
  • ssrValidatePath() must strip the language prefix before querying content and return a canonical language-prefixed URL when needed.
  • If route validation changes, inspect api/hooks/config.js, filter_public.js, and the frontend route-loading path together instead of patching only one side.

404 signaling

The SSR hook (get_read.js) checks context.is404 after rendering to determine the HTTP status code. If true, it returns HTTP 404 with the rendered 404 page HTML (and does not cache the result).

NotFound.svelte sets context.is404 = true during SSR. When the component renders (only when the page is not found), its top-level script sets the flag. The goja runtime provides context as a global during SSR, so it's available from the compiled frontend code.

When adding a 404 page or changing the not-found logic, ensure context.is404 is still set during SSR.

  • After SSR changes, run yarn build:server plus the narrowest reachable SSR/public-read check.
  • If caching or publication behavior changed, also rerun the relevant mutation-side invalidation check instead of relying on HTML diffing alone.