Skip to content

floatboatai/Nexus-Editor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

132 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Nexus-Editor

A headless, AST-driven Markdown editor engine β€” built for makers who need real Markdown, not another WYSIWYG.

Powered by CodeMirror 6 + the unified ecosystem. Framework-agnostic core Β· Official React & Vue bindings Β· MIT licensed.

δΈ­ζ–‡ζ–‡ζ‘£ Β· Quick Start Β· Why Nexus? Β· Roadmap Β· Contributing


πŸ—ΊοΈ Roadmap (TL;DR)

We ship in priority tiers β€” P0 is what we're working on right now.

Tier Theme Highlights
P0 β€” Now Core API completeness getSelectedText(), slash command sorting, <Editor /> onReady, TS strict coverage
P1 β€” Next Power-user features Multi-cursor, regex search, undo/redo grouping, widget API standardization, Electron packaging
P2 β€” Mid-term UX & ecosystem Advanced toolbar (emoji / table / color), fuzzy search, sync-scroll preview, web-component wrapper
P3 β€” Long-term Collaboration Realtime CRDT collab, shared comments / @mention, plugin hot-reload

πŸ‘‰ Full roadmap with package ownership, status, and OpenSpec linkage: docs/ROADMAP.md


πŸ’‘ Why Nexus-Editor?

Markdown editing on the web is a crowded space β€” yet every existing option forced us to compromise on something fundamental. We built Nexus because we needed an editor that treats Markdown text as the source of truth, stays out of the way of your UI, and is honest about extension points.

Side-by-side comparison

Nexus Tiptap Lexical Milkdown MDXEditor @uiw/react-md-editor
Foundation CodeMirror 6 + unified ProseMirror Built from scratch (Meta) ProseMirror + Remark Lexical CodeMirror + Marked
Source of truth Markdown text JSON tree JSON tree ProseMirror doc Lexical state Markdown text
Round-trip safe βœ… Lossless ⚠️ Format can drift ⚠️ Markdown is import/export ⚠️ Through PM schema ⚠️ Through Lexical βœ…
UI model Headless Headless Headless-ish WYSIWYG (built-in UI) WYSIWYG Split-pane
Live preview Obsidian-style inline None (BYO) None (BYO) Full WYSIWYG Full WYSIWYG Side-by-side pane
Framework support React Β· Vue Β· Vanilla React Β· Vue Β· Svelte Β· Vanilla React-first React Β· Vue Β· Vanilla React only React only
Plugin tiers 3 (shortcut / AST / CM6) 1 (Tiptap extension) 1 (node + transform) 1 (Milkdown plugin) 1 (Lexical plugin) None
Bundle (core, approx.) Small (CM6 ~110KB) Medium (PM + ext.) ~22KB core ~125KB / ~40KB gz ~851KB gz Medium
Local-first / file IO hooks βœ… First-class ❌ ❌ ❌ ❌ ❌
License MIT MIT (+ paid cloud) MIT MIT MIT MIT

Numbers are taken from public docs and recent third-party reviews. Bundle sizes vary with plugins enabled β€” treat the column as a rough order-of-magnitude.

What this means in practice

  • Tiptap / Lexical / Milkdown / MDXEditor all keep an internal JSON document model. Markdown is an import/export concern β€” round-tripping a .md file through them can quietly drift (lost soft-breaks, reordered attributes, normalized tables). If your product is the Markdown file (notes app, static-site authoring, LLM writing tools), this matters.
  • @uiw/react-md-editor keeps Markdown as the document, but offers a classic split-pane preview β€” no inline syntax reveal, no widget API, React only.
  • Obsidian has the UX we love, but it's closed source. You can't embed its engine in your own product.
  • Nexus keeps Markdown as the document and gives you Obsidian-style live preview, a widget API, three plugin altitudes, and framework-agnostic bindings β€” without the WYSIWYG lock-in.

If you're building a note-taking app, a docs CMS, a static-site authoring tool, a Markdown-native PKM, or an LLM-powered writing assistant, Nexus is meant to be the engine you don't have to fight.


