Bumps all 47 packages, the root manifest and the VS Code extension to 0.8.6, and rebuilds the editor compiler, language server and extension bundles that embed the version. The release carries the output delivery fix: camelCase outputs now reach parent bindings, and 18 components emit through output.* instead of hand-built CustomEvents. See the 0.8.6 migration entry for what changes for consumers. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@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
wrnexusnpm 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, elseseo.title, elsedefaultTitle, else"WrNexus". When the page sets its own title andseo.titleTemplatecontains%s, the template is applied. - Canonical / image URLs: resolved against
canonicalBase(or the requesturl's origin) into absolute URLs when possible. - Keywords: an array is joined with
", ". - Emitted tags:
<title>, and as applicabledescription,robots,keywords,theme-color, andcanonicallink, 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 includescharset,viewport, and a/favicon.icoicon 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/coreforescapeHtmland thePageMeta/SeoConfigtypes. - Bun-only — like the rest of WrNexus, this package targets the Bun runtime (Node is not supported).