Building a Write-Once Publishing Pipeline
Source: Dev.to
The problem
Writing content is the easy part.
Publishing it consistently across platforms — with the right metadata, images, tags, canonical URLs, and updates — is where things usually fall apart.
Most workflows still look like this:
- Write content in one tool
- Copy/paste it into WordPress
- Reformat it for another platform
- Forget what was published where
- Lose track of updates and fixes
I wanted something different:
Write once. Publish many. Update safely. Automate everything.
That goal led to building a fully automated, Git‑driven publishing pipeline.
The core idea
At the heart of this system is a simple principle:
Markdown in Git is the single source of truth.
Everything else — publishing, updating, tracking, media handling — is derived from that.
The pipeline is designed to be:
- Idempotent (safe to run repeatedly)
- Stateless at the CI level
- State‑aware via a database
- Extensible to new platforms
- Ready for containerization and Kubernetes
Current feature set
Content & metadata
- Markdown with YAML frontmatter
- Title, slug, tags, featured image
- Per‑platform publish switches
- Optional
force_updateflag
Publishing
- WordPress publishing via REST API (automatic post creation and updates)
- Draft or published status
- Automatic canonical URL generation
Featured images
- Uploads media via WordPress REST API
- Reuses existing media (idempotent)
- Declares images directly in Markdown
State tracking
- PostgreSQL‑backed state tracking:
- Which platform a post was published to
- Platform‑specific post IDs
- Content hashes
- Publication timestamps
- Automatic detection of content changes
Safe updates
- Content hash comparison
- Automatic post updates when Markdown changes
- No duplicate publishing
- No manual DB editing required
The workflow
- Write or edit a Markdown file
- Commit and push to Git
- Jenkins pipeline runs
The publisher:
- Parses frontmatter
- Computes content hash
- Checks platform state in PostgreSQL
- Uploads featured image if needed
- Creates or updates the WordPress post
- Updates state in the database
The pipeline finishes — safely and repeatably.
Flow diagram

Why this architecture works
Git is truth
All content and intent live in Git. No hidden state, no UI‑only changes.
Database is state
The database tracks what happened, not what should happen. This makes updates and corrections safe.
CI is stateless
Jenkins doesn’t store anything between runs, making the system portable and container‑friendly.
Platform abstraction
WordPress is just one publisher. Adding Dev.to, Substack, Patreon, or other targets requires no core changes.
Where this is heading
The pipeline already behaves like a backend service. Natural next steps:
- Add more publishing targets (Dev.to, Substack, etc.)
- Introduce analytics and engagement tracking
- Package the publisher as a container
- Run it inside Kubernetes
- Add a simple UI on top
Offer it as Publishing as a Service: one repo, one workflow, one source of truth — for years of content.
Final thoughts
What started as “I just want to publish more easily” turned into a fully automated publishing platform with:
- Git‑based content management
- CI‑driven execution
- Database‑backed state
- Idempotent, update‑safe publishing
The best part? Writing content is now the only manual step left. Everything else is automation.