madapes

@aurora/runtime-ssr (0.3.2)

Published 2025-12-27 10:26:37 +00:00 by vlad

Installation

@aurora:registry=
npm install @aurora/runtime-ssr@0.3.2
"@aurora/runtime-ssr": "0.3.2"

About this package

@aurora/runtime-ssr

Server-Side Rendering (SSR) for Aurora applications.

Overview

Aurora's SSR package provides:

  • Page routing with data fetching
  • Layout support
  • HTML rendering
  • Integration with Aurora API routes

Installation

bun add @aurora/runtime-ssr

Quick Start

import { PageRouter, Renderer } from "@aurora/runtime-ssr";

// Define pages
const router = new PageRouter();

router.page("/dashboard/:tenantId", async (params) => {
  const orders = await api.getOrders({ tenantId: params.tenantId });
  
  return {
    title: "Dashboard",
    layout: "main",
    props: { orders },
  };
});

// Create renderer
const renderer = new Renderer({
  pages: router,
  templates: "./templates",
});

// Use with HTTP server
import { Server } from "@aurora/runtime-http";

const server = new Server({ port: 3000 });
server.get("*", async (req) => {
  const html = await renderer.render(req.url);
  return new Response(html, {
    headers: { "Content-Type": "text/html" },
  });
});

Page Routes

Defining Pages

router.page("/dashboard/:tenantId", async (params) => {
  const tenant = await database.findTenant(params.tenantId);
  const orders = await database.findOrders(params.tenantId);
  
  return {
    title: `${tenant.name} - Dashboard`,
    layout: "main",
    props: { tenant, orders },
  };
});

Page Context

router.page("/orders/:orderId", async (params, context) => {
  const order = await database.findOrder(params.orderId);
  
  return {
    title: `Order ${order.orderId}`,
    layout: "main",
    props: { order },
    meta: {
      description: `Order ${order.orderId} - ${order.status}`,
    },
  };
});

Layouts

Defining Layouts

const layouts = {
  main: (props) => `
    <!DOCTYPE html>
    <html>
      <head>
        <title>${props.title}</title>
      </head>
      <body>
        <header>Aurora App</header>
        <main>${props.content}</main>
        <footer>&copy; 2024</footer>
      </body>
    </html>
  `,
  
  admin: (props) => `
    <!DOCTYPE html>
    <html>
      <head>
        <title>${props.title} - Admin</title>
      </head>
      <body>
        <nav>Admin Panel</nav>
        <main>${props.content}</main>
      </body>
    </html>
  `,
};

Nested Layouts

router.layout("admin", async (params) => {
  const user = await context.getUser();
  
  if (!user || !user.isAdmin) {
    throw new RedirectError("/login");
  }
  
  return { user };
});

Renderer

Creating Renderer

import { Renderer } from "@aurora/runtime-ssr";

const renderer = new Renderer({
  pages: router,
  templates: "./templates",
  defaultLayout: "main",
});

Rendering Pages

// Render to string
const html = await renderer.render("/dashboard/tenant-1");

// Render with custom context
const html = await renderer.render("/orders/123", {
  user: currentUser,
});

Templates

Create HTML templates:

<!-- templates/dashboard.html -->
<div class="dashboard">
  <h1>Dashboard</h1>
  <table>
    <thead>
      <tr>
        <th>Order ID</th>
        <th>Status</th>
        <th>Amount</th>
      </tr>
    </thead>
    <tbody>
      {{#each orders}}
      <tr>
        <td>{{orderId}}</td>
        <td>{{status}}</td>
        <td>{{amount}}</td>
      </tr>
      {{/each}}
    </tbody>
  </table>
</div>

Data Fetching

Server-Side Data

router.page("/orders/:orderId", async (params) => {
  const order = await api.getOrder({ orderId: params.orderId });
  
  return {
    title: `Order ${order.orderId}`,
    props: { order },
  };
});

Client-Side Data

<div id="orders-container"></div>
<script>
  const { useGetOrders } = await import('./generated/hooks');
  
  const { data: orders, loading } = useGetOrders(
    { tenantId: 'tenant-1' }
  );
  
  // Render orders...
</script>

Error Handling

404 Not Found

router.notFound(async (url) => {
  return {
    title: "Not Found",
    layout: "main",
    props: { url },
  };
});

Error Pages

router.error(async (error) => {
  if (error instanceof NotFoundError) {
    return {
      title: "Not Found",
      layout: "main",
      props: { error },
    };
  }
  
  return {
    title: "Server Error",
    layout: "main",
    props: { error },
  };
});

Redirects

import { RedirectError } from "@aurora/runtime-ssr";

router.page("/old-path", async () => {
  throw new RedirectError("/new-path", 301);
});

router.page("/private", async (params, context) => {
  if (!context.user) {
    throw new RedirectError("/login", 302);
  }
  
  return { /* ... */ };
});

Integration with HTTP Server

import { Server } from "@aurora/runtime-http";
import { Renderer } from "@aurora/runtime-ssr";

const server = new Server({ port: 3000 });
const renderer = new Renderer({ pages: router, templates: "./templates" });

// SSR routes
server.get("/dashboard/*", async (req) => {
  const html = await renderer.render(req.url);
  return new Response(html, {
    headers: { "Content-Type": "text/html" },
  });
});

// API routes
server.post("/api/v1/orders", apiHandler);

// Static assets
server.get("/static/*", staticHandler);

await server.start();

License

MIT

Dependencies

Dependencies

ID Version
@aurora/runtime-effect 0.3.2
@aurora/runtime-http 0.3.2
@aurora/schema 0.3.2
Details
npm
2025-12-27 10:26:37 +00:00
8
3.8 KiB
Assets (1)
Versions (3) View all
0.3.3 2025-12-27
0.3.2 2025-12-27
0.3.1 2025-12-27