<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aditya Bhalsod</title>
    <description>The latest articles on DEV Community by Aditya Bhalsod (@aditya_bhalsod).</description>
    <link>https://dev.to/aditya_bhalsod</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4199949%2F1d3399a4-495e-43e8-bedb-e8dc1781cb0e.png</url>
      <title>DEV Community: Aditya Bhalsod</title>
      <link>https://dev.to/aditya_bhalsod</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aditya_bhalsod"/>
    <language>en</language>
    <item>
      <title>I built a rich-text editor from scratch. No ProseMirror, no dependencies.</title>
      <dc:creator>Aditya Bhalsod</dc:creator>
      <pubDate>Thu, 22 Oct 2026 08:48:15 +0000</pubDate>
      <link>https://dev.to/aditya_bhalsod/i-built-a-rich-text-editor-from-scratch-no-prosemirror-no-dependencies-52b6</link>
      <guid>https://dev.to/aditya_bhalsod/i-built-a-rich-text-editor-from-scratch-no-prosemirror-no-dependencies-52b6</guid>
      <description>&lt;h1&gt;
  
  
  I built a rich-text editor from scratch. No ProseMirror, no dependencies.
&lt;/h1&gt;

&lt;p&gt;Almost every rich-text editor you can install today is a layer over one of a handful of engines: ProseMirror, Lexical, Slate, Quill, Draft.js. That is a sensible way to build one. I wanted to find out what happens if you don't.&lt;/p&gt;

&lt;p&gt;So I wrote &lt;strong&gt;Trevixal&lt;/strong&gt;: a WYSIWYG editor engine in about 60,000 lines of TypeScript and SCSS, with the document model, the undo system, the HTML sanitizer, the DOM renderer, the ZIP and XML writers behind Word export, and the LaTeX-to-MathML converter all written in this repository. It is Apache-2.0, and no package it ships has a runtime dependency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it before you read any further:&lt;/strong&gt; &lt;a href="https://trevixal-editor.vercel.app/full-editor" rel="noopener noreferrer"&gt;the live editor&lt;/a&gt;. Paste something ugly into it and see what happens. That is the best test I know.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feaeh3dvuubn06lefm2ed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feaeh3dvuubn06lefm2ed.png" alt="The full editor: menubar, toolbar, outline and a document" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  It is a building block, not an app
&lt;/h2&gt;

&lt;p&gt;Trevixal is not a finished product you send people to. It is the text box you put inside your own product (a CMS, a support desk, a notes tool, an internal wiki), so your users get the writing surface they expect from Google Docs or Notion while your app keeps the document, the storage and everything around it.&lt;/p&gt;

&lt;p&gt;That shapes how it is built. The core is headless. The chrome (menus, toolbar, dialogs) is a separate, optional package. There are adapters for React, Vue, Svelte and Angular, a web component, and an assembled "whole editor" you can mount in one call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three decisions that shaped everything
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. The document is data, not HTML.&lt;/strong&gt; Every document is a schema-validated JSON object you can store in a database, validate, transform and render anywhere. The editor on screen is one view of it. A &lt;code&gt;.docx&lt;/code&gt;, an &lt;code&gt;.rtf&lt;/code&gt;, a web page or a PDF are others.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Every edit is a list of small, invertible steps.&lt;/strong&gt; Undo is not a second bookkeeping system bolted on later; it falls out of inverting the steps. The same steps remap positions through a transaction, so selections do not drift when something changes above them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Pasted HTML is hostile until proven otherwise.&lt;/strong&gt; Content from the web is parsed inside an inert template and passed through an allowlist, and the sanitizer is tested against a corpus of real attack payloads.&lt;/p&gt;

&lt;p&gt;None of these is novel on its own. The interesting part was that owning all three at once let me fix whole classes of bugs in one place instead of working around someone else's engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the editor does
&lt;/h2&gt;

&lt;p&gt;Everything below is reachable from the editor's own menus and toolbar, and every screenshot in this post was taken from the real demo, not a mock-up.&lt;/p&gt;

