Template workflow
Experimental
This feature is experimental and may change in future releases.
Fill structured Tiptap templates with AI-generated content and insert the result into the editor.
See the source code on GitHub.
How templates work
Tiptap templates are Tiptap JSON structures with special attributes that mark dynamic parts:
_templateSlot(string key): The entire node is replaced with AI-generated HTML content._templateIf(string key): The node is conditionally included based on a boolean value._templateAttributes(array of{key, attribute}objects): Specific node attributes are set from AI-generated values.
Here is an example template in Tiptap JSON format:
{
"type": "doc",
"content": [
{
"type": "heading",
"attrs": { "level": 1 },
"content": [{ "type": "text", "text": "Non-Disclosure Agreement" }]
},
{
"type": "paragraph",
"attrs": { "_templateSlot": "parties" },
"content": [{ "type": "text", "text": "Party details will be generated here." }]
},
{
"type": "paragraph",
"attrs": { "_templateIf": "includeArbitration" },
"content": [{ "type": "text", "text": "Arbitration clause content..." }]
},
{
"type": "heading",
"attrs": {
"level": 1,
"_templateAttributes": [{ "key": "sectionLevel", "attribute": "level" }]
},
"content": [{ "type": "text", "text": "Governing Law" }]
}
]
}The AI generates a JSON object with values for each key:
{
"parties": "<p>This agreement is between <strong>Acme Corp</strong> and <strong>Beta LLC</strong>.</p>",
"includeArbitration": true,
"sectionLevel": 2
}Tech stack
- React + Next.js
- AI SDK by Vercel + OpenAI models
- Tiptap AI Toolkit
Project overview
This demo uses the AI Toolkit's template workflow to fill a legal document template (Non-Disclosure Agreement) with AI-generated content. The template has predefined sections with slots, conditional clauses, and dynamic attributes. The AI fills in the dynamic parts while the fixed legal boilerplate is preserved.
Installation
Create a Next.js project:
npx create-next-app@latest template-workflowInstall the core Tiptap packages and the Vercel AI SDK for OpenAI:
npm install @tiptap/react @tiptap/starter-kit ai @ai-sdk/openai zodInstall the Tiptap AI Toolkit:
Pro package
The AI Toolkit is a pro package. Before installation, set up access to the private NPM registry by following the private registry guide.
npm install @tiptap-pro/ai-toolkit @tiptap-pro/ai-toolkit-tool-definitionsServer setup
Create an API endpoint that uses the Vercel AI SDK to call the OpenAI model.
Inside the API endpoint, convert the HTML template to a workflow configuration using createTemplateWorkflow. The function auto-extracts all template keys from the HTML, generates the system prompt, and creates the output schema.
// app/api/template-workflow/route.ts
import { openai } from '@ai-sdk/openai'
import { createTemplateWorkflow } from '@tiptap-pro/ai-toolkit-tool-definitions'
import { Output, streamText } from 'ai'
export async function POST(req: Request) {
const { htmlTemplate, task } = await req.json()
// Create the workflow from the HTML template.
// It auto-extracts template keys and generates the prompt and schema.
const workflow = createTemplateWorkflow({ htmlTemplate })
const result = streamText({
model: openai('gpt-5-mini'),
system: workflow.systemPrompt,
prompt: JSON.stringify({ task, context: "Additional background information related to the task" }),
output: Output.object({ schema: workflow.zodOutputSchema }),
})
return result.toTextStreamResponse()
}Client setup
On the client side, define the template as Tiptap JSON. Use the Vercel AI SDK's useObject hook to stream partial values from the server. Pass a permissive Zod schema (z.object({}).passthrough()) to accept any properties the server returns.
As partial values arrive, call templateWorkflow with hasFinished and workflowId to progressively fill the template. The workflowId enables streaming mode where the method tracks the insertion range across calls and replaces content progressively. Before calling the API, convert the template to HTML using the createHtmlTemplate method so the server can parse the template keys.
// app/template-workflow/page.tsx
'use client'
import { experimental_useObject as useObject } from '@ai-sdk/react'
import { EditorContent, useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import { AiToolkit, getAiToolkit } from '@tiptap-pro/ai-toolkit'
import { useEffect, useState } from 'react'
import { v4 as uuid } from 'uuid'
import { z } from 'zod'
// Define the template as Tiptap JSON
const template = {
type: 'doc',
content: [
{
type: 'heading',
attrs: { level: 1 },
content: [{ type: 'text', text: 'Non-Disclosure Agreement' }],
},
{
type: 'paragraph',
attrs: { _templateSlot: 'parties' },
content: [{ type: 'text', text: 'Party details...' }],
},
// ... more template content
],
}
// A permissive schema that accepts any properties from the server
const templateSchema = z.object({}).passthrough()
export default function Page() {
const editor = useEditor({
immediatelyRender: false,
extensions: [StarterKit, AiToolkit],
content: '<p>Click "Generate" to fill the template.</p>',
})
const [workflowId, setWorkflowId] = useState('')
const { submit, isLoading, object } = useObject({
api: '/api/template-workflow',
schema: templateSchema,
})
// Stream partial results as they arrive
useEffect(() => {
if (!editor || !object) return
const toolkit = getAiToolkit(editor)
toolkit.templateWorkflow({
template,
values: object as Record<string, unknown>,
position: 'document',
hasFinished: !isLoading,
workflowId,
})
}, [object, workflowId, editor, isLoading])
const generate = () => {
if (!editor) return
const toolkit = getAiToolkit(editor)
const htmlTemplate = toolkit.createHtmlTemplate(template)
setWorkflowId(uuid())
submit({
htmlTemplate,
task: 'Generate an NDA between Acme Corp and Beta LLC',
})
}
if (!editor) return null
return (
<div>
<EditorContent editor={editor} />
<button onClick={generate} disabled={isLoading}>
{isLoading ? 'Generating...' : 'Generate'}
</button>
</div>
)
}End result
With additional CSS styles, the result is a polished template workflow application:
See the source code on GitHub.
Related guides
- API reference of the
templateWorkflowmethod - API reference of the
createHtmlTemplatemethod - API reference of the
createTemplateWorkflowutility