lemma-widget

GitHub

指导创建轻量级内联 Lemma 组件,用于在对话中展示结构化数据、图表或列表。通过 display_resource 嵌入自包含 HTML/CSS/JS 或 SVG,支持实时 Pod 数据,强调轻量化与无状态特性。

lemma-skills/lemma-widget/SKILL.md lemma-work/lemma-platform

触发场景

需要在对话中展示结构化数据或可视化图表 需要创建轻量级的内联 UI 组件而非完整应用

安装

npx skills add lemma-work/lemma-platform --skill lemma-widget -g -y
更多选项

非标准路径

npx skills add https://github.com/lemma-work/lemma-platform/tree/main/lemma-skills/lemma-widget -g -y

不安装直接使用

npx skills use lemma-work/lemma-platform@lemma-widget

指定 Agent (Claude Code)

npx skills add lemma-work/lemma-platform --skill lemma-widget -a claude-code -g -y

安装 repo 全部 skill

npx skills add lemma-work/lemma-platform --all -g -y

预览 repo 内 skill

npx skills add lemma-work/lemma-platform --list

SKILL.md

Frontmatter
{
    "name": "lemma-widget",
    "description": "Create lightweight inline Lemma widgets for conversations via display_resource(type=\"WIDGET\"): self-contained HTML\/CSS\/JS or SVG for metrics, lists, comparisons, timelines, record details, previews, and charts, optionally powered by live pod data through the browser Lemma SDK. Use an app, not a widget, when the UI needs React, routing, or substantial application state."
}

Lemma Widget

A widget is the default way to show an answer that is more than short prose. Use display_resource(type="WIDGET") whenever the useful result has structure or visual hierarchy: several values, records, statuses, steps, comparisons, a timeline, a compact table, a preview, or a chart.

Use plain text only for a single fact, a short explanation, or narration around the widget. If an existing FILE, TABLE, APP, or other pod resource already represents the answer, display that resource directly instead of recreating it as a widget.

Widget or app?

  • Widget: one compact inline view; plain HTML/CSS/JS or SVG; quick to render in the conversation; little local state.
  • Vite app: React, routing, multiple screens, reusable components, substantial interaction/state, or a UI people will return to as a product.

Do not load React, ReactDOM, Tailwind, or the agent web-component bundle inside a widget. Lemma already has full Vite app support for that class of UI. A widget may be saved as an HTML app later, but it should remain lightweight.

Widgets are display surfaces. They do not submit values into the conversation. Use ask_user for fixed choices or ask for free-form input in prose.

Build one

  1. If the widget uses pod data, inspect the real table and column names first:

    lemma tables list
    lemma tables get <table>          # exact columns; `pods describe` folds them
    lemma query run "select * from <table> limit 5"
    
  2. Load the closest maintained starter with load_skill, using name="lemma-widget" and one of these resource_path values:

    Answer shape Starter
    Metrics grouped by one field assets/widget-starter-v1.html
    Compact record list assets/widget-list-v1.html
    Bar chart grouped by one field assets/widget-chart-v1.html
    One record with selected fields assets/widget-detail-v1.html
  3. Replace every uppercase __PLACEHOLDER__ with inspected names and useful labels. For __FIELD_CONFIG__, insert a JSON array such as [{"label":"Owner","field":"owner"}].

  4. Adapt the content and styling, then call display_resource with type="WIDGET". Do not rebuild the SDK loader or loading/empty/error scaffolding from scratch.

The backend rejects unresolved placeholders and broken SDK loaders before display.

The display_resource call

type="WIDGET" takes exactly one of:

  • content — your inline HTML/SVG fragment (the usual case), or
  • public_url — a URL to embed instead.

Passing both, or neither, is rejected. Two more WIDGET-only fields:

  • loading_messages — up to 4 short lines shown while the widget renders. They are WIDGET-only; setting them on any other resource type is rejected.
  • name / path / filters / query belong to other types and don't apply.

Fixed contract

  • Send an HTML/SVG fragment, never <!doctype>, <html>, <head>, or <body>.
  • Keep all CSS local. The widget runs in its own iframe and inherits no frontend CSS.
  • Use plain browser JavaScript. No build step, JSX, React, or framework runtime.
  • Never put secrets, credentials, a pod id, or an environment hostname in the HTML.
  • Show deliberate loading, empty, error, and narrow-screen states.
  • Escape values before inserting them with innerHTML; prefer textContent.
  • Keep the view compact: no fixed positioning or nested scrolling.
  • Height is capped. The inline view clips at 480px with a fade and an Expand control, and a self-reported height above 2400px is ignored. Design for the fold: put the answer at the top, not below a long table.
  • Widgets are display-only — they cannot send anything back into the conversation. The host accepts one message from the frame, a height report. Use ask_user when you need an answer.