&lt;p&gt;Type &lt;code&gt;/&lt;/code&gt; at the start of a block and the insert menu opens: headings, lists, quotes, code, tables, images, diagrams, equations, callouts, columns and toggles.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqodqo5uhtdsld0tfvuc8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqodqo5uhtdsld0tfvuc8.png" alt="The slash menu opened on an empty line" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tables are real tables: click a cell for its own toolbar, drag a border to resize, merge and split cells in both directions, and use Word-style formulas such as &lt;code&gt;SUM&lt;/code&gt; and &lt;code&gt;AVERAGE&lt;/code&gt; over &lt;code&gt;ABOVE&lt;/code&gt;, &lt;code&gt;BELOW&lt;/code&gt;, &lt;code&gt;LEFT&lt;/code&gt; or &lt;code&gt;RIGHT&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foxsskc2igxxq1flmxgco.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foxsskc2igxxq1flmxgco.png" alt="A table with a nested table inside a cell, a numbered caption and right-aligned costs" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Equations are LaTeX, rendered as MathML. Double-click one to edit it with a symbol palette and a live preview.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3b51a1eyxvg779zpx26p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3b51a1eyxvg779zpx26p.png" alt="Inline and block equations, with an automatic equation number" width="799" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Diagrams are code blocks that draw themselves. Mermaid, Graphviz and PlantUML all work, and the picture lands in your exports too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmcxhqdn7gyglr3fecyqt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmcxhqdn7gyglr3fecyqt.png" alt="A Mermaid flowchart rendered under its source, followed by tabs and accordions" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Review works like Word's suggesting mode. Switch it on, and edits arrive as attributed suggestions that someone can accept or reject, one at a time or all at once.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxsrqyh0jujh044ibn0r9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxsrqyh0jujh044ibn0r9.png" alt="Suggesting mode: a reviewer's edit highlighted, with Accept and Reject controls" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are seven built-in themes (Light, Dark, Sepia, Nord, Solarized, High contrast and Midnight), an option to follow the system setting, and you can define your own.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwy21kzz43u0q22e2p56u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwy21kzz43u0q22e2p56u.png" alt="The same document in the Dark theme" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And it exports. The File menu writes the document as HTML, Markdown, MDX, plain text, JSON, Word, RTF, OpenDocument, EPUB, LaTeX, PowerPoint, a fillable PDF, a PDF through print, or a password-encrypted &lt;code&gt;.tvx&lt;/code&gt; file. The exports are checked by rendering the real files, not by reading the markup, so a downloaded document looks like the editor did.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6cdqvky5nv2j31m7sf7e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6cdqvky5nv2j31m7sf7e.png" alt="The File menu listing every download format" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using it takes three lines
&lt;/h2&gt;

&lt;p&gt;The no-build version is one HTML file. Save this and open it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My Web Page&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/@trevixal/ui/styles.css"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/@trevixal/editor-kit/styles.css"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/@trevixal/editor-kit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;TrevixalKit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mountFullEditor&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a real app you pin a version in those URLs. If you want the engine without any chrome, it is a few lines of TypeScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createEditor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;defaultNodes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;defaultMarks&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@trevixal/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@trevixal/ui/styles.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createEditor&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;defaultNodes&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;marks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;defaultMarks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#editor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Write something…&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggleMark&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bold&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getJSON&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// the document, as data you can store and validate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How it compares to Tiptap
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://tiptap.dev" rel="noopener noreferrer"&gt;Tiptap&lt;/a&gt; is the editor most people compare this one to, and the comparison is fair: both are headless, extension-driven and have adapters for the major frameworks. The real difference is that Tiptap is a layer over ProseMirror and Trevixal is not a layer over anything.&lt;/p&gt;

