simple server-side rendering via happy-dom for vode based apps
  • TypeScript 100%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Michael Scherbakow 0fa69233cf
Some checks failed
Publish release to NPM, GitHub & Chimps Packages / Verify Release and Run Tests (release) Failing after 12s
Publish release to NPM, GitHub & Chimps Packages / Publish to NPM (release) Has been skipped
Publish release to NPM, GitHub & Chimps Packages / Publish to GitHub Packages (release) Has been skipped
Publish release to NPM, GitHub & Chimps Packages / Publish to Chimps Packages (release) Has been skipped
Unit Tests / Check Unit Tests (push) Failing after 16s
initial commit
2026-08-17 20:20:33 +02:00
.github/workflows initial commit 2026-08-17 20:20:33 +02:00
dist initial commit 2026-08-17 20:20:33 +02:00
src initial commit 2026-08-17 20:20:33 +02:00
.gitignore initial commit 2026-08-17 20:20:33 +02:00
api-extractor.json initial commit 2026-08-17 20:20:33 +02:00
index.ts initial commit 2026-08-17 20:20:33 +02:00
LICENSE initial commit 2026-08-17 20:20:33 +02:00
package-lock.json initial commit 2026-08-17 20:20:33 +02:00
package.json initial commit 2026-08-17 20:20:33 +02:00
README.md initial commit 2026-08-17 20:20:33 +02:00
tsconfig.json initial commit 2026-08-17 20:20:33 +02:00
tsconfig.types.json initial commit 2026-08-17 20:20:33 +02:00

vode-ssr

Server-side rendering utilities for vode apps.

Note: this is a very early/untested implementation

Usage

There are 2 main render functions.

renderURL(options, req)

Vode independent rendering of a url inside an isolated window. Waits for all asynchronous operations to settle (with timeout) and the returnes the full html document as string.

Hono Example

import { Context } from "hono";
import { H } from "hono/types";
import { renderURL, ForwardedRequest, RequestBasedRenderOptions } from "@ryupold/vode-ssr";

/**
 * Creates a Hono endpoint that performs server-side rendering (SSR) for a given request URL.
 * @param { RequestBasedRenderOptions } options
 * @returns Hono endpoint handler function
 */
export function createSSREndpoint(options: RequestBasedRenderOptions): H {
    return async (c: Context) => {
        if (c.req.method !== "POST") {
            return new Response("Method Not Allowed. You must POST with a ForwardedRequest ({url: string, headers?: Record<string, string>;}) as JSON body.", { status: 405 });
        }

        const forwardedRequest: ForwardedRequest = JSON.parse(await c.req.text());

        if (typeof forwardedRequest.url !== "string")
            return new Response("forwarded request must contain a { url: string }", { status: 400 });

        if (forwardedRequest.headers && typeof forwardedRequest.headers !== "object")
            return new Response("forwarded request contained invalid headers. must be: { url: string, headers?: Record<string, string> }", { status: 400 });

        const renderedHTML = await renderURL(options, forwardedRequest);

        return new Response(renderedHTML, {
            headers: { "Content-Type": "text/html" },
        });
    };
}

Then use it in your api backend.

const app = new Hono();

app.post('/ssr', createSSREndpoint({
    baseUrl: "https://ryupold.de",
    ssrHeader: { "X-SSR": "IGNORE" }
}));

renderVodeApp(options, state, view, initialPatches = [])

Specific to vode and with more control you can render a vode view as app for a specific state (+ patches) in a given HTML shell

renderVodeApp(
    // Render Options
    {
        shell: {
            html: `<html>
                    <head><meta charset="utf-8"></head>
                    <body><div id="app"></div></body>
                    </html>`,
            containerSelector: '#app',
        },
        prefersColorScheme: 'dark',
        windowSize: { width: 1024, height: 768 },
        timeoutMs: 30000,
    },
    
    // App State
    { name: "World" },
    
    // App View
    (s) => [DIV, { id: 'app' }, [H1, "Hello"], [P, s.name]],

    // you can add an optional array of patches that will be applied after the first render
    // ...
)

Thanks

I'm very thankful that we live in a world where libraries like happy-dom exist for free to use and tinker with.

License

License: MIT