Recipes
HTML report from Orbit
Generate a styled HTML report and serve it from a signed Orbit storage URL. (Beta)
Beta
Uses /sdk/orbit HTML templates which are part of the
Apps/Functions beta surface.
A Function that generates a polished HTML artifact (a weekly board, a
project status, a per-customer report) and stores it under
orbit.storage. You get a signed URL anyone with the link can open — no
Harbor login required.
defineJob({
name: "weekly-status",
description: "Generate this week's status report as a sharable HTML page.",
handler: async (ctx) => {
const rows = await ctx.plugins.linearMcp.listIssues({
filter: { updatedAt: { gte: lastWeekISO() } },
limit: 100,
});
const html = listPage({
title: "Weekly status",
lead: `${rows.length} updates this week.`,
columns: [
{ key: "title", label: "Issue" },
{ key: "state.name", label: "State" },
{ key: "assignee.name", label: "Owner" },
{ key: "updatedAt", label: "Updated", type: "datetime" },
],
rows,
});
const path = \`reports/weekly-\${todayISO()}.html\`;
await ctx.orbit.storage.put(path, html, { contentType: "text/html" });
const url = await ctx.orbit.storage.url(path, { expiresIn: "14d" });
return { url, count: rows.length };
},
});
function todayISO() { return new Date().toISOString().slice(0, 10); }
function lastWeekISO() {
return new Date(Date.now() - 7 * 86_400_000).toISOString();
}What you get
The listPage template applies sensible defaults (Inter font, neutral
palette, responsive table). For your own brand colors, override CSS
variables in the template options.
Variations
- Per-team reports: loop teams, generate one file per team, return the list of URLs.
- Public report: drop the signed-URL step and instead expose via an
App route with
auth: "public". - Embeddable widget: include
{ embedMode: true }to render without the page chrome.
See Authoring → App UI for the full template catalogue.