Custom Components
Custom components are React applications that render inside the NoClick interface tab. They run in sandboxed iframes with access to the full@noclick/sdk API, Tailwind CSS, and any npm package.
Creating a Component
From the Canvas
- Open the Interface tab in the workflow editor
- Drag Custom Component from the UX panel onto the grid
- Click the node on the canvas to open its config
- Write JSX in the code editor
From MCP (Claude Code, Cursor)
How It Works
- You write JSX/TSX in the node’s
jsx_sourceconfig field - When the node executes, the backend transpiles it via Sucrase (runs in QuickJS, ~15ms)
- An import map is generated with React 19 from esm.sh, Tailwind CSS CDN, and any npm packages you import
- The
@noclick/sdkis injected as a base64 data URI in the import map - Everything is assembled into an HTML document (
srcdoc) and rendered in an iframe
Using npm Packages
Just import them — the transpiler auto-detects imports and maps them to esm.sh:&bundle to avoid transitive dependency issues.
Fullscreen Mode
Setfullscreen="true" in the node config to render the component as a full-viewport tab instead of a grid block:
- Draggable — reorder by dragging
- Renamable — click the active tab label to edit
- Persistent — tab order survives page reloads
Styling
Tailwind CSS is included automatically. Use standard Tailwind classes:Using the SDK
Import any SDK namespace directly:Read Node Output
Run a Node and Get Results
Persistent State
Requires a State Manager node in the workflow:OAuth and Credentials
File Upload
Dataset CRUD
Caching
Compiledsrcdoc is cached in IndexedDB (one slot per node). Components render instantly on tab switch and page reload without re-transpilation. The cache auto-invalidates when jsx_source changes. Copied/duplicated nodes share cache via source hash matching.
Troubleshooting
| Issue | Solution |
|---|---|
| Gray iframe on first load | esm.sh cold start (~3-5s). Packages are cached after first load. |
< in stored JSX | Use field="jsx_source" body syntax in MCP XML. Entity escaping is handled automatically. |
{{ }} in JSX stripped | Fixed — unresolvable {{ }} patterns (like JSX inline styles) are preserved as-is. |
| Drag/resize stuck on canvas | Fixed — pointer-events: none on iframes during drag/resize via CSS. |
| SDK method hangs | All requests timeout after 30s with a descriptive error. |