Files
WRNexusJS/packages/ssr
2026-07-24 12:46:44 +05:30
..
2026-07-24 12:46:44 +05:30
2026-07-24 12:46:44 +05:30
2026-07-24 12:46:44 +05:30

@wrnexus/ssr

Server-side rendering: wraps a page's HTML body in a complete HTML document with a metadata-driven <head>.

Part of the WrNexus framework — an SSR-first, Bun-native full-stack web framework.

Overview

Pages in WrNexus return an HTML string for the body. @wrnexus/ssr takes that body and produces a full HTML document — building the <head> from page metadata and global SEO defaults, resolving canonical/Open Graph/Twitter tags, and injecting module preloads and <script type="module"> tags. It is deliberately server-only: nothing in this package touches the DOM or ships to the browser, keeping server code genuinely server-only. Reach for it on the server when turning a rendered page body into a response document.

Installation

bun add @wrnexus/ssr

Private package — the machine must be authenticated to the wrnexus npm org (a read token in ~/.npmrc). Requires Bun (Node is not supported).

API

The package has a single export.

renderDocument(opts: RenderOptions): string

Renders a complete HTML document as a string, beginning with <!doctype html>. All metadata is HTML-escaped (via escapeHtml from @wrnexus/core), so a malicious title or description cannot break out of its element or attribute. The body is placed inside <div id="app">.

RenderOptions

Field Type Description
meta PageMeta Page metadata for the document head (required).
body string Rendered HTML for the body, placed inside #app (required).
seo SeoConfig Global SEO defaults, typically from wrnexus.config.ts.
url URL Current request URL, used to resolve canonical/Open Graph URLs.
scripts string[] URLs of <script type="module"> tags to load (e.g. per-island chunks or the reactive runtime). Each also gets a <link rel="modulepreload">.
defaultTitle string Default document title used when meta.title is absent.
extraHead string Raw HTML injected at the end of <head> (trusted, framework-controlled — not escaped).
extraBody string Raw HTML injected at the end of <body> (trusted, framework-controlled — not escaped).
htmlAttrs string Attributes for the <html> element, e.g. data-theme="dark" (trusted).

PageMeta and SeoConfig come from @wrnexus/core. PageMeta is an alias of SeoConfig, whose fields are all optional:

type SeoConfig = {
  title?: string;
  titleTemplate?: string; // e.g. "%s — My Site"; %s is replaced with the page title
  description?: string;
  canonical?: string;
  canonicalBase?: string; // origin used to absolutize canonical/image URLs
  robots?: string;
  keywords?: string | string[];
  image?: string;
  siteName?: string;
  type?: string; // Open Graph type; defaults to "website"
  locale?: string;
  twitterCard?: string; // defaults to "summary"
  twitterSite?: string;
  themeColor?: string;
};

Metadata resolution

renderDocument merges page metadata (meta) over global defaults (seo), field by field, so per-page values win. Notable behavior:

  • Title: uses meta.title, else seo.title, else defaultTitle, else "WrNexus". When the page sets its own title and seo.titleTemplate contains %s, the template is applied.
  • Canonical / image URLs: resolved against canonicalBase (or the request url's origin) into absolute URLs when possible.
  • Keywords: an array is joined with ", ".
  • Emitted tags: <title>, and as applicable description, robots, keywords, theme-color, and canonical link, plus Open Graph (og:title, og:description, og:type, og:url, og:site_name, og:locale, og:image) and Twitter (twitter:card, twitter:title, twitter:description, twitter:image, twitter:site) meta tags. The document always includes charset, viewport, and a /favicon.ico icon link.

Usage

Render an SEO-ready application page

import { renderDocument } from "@wrnexus/ssr";

const html = renderDocument({
  meta: {
    title: "About Us",
    description: "Learn more about our team.",
  },
  seo: {
    titleTemplate: "%s — Acme",
    siteName: "Acme",
    canonicalBase: "https://acme.example",
    twitterSite: "@acme",
  },
  url: new URL("https://acme.example/about"),
  body: "<h1>About Us</h1>",
  scripts: ["/_wire/runtime.js", "/_wire/islands/about.js"],
  htmlAttrs: ' data-theme="dark"',
});

return new Response(html, {
  headers: { "content-type": "text/html; charset=utf-8" },
});

The produced document has <title>About Us — Acme</title>, the SEO/Open Graph/Twitter tags derived from the merged metadata, a modulepreload link and module <script> for each entry in scripts, and the body wrapped in <div id="app">.

Add trusted framework assets and boot data

Use extraHead and extraBody only for HTML generated by your application or the framework. User-provided values belong in meta, where they are escaped.

const html = renderDocument({
  meta: { title: "Dashboard", robots: "noindex" },
  body: dashboardHtml,
  url: ctx.url,
  extraHead: '<link rel="stylesheet" href="/_wrnexus/admin.css">',
  extraBody: `<script type="application/json" id="boot">${JSON.stringify(bootData).replaceAll("<", "\\u003c")}</script>`,
});

return new Response(html, { headers: { "content-type": "text/html; charset=utf-8" } });

Requirements / Notes

  • Server-only. This module never imports or touches the DOM and is safe to keep out of client bundles.
  • Depends on @wrnexus/core for escapeHtml and the PageMeta / SeoConfig types.
  • Bun-only — like the rest of WrNexus, this package targets the Bun runtime (Node is not supported).