Grist Widgets

Build a Grist custom widget in minutes

Scaffold a React + TypeScript + Tailwind widget from the starter template, with or without an AI coding agent.

What it looks like

The hello-world demo is the whole idea in a handful of lines. The provider and boundary handle the Grist handshake; you only write:

import { useGrist, type UseGristOptions } from "grist-widget-sdk"

export const GRIST_OPTIONS: UseGristOptions = {
  requiredAccess: "read table",
}

export function WidgetApp() {
  const w = useGrist()
  const rowKey =
    w.record && typeof w.record.id === "number" ? String(w.record.id) : w.mode

  if (w.mode === "empty") return <p>Select a row.</p>
  if (w.mode === "new-row") return <p>New row flow</p>
  return <p key={rowKey}>Selected row #{String(w.record!.id)}</p>
}

Try it live in the playground, against a real Grist document.

Start with Vite

npm create grist-widget my-widget
cd my-widget
pnpm install
pnpm dev

See Getting started for manual install, typing, and local testing.

Scaffold a deployable repo

Copy this starter repo

Use grist-widget-template to create your own copy. On the next page, check Include all branches so GitHub Pages comes already configured — no manual Settings step.

Push and go

Your new widget starts deploying on its first push. Ask your AI coding agent for two URLs: the dev build (auto-reloads as you iterate) and the latest build (ready to paste into a production Grist document).

If your AI can't see the new widget repo

Check its GitHub App has been granted access to it: Claude, Codex, or Cursor.

Prefer to run the CLI yourself, outside an AI agent? See the CLI reference.

On this page