Skip to content

Getting Started

For LLMs, see /llms.txt.

Inkwell is a Markdown editor and renderer for React that treats Markdown as the canonical content.

You write and edit content in a visual WYSIWYG interface, but the underlying content is always the Markdown source; the Markdown source is the text.

It ships with WYSIWYG basics such as bold, italic, strike, code, and an extensible plugin system with batteries included for everything else.

Terminal window
npm install @railway/inkwell

Requires React 19 or later as a peer dependency.

Render InkwellEditor with a content string and an onChange handler.

import { InkwellEditor } from "@railway/inkwell";
import { useState } from "react";
import "@railway/inkwell/styles.css";
function App() {
const [content, setContent] = useState("# Hello **world**");
return <InkwellEditor content={content} onChange={setContent} />;
}

This gives you a fully featured Markdown editor out of the box:

  • Block formatting — headings, blockquotes, and fenced code blocks, all triggered by typing their Markdown syntax
  • Inline formatting — bold, italic, strikethrough, and inline code, rendered visually as you type
  • Floating toolbar — select text to reveal bold, italic, and strikethrough buttons
  • Syntax highlighting — fenced code blocks are highlighted automatically
  • Keyboard shortcuts⌘B bold, ⌘I italic, ⌘D strikethrough

The floating toolbar is powered by the Bubble Menu plugin.

InkwellRenderer turns a Markdown string into formatted HTML. No browser dependencies — works anywhere React runs, including server-side rendering.

import { InkwellRenderer } from "@railway/inkwell";
import "@railway/inkwell/styles.css";
function Preview({ content }: { content: string }) {
return <InkwellRenderer content={content} />;
}

Pair them together for a live preview:

import { InkwellRenderer, InkwellEditor } from "@railway/inkwell";
import "@railway/inkwell/styles.css";
import { useState } from "react";
function EditorWithPreview() {
const [content, setContent] = useState("# Hello **world**");
return (
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "1rem" }}>
<InkwellEditor content={content} onChange={setContent} />
<InkwellRenderer content={content} />
</div>
);
}

Inkwell ships default editor, plugin, and renderer styles. Import them once in your app entry point:

import "@railway/inkwell/styles.css";

You can override any class to match your product. See the Styling guide for the full list of CSS classes.

  • Editor — formatting options, syntax highlighting, and the full props reference
  • Renderer — custom component overrides and rendering configuration
  • Plugins — built-in plugins, custom plugins, and keyboard shortcuts
  • Styling — CSS classes for every element in the editor and renderer