How To Workflow! Automated AI Blog Content Publishing
*Click Publish* - Our One and Final Step for Weekly Blog Posts
If you've ever stared at a blank CMS draft wondering how you're going to maintain a consistent publishing cadence while also running everything else, this workflow is worth understanding in detail!
At Speak About AI, our blog publishing pipeline is fully automated, leaving you with just one final step: PUBLISH.
It's truly that easy:
- Automated brief prompts --> Automated content --> Automated connector --> Automated publish scheduling
We're just left with reviewing the post and confirming the Publish Date.
It's Magic.
Below is exactly how it works, step by step.
The Foundation: Google Sheets as a Content Database
Most content teams already live in spreadsheets. The insight here is treating Google Sheets not as a planning tool but as a structured data source — essentially a lightweight CMS backend that feeds a publishing pipeline.
Understanding the Contentful Content Model First
Before any automation, you need to map your Contentful content type fields to the data you're generating. Our blog post content type has fields like:
- Title — the working headline
- Brief — a short paragraph describing the angle, key points, and any specific instructions for tone or examples
- Status — a field that tracks where each post is in the pipeline (e.g., `pending`, `in_progress`, `sent_to_contentful`, `published`)
- Slug — the intended URL slug for the post
- Category/Tags — content classification fields that map directly to Contentful taxonomy
- Target length — word count guidance passed to Claude
- Contentful Entry ID — populated automatically once the entry is created, so you can trace back from the sheet to the CMS
Each of these maps to a column in the sheet or gets derived from the Claude output. The slug comes directly from the sheet. The body is the markdown Claude generated. Tags and category come from the sheet columns.
The Brief Prompt: Automated Roux
Using Anthropic's APIs, each month's briefs are generated based on our initial prompting:
- Use Claude to brainstorm fresh AI-related blog brief prompts that will be used to write detailed, up to date, content.
(There's more to our actual prompt, but you get the idea)
The prompt is assembled programmatically, so every post gets the same baseline instructions plus the unique brief for that specific article. This consistency is what makes the output reliable enough to go straight to a draft stage without heavy editing.
The generated brief gets automatically filled into the Google Sheet, where we can either edit or keep.
But why just create a brief and not the entire blog right away?
There are a couple of reasons this was a choice.
- We get to intervene on the prompt before the content is fully created.
- We get to test Claude's prompting capabilities over our own prompting.
This becomes a way to wedge human intervention into the process AND monitor the efficacy of Claude's modal.
Why Sheets Works Better Than a Fancy Tool Here
You could use Airtable, Notion, or a dedicated editorial calendar tool. But Sheets has one practical advantage: it's trivially easy to read with scripts and APIs. Google Apps Script, Python with the Sheets API, or tools like Make (formerly Integromat) and Zapier can all query a spreadsheet with minimal setup. There's no authentication complexity beyond OAuth, and the data structure is flat and predictable. For a pipeline that needs to run reliably and be debuggable by a non-engineer, that simplicity matters.
Pulling the Data and Constructing from the Prompt
Once a row is marked as `pending`, the automation kicks off. The script — in our case a Python script triggered on a schedule — reads all rows with `pending` status and processes them one at a time.
RE: Claude API Call - Phase 2
The script sends the constructed brief prompt back to Claude via Anthropic's API. We use the Messages API with a system prompt that establishes the persistent context: the voice, the audience, the site's purpose.
A few configuration choices that matter here:
Model selection affects output quality and cost. For long-form content, using a capable model like Claude 3.5 Sonnet hits the right balance between quality and cost per post. Running the cheaper, faster models on long-form content often produces noticeably flatter writing.
Max tokens needs to be set high enough to accommodate the full post. A 1500-word article in markdown with headers runs roughly 2000-2500 tokens of output. Setting max tokens too low truncates the post mid-sentence, which creates a silent failure that's annoying to debug.
Temperature — we run this at a moderate setting. Too low and the writing becomes robotic and repetitive across posts. Too high and it starts hallucinating specific examples or going off-brief.
The API returns the full markdown body of the post. The script captures this and moves to the next stage.
Putting it all together: Sending to Contentful
Contentful is a headless CMS with a well-documented Content Management API. Creating a draft entry programmatically is straightforward once you understand the content model.
*NERD TALK WARNING* The API Call to Create the Entry
Using the Contentful Management API, the script makes a POST request to create a new entry. The request includes:
- The space ID and environment (usually `master`)
- The content type ID
- The field values, structured as a locale-keyed object (Contentful requires every field value to specify a locale, e.g., `"en-US"`)
- A `Content-Type` header of `application/vnd.contentful.management.v1+json`
The entry is created in draft state by default — it won't go live until someone explicitly publishes it in the Contentful web app or via a separate publish API call. This is intentional. The automation handles creation; a human handles the final review and publish decision.
Once the entry is created, Contentful returns the new entry's ID. The script writes this back to the Google Sheet in the `Contentful Entry ID` column and updates the `Status` field to `sent_to_contentful`. Now you have a direct link between your editorial planning sheet and your CMS.
Handling Rich Text vs. Markdown
One thing that trips people up: Contentful's native rich text field type is not markdown. It uses a proprietary JSON structure called Contentful Rich Text. If your content type uses a rich text field, you can't just dump markdown into it — you'll get an error or malformed content.
There are two solutions. The simpler one is to use a plain long text field set to markdown, and handle the markdown-to-HTML conversion on the frontend. The more complex option is to convert the markdown to Contentful Rich Text JSON before sending it, using a library like `@contentful/rich-text-types` combined with a markdown parser. For most setups, the plain text + markdown approach is easier to maintain and debug.
*OK, NERD Talk Done* - The Human Checkpoint
It's worth being explicit about what this pipeline does and doesn't automate. It automates the creation of a structured draft — it does not automate publishing.
Every post lands in Contentful as a draft. A human then opens it, reads through it, makes any edits, adds a featured image, adjusts the SEO fields if needed, and hits publish.
Right now, I'm actually reviewing, editing, and providing the sprinkled human elements in this very post!
The automation saves the 45-60 minutes it would take to write the post from scratch and the 10-15 minutes of manually setting up the CMS entry. It doesn't eliminate editorial judgment.
In practice, the review step for a well-briefed post takes about 10-15 minutes. You're checking for accuracy, making sure the examples land correctly, tightening any loose paragraphs, and doing a final read for voice consistency. That's a reasonable division of labor between automation and human oversight.
Debugging and Maintaining the Pipeline
Any automation that touches multiple external services will break eventually. The failure points in this pipeline are predictable:
Google Sheets API — usually authentication token expiry. Set up a service account with a long-lived credential rather than relying on user OAuth tokens that expire.
Claude API — rate limits if you're processing many posts at once, or occasional timeouts on long generations. Build in retry logic with exponential backoff. Also log the raw API response before trying to parse it — if the generation fails silently, you want to know what came back.
Contentful API — field validation errors are the most common issue. If a field expects a reference to a Category entry and you pass a string, it rejects the whole entry creation. Test your field mappings carefully against the content model before running at scale.
Status field hygiene — if a row gets stuck in `in_progress` due to a crash, it won't get reprocessed. Build a timeout check: any row that's been `in_progress` for more than an hour gets reset to `pending` so it can retry.
Scaling and Adapting the Pattern
Once the core pipeline is working, it's extensible in useful ways. You can add a step that generates the SEO meta description from the post body using a second, shorter Claude call. You can add a Slack notification when a new draft lands in Contentful so the editorial team knows to review it. You can add a column for "featured image prompt" and route that to an image generation API before the Contentful entry is created.
The underlying pattern — structured data in Sheets, AI generation via API, programmatic CMS entry creation — applies beyond blog posts. Product descriptions, speaker bios, event summaries, email drafts. Any content type with a consistent structure and variable inputs is a candidate for this kind of workflow.
The point isn't to remove humans from content creation. It's to remove humans from the repetitive scaffolding work so they can focus on the judgment calls that actually require them.
