Updated September 5, 2026: this article began as a Domternal v0.2.0 build log. Domternal is now framework-agnostic, with first-party Angular, React, Vue 3 and Vanilla JavaScript integrations. The Angular motivation remains the same, while obsolete package counts, bundle figures and roadmap claims have been updated. The v1 package table and Angular guide are the maintained sources for current details.
If you've ever tried to add a rich text editor to an Angular app, you know how it goes.
Many options can put an editor on the page quickly. The harder part begins when the editor has to behave like a real Angular dependency: predictable OnPush updates, standalone components, reactive forms, typed events, theme customization and UI that stays in sync with the editing state.
I kept reaching the same point in Angular projects: the editing engine worked, but the surrounding integration still needed application-specific glue. After years of rebuilding that layer, I decided to build the editor integration I wanted to use.
What I built
Domternal is a framework-agnostic rich text editor toolkit built on ProseMirror. Its core owns the document model, extensions and commands without depending on a component framework. The Angular package adds first-party components built with Signals, OnPush, standalone APIs and reactive forms support.
Domternal now ships as 17 MIT-licensed npm packages under the @domternal scope. First-party Angular, React, Vue 3 and Vanilla JavaScript integrations all use the same core. Angular is a first-class integration, not the only framework Domternal supports.
The Angular experience I wanted
The problem was not that every alternative was bad. Different editors optimize for different constraints. Some begin with a framework-neutral JavaScript engine and add Angular bindings. Others rely on community-maintained wrappers, while commercial suites package features and licensing in different ways.
I needed a particular combination:
- standalone Angular components with Signals and
OnPush -
ControlValueAccessorsupport forngModeland reactive forms - extension-driven toolbars and menus that track editor state automatically
- normal theme customization without application-specific editor overrides
- a typed ProseMirror foundation that also works outside Angular
- a complete Free editor that remains independently available under MIT
That combination became Domternal. The Free edition is a complete MIT-licensed editor, not a time-limited trial. Domternal Pro is a separate commercial, self-hosted layer for collaboration, comments, version history, columns, AI-assisted workflows and document export.
If you are evaluating alternatives today, the maintained Tiptap vs Domternal comparison and CKEditor vs Domternal comparison separate editor capabilities, framework integrations, hosting models and licensing without treating unlike plans as equivalent.
What makes Domternal different
6 Angular components: editor, toolbar, bubble menu, floating menu, emoji picker and Notion color picker. All use Signals, OnPush and standalone components. No NgModules are required.
Tables are free. Cell merge/split, column resize, cell styling and the cell toolbar are included in Domternal Free, with 18 table commands published under MIT.
The toolbar is extension-driven. Extensions that contribute toolbar items are discovered automatically, so their controls appear with active and disabled states without repeated button wiring in the application.
70+ extensions across core and 10 extension packages: headings, lists, code blocks with syntax highlighting, images, emoji, details, text color, font size, math, Markdown, block controls and more. Core, the four integrations, the theme and those extension packages make 17 current MIT packages in total.
JavaScript exports are tree-shakeable. The full Domternal-owned core entry is about 51 KiB minified and gzipped before ProseMirror and helper dependencies, while the current complete core bundle is about 132 KiB with those runtime dependencies. Additional extensions such as tables, images and emoji are separate packages. Actual output depends on your imports, configuration and bundler; the theme is delivered as a complete CSS stylesheet. See the maintained bundle size breakdown.
17,000+ automated test executions across unit coverage and a browser matrix for Angular, React, Vue and Vanilla. The exact current breakdown belongs in the repository and maintained documentation rather than in this historical article.
Light and dark themes with 150+ CSS custom properties. Applications can change color, spacing and typography without forking the editor styles.
TypeScript APIs. Public extensions and commands expose typed APIs and command inference without making this article a permanent claim about every internal implementation detail.
Schema conflict detection: if you accidentally register two extensions with the same name, which can happen when using StarterKit alongside individual extensions, Domternal throws a clear error instead of silently letting the last one win.
Free and Pro today
Everything described above belongs to Domternal Free unless explicitly stated otherwise. All 17 currently published packages under the @domternal scope are MIT licensed.
Domternal Pro is a separate, optional set of commercially licensed packages under the @domternal-pro scope. It adds real-time collaboration, comments, version history, columns, AI-assisted workflows and local Word/PDF export. The Pro packages run with infrastructure selected by the application and do not require a Domternal-hosted editing service.
Quick setup
Here's a minimal Angular example:
pnpm add @domternal/core @domternal/angular @domternal/theme
import { Component, signal } from '@angular/core';
import {
DomternalEditorComponent,
DomternalToolbarComponent,
} from '@domternal/angular';
import { Editor, StarterKit } from '@domternal/core';
@Component({
selector: 'app-editor',
imports: [DomternalEditorComponent, DomternalToolbarComponent],
template: `
@if (editor(); as ed) {
<domternal-toolbar [editor]="ed" />
}
<domternal-editor
[extensions]="extensions"
[content]="content"
(editorCreated)="editor.set($event)"
/>
`
})
export class EditorComponent {
editor = signal<Editor | null>(null);
extensions = [StarterKit];
content = '<p>Hello world</p>';
}
Add the theme import to your styles and you're done:
@use '@domternal/theme';
See the full Angular example with all extensions, toolbar and bubble menu, or read the Getting Started guide.
No framework? No problem.
The core is fully headless and works without any framework:
pnpm add @domternal/core
import {
Editor, Document, Text, Paragraph,
Bold, Italic, Underline,
} from '@domternal/core';
const editor = new Editor({
element: document.getElementById('editor')!,
extensions: [Document, Text, Paragraph, Bold, Italic, Underline],
content: '<p>Hello <strong>Bold</strong>, <em>Italic</em> and <u>Underline</u>!</p>',
});
Import the extensions you need for direct control, or use StarterKit for a batteries-included setup with headings, lists, code blocks, history and more. Your final JavaScript output depends on the imports and bundler configuration you choose.
See the full Vanilla TS example with toolbar, bubble menu and all extensions, or read the Getting Started guide.
Domternal Free today
| Domternal Free | |
|---|---|
| Framework integrations | Angular, React, Vue 3 and Vanilla JavaScript |
| Angular components | 6: editor, toolbar, bubble menu, floating menu, emoji picker and Notion color picker |
| Current MIT packages | 17 |
| Extensions | 70+ across core and 10 extension packages |
| Nodes | 27 |
| Marks | 9 |
| Commands | 130+ chainable commands |
| Tests | 17,000+ automated test executions across maintained suites |
| Domternal-owned core surface | ~51 KiB minified and gzipped before dependencies |
| Full core with current dependencies | ~132 KiB minified and gzipped |
| Tree-shaking | Actual output depends on imports, configuration and bundler behavior |
| TypeScript | Typed public extension and command APIs |
| Table commands | 18 |
| License | MIT |
Try it now
Website: domternal.dev
Angular guide: domternal.dev/v1/guides/angular
Getting started: domternal.dev/v1/getting-started
Packages and bundle size: domternal.dev/v1/packages
GitHub: github.com/domternal/domternal
Live playground: domternal.dev/playground
Since the original v0.2.0 article
React and Vue integrations, math, drag handles, block controls and other features that were once described as future work now exist in the maintained v1 documentation. Future requests can inform product planning, but neither this historical post nor a request is a delivery commitment.
The complete Free editor remains MIT licensed. The optional Domternal Pro packages now add collaboration, comments, version history, columns, AI-assisted workflows and Word/PDF export for teams that need those workflows while retaining control of their application infrastructure.
The current release status, supported packages and installation instructions are published in the v1 documentation. I would still appreciate feedback on the API design, documentation or anything that could be better.
What's been your biggest pain point with rich text editing in Angular? I'd love to hear about it in the comments.
Top comments (0)