I Built a Vim Mode for Froala to Show What the Plugin API Can Do
Table of contents
- Key Takeaways
- What modal editing brings to a WYSIWYG
- Why extensibility matters when you compare editors
- How the plugin works under the hood
- Motions ride on the browser's selection API
- Edits respect Froala's undo stack
- One runtime API for everything
- See it in action
- The key map at a glance
- What the plugin focuses on
- Try the same approach yourself
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 code —
enable(),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.
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.
- Whats on this page hide
No comment yet, add your voice below!