You know the producer-consumer problem from computer science, right? One process creates stuff, another process consumes it, and if they're not synchronized, chaos ensues.
Turns out, content creation has the exact same problem.
The Problem: Bursty Writers, Consistent Readers
Here's how blog writing actually works:
Producer (Me):
Monday: Write 4 posts in a caffeine-fueled frenzy
Tuesday-Sunday: *crickets*
Next Monday: Panic, write 3 more posts
Consumer (Readers & SEO):
Expectation: Consistent 3x/week publishing
Reality: 4 posts on Monday, nothing for 2 weeks, then 7 posts on a random Tuesday
Google hates inconsistency. Readers forget you exist. Your newsletter goes from "weekly insights" to "occasional ramblings from someone who may or may not still be alive."
Classic producer-consumer mismatch.
The Traditional Solutions (That Don't Work)
1. "Just Be Consistent"
Ah yes, the "just don't have ADHD" approach. Revolutionary.
The problem isn't motivation—it's that creative energy comes in bursts. Some days you write 3,000 words before breakfast. Other days, you stare at a blank screen and contemplate becoming a goat farmer.
2. Use a CMS with Scheduling
WordPress, Ghost, and others have scheduling. But they require:
- Manual date picking for each post
- Remembering what you've already scheduled
- A calendar that doesn't sync with your actual life
- Discipline (see point #1)
3. Hire a Content Manager
laughs in solo developer budget
Our Solution: Stock-Based Scheduling
We built a simple system with one core idea: treat blog posts like inventory.
The Stock File
{
"_articleStockWouldLastUpto": "2026-02-26",
"getting-started-with-jo4": "2026-01-31",
"api-first-url-shortener": "2026-02-03",
"claude-code-hooks": "2026-02-05",
"elasticache-vs-memorydb": "2026-02-07"
}
Each post gets a publishAfter date in its frontmatter. The stock.json file tracks everything:
- What's scheduled
- When each post goes live
- When you'll run out of content
That last field—_articleStockWouldLastUpto—is the magic. It's your inventory level.
The Workflow
When I write (producer):
- Create post with content
- Set
publishAfterto the next available slot - Update
stock.jsonwith the new entry - Update
_articleStockWouldLastUptoif this is the latest
When GitHub Actions runs (consumer):
- Check which posts have
publishAfter <= today - Build and publish those posts
- Crosspost to dev.to
- Check stock levels
The Low Stock Warning
Here's the clever bit. Every day at 1 AM UTC, our CI pipeline checks:
STOCK_DATE=$(jq -r '._articleStockWouldLastUpto' stock.json)
DAYS_LEFT=$(( (STOCK_EPOCH - TODAY_EPOCH) / 86400 ))
if [ "$DAYS_LEFT" -lt 3 ]; then
echo "LOW STOCK! Only $DAYS_LEFT days remaining!"
# Send Slack notification
fi
If I have less than 3 days of content queued up, I get a Slack message:
⚠️ LOW ARTICLE STOCK! Only 2 days of scheduled articles remaining. Time to write more blog posts!
It's like a grocery store inventory system, but for words.
Why This Works
1. Decouples Writing from Publishing
I can write 5 posts on a Sunday afternoon and not worry about when they'll go live. The system handles the "when," I handle the "what."
2. Visualizes the Buffer
Seeing _articleStockWouldLastUpto: "2026-02-26" is motivating. It's concrete. "I have 25 days of content" is way more actionable than "I should probably write more."
3. Prevents Feast-or-Famine
The warning system catches problems before they become crises. No more "oh no, I haven't posted in 3 weeks" panic.
4. Works with Bursts
Write 10 posts in a weekend? Great, you just bought yourself a month. The system doesn't care when you write, just that you eventually do.
The Implementation
Post Frontmatter
---
title: "My Post Title"
description: "SEO-friendly description"
blogPath: my-post-slug
publishAfter: "2026-03-02"
author: Jo4 Team
tags:
- tag1
- tag2
- tag3
- tag4
---
The publishAfter field is the key. Posts with future dates exist in the repo but aren't built into the public site.
Build Logic
// In 11ty config
eleventyConfig.addCollection("posts", function(collection) {
const today = new Date().toISOString().split('T')[0];
return collection
.getFilteredByGlob("posts/**/index.md")
.filter(post => post.data.publishAfter <= today)
.sort((a, b) => b.data.publishAfter.localeCompare(a.data.publishAfter));
});
Future posts are filtered out at build time. Simple.
GitHub Actions Cron
schedule:
- cron: "0 1 * * *" # Daily at 1 AM UTC
The pipeline runs daily, checks for newly-eligible posts, builds, deploys, and crossposts.
The Meta Irony
Yes, I'm writing a blog post about automating blog posts.
Yes, this post will be scheduled using the system I'm describing.
Yes, I wrote this during a burst of productivity and it's scheduled 3 weeks out.
The system works.
Lessons Learned
- Treat creative work like inventory - Buffers smooth out inconsistency
- Automate the boring parts - Date calculation, crossposting, warnings
- Make the invisible visible -
_articleStockWouldLastUptoturns abstract anxiety into concrete numbers - Design for how you actually work - Bursts are fine if the system handles them
Try It Yourself
The full system is:
- 11ty for static site generation
- GitHub Actions for scheduling and deployment
- A simple JSON file for inventory tracking
- Slack webhook for low-stock alerts
Total lines of custom code: ~50.
Sometimes the best solutions aren't frameworks or SaaS products. Sometimes it's just a JSON file and a cron job.
How do you handle content scheduling? Built your own system, or using something off-the-shelf?
Building jo4.io - URL shortener with analytics. Yes, we practice what we preach with consistent publishing.