HarborHarbor
DocumentationGuidesPlugins
Authoring

App UI (Beta)

/sdk/orbit templates and primitives — server-rendered HTML without React. (Beta)

Beta

App UI is part of the Apps beta surface. Templates and primitives may change before v1.

/sdk/orbit is the authoring import for App routes that want to render HTML. It's a small library of polished server-rendered templates — no React, no Tailwind config, no build step.

Forbidden in hrbr exec. There's no runtime orbit.ui.* namespace. App UI is import-only, used inside Function handlers and App routes.

Templates shipped

TemplateUse for
formPageIntake forms, feedback, surveys
listPageTables / boards of workspace records
statusPageMulti-section status (OK / Degraded / Outage)
reportPageHTML artifact for orbit.storage (e.g. weekly reports)
landingPageLightweight CTA / marketing page for an App

formPage


formPage({
  title:    "Send us feedback",
  lead:     "We read every word.",
  submitTo: "POST /",
  fields: [
    { name: "subject", label: "Subject",            required: true },
    { name: "body",    label: "Details",            required: true, type: "textarea" },
    { name: "email",   label: "Your email (opt)",   type: "email" },
    { name: "topic",   label: "Topic",              type: "select", options: ["bug", "feature", "other"] },
  ],
});

Returns a fully-rendered HTML string. Validates required fields client-side, posts to submitTo.

listPage


listPage({
  title:   "Active issues",
  columns: [
    { key: "title",     label: "Title" },
    { key: "state",     label: "State" },
    { key: "owner",     label: "Owner" },
    { key: "updatedAt", label: "Updated", type: "datetime" },
  ],
  rows: await ctx.plugins.linearMcp.listIssues({ limit: 100 }),
});
FieldNotes
columns[].keyDot-path into the row object (state.name, assignee.email, etc.)
columns[].type"datetime", "badge", "link", "text" (default)
rowsArray of any objects

statusPage

statusPage({
  title: "Production status",
  sections: [
    { name: "API",          status: "ok",       summary: "All systems normal" },
    { name: "Workers",      status: "degraded", summary: "Elevated latency" },
    { name: "Background",   status: "ok",       summary: "Queues drained" },
  ],
});

Customisation

Templates accept a theme option:

formPage({
  /* … */,
  theme: {
    primary:    "#0a0a0a",
    background: "#fafafa",
    font:       "Inter, system-ui",
  },
});

For deeper customisation, the templates return plain HTML strings — post-process with whatever you want (DOMPurify for sanitising user content, your own CSS injection).

Where to go next