How to convert markdown to html for a static site
- Step 1Strip front matter, then paste the body — Remove any YAML/TOML front matter first — marked does not strip it and it will leak into the HTML. Paste the body Markdown or drop the
.mdfile (one per run). - Step 2Turn Full document OFF for layout partials — For an SSG that already has a layout, turn Full document OFF so you get the body fragment to inject into your
{{ content }}slot. Leave it ON only for a standalone preview page. - Step 3Run the conversion — marked parses locally and renders HTML instantly — no Node, no build, nothing uploaded.
- Step 4Add heading ids in your pipeline if needed — marked does not emit
idattributes on headings, so anchor links won't resolve from this output. If your theme uses heading anchors, add them with your SSG's slug/anchor plugin (e.g. rehype-slug) rather than relying on this tool. - Step 5Drop the fragment into your source tree — Paste the body HTML into your template's content area, an
.htmlpartial, or an MDX/HTML island. Your layout supplies the<head>, CSS, and scripts. - Step 6Preview and commit — Run your usual local preview to confirm the fragment composes with the theme. For repeatable conversion in a build, wire marked into your SSG's Markdown pipeline directly — this browser tool is for one-offs and spot checks.
What converts for SSG content
Verified against marked 14.1.4. GFM is on by default; these are the things SSG content uses most.
| Element | Markdown | HTML output | SSG note |
|---|---|---|---|
| Heading | ### API | <h3>API</h3> (no id) | Add ids via rehype-slug / theme plugin |
| GFM table | pipe table | <table> with thead/tbody | Styled by theme CSS |
| Fenced code | ` ts ` | <pre><code class="language-ts"> | Wire to your highlighter |
| Task list | - [ ] todo | <input disabled type="checkbox"> | Style with theme CSS |
| Internal link | [Docs](/docs) | <a href="/docs">Docs</a> | Path kept verbatim |
| Image |  | <img src="/img/x.png"> | Path verbatim — match your asset dir |
| Front matter | --- … --- | leaks into output as text/<hr> | Strip before converting |
Fragment vs full document for SSGs
The single fullDocument option (default true) decides the wrapper.
| Scenario | Mode | Reason |
|---|---|---|
Inject into a layout {{ content }} | Full document OFF (fragment) | Layout already has <head> + CSS |
| Standalone one-off page | Full document ON | Complete openable page with built-in stylesheet |
| HTML partial / include | Full document OFF (fragment) | Partials are body snippets, not whole pages |
| Quick local preview without dev server | Full document ON | Open the .html directly in a browser |
Tier limits (markdown family)
Per-file limits. Character cap is independent of byte size.
| Plan | Max file size | Max characters | Files per run |
|---|---|---|---|
| Free | 1 MB | 500,000 | 1 |
| Pro | 10 MB | 5,000,000 | 10 |
| Pro + Media | 50 MB | 20,000,000 | 50 |
| Developer | 500 MB | unlimited | unlimited |
Cookbook
SSG content snippets, the HTML this tool produces, and how each fits a static-site workflow.
Body fragment for a layout content slot
With Full document OFF you get exactly the body HTML to inject into a Nunjucks/Liquid/Astro layout's content placeholder.
Input:
## Getting started
Install and run.
Output (fragment, Full document OFF):
<h2>Getting started</h2>
<p>Install and run.</p>
Layout:
<main>{{ content }}</main> ← paste the fragment hereCode block ready for your highlighter
The language class is preserved so the highlight.js/Prism you already load in the theme colours it on render — no colour markup is baked in.
Input: ```ts export const x: number = 1; ``` Output: <pre><code class="language-ts">export const x: number = 1; </code></pre>
Headings have no ids — add them in your pipeline
An on-page anchor menu won't work from this output because headings carry no id. SSGs solve this with a slug plugin; rely on that rather than this tool.
Output from this tool: <h2>Configuration</h2> <!-- no id --> After rehype-slug (in your SSG build): <h2 id="configuration">Configuration</h2> So [Config](#configuration) resolves.
Strip front matter before converting
marked does not strip front matter. Feeding it a file that still has the --- block leaks the metadata into the HTML.
Input (WRONG — front matter left in): --- title: Home --- # Welcome Output (front matter leaks): <hr> <h2>title: Home</h2> <h1>Welcome</h1> Fix: remove the --- block first, then convert.
Full document for a no-build preview
When you just want to eyeball a page without starting the dev server, Full document ON gives a self-contained file you open in the browser.
Full document ON → complete page: <!DOCTYPE html><html lang="en"><head>…built-in <style>… </head><body>… your content …</body></html> Double-click the .html to preview — no SSG build needed.
Edge cases and what actually happens
Front matter is not stripped
Leaks into outputmarked does not understand YAML/TOML front matter. If you convert a file with a --- block still at the top, the metadata appears in the HTML as text or an <hr> plus heading. Always strip front matter before converting (your SSG normally does this — this browser tool does not).
Headings have no id attributes
By designNo id slugs are emitted, so anchor links and on-page menus won't resolve from this output. In an SSG you'd add ids with a plugin like rehype-slug; don't rely on this tool to provide working heading anchors.
Link and image paths are kept verbatim
Preserved[Docs](/docs) and  keep their paths exactly. That's usually what you want for an SSG with absolute routes — just confirm the paths match your site's routing and asset directory. To rewrite image bases, use md-image-path-rewriter.
Raw HTML passes through unsanitized
Not sanitizedInline HTML in your Markdown is preserved verbatim, including <script>. Fine for trusted first-party content; if you convert untrusted contributor Markdown, sanitize the HTML in your build before publishing.
MDX components are not executed
Treated as HTMLIf your content is .mdx with JSX components, marked treats the JSX as raw HTML — it does not render components. Use your MDX toolchain for component-bearing content; this tool targets CommonMark + GFM.
Footnotes render as broken links
Not supportedFootnote syntax ([^1]) is not in core marked and produces a broken reference link. Many SSGs add footnote support via a remark plugin; this browser tool does not. Convert footnotes to inline references first if you need them.
No syntax highlighting baked in
By designCode blocks get a language-* class but no colour spans. Your theme's highlighter applies colours on render. The raw HTML is intentionally plain so it stays portable across themes.
Not the same as your theme's render
ExpectedFull-document mode uses a generic built-in stylesheet, not your site theme. It's for quick previews. The fragment, once inside your layout, picks up your theme's CSS and will look correct there.
Math expressions stay literal
Not supportedmarked doesn't parse LaTeX. $…$ and $$…$$ pass through as text. Normalise delimiters with md-math-normalizer and add KaTeX/MathJax in your theme to render them.
File exceeds the free character cap
400 rejectedOver 500,000 characters / 1 MB and Free rejects the file before conversion. Most single pages are far smaller; a giant concatenated doc could trip it. Pro raises the cap to 5,000,000 / 10 MB.
Frequently asked questions
Should I use fragment or full-document mode for my static site?
Fragment — turn Full document OFF. Your SSG layout already provides <head>, CSS, and the page shell, so you only need the body to inject into the {{ content }} slot. Full-document mode is for a quick standalone preview without running the dev server.
Why don't anchor links work in the converted HTML?
marked emits headings without id attributes, so #section anchors have nothing to target. In an SSG you add ids with a plugin like rehype-slug during the build. This browser tool doesn't add them — rely on your pipeline for working heading anchors.
Does it strip YAML front matter?
No. marked doesn't recognise front matter, so a --- block at the top leaks into the HTML as text or an <hr>. Strip front matter before converting — your SSG normally handles this, but this manual tool does not.
Are code blocks ready for my highlighter?
Yes — fenced blocks keep their class="language-ts" hook, which is exactly what highlight.js and Prism use. No colour markup is baked in, so the same HTML works with whatever highlighter your theme already loads.
Will it execute MDX components?
No. marked treats JSX as raw HTML — it does not render components. For component-bearing .mdx content use your MDX toolchain. This tool targets CommonMark + GFM and is best for plain content pages.
Are internal links and image paths preserved?
Yes, verbatim — /docs stays /docs, /img/x.png stays /img/x.png. That suits absolute-route SSGs; just verify the paths match your routing and asset directory. Use md-image-path-rewriter to rewrite image bases in bulk.
Is the output safe to publish from untrusted Markdown?
Not without sanitizing. marked passes raw HTML through verbatim, including <script>. For first-party content that's fine; for contributor or user-supplied Markdown, sanitize the HTML in your build before publishing.
How is this different from my SSG's built-in Markdown rendering?
It's the same family of engine (marked), but run manually in the browser with no build step — good for one-off pages and content spot-checks. For repeatable per-build conversion, wire marked (or your SSG's renderer) into the build pipeline directly.
Can I get a GitHub-styled output instead of the plain one?
Yes — md-to-github-html wraps the body in GitHub's Primer CSS. This tool's full-document mode uses a generic built-in stylesheet, and its fragment mode carries no styles at all (your theme provides them).
Is my content uploaded?
No. Conversion runs in your browser via marked — your Markdown never leaves your machine. Only an anonymous processed-file counter is recorded for dashboard stats, never the content.
How large a file can I convert?
Free: 1 MB / 500,000 characters. Pro: 10 MB / 5,000,000. Pro + Media: 50 MB / 20,000,000. Developer: 500 MB / unlimited. The character cap is separate from byte size, so a multibyte file may hit the char limit first.
Can I automate conversion in my build instead of using this tool?
Yes — the public API exposes md-to-html via GET /api/v1/tools/md-to-html for the option schema, and most SSGs already run a marked-family renderer internally. This browser tool is best for one-off pages and content spot-checks; for every-build conversion, wire your SSG's Markdown pipeline (or marked directly) into the build.
Privacy first
All Markdown processing runs locally in your browser using JavaScript. No file is ever uploaded to JAD Apps servers — only metadata counters are saved for signed-in dashboard stats.