AI-powered rich text editor custom component for Retool
John Miniadis
AI-powered editing | Block-level transforms | Open source |
|---|
tl;dr here's the repository
This Retool custom component brings block-level AI actions into a rich text editor built on editor.js. Operators can rewrite a paragraph, summarize a section, or draft a reply from ticket context all from inside a single Retool app, without switching tools or copying text to an external AI interface.
We built it for a client's internal support tool and walked through it live at Retool's Build Together session. The component is open source and documented.
If you're looking for the base Editor.js component without AI, that's in our component library.
Why Retool's stock text area isn't enough for block-level AI
Retool's text area outputs a string. That works for simple inputs, but it creates two problems once AI enters the picture.
The first is granularity. When an operator wants to rewrite one paragraph of a draft reply, the text area has no concept of that block. You'd need to write your own selection and parsing logic, all of it outside Retool's low-code surface.
The second is structured output. Once the operator is done, the data needs to flow into queries, tables, and workflow nodes without a parsing step. A markdown or HTML blob is the wrong shape for that.
We needed a rich text editor that outputs structured JSON per block, and lets AI act on individual blocks without touching the rest. The base Editor.js component already solved the structured output problem. This component adds the AI layer on top.
What this Retool custom component does
The AI Editor is a Retool custom component built on editor.js. Every block, wether paragraph, heading, list is its own JSON object. Two AI actions live in each block's settings panel: Rewrite and Summarize. A slash-menu action handles Draft reply, inserting a new block grounded in whatever app state you pass to the query.
All three AI actions route through a Retool JavaScript query, not through the component itself. The component fires an event; the query reads the context, calls the LLM, and writes the response back. That means the prompt, the model, and the context stay fully configurable in Retool with no component code to touch, and you can wire it to any LLM endpoint: Retool AI, OpenAI, Anthropic, or your own.
[VIDEO EMBED Build Together session]
Features
Block-level AI transforms: Rewrite and Summarize actions on every block via the three-dot settings panel. Each fires a Retool event with the block's content and type; the LLM response replaces that block in place via
editor.blocks.update(id, data).Slash-menu Draft reply: Typing
/opens the slash menu with a Draft reply entry. Inserts a placeholder block and firesaiTransformRequestwithtransformScope: 'insert'. Grounds the draft from app state in your query, not block content.LLM-agnostic: Wire to any endpoint via a Retool JavaScript query. Retool AI, OpenAI, Anthropic, or custom so no component changes needed.
Structured JSON output:
editorDataexposes the full editor.js block structure in real time. Bind directly to queries, tables, or workflow nodes with{{ AIEditor1.editorData.blocks }}.Retool-native event model: Two events:
aiTransformRequest(fires when an operator triggers any AI action) andeditorChange(fires on content change, debounced 400ms).Isolated Retool surface: All Retool-specific wiring lives in one file (
index.tsx). Swap a few hooks and you have a standalone React component.TypeScript throughout: Hooks, refs, CSS modules. Full React surface, no sandboxing.
How the Retool custom component event model works
Retool custom component events carry no payload. The pattern is: the component sets state properties first, then fires the event. Your query reads the state.
When the query has a result, it writes back:
The salt is String.fromCharCode(8203) a zero-width space that forces Retool to detect a value change even when the AI returns identical text twice in a row.
Component properties
Output: component writes, your app reads
Property
| Type
| Description
|
| object
| Full editor.js JSON, updated on every change (debounced 400ms)
|
| string
| Text of the block being transformed (empty for
|
| string
|
|
| string
| editor.js id of the block being transformed or replaced
|
| string
|
|
Input: your app writes, component reads
Property
| Type
| Description
|
| string
| LLM response. Bind to your query result.
|
| boolean
| Toggle read-only mode.
|
Installation & usage
Clone the repository
Install dependencies
Log in to Retool
You'll need an API access token with read and write scopes for Custom Component Libraries.
Start development mode
This syncs local changes to Retool on every save. Open any Retool app and drag the AIEditor component onto the canvas.
Deploy
Once deployed, pin your app to the published version in Custom Component settings. Anyone in the org can use the component from the component panel.
Wiring up the AI query
Create a JavaScript query that calls your LLM endpoint. Switch on {{ AIEditor1.transformScope }} to handle block transforms vs. draft inserts, then on {{ AIEditor1.transformType }} for the action. For block-scope transforms, use {{ AIEditor1.transformBlockContent }} as user content. Reference any other app state directly in the prompt, the query runs in the full Retool app scope.
Add an event handler on the AIEditor1 component:
Event:
aiTransformRequestAction: Trigger your transform query
Then: Set
AIEditor1.transformResponseto{{ yourTransformQuery.data }}
The component routes the response to the correct block internally; your query doesn't need to track transformBlockId.
Limitations
Gets heavy past ~50 blocks. Right for replies, drafts, and short-form content, not for long documents.
No collaborative editing. editor.js doesn't support it natively.
No streaming on AI responses. The editor waits for the full response, showing a "Drafting reply..." state while the query runs.
Get involved
The component is open source and documented. If you're building AI-assisted workflows in Retool such as support tools, sales ops, content review, the repo is a good starting point.
We're always open to pull requests, feature ideas, or new use cases. If you're thinking about what else is possible in Retool, take a look at our component library or get in touch.
GitHub: StackdropCO/retool-ai-editor