The starters are platform-themed and system-aware by default. Preserve their prefers-color-scheme: dark rules and semantic fallbacks. They consume the public token layer — --lemma-widget-bg, surface, subtle, text, muted, border, accent, danger, danger-soft, radius, font, and color-scheme (each with the full --lemma-widget- prefix). Chart starters also expose chart-1 through chart-5.

That list is exhaustive — the host injects only these. The frontend posts a larger palette (success, warning, info, accent-hover, …), but anything outside the published set is filtered out before it reaches your iframe, so a reference to --lemma-widget-success silently falls back. Use only the tokens above, and never reference frontend-only variables such as --text-primary.

For a data-backed widget, preserve the starter's browser SDK loader:

  • Build the SDK URL from window.__LEMMA_CONFIG__.apiUrl.
  • Load /public/sdk/lemma-client.js dynamically and start in sdk.onload.
  • Construct new window.LemmaClient.LemmaClient() with no arguments.
  • Call client.initialize() and handle a non-authenticated state.
  • SDK calls run as the signed-in user under normal RLS and grants.
  • unauthenticated does not mean "signed out." The widget is a cross-site iframe and the browser SDK authenticates by cookie, which some browsers and local HTTP setups withhold. So write that branch as "this view can't load your data here", not "sign in to Lemma" — the user usually is signed in. Keep the widget useful without data where you can.
  • Shared files use /…; personal files use /me; never use /pod/....

Common calls:

await client.records.list("tickets", { limit: 50 });
await client.records.get("tickets", "record-id");
await client.datastore.query(
  "select status, count(*) as total from tickets group by status"
);
await client.files.search("quarterly planning", { limit: 10 });
await client.files.children.markdown("/knowledge/report.pdf");
await client.files.children.content(
  "/knowledge/report.pdf/pages/page_0001.jpg"
);

Prefer datastore.query for aggregates. Never poll with setInterval — if a widget must stay live, open the change stream:

const handle = client.datastore.watchChanges({
  table: "tickets",              // options object is required
  onChange: (f) => { /* f.operation, f.record_id, f.payload */ },
});
// later: handle.close();

It is a WebSocket with its own auth, so it is subject to the same cross-site constraint as initialize() above — always keep the non-live render working.

Visual standard

  • Lead with the answer, not a title-heavy dashboard shell.
  • Follow Lemma's neutral surfaces, near-black/near-white text, indigo action color, restrained borders, and compact radii unless the content needs a distinct visual language.
  • For a very small widget, the token-light set is just surface, text, muted, border, and accent.
  • Format numbers and dates for humans.
  • Use a list for repeated records, cards for a handful of metrics, a detail layout for one record, and a chart only when shape or comparison matters.
  • For Chart.js, give the canvas wrapper an explicit height and read chart/text/grid colors from the starter's semantic variables.
  • Keep explanation outside the widget in the assistant response.

Before display

  • The chosen view is genuinely more useful than short prose.
  • The closest versioned starter was used and all placeholders were replaced.
  • The fragment contains no full-document tags, secrets, hardcoded hosts, or pod ids.
  • SDK code uses injected config and boots from the script load handler.
  • Loading, empty, error, and mobile states are present.

For React or a full product UI, load lemma-builder and follow references/apps.md. For interaction-tool behavior, see lemma-builder/references/agent-tools.md.

版本历史

  • 20197d6 当前 2026-08-04 20:37

    修正了构建步骤中的命令错误,将 'lemma pods describe' 替换为正确的 'lemma tables get <table>' 以获取确切列名。

  • 0b61713 2026-07-19 09:57

同 Skill 集合

lemma-backend/lemma-connectors/skills/integration-creator/SKILL.md
lemma-skills/browser/SKILL.md
lemma-skills/lemma-artifact-author/SKILL.md
lemma-skills/lemma-builder/SKILL.md
lemma-skills/lemma-research/SKILL.md
lemma-skills/lemma-skill-creator/SKILL.md
lemma-skills/lemma-user/SKILL.md
lemma-skills/liteparse-documents/SKILL.md
lemma-skills/lemma-app-design/SKILL.md
lemma-skills/lemma-app-qa/SKILL.md
lemma-skills/lemma-data-analysis/SKILL.md
lemma-skills/lemma-evals/SKILL.md

元信息

文件数
0
版本
bfdfb4b
Hash
4de24344
收录时间
2026-07-19 09:57

首页 - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-06 18:54
浙ICP备14020137号-1 $访客地图$