sheengemologic ui

Application Composer

Start from the compact AdminApp baseline, then move branded chrome and compose real Sheen components. Output is copyable TSX, not a runtime page schema.
Starter ready. Select a block or add a component.
Place navigation, account, and app chrome

Preview canvas

Resize the frame, use the viewport presets, or drag a palette item to a semantic region.

Copyable output

The JSON schema is private and unstable. Generated TSX uses public Sheen imports and deterministic fixtures.
northstar-admin-starter.tsxGenerated Composer TSX
import { ActivityTimeline, Button, Card, Grid, Heading, Input, SearchInput, Stack, Text, ThemeProvider } from "@gemologic/sheen";
import type { ActivityTimelineItem } from "@gemologic/sheen";
import { defineSeries } from "@gemologic/sheen-charts/core";
import type { ChartData } from "@gemologic/sheen-charts/core";
import { TimeSeries } from "@gemologic/sheen-charts/time-series";
import { PageHeader, StatusBar } from "@gemologic/sheen-patterns";
import { AdminApp } from "@gemologic/sheen-patterns/admin";
import type { AdminPlacementOverride } from "@gemologic/sheen-patterns/admin";
import { DataTable, QueryBuilder, defineColumns } from "@gemologic/sheen-table";
import type { FilterNode, QueryBuilderColumn } from "@gemologic/sheen-table/core";
import { createSignal } from "solid-js";

export interface GeneratedRecord { readonly id: string; readonly account: string; readonly owner: string; readonly status: "Active" | "Review" | "Paused"; readonly amount: number; }

const columns = defineColumns<GeneratedRecord>([
  { id: "account", header: "Account", accessor: row => row.account, search: true, filter: { type: "text" }, sort: "text", width: "fill" },
  { id: "owner", header: "Owner", accessor: row => row.owner, search: true, filter: { type: "text" }, sort: "text", width: 180 },
  { id: "status", header: "Status", accessor: row => row.status, filter: { type: "enum", options: ["Active", "Review", "Paused"], faceted: true }, sort: "text", width: 120 },
  { id: "amount", header: "Amount", accessor: row => row.amount, filter: { type: "number" }, sort: "number", numeric: true, width: 140 },
]);

const queryColumns = [
  { id: "account", label: "Account", type: "text" },
  { id: "owner", label: "Owner", type: "text" },
  { id: "status", label: "Status", type: "enum", options: ["Active", "Review", "Paused"] },
  { id: "amount", label: "Amount", type: "number" },
] satisfies readonly QueryBuilderColumn[];

const initialQuery: FilterNode = { kind: "and", children: [
  { kind: "enum", column: "status", operator: "in", values: ["Active", "Review", "Paused"] },
] };

const series = defineSeries([
  { key: "p50", label: "p50", color: "chart-1" },
  { key: "p99", label: "p99", color: "chart-3", encoding: "dashed" },
]);

const records: readonly GeneratedRecord[] = [
  {
    "id": "record-0001",
    "account": "Aperture 001",
    "owner": "Katherine Thompson",
    "status": "Paused",
    "amount": 66135.25
  },
  {
    "id": "record-0002",
    "account": "Beacon 002",
    "owner": "Grace Lovelace",
    "status": "Active",
    "amount": 75639.03
  },
  {
    "id": "record-0003",
    "account": "Cinder 003",
    "owner": "Katherine Thompson",
    "status": "Active",
    "amount": 76422.87
  },
  {
    "id": "record-0004",
    "account": "Drift 004",
    "owner": "Margaret Dijkstra",
    "status": "Active",
    "amount": 65692.84
  },
  {
    "id": "record-0005",
    "account": "Evergreen 005",
    "owner": "Grace Hamilton",
    "status": "Active",
    "amount": 39828.95
  },
  {
    "id": "record-0006",
    "account": "Fable 006",
    "owner": "Grace Hamilton",
    "status": "Review",
    "amount": 20680.69
  },
  {
    "id": "record-0007",
    "account": "Granite 007",
    "owner": "Ada Torvalds",
    "status": "Active",
    "amount": 24946.58
  },
  {
    "id": "record-0008",
    "account": "Harbor 008",
    "owner": "Margaret Dijkstra",
    "status": "Active",
    "amount": 15768.08
  },
  {
    "id": "record-0009",
    "account": "Aperture 009",
    "owner": "Radia Perlman",
    "status": "Active",
    "amount": 15422.77
  },
  {
    "id": "record-0010",
    "account": "Beacon 010",
    "owner": "Grace Lovelace",
    "status": "Active",
    "amount": 67416.74
  },
  {
    "id": "record-0011",
    "account": "Cinder 011",
    "owner": "Grace Dijkstra",
    "status": "Review",
    "amount": 60648.54
  },
  {
    "id": "record-0012",
    "account": "Drift 012",
    "owner": "Radia Perlman",
    "status": "Paused",
    "amount": 77649.89
  },
  {
    "id": "record-0013",
    "account": "Evergreen 013",
    "owner": "Grace Perlman",
    "status": "Active",
    "amount": 50811.89
  },
  {
    "id": "record-0014",
    "account": "Fable 014",
    "owner": "Edsger Torvalds",
    "status": "Active",
    "amount": 17623.59
  },
  {
    "id": "record-0015",
    "account": "Granite 015",
    "owner": "Grace Lovelace",
    "status": "Active",
    "amount": 37415.62
  },
  {
    "id": "record-0016",
    "account": "Harbor 016",
    "owner": "Grace Hamilton",
    "status": "Review",
    "amount": 78604.25
  },
  {
    "id": "record-0017",
    "account": "Aperture 017",
    "owner": "Ada Torvalds",
    "status": "Active",
    "amount": 71626.27
  },
  {
    "id": "record-0018",
    "account": "Beacon 018",
    "owner": "Grace Lovelace",
    "status": "Active",
    "amount": 84664.2
  },
  {
    "id": "record-0019",
    "account": "Cinder 019",
    "owner": "Ada Torvalds",
    "status": "Active",
    "amount": 64363.83
  },
  {
    "id": "record-0020",
    "account": "Drift 020",
    "owner": "Margaret Dijkstra",
    "status": "Active",
    "amount": 29903.19
  },
  {
    "id": "record-0021",
    "account": "Evergreen 021",
    "owner": "Grace Dijkstra",
    "status": "Review",
    "amount": 86528.07
  },
  {
    "id": "record-0022",
    "account": "Fable 022",
    "owner": "Radia Perlman",
    "status": "Active",
    "amount": 8746.32
  },
  {
    "id": "record-0023",
    "account": "Granite 023",
    "owner": "Margaret Hopper",
    "status": "Paused",
    "amount": 36713.12
  },
  {
    "id": "record-0024",
    "account": "Harbor 024",
    "owner": "Edsger Torvalds",
    "status": "Active",
    "amount": 86492.06
  }
];
const activity: readonly ActivityTimelineItem[] = [
  {
    "id": "requested",
    "title": "Change requested",
    "description": "The release candidate entered review.",
    "actor": "Radia Torvalds",
    "timestamp": "2026-09-09T10:00:00.000Z",
    "timeLabel": "10:00 AM",
    "state": "completed"
  },
  {
    "id": "approved",
    "title": "Policy approved",
    "description": "Automated and operator gates accepted the change.",
    "actor": "Grace Dijkstra",
    "timestamp": "2026-09-09T11:00:00.000Z",
    "timeLabel": "11:00 AM",
    "state": "completed"
  },
  {
    "id": "deploying",
    "title": "Deployment running",
    "description": "Three regions are receiving revision 1842.",
    "actor": "Ada Torvalds",
    "timestamp": "2026-09-09T12:00:00.000Z",
    "timeLabel": "12:00 PM",
    "state": "current"
  },
  {
    "id": "verify",
    "title": "Verify production",
    "description": "Confirm service health and error budgets.",
    "state": "upcoming"
  }
];
const chartData: ChartData = {
  t: new Float64Array([1788955200000, 1788955260000, 1788955320000, 1788955380000, 1788955440000, 1788955500000, 1788955560000, 1788955620000, 1788955680000, 1788955740000, 1788955800000, 1788955860000, 1788955920000, 1788955980000, 1788956040000, 1788956100000, 1788956160000, 1788956220000, 1788956280000, 1788956340000, 1788956400000, 1788956460000, 1788956520000, 1788956580000, 1788956640000, 1788956700000, 1788956760000, 1788956820000, 1788956880000, 1788956940000, 1788957000000, 1788957060000, 1788957120000, 1788957180000, 1788957240000, 1788957300000, 1788957360000, 1788957420000, 1788957480000, 1788957540000, 1788957600000, 1788957660000, 1788957720000, 1788957780000, 1788957840000, 1788957900000, 1788957960000, 1788958020000]),
  p50: new Float64Array([19.346, 20.625, 19.728, 21.066, 20.916, 22.814, 22.34, 22.938, 22.791, 22.339, 23.478, 21.883, 20.974, 20.408, 20.979, 19.03, 19.213, 17.285, 18.025, 17.219, 16.571, 16.156, 14.804, 15.069, 15.947, 14.432, 15.433, 15.143, 16.468, 18.118, 17.683, 19.475, 18.704, 20.81, 21.346, 21.533, 23.069, 22.509, 22.041, 22.244, 23.796, 22.222, 21.825, 22.11, 21.563, 21.443, 20.012, 19.218]),
  p99: new Float64Array([48.591, 49.452, 50.379, 49.82, 53.645, 54.723, 53.217, 53.9, 54.248, 54.816, 56.716, 58.41, 57.791, 55.083, 55.767, 53.762, 55.054, 53.85, 52.381, 50.249, 51.945, 51.054, 48.842, 46.916, 44.63, 43.902, 45.072, 43.264, 39.736, Number.NaN, 40.641, 39.314, 37.988, 39.442, 40.052, 39.837, 38.791, 39.553, 41.201, 43.032, 43.64, 45.355, 43.56, 47.04, 49.555, 47.386, 52.111, 53.449]),
};

