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

Type “/” for blocks, select text for formatting, or start a line with “# ” or “- [ ] ”.

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.2

Long 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

  • Heading 1
  • Bulleted List
  • To-do List
  • Code Block
  • Image
  • 제목 1
  • 글머리표 목록
  • 체크리스트
  • 코드 블록
  • 이미지
  • 見出し1
  • 箇条書きリスト
  • ToDoリスト
  • コードブロック
  • 画像

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

  1. From install to editor

    npm install @yonailab/levit

    First, install one package.

  2. import { createLevitEditor } from '@yonailab/levit';
    import '@yonailab/levit/levit.css';
    
    const editor = createLevitEditor(
      document.querySelector('#editor'),
    );

    Then mount it on any element.

  3. const editor = createLevitEditor(el, {
      onChange: (editor) =>
        save(editor.getJSON()),
    });

    Save the document as JSON.

  4. createLevitEditor(el, {
      plugins: [
        commentsPlugin(),
        aiPlugin({ provider }),
      ],
    });
    bindYjs(editor, ydoc.getArray('blocks'));

    Add AI, comments or Yjs later.

Packages and support

Packages

Read more

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.