πŸš€ Quick Start

1. Install

# pnpm (recommended)
pnpm add @floatboat/nexus-core @floatboat/nexus-preset-gfm

# or npm / yarn
npm install @floatboat/nexus-core @floatboat/nexus-preset-gfm

2. Pick your flavor

React β€” the fast path
import { Editor } from "@floatboat/nexus-react";
import { createGfmPreset } from "@floatboat/nexus-preset-gfm";

export default function App() {
  return (
    <Editor
      initialValue="# Hello, Nexus πŸ‘‹"
      plugins={[createGfmPreset()]}
      livePreview
      onChange={(doc, ast) => console.log(doc)}
    />
  );
}

πŸ’‘ New to CodeMirror? You don't need to know it. <Editor /> handles the lifecycle β€” just drop it in.

Vue 3
<script setup>
import { Editor } from "@floatboat/nexus-vue";
import { createGfmPreset } from "@floatboat/nexus-preset-gfm";
</script>

<template>
  <Editor
    initial-value="# Hello"
    :plugins="[createGfmPreset()]"
    :live-preview="true"
    @change="(doc) => console.log(doc)"
  />
</template>
Vanilla / Plain DOM
import { createEditor } from "@floatboat/nexus-core";
import { createGfmPreset } from "@floatboat/nexus-preset-gfm";
import { createHistoryPlugin } from "@floatboat/nexus-plugin-history";

const editor = createEditor({
  container: document.getElementById("editor")!,
  initialValue: "# Hello\n\nStart typing...",
  plugins: [createGfmPreset(), createHistoryPlugin()],
  livePreview: true,
  onChange(doc, ast) {
    console.log("Markdown:", doc);
    console.log("AST:", ast);
  },
});

3. New here? Read this first

🐣 Things we wish someone had told us when we started

  • You don't need to know CodeMirror. The React / Vue wrapper handles the lifecycle. You only meet CodeMirror if you write a low-level plugin.
  • Headless means no theme. We ship logic, not looks. Plan a few hours for styling β€” the Electron demo is a copy-pasteable starting point.
  • Live preview is opt-in. If you just want a raw Markdown editor, leave it off and you get a clean text-editing experience.
  • The AST is mdast β€” the same tree used by remark and the unified ecosystem. If you've never seen it, the mdast spec is the one-page cheat sheet you actually need.
  • Don't auto-save on every keystroke. onChange fires constantly β€” debounce before writing to disk or hitting the network.
  • Blank screen? Nine times out of ten, the container has no height. Give it one and the editor appears.
  • Lost? Open an issue with the question label β€” we'd rather answer the same question 20 times than have you give up.

4. Try the demo

git clone https://github.com/floatboatai/Nexus-Editor.git
cd Nexus-Editor
pnpm install
pnpm dev:electron-demo

A real Electron app with file IO, live preview, and every plugin enabled β€” the fastest way to see what's possible.


πŸ“¦ Packages

Full package list (11 packages) β€” click to expand
Package Description
@floatboat/nexus-core Editor engine β€” CM6 state, AST pipeline, live preview, events, widget API
@floatboat/nexus-react React binding β€” useEditor hook and <Editor /> component
@floatboat/nexus-vue Vue 3 binding β€” useEditor composable
@floatboat/nexus-preset-gfm GitHub Flavored Markdown preset (tables, strikethrough, task lists)
@floatboat/nexus-plugin-history Undo/redo with Ctrl+Z / Ctrl+Shift+Z
@floatboat/nexus-plugin-search Search and replace helpers
@floatboat/nexus-plugin-slash Slash command detection, ranking, and a vanilla-DOM floating menu UI
@floatboat/nexus-plugin-toolbar Toolbar primitives for formatting commands
@floatboat/nexus-plugin-math Inline / block math rendering (KaTeX)
@floatboat/nexus-plugin-vim Vim keybindings powered by @replit/codemirror-vim
@floatboat/nexus-plugin-wordcount Markdown-aware word / character / CJK / reading-time stats + ARIA-live status bar

