Get Started for FREE

I Built a Vim Mode for Froala to Show What the Plugin API Can Do

froala vim

Most teams choose a rich text editor by scanning the default feature list. The real test comes later, once your product needs something the editor never shipped with. That is when the plugin API starts to matter.

So I ran an experiment. I built modal, Vim-style editing for Froala as a single-file plugin, with one script tag and no build step. To be clear up front, this is not an official Froala feature and it is not on the roadmap. It is a personal project I put together to see how far the plugin model goes, and to give you a concrete sense of what you could build yourself.

If you have spent time in Vim, the appeal is familiar. Your keyboard does different things depending on the mode you are in. You move, delete, and change text while your hands stay on the home row. This plugin brings that same flow into a Froala editor, running as plain Froala plus one extra script.

Disclaimer: this is not an official Froala Plugin, this was made by the internal team to speed up our workflow and to show how Froala APIs work.

Key Takeaways

  • The plugin API matters more than the feature list — editors look alike until your product needs custom behavior the editor never shipped with.
  • A full Vim mode fits in one file, no build step — single script tag, self-registers, adds its own toolbar command.
  • It covers everyday Vim, on purpose — modes, motions with counts, visual operators, doubled commands, line jumps; deeper grammar left out to stay auditable.
  • Built on solid primitives — motions ride on Selection.modify(), and every edit respects Froala’s undo stack.
  • A small runtime API drives it from your codeenable(), disable(), toggle(), getMode(), and disabling restores vanilla Froala.

What modal editing brings to a WYSIWYG

Vim splits editing into modes, and this plugin keeps the three that matter day to day.

 

In normal mode, your keys run commands. You move with h j k l, jump by word with w b e, and delete a line with dd. In insert mode, the keyboard types text the way a WYSIWYG normally does. In visual mode, you select a range and then act on it with one key, such as d to delete or y to yank.

 

A small badge sits in the bottom-left corner of the editor and shows the current mode, so you always know which keys are live. The block cursor and the badge share a configurable color, which makes the active mode easy to read at a glance.

Why extensibility matters when you compare editors

When you put Froala next to other editors, the headline feature lists look similar. The difference shows up the day your product needs custom behavior, and the cost of that difference lands on your team.

 

A modal editing layer is a good stress test for a plugin API. It intercepts keystrokes, tracks state, moves the caret, mutates content, and talks to the undo manager. The fact that I could build all of that in a single, readable file, on my own time, tells you the architecture is open and approachable. That same door stays open for the features you actually need, whether that means custom toolbar buttons, custom commands, or custom keybindings tied to your own product shortcuts.

 

For a bottom-of-funnel decision, this is the signal worth weighing. Froala gives you an editor that works out of the box and a plugin model you can grow into, as this side project shows.

How the plugin works under the hood

The plugin self-registers on FroalaEditor.PLUGINS.vim and adds a vim toolbar command when it loads. You add it to a page by dropping one script after the Froala bundle.

 

<link href="froala_editor.pkgd.min.css" rel="stylesheet">

<script src="froala_editor.pkgd.min.js"></script>

<script src="froala.vim.js"></script>

<script>
  new FroalaEditor('#editor', {
    toolbarButtons: ['bold', 'italic', '|', 'vim'],
    vim: {
      enabled: true,
      navLayout: 'hjkl',   // 'hjkl' or 'ijkl'
      leader: ',',
      startMode: 'normal',
      cursorColor: '#0098F7',
      showLineNumbers: false
    }
  });
</script>

 

 

Three design choices keep it reliable and small.

Motions ride on the browser’s selection API

Caret movement runs through Selection.modify(alter, direction, granularity), the same primitive the browser uses internally. As a result, motions follow soft-wrapped lines correctly, and j lands where a human expects it to. The API is non-standard, yet it is implemented in Chromium, WebKit, and Firefox, which covers every browser Froala supports. When modify throws on an edge case, that one motion becomes a no-op and the rest of the key map keeps working.

Edits respect Froala’s undo stack

Every mutation pushes a pre-state and a post-state onto Froala’s undo manager. Because of that, a single u reverses exactly one operator, and Ctrl-r redoes it. Your editing history stays clean whether the change came from the toolbar or from a Vim command.

One runtime API for everything

The plugin exposes a small API so you can drive it from your own code.

const ed = new FroalaEditor(‘#editor’, { /* … */ });

ed.vim.enable(); // turn vim keybindings on
ed.vim.disable(); // back to vanilla Froala
ed.vim.toggle();
ed.vim.getMode(); // ‘normal’ | ‘insert’ | ‘visual’
ed.vim.setLeader(‘\\’); // change the leader at runtime
ed.vim.setCursorColor(‘#15B69B’);
ed.vim.toggleLineNumbers(); // also bound to leader ‘n’

When you disable it at runtime, the editor returns to standard Froala behavior, with the keystroke interception, the badge, and the block cursor all removed.

See it in action

Video goes here. Drop in your screen recording of the plugin running, with the on-screen keyboard showing each keystroke. An interactive key-cast demo ships alongside this article if you want a self-running visual in the meantime.

The key map at a glance

Keys Mode Action
h j k l normal move left, down, up, right
w b e normal next word, previous word, end of word
0 ^ $ normal line start, first text, line end
gg G normal document start, document end
3j 5l 10w normal counts repeat any motion
i a I A o O normal enter insert at various points
v normal enter visual mode
d c y visual delete, change, yank the selection
dd yy cc normal act on the whole line, counts supported
x D C p normal delete char, delete to end, change to end, paste
<n>G :N normal jump to line n
u Ctrl-r normal undo, redo
,b ,i ,u leader bold, italic, underline
,n ,h leader toggle line numbers, toggle help overlay

What the plugin focuses on

The plugin covers the part of Vim you reach for every day: modes, the common motions with count prefixes, the visual-mode operators, the doubled commands, line jumping, an optional line-number gutter, and a configurable leader.

 

The deeper Vim grammar stays out of scope on purpose. Operator-plus-motion composition like dw, named registers, marks, macros, the . repeat, and / search all sit outside the spec. Keeping that boundary is what lets the whole thing stay one readable file you can audit and extend yourself.

Try the same approach yourself

 

If you want to wire this kind of behavior into your own editor, the pattern is the same one I followed. First, load the Froala bundle on your page. Next, add your plugin script after it so it can register on FroalaEditor.PLUGINS. Finally, expose a toolbar command and a small runtime API, then set your preferences in the Froala init. From there, the toolbar button toggles your feature and the API lets you wire it to anything else in your app.

 

If you are evaluating Froala right now, building a small plugin like this is a good way to see how far the model goes before you commit. Start a free Froala trial and try the editor with your own content, browse the Github Repo to see the full API, or review Froala pricing when you are ready to ship.

 

Explore a Vim-style Froala plugin that shows how the editor’s plugin API supports custom keybindings, toolbar commands, undo handling, and extensibility.

graphical user interface, text

Posted on June 5, 2026

Carl Cruz

Product Marketing Manager for Froala. With four years of experience and a background in development, they specialize in translating complex technical features into clear value for a developer-focused audience.

No comment yet, add your voice below!


Add a Comment

Your email address will not be published. Required fields are marked *