This example demonstrates the use of Shadcn-ui for ui, but alternative libraries and components can also be employed.


You can find more info about installing shadcn-ui here. You will need to add the following components: Button, Separator, Popover, Command, Dialog

This example will use the same stucture from here: Anatomy
You can find the full example here: Tailwind Example

Configure Wrapper

"use client";

import { EditorContent, EditorRoot } from "novel";
import { useState } from "react";

const TailwindEditor = () => {
  const [content, setContent] = useState(null);
  return (
        onUpdate={({ editor }) => {
          const json = editor.getJSON();
export default TailwindEditor;

onUpdate runs on every change. In most cases, you will want to debounce the updates to prevent too many state changes.

import { EditorInstance } from "novel"

const debouncedUpdates = useDebouncedCallback(async (editor: EditorInstance) => {
  const json = editor.getJSON();
}, 500);


Configure Extensions


You can find here example of extensions

import { defaultExtensions } from "./extensions";

const extensions = [...defaultExtensions];


Create Menus

Add Editor Props

handleCommandNavigation is required for fixing the arrow navigation in the / command;

import { handleCommandNavigation } from "novel/extensions";
import { defaultEditorProps, EditorContent } from "novel";

      handleDOMEvents: {
        keydown: (_view, event) => handleCommandNavigation(event),
      attributes: {
        class: `prose prose-lg dark:prose-invert prose-headings:font-title font-default focus:outline-none max-w-full`,

Add Styles

You need require("@tailwindcss/typography") for the prose styling

Usage within Dialogs

Novel has been designed to work automatically within Radix Dialogs, namely by looking for the closest parent attribute [role="dialog"]. If you’re using a different implementation for popups and dialogs, ensure you add this attribute above the editor so the drag handle calculates the correct position.