const placements = [
  { zone: "current-view", target: "topbar-start" },
  { zone: "command-trigger", target: "topbar-center" },
  { zone: "global-search", target: "topbar-center" },
  { zone: "primary-actions", target: "topbar-end" },
  { zone: "utility-actions", target: "topbar-end" },
  { zone: "notifications", target: "topbar-end" },
  { zone: "help", target: "topbar-end" },
  { zone: "product", target: "sidebar-header" },
  { zone: "workspace", target: "sidebar-header" },
  { zone: "primary-navigation", target: "sidebar-navigation" },
  { zone: "secondary-navigation", target: "sidebar-navigation" },
  { zone: "account", target: "sidebar-footer" },
] satisfies readonly AdminPlacementOverride[];

export default function GeneratedAdminApp() {
  const [workspace, setWorkspace] = createSignal("production");
  const [detailsOpen, setDetailsOpen] = createSignal(true);
  const [queryFilter, setQueryFilter] = createSignal<FilterNode>(initialQuery);
  return (
  <ThemeProvider>
    <AdminApp
          label="Northstar operations application"
          pathname="/accounts"
          preset="standard"
          appearance={{"chrome":"layered","navigation":"subtle","actions":"quiet"}}
          placements={placements}
          product={{ name: "Northstar operations", href: "/" }}
          workspace={{ label: "Workspace", currentId: workspace(), items: [{ id: "production", label: "Production" }, { id: "staging", label: "Staging" }], onChange: setWorkspace }}
          primaryNavigation={{ id: "primary", label: "Primary navigation", items: [{ kind: "link", id: "overview", label: "Overview", href: "/" }, { kind: "link", id: "accounts", label: "Accounts", href: "/accounts", match: "prefix" }] }}
          currentView={<strong>Accounts</strong>}
          globalSearch={<SearchInput label="Search application" />}
          actionGroups={[{ id: "create", label: "Create", role: "primary", items: [{ kind: "action", id: "new", label: "New account", onSelect: () => setDetailsOpen(true) }] }]}
          notifications={{ items: [{ kind: "link", id: "deployed", title: "Deploy completed", href: "/", timeLabel: "4 minutes ago" }] }}
          account={{ id: "ada", name: "Ada Lovelace", email: "ada@northstar.example.test", items: [{ kind: "action", id: "profile", label: "Profile settings", onSelect: () => undefined }] }}
          commandPalette={{ sources: [{ kind: "static", id: "application", commands: [{ id: "accounts", label: "Open accounts", group: "Navigation", run: () => undefined }] }] }}
          details={{ id: "details", title: "Account details", open: detailsOpen(), onOpenChange: setDetailsOpen, content: <>
            <Card bordered={true} padding={"lg"} variant={"subtle"}>
              <Heading level={2} size={"h3"}>{"Account details"}</Heading>
              <Text numeric={false} size={"body"} tone={"muted"}>{"Select a record to inspect ownership, status, and recent changes."}</Text>
            </Card>
          </> }}
          statusBar={<StatusBar connection="connected" tasks={0} counts={[{ label: "Records", value: records.length }]}><>
            <Text numeric={true} size={"caption"} tone={"muted"}>{"96 records · revision 1842"}</Text>
          </></StatusBar>}
        >
          <Stack gap="lg">
          <PageHeader headingLevel={1} title={"Accounts"} actions={<Button>Export records</Button>} />
          <Stack gap={"sm"}>
            <Input label={"Search accounts"} placeholder={"Name, owner, or status"} />
            <Button size={"sm"} tone={"accent"} variant={"solid"} onClick={() => setDetailsOpen(true)}>{"Create account"}</Button>
          </Stack>
          <Grid columns={2} gap={"lg"}>
            <Card bordered={true} padding={"lg"} variant={"raised"}>
              <Heading level={2} size={"h3"}>{"API latency"}</Heading>
              <TimeSeries height={220} label={"API latency"} summary={"Median latency is steady; one p99 sample is missing."} tooltip={true} xLabel={"Time"} series={series} data={chartData} x={{ type: "time", tz: "UTC" }} y={{ format: "duration" }} legend={"inline"} />
            </Card>
            <Card bordered={true} padding={"lg"} variant={"raised"}>
              <Heading level={2} size={"h3"}>{"Recent activity"}</Heading>
              <ActivityTimeline density={"compact"} label={"Deployment activity"} items={activity} />
            </Card>
            <QueryBuilder columns={queryColumns} value={queryFilter()} onChange={setQueryFilter} disabled={false} label={"Account query"} />
            <DataTable data={records} columns={columns} getRowId={row => row.id} caption={"Northstar accounts"} variant="integrated" density="compact" pagination={{ pageIndex: 0, pageSize: 12 }} filter={queryFilter()} onAcceptedStateChange={state => setQueryFilter(state.filter)} search={{}} filterBar columnControls export={{ filename: "application-records" }} initialViewportHeight={320} mobileLayout={{ pageSize: 12, titleColumn: "account" }} />
          </Grid>
          </Stack>
        </AdminApp>
  </ThemeProvider>
  );
}
Import or inspect private Composer JSON