Quick Start

Build a minimal uSketch plugin in 5 minutes.

This guide walks you through creating a minimal shape plugin — a diamond — and registering it with the app.

1. Create the Package

mkdir -p plugins/usketch-plugin-shape-diamond/src
cd plugins/usketch-plugin-shape-diamond

Create package.json:

{
  "name": "@edv4h/usketch-plugin-shape-diamond",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "main": "dist/plugin.js",
  "types": "dist/plugin.d.ts",
  "scripts": {
    "build": "tsc",
    "clean": "rm -rf dist"
  },
  "dependencies": {
    "@edv4h/usketch-shared": "workspace:*"
  },
  "devDependencies": {
    "@types/react": "^19",
    "typescript": "^5.8"
  },
  "peerDependencies": {
    "react": "^19"
  }
}

Create tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "jsx": "react-jsx",
    "declaration": true,
    "outDir": "dist",
    "strict": true,
    "skipLibCheck": true
  },
  "include": ["src"]
}

2. Implement the Plugin

Create src/plugin.tsx:

import type {
  BoundingBox,
  PluginContext,
  Point,
  ShapeData,
  UsketchPlugin,
} from "@edv4h/usketch-shared";
import { DEFAULT_STYLE } from "@edv4h/usketch-shared";

function render(data: ShapeData) {
  const cx = data.x + data.width / 2;
  const cy = data.y + data.height / 2;
  const points = [
    `${cx},${data.y}`,
    `${data.x + data.width},${cy}`,
    `${cx},${data.y + data.height}`,
    `${data.x},${cy}`,
  ].join(" ");

  return (
    <polygon
      points={points}
      fill={data.style.fill}
      stroke={data.style.stroke}
      strokeWidth={data.style.strokeWidth}
      opacity={data.style.opacity}
    />
  );
}

function getBounds(data: ShapeData): BoundingBox {
  return { x: data.x, y: data.y, width: data.width, height: data.height };
}

function hitTest(data: ShapeData, point: Point): boolean {
  // Simplified AABB check
  return (
    point.x >= data.x &&
    point.x <= data.x + data.width &&
    point.y >= data.y &&
    point.y <= data.y + data.height
  );
}

function createDefault(params: { id: string; x: number; y: number }): ShapeData {
  return {
    id: params.id,
    type: "diamond",
    x: params.x,
    y: params.y,
    width: 80,
    height: 80,
    style: { ...DEFAULT_STYLE },
  };
}

export const diamondPlugin: UsketchPlugin = {
  id: "usketch-plugin-shape-diamond",
  name: "Diamond",

  setup(ctx: PluginContext) {
    ctx.shapes.register("diamond", {
      render,
      getBounds,
      hitTest,
      resize: (data, _handle, _delta) => data, // stub
      createDefault,
    });
  },
};

3. Register the Plugin

In your app entry point, add the plugin to the createApp call:

import { createApp } from "@edv4h/usketch-core";
import { diamondPlugin } from "@edv4h/usketch-plugin-shape-diamond";

const app = await createApp({
  store: myStore,
  plugins: [
    // ...other plugins
    diamondPlugin,
  ],
});

That’s all it takes. The diamond shape type is now available and can be created via the BoardStore.addShape() API.

Next Steps