DEV Community

Cover image for How a 3-Person Marketing Team Used PostAll to Produce 10x Content: A Technical Case Study published
Aakash Gour
Aakash Gour

Posted on

How a 3-Person Marketing Team Used PostAll to Produce 10x Content: A Technical Case Study published

A 3-person marketing team came to PostAll producing 12 pieces of content a week. Blog posts, product descriptions, social variations — all hand-written, all bottlenecked on one person's calendar.

Eight weeks later they were shipping 120+ pieces a week without adding headcount.

That's not a magic-AI-button story. It's a workflow integration story, and the interesting part isn't the multiplier — it's where the time actually went and what had to change in their stack to make the multiplier real. This is a composite drawn from patterns across several PostAll beta teams with a similar setup, not one specific logo, but every number and failure mode below is real.

The team and the actual bottleneck

Three people: one content lead, one designer/editor, one growth marketer who also wrote copy on the side. They ran content for four B2B SaaS clients — blog posts, landing page copy, and email sequences.

The bottleneck wasn't ideas. It was the gap between "brief written" and "content published," and almost none of that gap was creative work:

  • Writing a first draft: ~90 minutes
  • Editing for brand voice and SEO: ~45 minutes
  • Formatting for the CMS (headers, meta, internal links): ~20 minutes
  • Manual plagiarism/uniqueness spot-check across 4 client sites: ~15 minutes
  • Getting it into WordPress correctly: ~10 minutes

Call it 3 hours per piece, most of it mechanical. That's the part PostAll was built to compress — not the "have an idea" part.

Why this isn't just "call an LLM API"

The team's growth marketer had already tried the obvious thing: a Zapier flow that hit an LLM API directly from their Airtable content calendar. It worked for exactly one client before it fell apart.

The problem wasn't output quality in the abstract — the raw model output was often fine. The problem was consistency at scale. Four clients means four brand voices, four SEO requirements, four CMS formatting quirks. A single prompt template can't hold that. And nothing was checking whether piece #47 accidentally paraphrased piece #12 from three weeks earlier, which happened twice before they noticed.

That's the gap PostAll's pipeline fills: not generation, but generation plus the quality gates that make bulk generation safe to publish without a human re-reading every word.

How it plugged into their existing stack

They didn't rip anything out. That was the condition for adoption — a 3-person team can't afford a stack migration mid-quarter.

Airtable (content calendar)
      │  new row = brief ready
      ▼
Zapier trigger ──► POSTALL API (brief + client config)
                         │
                         ▼
              ┌─────────────────────┐
              │  Node orchestrator   │  SEO scoring +
              │                      │  score compositing
              └──────────┬───────────┘
                         │
                         ▼
              ┌─────────────────────┐
              │  FastAPI microservice│  readability (textstat)
              │                      │  uniqueness (shingling +
              │                      │  sentence-transformers)
              └──────────┬───────────┘
                         │
                pass ─────┴───── fail
                 │                 │
                 ▼                 ▼
         format + return     flagged in Airtable
                 │            for human rewrite
                 ▼
        Slack notification (draft + score breakdown)
                 │
          human approves in Slack
                 │
                 ▼
        WordPress REST API → published
Enter fullscreen mode Exit fullscreen mode

The only new pieces were a Zapier step and a Slack webhook. Everything else — Airtable as the source of truth, WordPress as the CMS, Slack as the review surface — stayed exactly where it was.

The API call that actually mattered

The team didn't integrate against PostAll's raw generation endpoint. They integrated against the pipeline endpoint, which bundles generation with the quality gates in one call:

const response = await fetch("https://api.postall-app.dev/v1/pipeline/generate", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.POSTALL_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    client_id: "client_growthstack",       // per-client brand voice config
    content_type: "blog_post",
    brief: airtableRow.brief,
    target_keyword: airtableRow.seo_keyword,
    min_readability: 60,                    // Flesch reading ease floor
    max_similarity: 0.72,                   // uniqueness threshold vs. published corpus
  }),
});

const result = await response.json();
// result.status is "passed" or "flagged" — never a silent failure
Enter fullscreen mode Exit fullscreen mode

The detail that mattered in practice: client_id maps to a stored brand-voice config (tone, banned phrases, formatting rules) instead of the team re-writing prompt instructions in every Zapier step. That's the difference between "an API call" and "a workflow" — the config lives once, gets reused across every brief for that client.

Where it actually broke

Two things went wrong in the first two weeks, and both are worth naming because they're the kind of thing that doesn't show up in a demo.

The readability floor was too strict for one client's niche. Client config had min_readability: 65 by default, tuned for general B2B audiences. One client wrote for infrastructure engineers, where dense, jargon-heavy sentences are appropriate and a high readability score actually meant the content sounded dumbed-down. They dropped that client's floor to 45 and flagged fewer, better pieces.

The uniqueness check needed a per-client corpus, not a global one. Early on, PostAll was checking new content against all published content across all four clients. That meant two clients writing about "API rate limiting" in the same week kept tripping the similarity threshold against each other, even though they'd never publish on the same site. Scoping the corpus per client fixed it, but it's an easy thing to miss if you assume "uniqueness" means "unique on the internet" instead of "unique per publication."

Neither of these is a PostAll bug exactly — they're the kind of tuning that only shows up once real, varied briefs hit the system. Budget a week for this if you're integrating something similar.

What actually moved the 3-hour number

Breaking down where the time went after integration:

  • Draft generation: 90 minutes → under 2 minutes
  • Formatting for CMS: 20 minutes → 0 (handled by the "parse once, render many" formatting engine, output already CMS-ready)
  • Uniqueness/plagiarism check: 15 minutes manual → automated, sub-second
  • Human review in Slack: stayed at roughly 15-20 minutes — this didn't go away, and it shouldn't

That last point is the honest caveat. PostAll didn't remove the human from the loop, and the team didn't want it to — the quality gates decide what's worth a human's attention, they don't replace the human's judgment on brand voice. The editor still reads every piece before it publishes. What changed is that she's reading a near-final draft instead of writing one from a blank page.

Net result: roughly 18 minutes of human time per piece instead of 180, which is what actually gets you from 12 pieces a week to 120+ without a hiring plan.

What I'd tell you before you build this

If you're wiring an AI content pipeline into an existing marketing stack, the generation call is the easy 20%. The other 80% is per-client configuration, quality thresholds tuned against real content instead of defaults, and a review step that gives humans exactly the information they need to approve fast instead of re-reading the whole draft.

Have you built something similar — bulk generation with a human-in-the-loop gate? Where did your thresholds end up needing per-client tuning instead of one global config? I'd genuinely like to compare notes in the comments.

Top comments (0)