Skip to content
Development
Skill

/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 composition rules, theme-aware design tokens, loading skeletons, and the in-canvas date picker. Use after

From plugin
ai-plugin
95180 skills1 agent3 commands3 hooks
+1

Claude Code

$ npx -y skills add PostHog/ai-plugin --skill building-react-quill-canvases --agent claude-code

SKILL.md

building-react-quill-canvases.SKILL.md
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.

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`,

`-

Read more
@posthog
Ships withai-plugin

Official PostHog plugin for AI clients. Access PostHog products directly from your AI coding tool.

95180 skills1 agent1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
95
Star history of PostHog/ai-plugin on GitHub, a chart by star-history.com

Other skills on ai-plugin.

analyzing-ai-citations

analyzing-ai-citations

Answer AI citation and answer engine optimization (AEO) questions in PostHog: whether AI answer engines (ChatGPT, Claude, and an…

@posthog@posthogInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills10d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react1d252k
@facebook@facebookInstall Skill

Questions about building-react-quill-canvases.

Which coding agents can use building-react-quill-canvases?
building-react-quill-canvases installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.