&lt;p&gt;I measured both on 19 September 2026, using the smallest install on each side that gives an editor with a default schema, bundled the same way:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Trevixal&lt;/th&gt;
&lt;th&gt;Tiptap&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Engine + default schema (gzipped)&lt;/td&gt;
&lt;td&gt;27.3 kB&lt;/td&gt;
&lt;td&gt;117.2 kB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;npm packages installed&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ProseMirror packages&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Track changes&lt;/td&gt;
&lt;td&gt;In the box&lt;/td&gt;
&lt;td&gt;Paid extension&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DOCX / RTF export&lt;/td&gt;
&lt;td&gt;In the box&lt;/td&gt;
&lt;td&gt;Paid extension or your own&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Collaborative editing&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes, first-class&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Production maturity&lt;/td&gt;
&lt;td&gt;New (1.0.0, September 2026)&lt;/td&gt;
&lt;td&gt;Years&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I would pick Tiptap if you need collaborative editing, you are shipping on a deadline and want years of hardening, you want a large community and Stack Overflow answers, or you want commercial support. Those are real advantages and none of them are close.&lt;/p&gt;

&lt;p&gt;I would pick Trevixal if you want to read the whole stack in one repository, your supply chain makes dependency count a constraint, you want Word export and track changes without a paid tier, or you need an editor that runs from one &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it deliberately does not do
&lt;/h2&gt;

&lt;p&gt;Trevixal is a single-user editor. I built real-time collaboration, measured it, and removed it on 12 September 2026; the decision is recorded as an architecture decision record in the repository. There is no live co-editing, so if that is your requirement, use something else. Comment threads on a selection are available as an optional extension as of 1.1.0, saved in the document and written to Word files as Word comments. It is also a young project: the first release was in September 2026. Treat it that way.&lt;/p&gt;

&lt;h2&gt;
  
  
  What 1.1.0 added
&lt;/h2&gt;

&lt;p&gt;The latest release is built around long documents and real Word interop: heading numbering in four schemes, numbered captions with cross-references, tables of figures, endnotes and an index, named styles, drop caps, columns and tab stops, merge-and-split tables, comments, fillable forms with mail merge, and a scaffold, &lt;code&gt;npm create @trevixal/extension &amp;lt;name&amp;gt;&lt;/code&gt;, for writing your own extension. The additions are backwards compatible: nothing was removed, and every new option is optional.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers, for the skeptics
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;26 packages&lt;/strong&gt; under &lt;code&gt;@trevixal/*&lt;/code&gt;: a headless core, an optional UI chrome, an assembled editor, five adapters (React, Vue, Svelte, Angular, web component) and seventeen extensions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3,051 unit tests&lt;/strong&gt; across 212 files, and &lt;strong&gt;333 browser tests&lt;/strong&gt; across 48 specs, run on Chromium, Firefox and WebKit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero runtime dependencies&lt;/strong&gt; in any published package.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Apache-2.0.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  If you try it
&lt;/h2&gt;

&lt;p&gt;The most useful thing you can do is break it. Open the &lt;a href="https://trevixal-editor.vercel.app/full-editor" rel="noopener noreferrer"&gt;live editor&lt;/a&gt;, paste the ugliest thing you have (a Word document, a Google Doc, a web page full of inline styles), and &lt;a href="https://github.com/adityabhalsod/trevixal-editor/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt; with what went wrong. Paste handling is the hardest part of any editor, and real-world input is what finds the bugs.&lt;/p&gt;

&lt;p&gt;If Trevixal looks useful, or just interesting, &lt;strong&gt;&lt;a href="https://github.com/adityabhalsod/trevixal-editor" rel="noopener noreferrer"&gt;a star on GitHub&lt;/a&gt;&lt;/strong&gt; is the cheapest way to help other developers find it. It is a small project and every star is noticed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href="https://github.com/adityabhalsod/trevixal-editor" rel="noopener noreferrer"&gt;github.com/adityabhalsod/trevixal-editor&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://trevixal-editor.vercel.app" rel="noopener noreferrer"&gt;trevixal-editor.vercel.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live editor:&lt;/strong&gt; &lt;a href="https://trevixal-editor.vercel.app/full-editor" rel="noopener noreferrer"&gt;trevixal-editor.vercel.app/full-editor&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;npm:&lt;/strong&gt; &lt;a href="https://www.npmjs.com/search?q=%40trevixal" rel="noopener noreferrer"&gt;&lt;code&gt;@trevixal/*&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading. I would genuinely like to hear what you would build with it.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
