ContentSync — Multi-Platform Content Syndication
Write Markdown once, publish everywhere — a TypeScript CLI that syndicates one folder of Markdown posts to 11 blogging platforms and builds a static site from the same source.
What it is / why it exists
Cross-posting the same article to Dev.to, Hashnode, Medium, WordPress and half a dozen other platforms by hand is slow and error-prone, and re-posting an edit creates duplicates. ContentSync solves that: keep your posts as Markdown files with YAML front-matter, run one command, and each post is published (or updated) on every platform you've configured. It tracks per-post, per-platform state so re-runs update the existing post instead of creating a copy — and it builds a static HTML site from the very same Markdown.
Links
- Live site: https://contentsync-multiplatform-content-syndication-web-app.oriz.in
- Landing page (GitHub Pages): https://contentsync-multiplatform-content-syndication-web-app.oriz.in
- Repo: https://github.com/chirag127/ContentSync-MultiPlatform-Content-Syndication-Web-App
⭐ If this is useful, please star the repo — it helps others find it.
How it works
flowchart TD
MD[content/posts/*.md\nMarkdown + front-matter]
PUB[publish.ts\norchestrator]
ST[.postmap.json\nstate: slug → platform → id/url]
MD --> PUB
PUB <-->|read/write| ST
PUB --> A1[devto]
PUB --> A2[hashnode]
PUB --> A3[medium]
PUB --> A4[wordpress]
PUB --> A5[blogger]
PUB --> A6[tumblr · wix · writeas]MD -- BS[build-site.ts] BS -- SITE[static HTML site]
sequenceDiagram participant CLI as publish.ts participant State as .postmap.json participant Adapter participant Platform CLI-State: look up post slug for this platform alt first publish CLI-Adapter: create(post) Adapter-Platform: POST new article Platform--Adapter: { id, url } Adapter--State: record id + url else already published CLI-Adapter: update(post, id) Adapter-Platform: PUT existing article end
## Features
- **One source of truth** — `content/posts/*.md` with YAML front-matter (title, slug, tags, …).
- **Pluggable adapters** — one file per platform in `src/adapters/`; add a platform by dropping in an adapter and registering it.
- **Idempotent** — `.postmap.json` maps `slug → platform → { id, url, lastUpdated }`, so re-runs update instead of duplicate.
- **Static-site generator** — `build-site.ts` renders the same Markdown into an HTML site.
- **Safe local testing** — `--dry-run` (no API calls) and `--mock` (against a bundled mock server).
- **Credential-aware** — platforms without configured tokens are skipped automatically.
- **Concurrency control** — `--concurrency <n>` (default 2).
## Supported platformsDev.to · Hashnode · Medium · WordPress · Blogger · Tumblr · Wix · Write.as · Telegraph · Micro.blog · Substack
Tech stack
| Concern | Technology | | --- | --- | | Language | TypeScript 5 (Node 18+, ts-node) | | CLI | commander, chalk | | Markdown | marked, gray-matter | | HTTP | axios, oauth-1.0a (Tumblr) | | Files / config | fs-extra, glob, js-yaml, dotenv | | Logging | winston | | Lint | ESLint |
Repository structure
content/posts/ Markdown source posts (front-matter + body)
src/
├── publish.ts CLI entrypoint — publish orchestration
├── build-site.ts static-site generator
├── generate-content.ts content-generation helper
├── mock-server.ts local mock API for --mock / npm test
├── adapters/ one file per platform (devto, hashnode, medium, wordpress,
│ blogger, tumblr, wix, writeas, telegraph, microblog, substack)
│ ├── index.ts adapter registry
│ └── types.ts shared adapter interface
└── utils/ markdown.ts · state.ts · logger.ts
scripts/ content generation helpers