building-react-quill-canvases
Author the React + Quill implementation of a PostHog canvas: the single-component contract, the allowed imports, Quill (PostHog's design system) component and…
Skill by PostHogOfficial
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/posthog-building-react-quill-canvases-028223
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: documents, design, frontend, data
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions: not checked yet.
What's inside
- Skill name
building-react-quill-canvases- Description
- Author the React + Quill implementation of a PostHog canvas: the single-component contract, the allowed imports, Quill (PostHog's design system) component and composition rules, theme-aware design tokens, loading skeletons, and the in-canvas date picker. Use after building-canvases has routed a canvas request to a React implementation — dashboards, data boards, forms, tools, or any canvas that should look native to PostHog.
- License
- MIT
- Instructions
- 173 lines in SKILL.md · view on GitHub
Files (4)
- SKILL.md
- checklist-example.md · references/
- platform-libraries.md · references/
- starter-scaffold.md · references/
SKILL.md (first lines)
# Building React + Quill canvases
The whole application is one React/TSX file (`src/canvas.tsx` in the source project). It must
`export default` a single React component that takes no props — the host mounts it. Do not import
react-dom or call createRoot.
Start from the working scaffold in [references/starter-scaffold.md](references/starter-scaffold.md)
on a first build: it already wires the date picker, theme tokens, per-query loading state (every
card fills in independently as its own data lands), and correct typed-node result reading. Keep
that wiring; replace the sample metrics and layout.
Keep its pattern of one component per card with `editable()` params, and follow the "Params" section of the `building-canvases` skill for each card you add.
## Imports
Use React, Quill, Recharts, Lucide, and Day.js for the standard application shell. The platform
also admits ten optional libraries for specialized work. Read
[references/platform-libraries.md](references/platform-libraries.md) before choosing one.
PostHog data comes through `import { ph } from "@posthog/canvas-sdk"` — a platform-provided
module, so it needs no `dependencies` entry. The same object exists as the `window.ph` global
(how existing canvases reach it); prefer the import in new code.
Other bare imports, dynamic `import()`, `require()`, `<script>` tags, and remote code fail
validation. Direct network requests and external images, fonts, media, or frames require an exact
HTTPS origin in `capabilities.network.origins`. They work only in the **published** canvas — the
edit-mode preview blocks direct network access regardless of declaration. Stylesheets from declared
origins are allowed; remote scripts remain blocked, so bundle code with the canvas.
## Quill component rules
A PostHog data board must be built entirely from `@posthog/quill` components — never a native
control or a styled `<div>` standing in for one:
- Dropdown/picker → `Select` (never a native `<select>`); button → `Button` (never `<button>`);
text field → `Input`/`Textarea`; checkbox → `Checkbox`; label → `Label`.
- Table → `Table` (`TableHeader` > `TableRow` > `TableHead`, then `TableBody` > `TableRow` > `TableCell`);
panel → `Card` (`CardHeader` + `CardTitle` + `CardContent`); pill → `Badge`; titles → `Heading`; body → `Text`.
- A `Table` inside a `Card` needs `<Card size="sm" flush>` around `<Table size="sm" fullWidth>`.
Without `flush` the card's padding insets the table, so its header and rows stop meeting the card's edges.
`flush` drops the card's section gap, bottom padding, and the `CardContent` inline padding, while the header keeps its own padding and divider.
Matching `size="sm"` on both lines the table's edge columns up with the card's title.
- The only non-Quill tags allowed are plain layout `<div>`s and `recharts` elements.
- Quill is built on Base UI: compose compound parts (`Select` + `SelectTrigger`/`SelectContent`/`SelectItem`),
use controlled `value` + `onValueChange`, and swap a part's element with the `render` prop
(e.g. `<PopoverTrigger render={<Button …/>} />`) instead of wrapping it.
- Quill components are already themed — never restyle one with Tailwind classes or inline `style`;
use their `variant`/`size` props. Put layout utilities (`flex`, `grid`, `gap-4`, `p-4`) on your own
wrapper `<div>`s.
- Buttons: default to `variant="outline"`; `variant="primary"` for the one main action only.
## Styling and theme
- Give the canvas's outermost element `min-h-screen` (`min-height: 100vh`) so it fills the iframe viewport and grows past it as content demands.
Do not use `h-screen` there: a fixed viewport height caps a flex column, so tall children shrink and clip instead of scrolling.
Do not use `h-full` there either: a published canvas's artifact shell gives its `html`, `body`, and `#root` elements no explicit height, so a percentage root height collapses to content height.
- The root needs no `overflow-y-auto`: once it grows past the viewport the iframe's own document scrolls.
- A `min-height` root is not a definite height, so `h-full` on a direct child still collapses to content height.
Give an intermediate wrapper an explicit height (`h-[280px]`) when a child must fill a box.
- Style with Tailwind utilities and Quill components; reserve inline `style` for genuinely dynamic
runtime values (fixed sizes use arbitrary-value utilities like `h-[280px]`).
- Write specific interface copy. Never use lorem ipsum or placeholder labels in a finished canvas.
- The canvas follows the user's PostHog theme; a `.dark` class on the document root flips at runtime.
Color only from the design-token utilities — surfaces `bg-background bg-card bg-muted bg-primary
bg-success bg-warning bg-info bg-destructive`; text `text-foreground text-muted-foreground
text-card-foreground`; borders `border-border`. Never a hardcoded hex or light-only color.
- Status tokens invert the usual convention: the bare token (`bg-success`) is a pale background fill
and `-foreground` (`text-success-foreground`) is the strong readable color. Colored text or icons
always use the `-foreground` utility; a filled pill pairs `bg-success text-success-foreground`.
Prefer the Quill `Badge` (`variant="success"`/`"destructive"`) for deltas so you don't hand-pick.
- `bg-secondary`, `text-secondary`, `bg-accent`, and `bg-popover` are not defined in the canvas — avoid them.
- Never declare a CSS variable with a platform token name (`--background`, `--border`, `--card`,
`--chrome`, `--input`, `--muted`, `--primary`, `--fill-*`), in a stylesheet or a `<style>` block.
Quill sets those on every element, so your value never applies and text can turn unreadable.
Prefix your own variables (`--doc-muted`); validation rejects the collision with
`platform_token_redeclared`.
- recharts strokes/fills use token CSS variables (`stroke="var(--primary)"`, grid/axes in
`var(--border)`/`var(--muted-foreground)`).
- Some recharts defaults are hardcoded for a light theme and go wrong on a dark canvas. The
platform stylesheet corrects them, so do not work around one in canvas code. Pie slice outlines
are one: recharts strokes every sector white, and the stylesheet removes the outline. The
antialiasing seam between stacked bar segments is another, and so is the default tooltip, which
the stylesheet inverts against the page so its text always meets contrast. A bare `<Tooltip />`
is the right thing to write.
- Write Unicode glyphs (curly quotes, ellipsis, arrows, emoji) as literal characters in JSX —
`\uXXXX` escapes render verbatim in JSX text.
## Loading, error, and empty states
Every data point renders a skeleton in its own `Card` while loading or refreshing: `SkeletonText`
(matching `lines` and text-size `className`) for text/number values, `Skeleton` for blocks/charts.
Render progressively — each query owns its loading state. The chrome (heading, date picker,
card frames with skeletons inside) renders immediately, every independent query fires
concurrently on mount, and each card swaps its skeleton for data the moment its own query
resolves, so a slow query only holds back its own card. Never drive the whole canvas off one
shared `loading` flag or a `Promise.all` across independent queries — that makes the fastest
metric wait for the slowest. Set each section's loading state true again on refresh; never show
a blank or a jumping layout. Content the first paint doesn't show (an inactive tab, a collapsed
section, a drill-down) defers its query until the user reveals it.
A failed query and an empty result are different states — never let one render as the other.
`.catch` on every `ph.query`/`ph.loadInsight` must set an error state that renders visibly (the
message plus a Retry button wired to the refresh nonce, as in the starter scaffold), not fall
through to zeros, an empty chart, or a "no data yet" message. A query that silently swallows its
error makes real breakage (a missing table, an auth failure, a bad query) look like missing data.
Reserve the empty state for a query that succeeded with no rows.
## Data-product patterns
Treat these as starting shapes and adapt them to the request and available data.
### Product dashboard
- Build a live board from verified PostHog data, never a static mockup.
- Start with a `Heading`, then a responsive grid of compact `Card` KPIs, trend charts, and useful
breakdown tables.
- Show a `Badge` delta for KPIs when a meaningful comparison period exists.
- Use a `LineChart` for time series and a `BarChart` for discrete categories. Do not turn every
result into a table.From PostHog/skills, MIT.
Signals
- Stars
- 75
- Forks
- 8
- Open issues
- 2
- Last commit (this folder)
- Sep 30, 2026 (28 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/PostHog/skills
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
Same skill elsewhere
Copies of this SKILL.md published by others; search shows only one of them.
- 0.683score
building-react-quill-canvases
PostHogOfficial
Author the React + Quill implementation of a PostHog canvas: the single-component contract, the allowed imports, Quill (PostHog's design system) component and…
SkillAFreshness: A★ 95Claude Code +9 - 0.339score
building-react-quill-canvases
anny-co
Author the React + Quill implementation of a PostHog canvas: the single-component contract, the allowed imports, Quill (PostHog's design system) component and…
SkillAFreshness: AClaude Code +9
More from PostHog
- 0.759score
PostHog MCP Server
PostHogOfficial
Official PostHog MCP Server for product analytics, feature flags, experiments, and more.
ConnectorAFreshness: ARemote★ 40.4KClaude Code +3 - 0.754score
code-reviewer
PostHog
Subagent "code-reviewer" from PostHog/posthog: Use this agent when you need expert code review of recently written or modified code.
TemplateAFreshness: A★ 40.4KClaude Code - 0.683score
authoring-log-alerts
PostHogOfficial
Author useful, low-noise log alerts on services in a PostHog project.
SkillAFreshness: A★ 95Claude Code +9 - 0.683score
auditing-experiments-flags
PostHogOfficial
Audit PostHog experiments and feature flags for configuration issues, staleness, and best-practice violations.
SkillAFreshness: A★ 95Claude Code +9 - 0.683score
analyzing-offline-evaluations
PostHogOfficial
Inspect and compare offline AI evaluation experiments, diagnose case-level regressions, and follow scorer history across application, model, or prompt changes.
SkillAFreshness: A★ 95Claude Code +9 - 0.683score
authoring-error-tracking-alerts
PostHogOfficial
Author error tracking alerts that fire when an issue is created, reopened, or starts spiking.
SkillAFreshness: A★ 95Claude Code +9
Cite this page
building-react-quill-canvases skill. Agent Mart. https://agentmart.dev/skills/posthog-building-react-quill-canvases-028223 (last updated 2026-10-24)