# Build a Markdown Editor with Live Preview

Source: https://www.techinterview.org/post/3233475208/build-markdown-editor-live-preview/
Updated: 2026-07-26 · techinterview.org

Markdown editors are everywhere — GitHub issues, Notion, [Linear](/companies/linear/), Reddit. The interview tests whether you understand parsing, security (XSS via injected HTML), and the editor patterns that make Markdown editing feel responsive.

## Functional requirements

- Textarea or contenteditable for typing. A plain textarea is easier to reason about and to make accessible; contenteditable gives you inline formatting but drags in selection and cursor-position bugs. Interviewers often ask which you'd choose and why.

- Live preview pane. It renders the parsed HTML as the user types. The interesting discussion is *when* to re-render — doing it on every keystroke is wasteful, so you debounce.

- Syntax highlighting in the source. Coloring Markdown tokens (headings, links, emphasis) in the editing pane. A bare textarea can't do this, so you overlay a highlighted layer behind transparent text or use a dedicated code editor.

- Toolbar (Bold, Italic, Link). Buttons that wrap the current selection in Markdown markers. Interviewers probe how you keep the cursor and selection correct after the insert.

- Sanitized HTML output. The rendered HTML must be scrubbed before it reaches the DOM, or raw HTML inside the Markdown becomes an XSS vector. This is the security point they most want to hear you raise unprompted.

## Architecture

Three pieces:

- Source editor (textarea or rich) — where the user types the Markdown and where selection, undo, and highlighting live.

- Markdown parser (markdown → HTML) — turns the source string into an HTML string on each update; this is the step you debounce.

- Sanitizer (clean HTML) — strips dangerous tags and attributes from that HTML before it renders, so parsing and safety stay separate concerns.

## Source editor: textarea vs CodeMirror

### Textarea

Simplest. Plain text. No syntax highlighting. Good for short content.

### CodeMirror

Code-editor-style. Syntax highlighting, theming, line numbers. Best for technical Markdown.

### Monaco Editor

VS Code's editor. Heavy (~3MB) but powerful. Overkill for typical Markdown.

### Tiptap / ProseMirror

Rich-text editors that can handle Markdown via WYSIWYG-meets-source. Linear and Notion-style. Complex.

For a basic Markdown editor: textarea + syntax highlighting overlay.

## Parsing libraries

- **marked:** fast, simple, the default

- **markdown-it:** more configurable, plugin ecosystem

- **remark / unified:** AST-based, powerful but more setup

For most apps, markdown-it is the modern choice.

## Sanitization

Markdown allows raw HTML. Without sanitization, an attacker can inject `<script>`.

Use DOMPurify to clean HTML before rendering. Configure to allow safe elements (img, a) and disallow scripts.

## Live preview

Two patterns:

- **Split view:** source on left, preview on right (Markdown.com, StackEdit)

- **Tabs:** Edit / Preview tabs (GitHub)

- **Inline:** formatting appears as you type (Notion, Linear)

Split view is simplest. Inline is more polished but technically demanding.

## Performance

For long documents, parsing on every keystroke is slow. Mitigations:

- Debounce parsing (100–200ms) so you re-parse once the user pauses instead of on every keypress. This is the single biggest win and the first thing interviewers expect.

- Incremental parsing (markdown-it supports) — re-parse only the block that changed rather than the whole document, which matters once a doc runs to thousands of lines.

- Run the parser in a Web Worker for very long docs so parsing happens off the main thread and typing and scrolling stay smooth.

## Toolbar

Common buttons:

- Bold, Italic, Strike

- Headings (H1, H2, H3)

- Link, Image

- Code block

- Bulleted list, Numbered list, Blockquote

Implementation: each button wraps selected text in Markdown markers.

## Image handling

Most editors support drag-drop or paste of images:

- Detect image in clipboard / drop

- Upload to your server (or S3)

- Insert `![alt](url)` at cursor position

- Show upload progress

## Slash commands

Notion-style: type `/` to open command menu (heading, code block, list). Powerful UX. Implementation: detect "/" at line start; show floating menu.

## Persistence

Auto-save:

- Debounce 1–2 seconds — save shortly after the user stops typing, not on every change, to avoid hammering the network.

- Save to local storage as a fallback so a dropped connection or an accidental refresh doesn't lose the draft.

- Sync to server when online, reconciling the local draft with the server copy so the two don't silently diverge.

Important for long-form content; users hate losing work.

## Accessibility

- Toolbar buttons have explicit labels — an icon-only button needs an aria-label so a screen reader announces "Bold" instead of nothing.

- Keyboard shortcuts (Cmd+B for bold, Cmd+I for italic) so the toolbar isn't the only path to formatting.

- Preview is screen-reader-friendly — render real semantic HTML (headings, lists, links) rather than dumping raw markup, so assistive tech can navigate it.

- Source mode is plain textarea — the most accessible option, since it's a native control every assistive tool already understands.

## Common mistakes

- Not sanitizing HTML output (XSS hole)

- Parsing on every keystroke without debounce

- Image paste does not work

- No auto-save (users lose work)

## Frequently Asked Questions

### Should I support GFM (GitHub Flavored Markdown)?

For developer audiences: yes. Tables, task lists, strikethrough are useful. markdown-it supports via plugin.

### How do I handle math (LaTeX)?

KaTeX or MathJax. Preview pane renders the math; source shows the LaTeX.

### What about diff / comments?

Out of scope for typical Markdown editor. For [collaborative review](/post/3233460997/system-design-collaborative-editing/), look at ProseMirror-based editors or specialized tools.