✨ Features

  • Headless β€” no built-in UI. Render with any framework or plain DOM.
  • AST-Driven β€” real-time Markdown β†’ mdast parsing with every keystroke.
  • Live Preview β€” inline rendering that reveals raw syntax on cursor focus (Obsidian-style).
  • Plugin System β€” three tiers: shortcuts & slash commands, remark plugins & widgets, raw CM6 extensions.
  • Event System β€” subscribe to change, focus, blur, selectionChange, slashMenuChange.
  • Widget API β€” render custom components for any AST node type (code blocks, tables, diagrams).
  • Local-First β€” built for Electron/Tauri with file IO hooks and debounced parsing.

πŸ“– API Reference

Editor API β€” methods and events

createEditor(config) returns an EditorAPI with:

editor.getDocument()          // current Markdown string
editor.getAst()               // current mdast Root
editor.setDocument(md)        // replace entire document
editor.setDocument(md, { silent: true, preserveSelection: true })
editor.setDocument(md, { selection: { anchor: 0 } })
editor.setSelection(pos)      // move cursor
editor.focus() / editor.blur()
editor.destroy()

// Event system
editor.on("change", (doc, ast) => { ... })
editor.on("selectionChange", ({ anchor, head }) => { ... })
editor.on("slashMenuChange", ({ isOpen, query, commands, coords }) => { ... })
editor.off("change", handler)

// Coordinates (for floating UI)
editor.getCoordsAtPos(pos)     // { left, right, top, bottom } | null
Plugin authoring β€” three tiers, one shape
const myPlugin: NexusPlugin = {
  name: "my-plugin",

  // Tier 1: Shortcuts & slash commands
  shortcuts: [{ key: "Mod-b", run: (editor) => { /* toggle bold */ return true; } }],
  slashCommands: [{ id: "heading", title: "Heading", keywords: ["h1"] }],

  // Tier 2: AST & widgets
  remarkPlugins: [remarkMath],
  widgets: [{
    nodeType: "code",
    match: (node) => node.lang === "mermaid",
    render: (node, source) => renderMermaidChart(source),
    destroy: (el) => el.remove(),
  }],

  // Tier 3: Raw CM6
  cmExtensions: [myCodeMirrorExtension],
};

πŸ› οΈ Development

Build, test, and run the demo
pnpm install
pnpm build          # build all packages
pnpm test           # run all tests

# Electron demo
pnpm dev:electron-demo

🀝 Contributing

We'd love your help β€” whether it's a typo fix, a new plugin, or a deep core change. Here's the 5-minute version:

  1. Fork this repo β€” click the Fork button at the top of the page.
  2. Clone your fork locally:
    git clone https://github.com/<your-username>/Nexus-Editor.git
    cd Nexus-Editor
    pnpm install
  3. Create a branch following our naming convention (see CONTRIBUTING.md):
    git checkout -b feat/<scope>/<short-description>
  4. Make your change β€” write tests, run pnpm test, run pnpm build.
  5. Commit using Conventional Commits:
    git commit -m "feat(core): add getSelectedText() API"
  6. Push to your fork and open a Pull Request against main.

Before opening a PR, please read

🟒 Good first issues are labeled good first issue β€” start there if you're new to the codebase.


πŸ“„ License

MIT Β© floatboat


⭐ Like what you see?

If Nexus-Editor saved you from writing yet another Markdown editor from scratch, the kindest thing you can do is hit the ⭐ button β€” it helps other devs find the project, and it genuinely makes our day.

Spread the word

  • 🐦 Tweet about it β€” tag us, we'll retweet
  • πŸ“ Blog about your integration β€” open a PR to list it in SHOWCASE.md
  • πŸ’¬ Share in your team's Slack / Discord β€” that's how 90% of devs discover tools
  • πŸ› Open an issue if something feels off β€” even "this is confusing" is valuable feedback

Built with ❀️ for makers who still believe Markdown is the right format.

About

Nexus Editor

Resources

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages