Publish a mod
Mods live in your own repository. The hub is a catalog: it points at your registry, validates it nightly, and lists it here.
1. Write the mod
A mod is one file, src/mods/<name>.tsx, whose default export is tldraw offline's own config-script function. Optional named exports tool and commands put it in the toolbar and context menu.
import type { ModConfig, ModTool } from '@/mod'
import { MyShapeTool, MyShapeUtil, myIcon } from './my-shape-impl'
export const tool: ModTool = { id: 'my-shape', label: 'My shape', icon: myIcon }
export default (({ config }) => {
config.shapeUtils.push(MyShapeUtil)
config.tools.push(MyShapeTool)
}) satisfies ModConfig
Develop it inside a workspace made by npx tldraw-mods init; npm run apply loads it into the open document.
2. Add registry.json to your repo root
{
"$schema": "https://ui.shadcn.com/schema/registry.json",
"name": "my-mods",
"homepage": "https://github.com/you/my-mods",
"items": [{
"name": "my-shape",
"type": "registry:component",
"title": "My shape",
"description": "One sentence.",
"dependencies": ["lucide-react"],
"registryDependencies": ["btn0s/tldraw-mods/tool-chrome"],
"files": [{ "path": "src/mods/my-shape.tsx", "type": "registry:component", "target": "~/src/mods/my-shape.tsx" }]
}]
}
- Targets are explicit
~/src/mods/…paths so relative imports keep working. - Never list
tldraw,react, orreact-domas dependencies; the app provides them. - Run
npx shadcn@latest registry validatebefore pushing.
At this point anyone can install it: npx tldraw-mods add you/my-mods/my-shape.
3. List it here
Open a pull request on btn0s/tldraw-mods adding a pointer item to registry.json:
{ "name": "my-shape", "type": "registry:component", "title": "My shape", "description": "One sentence.",
"categories": ["shape"], "registryDependencies": ["you/my-mods/my-shape"], "files": [] }
CI validates your registry on every PR and nightly; a broken upstream is flagged, not silently dropped.