Adding WordPress to a Multi-Platform Publishing System
When you’re building a system that publishes to multiple platforms, each new integration reveals something about your architecture. WordPress was the fourth platform I added to our auto-publishing API, and it exposed a design decision I’d made earlier that was both helping and limiting me.
The Pattern That Emerged
Looking at the existing publishers – Twitter, Dev.to, and LinkedIn – they all followed the same interface:
interface IPublisher {
supports(platform: Platform): boolean;
publish(request: PublishRequest): Promise;
}The registry pattern made adding WordPress straightforward: implement the interface, register the service, add it to the supported platforms list. Four files changed, mostly boilerplate.
But here’s what got interesting: the prompt builder.
The Prompt Builder Problem
Originally, I had platform-specific prompts embedded directly in the prompt builder – detailed guidelines for each platform’s voice and format. Twitter had examples of “good dev tweets.” LinkedIn had strict rules about what not to say. It worked, but it was getting unwieldy.
The old approach looked like this:
[Platform.TWITTER]: {
maxLength: 280,
format: 'A single tweet',
guidelines:
Under 280 characters. No emojis. No hashtags unless essential (max 1).
Write like these real dev tweets:
* "finally mass assigned where I didn't mean to"
* "the bug was in the config. it's always in the config"
...
Notice: short, lowercase ok, no "lesson learned", no wisdom...
,
}This was 120+ lines of platform rules. Adding WordPress would’ve meant another 40-50 lines of guidelines.
The Refactor
Instead of adding more guidelines, I simplified the entire prompt system:
private readonly platformConstraints: Record = {
[Platform.WORDPRESS]: {
maxLength: 10000,
formatNote: 'Blog post. Start with # Title. Use ## for sections. Include code blocks where relevant.',
voice: Blog voice: Teach through story. Explain the problem, your approach, what worked and didn't. Include code where helpful. Write for someone who might face the same problem.,
},
// ... other platforms
}Went from 451 lines to 48 in the prompt builder. The detailed examples and rules? Moved them to the system prompt that gets sent to the LLM once, not repeated for every platform config.
What Actually Changed
The WordPress publisher itself is straightforward – authenticate with WordPress REST API, convert markdown to HTML, handle the various HTTP error cases. The interesting part was that adding it forced me to see that the prompt builder had become a dumping ground for instructions that belonged elsewhere.
Sometimes you don’t see the mess until you’re about to add to it.
The markdown-to-HTML conversion is basic for now:
private markdownToHtml(markdown: string): string {
let html = markdown;
// Remove title line if it starts with #
const lines = html.split('\n');
if (lines[0].startsWith('# ')) {
html = lines.slice(1).join('\n');
}
// Headers
html = html.replace(/^### (.*$)/gim, '$1');
html = html.replace(/^## (.*$)/gim, '$1');
// Code blocks
html = html.replace(/(\w+)?\n([\s\S]*?)“/g,
'
$2');
// Paragraphs
html = html.split('\n\n')
.map(para =>
${para.trim()}
)
.join('\n');
return html;
}
“
This’ll need a proper markdown parser eventually, but it works for the generated content format we’re producing.
The Tradeoff
The refactor made the code cleaner but shifted complexity. Now the LLM gets more context up front in the system prompt instead of having it repeated in every platform config. That’s probably better – but it means the quality of the output depends more on prompt engineering in one place rather than being distributed across platform configs.
Not sure yet if that’s the right call, but adding WordPress made it clear the old approach wasn’t scaling.

Aniefon Umanah
Full Stack Engineer with 7+ years of experience. I write about software development, architecture patterns, and lessons learned from building real-world applications.