Easy to write. Light to develop.
A web editor with a slash menu, Markdown, AI suggestions, comments and live collaboration. The core is 30 kB and brings no other packages with it. Try every part of it right here.
npm install @yonailab/levit
Mina
Joon
Type “/” for blocks, select text for formatting, or start a line with “# ” or “- [ ] ”.
Select a sentence and improve it, or put the caret at the end and continue. Answers are canned; no AI service is called.
Two people, one document. Type on either side and watch the other cursor follow.
Select some text and press 💬, or the button below. Click a comment to find its text.
One document, three formats.
Type below. Levit keeps a JSON document and writes it out as Markdown and HTML.
Levit
HTML
JSON
What comes in the box
The core brings nothing along.
0 runtime dependencies: no other packages to trust · core 30 kB gzip · AI 7.5 kB · Yjs binding 5 kB, used with yjs you install
$ npm install @yonailab/levit
added 1 package in 1s
$ npm ls --all
my-app@1.0.0
└── @yonailab/levit@0.7.2Long documents stay quick.
20,000 blocks · about 5 ms of script per key, near a plain contenteditable
This editor holds 20,000 blocks. Type anywhere in it.
Menus speak three languages.
English, Korean and Japanese built in · screen-reader labels · Alt+F10 to the toolbar
Pasted HTML is cleaned up.
Scripts, event handlers and javascript: links are dropped · validateDocument() for the server
Pasted
Kept
Old browsers are welcome.
Chrome 87, Edge 88, Firefox 78, Safari 14 and later · tested in Chrome, Firefox and WebKit
- Chrome87+
- Edge88+
- Firefox78+
- Safari14+
Tested on every change
-
From install to editor
npm install @yonailab/levitFirst, install one package.
-
import { createLevitEditor } from '@yonailab/levit'; import '@yonailab/levit/levit.css'; const editor = createLevitEditor( document.querySelector('#editor'), );Then mount it on any element.
-
const editor = createLevitEditor(el, { onChange: (editor) => save(editor.getJSON()), });Save the document as JSON.
-
createLevitEditor(el, { plugins: [ commentsPlugin(), aiPlugin({ provider }), ], }); bindYjs(editor, ydoc.getArray('blocks'));Add AI, comments or Yjs later.
Packages and support
Packages
- @yonailab/levitThe editor
- @yonailab/levit-reactReact 18 and 19
- @yonailab/levit-vueVue 3
- @yonailab/levit-yjsYjs 13.6 and later
Read more
- Guide for writersGuide
- Developer docsDocs
- llms.txt for AI toolsllms.txt
- Source and issuesazusawa/levit
Questions
Is Levit free to use?
Yes. It is open source under the MIT licence, for personal and commercial projects.
Which frameworks does it work with?
Any. Use the <levit-editor> element or createLevitEditor() in plain JavaScript, Svelte or Angular; React and Vue have their own packages.
What should I store: HTML or JSON?
Store the JSON document. It is versioned and can be validated; HTML and Markdown are for display and export, and can be read back in.
Is it safe to show what users write?
Levit drops scripts, event handlers and unsafe links when it reads or pastes HTML. Still validate documents on the server with validateDocument() and use a Content Security Policy.
Does the AI feature call a service?
No. You pass a provider function that returns the model’s answer as a stream of Markdown, so you choose the model and keep the key on your server.
Do I need a server to write together?
Levit binds to Yjs, which syncs over any Yjs provider: y-websocket, y-webrtc, or your own. The demo on this page syncs two editors in the browser.
Does it handle Korean and Japanese input?
Yes. IME composition is handled throughout, including while changes from other people arrive.
Is it ready for production?
Levit is at 0.6. The API can still change between minor versions; each change is listed in the release notes, and security fixes go to the two latest minor versions.