Getting Started with BlockNote AI
First, install the @blocknote/xl-ai
package:
npm install @blocknote/xl-ai
Creating a Model
BlockNote AI uses the the AI SDK (opens in a new tab) to standardize integrating artificial intelligence (AI) models across supported providers (opens in a new tab).
As a first step, you'll need to register a new model with the AI SDK. For example, for Llama hosted on Groq:
npm install @ai-sdk/groq
import { createGroq } from "@ai-sdk/groq";
const provider = createGroq({
apiKey: "YOUR_GROQ_API_KEY",
});
const model = provider("llama-3.3-70b-versatile");
Note that this setup directly calls the provider from the client, and exposes your API keys on the client. For Production scenarios, a more common approach is to handle authentication on your own server and proxy requests to a provider. See our Demo AI Server (opens in a new tab) for a Node.js example or check the AI SDK best practices.
Setting up the editor
Now, you can create the editor with the AI Extension enabled:
import { createBlockNoteEditor } from "@blocknote/core";
import { BlockNoteAIExtension } from "@blocknote/xl-ai";
import {
AIToolbarButton,
BlockNoteAIUI,
locales as aiLocales,
createAIExtension,
createBlockNoteAIClient,
getAISlashMenuItems,
} from "@blocknote/xl-ai";
const editor = createBlockNoteEditor({
dictionary: {
...en,
ai: aiLocales.en, // add default translations for the AI extension
},
extensions: [
createAIExtension({
model,
}),
],
// ... other editor options
});
The createAIExtension
method
TODO
Adding AI UI elements
Now, the only thing left to do is to customize the UI elements of your editor.
<BlockNoteView
editor={editor}
// We're disabling some default UI elements
formattingToolbar={false}
slashMenu={false}>
{/* This has AI specific components like the AI Command menu */}
<BlockNoteAIUI />
{/* Create you own Formatting Toolbar with an AI button,
(see the full example code below) */}
<FormattingToolbarWithAI />
{/* Create you own SlashMenu with an AI option,
(see the full example code below) */}
<SuggestionMenuWithAI editor={editor} />
</BlockNoteView>
Full Example
import { createGroq } from "@ai-sdk/groq";
import { BlockNoteEditor, filterSuggestionItems } from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
import { en } from "@blocknote/core/locales";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import {
FormattingToolbar,
FormattingToolbarController,
SuggestionMenuController,
getDefaultReactSlashMenuItems,
getFormattingToolbarItems,
useCreateBlockNote,
} from "@blocknote/react";
import {
AIToolbarButton,
BlockNoteAIUI,
locales as aiLocales,
createAIExtension,
createBlockNoteAIClient,
getAISlashMenuItems,
} from "@blocknote/xl-ai";
import "@blocknote/xl-ai/style.css";
// Optional: proxy requests through the `@blocknote/xl-ai-server` proxy server
// so that we don't have to expose our API keys to the client
const client = createBlockNoteAIClient({
apiKey: getEnv("BLOCKNOTE_AI_SERVER_API_KEY") || "PLACEHOLDER",
baseURL:
getEnv("BLOCKNOTE_AI_SERVER_BASE_URL") || "https://localhost:3000/ai",
});
// Use an "open" model such as llama, in this case via groq.com
const model = createGroq({
// call via our proxy client
...client.getProviderSettings("groq"),
})("llama-3.3-70b-versatile");
/*
ALTERNATIVES:
Call a model directly (without the proxy):
const model = createGroq({
apiKey: "<YOUR_GROQ_API_KEY>",
})("llama-3.3-70b-versatile");
Or, use a different provider like OpenAI:
const model = createOpenAI({
...client.getProviderSettings("openai"),
})("gpt-4", {});
*/
export default function App() {
// Creates a new editor instance.
const editor = useCreateBlockNote({
dictionary: {
...en,
ai: aiLocales.en, // add default translations for the AI extension
},
// Register the AI extension
extensions: [
createAIExtension({
model,
}),
],
// We set some initial content for demo purposes
initialContent: [
{
type: "heading",
props: {
level: 1,
},
content: "I love cats",
},
{
type: "paragraph",
content:
"Cats are one of the most beloved and fascinating animals in the world. Known for their agility, independence, and charm, cats have been companions to humans for thousands of years. Domesticated cats, scientifically named Felis catus, come in various breeds, colors, and personalities, making them a popular choice for pet owners everywhere. Their mysterious behavior, sharp reflexes, and quiet affection have earned them a special place in countless households.",
},
{
type: "paragraph",
content:
"Beyond their role as pets, cats have a rich history and cultural significance. In ancient Egypt, they were revered and even worshipped as symbols of protection and grace. Throughout history, they’ve appeared in folklore, art, and literature, often associated with curiosity, luck, and mystery. Despite superstitions surrounding black cats in some cultures, many societies around the world admire and cherish these sleek and graceful animals.",
},
{
type: "paragraph",
content:
"Cats also offer emotional and physical benefits to their owners. Studies have shown that interacting with cats can reduce stress, lower blood pressure, and improve mental well-being. Their gentle purring, playful antics, and warm companionship provide comfort to people of all ages. Whether lounging in the sun, chasing a toy, or curling up on a lap, cats bring joy, peace, and a bit of magic to the lives of those who welcome them into their homes.",
},
],
});
// Renders the editor instance using a React component.
return (
<div>
<BlockNoteView
editor={editor}
// We're disabling some default UI elements
formattingToolbar={false}
slashMenu={false}
>
{/* This has AI specific components like the AI Command menu */}
<BlockNoteAIUI />
{/* We disabled the default formatting toolbar with `formattingToolbar=false`
and replace it for one with an "AI button" (defined below).
(See "Formatting Toolbar" in docs)
*/}
<FormattingToolbarWithAI />
{/* We disabled the default SlashMenu with `slashMenu=false`
and replace it for one with an AI option (defined below).
(See "Suggestion Menus" in docs)
*/}
<SuggestionMenuWithAI editor={editor} />
</BlockNoteView>
</div>
);
}
// Formatting toolbar with the `AIToolbarButton` added
function FormattingToolbarWithAI() {
return (
<FormattingToolbarController
formattingToolbar={() => (
<FormattingToolbar>
{...getFormattingToolbarItems()}
{/* Add the AI button */}
<AIToolbarButton />
</FormattingToolbar>
)}
/>
);
}
// Slash menu with the AI option added
function SuggestionMenuWithAI(props: {
editor: BlockNoteEditor<any, any, any>;
}) {
return (
<SuggestionMenuController
triggerCharacter="/"
getItems={async (query) =>
filterSuggestionItems(
[
...getDefaultReactSlashMenuItems(props.editor),
// add the default AI slash menu items, or define your own
...getAISlashMenuItems(props.editor),
],
query,
)
}
/>
);
}
// helper function to get env variables across next / vite
// only needed so this example works in BlockNote demos and docs
function getEnv(key: string) {
// TODO
// const env2 = process.env.NEXT_PUBLIC_BLOCKNOTE_AI_SERVER_BASE_URL;
return (import.meta as any).env
? (import.meta as any).env["VITE_" + key]
: process.env["NEXT_PUBLIC_" + key];
}