A browser-based Markdown playground that renders Markdown to HTML in real time — entirely client-side, with no server required.
The Markdown-to-HTML conversion is powered by comrak (a GitHub Flavored Markdown parser written in Rust), compiled to WebAssembly and running directly in the browser. The editor is Monaco (the engine behind VS Code), and the whole app is a static site hosted on GitHub Pages.
🔗 Live demo: dpokluda.github.io/markdownpad
- Rust → WebAssembly — compiling a Rust library to WASM with
wasm-packandwasm-bindgen - Calling Rust from JavaScript — the JS frontend calls Rust functions through auto-generated WASM bindings
- Static site + WASM — no backend, no Node.js build step, no bundler; just HTML, CSS, JS, and a
.wasmfile - GitHub Pages deployment — free hosting of a static site from a repository's
/docsfolder
- Live preview — edit Markdown on the left, see formatted HTML on the right, updated on every keystroke
- Monaco editor — VS Code's editor with Markdown syntax highlighting, line numbers, and word wrap
- GFM support — tables, task lists, strikethrough, and autolinks (GitHub Flavored Markdown)
- Configurable parser — toggle individual GFM extensions on/off via the Settings menu
- Sample documents — load pre-built examples (Welcome, Tables, Empty) from the toolbar
- Dark/light theme — GitHub-inspired themes with one-click toggle; preference saved to localStorage
markdownpad/
├── rustdown/ ← Rust WASM library
│ ├── Cargo.toml ← Rust dependencies and build config
│ └── src/
│ └── lib.rs ← Markdown parser (comrak wrapper exposed to JS)
├── docs/ ← Static website (served by GitHub Pages)
│ ├── index.html ← Page layout, Monaco loader, toolbar
│ ├── style.css ← GitHub-inspired dark/light themes
│ ├── app.js ← Editor setup, WASM integration, UI logic
│ ├── rustdown.js ← Auto-generated JS glue (wasm-bindgen output)
│ ├── rustdown_bg.wasm ← Compiled WASM binary (~500 KB)
│ ├── run-local.ps1 ← PowerShell script to start a local dev server
│ └── samples/ ← Sample Markdown files
│ ├── welcome.md
│ ├── tables.md
│ └── empty.md
├── .gitignore
├── LICENSE
└── README.md
The core of the project is a small Rust library that wraps comrak, a GFM-compatible Markdown parser. The library exposes two functions to JavaScript via wasm-bindgen:
parse_markdown(input)— converts Markdown to HTML with all GFM extensions enabledparse_markdown_with_options(input, table, tasklist, strikethrough, autolink)— same conversion but with individually toggleable GFM features
The Cargo.toml configures the crate as a cdylib (required for WASM output) and rlib (required for cargo test). The [profile.release] section optimizes for binary size (opt-level = "s") and enables link-time optimization (lto = true) to keep the .wasm file small.
Running wasm-pack build --target web compiles the Rust library to WebAssembly and generates:
rustdown_bg.wasm— the compiled WASM binary containing the parserrustdown.js— auto-generated JavaScript glue code that handles memory management (string passing between JS and WASM), module initialization, and function bindings
These two files are copied into docs/ to be served alongside the website.
The frontend is plain HTML, CSS, and JavaScript with no build tools or bundlers:
index.html— defines the layout (header, toolbar, split-pane editor/preview, footer) and loads Monaco Editor from a CDN via its AMD loaderstyle.css— implements GitHub-inspired dark and light themes using CSS custom properties. Theme switching simply changes adata-themeattribute on<html>, and all colors update via CSS variablesapp.js— the main application logic:- Loads Monaco Editor from the jsdelivr CDN (AMD pattern)
- Dynamically imports the WASM module and initializes it
- Creates the Monaco editor with Markdown language support
- On every editor change, calls the Rust
parse_markdown_with_options()function through the WASM bridge - Injects the returned HTML into the preview pane
- Handles toolbar interactions (samples dropdown, clear, settings toggles, theme switching)
The site is served from the docs/ folder on the main branch. GitHub Pages serves the static files as-is, including the .wasm binary. No CI/CD pipeline or build step is needed — just push and it's live.
| Tool | Purpose | Install |
|---|---|---|
| Rust (stable) | Compile the Markdown parser | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh |
| wasm-pack | Compile Rust to WASM + generate JS bindings | cargo install wasm-pack |
| Python 3 | Local HTTP server (any static server works) | Pre-installed on most systems |
# 1. Clone the repository
git clone https://github.com/dpokluda/markdownpad.git
cd markdownpad
# 2. Run the Rust unit tests
cd rustdown
cargo test
# 3. Build the WASM package
wasm-pack build --target web
# 4. Copy the WASM artifacts to the website directory
cp pkg/rustdown_bg.wasm ../docs/
cp pkg/rustdown.js ../docs/
# 5. Start a local web server
cd ../docs
python -m http.server 8080
# 6. Open in your browser
# http://localhost:8080Windows (PowerShell): Replace
cpwithCopy-Itemin step 4, or use the includeddocs/run-local.ps1script for step 5.
If you modify rustdown/src/lib.rs, repeat steps 2–4 to rebuild and copy the updated WASM artifacts.
- Push your changes to the
mainbranch - Go to Settings → Pages in your GitHub repository
- Set Source to "Deploy from a branch"
- Set branch to
mainand folder to/docs - Save — the site will be live at
https://<username>.github.io/markdownpad/
| Layer | Technology | Role |
|---|---|---|
| Parser | comrak (Rust) | GFM Markdown → HTML conversion |
| WASM bridge | wasm-bindgen | Rust ↔ JavaScript interop |
| Build tool | wasm-pack | Compiles Rust to .wasm + JS glue |
| Editor | Monaco Editor | VS Code-like editing experience |
| Hosting | GitHub Pages | Free static site hosting |
See LICENSE for details.