open source · MIT · npm

Content in Markdown.
Layout untouched.

A contract that separates text from structure. Mark your HTML with data-sync, edit the .md, run one command — only content changes.

~/my-project
$ html-md-sync push
↗ Reading content/home.md
↗ Mapping 4 keys found
✓ hero-title updated
✓ hero-description updated
✓ feature-1 updated
✓ cta-label updated
4/4 nodes synchronized — layout preserved.
$
Explicit contract
Preserves all
AI‑friendly
CLI in seconds

Built to not surprise.

Predictability is the feature. No magic, no heuristics, no invisible regressions.

Layout safety
Replaces only textContent or innerHTML on marked nodes. Nothing else is touched.
Explicit contract
One data-sync attribute in HTML. One # key section in Markdown. That’s it.
AI‑friendly
Give only the .md to the model. HTML stays protected. Run push to apply safely.
Minimal CLI
push, pull, init. Three commands to cover your workflow. Zero mandatory config.
Bidirectional
Extract HTML to Markdown with pull. Use it as a backup before iterating with AI.
Zero lock-in
No framework dependency. Works with static HTML, templates, or any pipeline that produces HTML.

Three steps, zero surprises.

Mapping is deterministic. What you write in .md goes exactly where you marked in HTML.

1
Annotate HTML with data-sync

Add data-sync="key" to any element. Use data-sync-mode="html" when you need rich HTML content.

HTML index.html
<h1 data-sync="hero-title">
  Original Title
</h1>

<p data-sync="hero-desc">
  Original description.
</p>

<div data-sync="features"
     data-sync-mode="html">
  <!-- Rich HTML here -->
</div>
2
Write content in Markdown

Create sections with # key matching the HTML data-sync values. Hand this file to the language model for copy edits.

MD content/home.md
# hero-title
The Future of AI Orchestration

# hero-desc
Turn briefs into
functional MVPs in 48 hours.

# features
<ul>
  <li>Fast</li>
  <li>Secure</li>
</ul>
3
Run the sync

Use push to apply Markdown to HTML or pull to extract HTML to Markdown. Layout remains untouched.

SH MD → HTML
html-md-sync push
# apply .md to .html
SH HTML → MD
html-md-sync pull
# extract HTML to .md

Ready in 30 seconds.

Install globally or as a project devDependency:

SH Global
npm i -g html-md-sync
SH Local (recommended)
npm i -D html-md-sync
npx html-md-sync init
SH Quick start
# create sync-config.json
html-md-sync init

# apply MD → HTML
html-md-sync push

# extract HTML → MD
html-md-sync pull

Command reference:

help Show help and available commands
version Installed CLI version
init [--config] Create a default sync-config.json
push [--config] Apply content from .md into .html
pull [--config] Extract content from .html to .md

One file. Everything mapped.

sync-config.json defines which files to sync and how.

JSON sync-config.json
{
  "mappings": [
    {
      "html": "./src/index.html",
      "md": "./content/home.md",
      "strategy": "data-attribute"
    }
  ],
  "options": {
    "preserveAttributes": true,
    "minifyOutput": false
  }
}
mappings[].html Path to the HTML file
mappings[].md Path to the Markdown file
strategy Reserved — MVP uses data-attribute
preserveAttributes Keep all HTML attributes intact
minifyOutput Minify HTML output (reserved)

↑ Contract guarantees

  • → Keys in MD with no match in HTML: ignored
  • → Keys in HTML with no match in MD: left unchanged
  • → Duplicate keys in MD: last occurrence wins

Frequently asked questions.

Can I use this with frameworks (React, Vue, etc.)? +

Yes. Point mappings[].html to the final HTML or to the templates that produce HTML. The tool is framework‑agnostic — it operates directly on the HTML file.

Does the tool modify attributes, classes or scripts? +

No. Only the content of nodes marked with data-sync is changed. Classes, IDs, event handlers, scripts and any other attributes remain untouched.

How should I version this? +

Version all three: .md, .html and sync-config.json. Before iterating with AI, run pull to capture the current HTML state in Markdown — a clean snapshot.

Can I sync rich HTML content? +

Yes. Mark the node with data-sync-mode="html" and write HTML directly in the corresponding Markdown section. The tool uses innerHTML instead of textContent.

What if a key exists in MD but not in HTML? +

It’s silently ignored during push. No error is thrown and HTML remains unaffected. The opposite — a key in HTML with no match in MD — keeps the original content unchanged.

How do I integrate with AI workflows? +

Give only the .md to the language model for copy edits. HTML stays protected. After editing, run html-md-sync push to safely apply the content. For a backup of the current state, run pull before iterating.

Sync with confidence.

One line in the terminal. Content updated. Layout untouched. Exactly as it should be.