* feat(blog): add Ralph autonomous agent loop tutorial for solopreneurs Add comprehensive tutorial on using Ralph, an autonomous AI agent loop with 7.9k GitHub stars, to build MVPs automatically. Includes real case study (SaaS dashboard in 24 hours), OPC Skills integration, step-by-step setup guide, and 10 GEO-optimized FAQ questions. * feat(scripts): add blog validation and creation tools Add comprehensive blog post management tools: - create-blog.py: Validate, check, and create blog posts - BLOG_GUIDELINES.md: Complete documentation for blog best practices Features: - Validate blog.json structure and required fields - Check markdown content quality (word count, headings, links) - Detect missing SEO/GEO optimization (keywords, FAQs, citations) - Create new blog post templates interactively * feat(workflows): add fast-track blog publishing with auto-merge Add automated blog publishing workflow to reduce time-to-live from 2+ days to 6 minutes: New workflow: - PR directly to main with 'blog-post' label - Auto-validates blog.json and markdown - Auto-approves and auto-merges if validation passes - Deploys to Cloudflare Workers automatically Documentation: - BLOG_PUBLISHING.md: Complete guide with 5 different publishing strategies - Comparison of workflows (Git Flow vs Fast-Track) - Implementation checklist and usage examples This allows blog posts to bypass develop branch while maintaining quality through automated validation.
10 KiB
Blog Publishing Best Practices
This document outlines optimized workflows for publishing blog posts quickly without sacrificing quality.
The Problem
Current workflow (too slow for blog posts):
feature/blog/post → PR to develop → merge → PR to main → merge → deploy
↓ review ↓ ↓ review ↓ ↓
1 day instant 1 day instant 5 min
Total time: 2+ days for a blog post to go live
Desired workflow (fast-track for content):
feature/blog/post → PR to main → auto-merge → deploy
↓ validation ↓ ↓
30 sec instant 5 min
Total time: 6 minutes from PR creation to live
Recommended Solutions
Option 1: Fast-Track Blog Posts with Auto-Merge (RECOMMENDED)
How it works:
- Create PR directly to
main(skipdevelop) - Add
blog-postlabel - GitHub Action validates blog.json and markdown
- If validation passes, auto-approves and auto-merges
- Cloudflare Workers deploys automatically
Setup:
Already created: .github/workflows/publish-blog.yml
Usage:
# Create blog post
git checkout -b feature/blog/my-post
# ... edit files ...
git add website/blog/
git commit -m "feat(blog): add my awesome post"
git push -u origin feature/blog/my-post
# Create PR to main (not develop!)
gh pr create --base main --label blog-post --title "feat(blog): add my awesome post"
# Auto-merge happens in ~1 minute
# Live in ~6 minutes total
Pros: ✅ Fast (6 minutes to live) ✅ Still validated automatically ✅ No manual review needed for content ✅ Works with existing infrastructure
Cons: ❌ Bypasses develop branch (Git Flow purists won't like it) ❌ Requires GitHub Actions secrets for auto-merge
Option 2: Scheduled Publishing
How it works:
- Create PR to
mainwith blog post - Add
publish-date: 2026-01-28label - GitHub Action waits until that date, then auto-merges
Setup:
Create .github/workflows/scheduled-publish.yml:
name: Scheduled Blog Publishing
on:
schedule:
- cron: '0 */6 * * *' # Every 6 hours
workflow_dispatch: # Manual trigger
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
- name: Get current date
id: date
run: echo "today=$(date +%Y-%m-%d)" >> $GITHUB_OUTPUT
- name: Find scheduled PRs
id: prs
uses: actions/github-script@v7
with:
script: |
const today = '${{ steps.date.outputs.today }}';
const prs = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
base: 'main'
});
const scheduled = prs.data.filter(pr => {
const publishLabel = pr.labels.find(l => l.name.startsWith('publish-date:'));
if (!publishLabel) return false;
const publishDate = publishLabel.name.split(':')[1].trim();
return publishDate <= today;
});
return scheduled.map(pr => pr.number);
- name: Auto-merge scheduled PRs
if: steps.prs.outputs.result != '[]'
uses: pascalgn/automerge-action@v0.15.6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Usage:
# Create blog post
git checkout -b feature/blog/my-post
# ... edit files ...
git commit -m "feat(blog): add my awesome post"
git push
# Schedule for future publication
gh pr create --base main --label "publish-date: 2026-01-30" \
--title "feat(blog): add my awesome post"
# Auto-publishes on Jan 30, 2026
Pros: ✅ Schedule posts in advance ✅ Great for content calendar ✅ Still automated validation
Cons: ❌ More complex setup ❌ Requires cron job monitoring
Option 3: Separate Blog Branch (Hot Deploy)
How it works:
- Maintain a
blogbranch that auto-deploys - Blog posts PR directly to
blog blogbranch continuously deploys- Periodically sync
blog→main
Setup:
Update .github/workflows/deploy-website.yml:
name: Deploy Website
on:
push:
branches: [main, blog] # Add blog branch
paths:
- 'website/**'
- 'skills.json'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate blog (if blog branch)
if: github.ref == 'refs/heads/blog'
run: python3 scripts/create-blog.py validate
- name: Deploy to Cloudflare Workers
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
workingDirectory: website
Usage:
# Create blog post
git checkout blog
git pull origin blog
git checkout -b feature/blog/my-post
# ... edit files ...
git commit -m "feat(blog): add my awesome post"
git push -u origin feature/blog/my-post
# PR to blog branch
gh pr create --base blog --title "feat(blog): add my awesome post"
# Merge and it deploys immediately
# Periodically: merge blog → main for history
Pros: ✅ Clean separation of blog vs code ✅ Very fast deployment ✅ Blog branch is always production-ready
Cons: ❌ Requires maintaining two branches ❌ Can diverge from main if not synced regularly
Option 4: Headless CMS (Most User-Friendly)
How it works:
- Use a headless CMS (Sanity, Contentful, TinaCMS)
- Non-technical users edit in UI
- CMS auto-commits to git
- Webhook triggers deployment
Popular Options:
| CMS | Complexity | Cost | Best For |
|---|---|---|---|
| TinaCMS | Low | Free | Markdown + Git workflow |
| Sanity | Medium | Free tier | Structured content |
| Contentful | Medium | Free tier | Team collaboration |
| Netlify CMS | Low | Free | Simple markdown editing |
Example with TinaCMS:
- Install TinaCMS:
npm install tinacms @tinacms/cli
- Configure
.tina/config.ts:
import { defineConfig } from "tinacms";
export default defineConfig({
branch: "main",
clientId: process.env.TINA_CLIENT_ID,
token: process.env.TINA_TOKEN,
build: {
outputFolder: "admin",
publicFolder: "website",
},
schema: {
collections: [
{
name: "blog",
label: "Blog Posts",
path: "website/blog/posts",
fields: [
{ type: "string", name: "title", label: "Title", required: true },
{ type: "rich-text", name: "body", label: "Body", isBody: true },
{ type: "datetime", name: "date", label: "Date" },
],
},
],
},
});
- Access UI at
/adminto edit blog posts
Pros: ✅ Non-technical users can publish ✅ Visual editing experience ✅ Preview before publishing ✅ Still uses git for version control
Cons: ❌ Requires setup and configuration ❌ More moving parts ❌ Some services have usage limits
Option 5: Direct Main Commits (Fastest, Least Safe)
How it works:
- Give trusted authors write access to
main - Push blog posts directly to
main - Skip PR process entirely
Setup:
Create .github/workflows/validate-on-push.yml:
name: Validate Blog on Push
on:
push:
branches: [main]
paths:
- 'website/blog/**'
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate blog
run: |
python3 scripts/create-blog.py validate
if [ $? -ne 0 ]; then
echo "❌ Blog validation failed! Reverting..."
git revert HEAD --no-edit
git push
exit 1
fi
Usage:
# Just push directly
git checkout main
git pull
# ... edit blog post ...
git add website/blog/
git commit -m "feat(blog): add post"
git push origin main
# Live in 5 minutes
Pros: ✅ Fastest possible (5 minutes) ✅ Zero PR overhead ✅ Simple workflow
Cons: ❌ No review process ❌ Easy to break main branch ❌ Not recommended for teams
Recommended Workflow
For OPC Skills, I recommend Option 1 (Fast-Track with Auto-Merge):
Complete Workflow
# 1. Create and write blog post
python3 scripts/create-blog.py new
# ... edit markdown file ...
# ... update blog.json ...
# 2. Validate locally
python3 scripts/create-blog.py validate
python3 scripts/create-blog.py check <slug>
# 3. Create PR directly to main
git checkout -b feature/blog/<slug>
git add website/blog/
git commit -m "feat(blog): add <topic> tutorial"
git push -u origin feature/blog/<slug>
# 4. Create PR with blog-post label
gh pr create --base main --label blog-post \
--title "feat(blog): add <topic> tutorial" \
--body "Auto-publish blog post. Validation will run automatically."
# 5. Wait ~1 minute for auto-merge
# 6. Live in ~6 minutes total!
When to Use Each Option
| Scenario | Best Option |
|---|---|
| Solo developer, need speed | Option 1 (Fast-Track) |
| Team with content calendar | Option 2 (Scheduled) |
| High blog post frequency | Option 3 (Blog Branch) |
| Non-technical authors | Option 4 (Headless CMS) |
| Complete trust, max speed | Option 5 (Direct Push) |
Implementation Checklist
To implement Option 1 (Fast-Track):
- Create
.github/workflows/publish-blog.yml - Enable GitHub Actions in repo settings
- Add required secrets (if using auto-merge action)
- Test with a draft blog post
- Update AGENTS.md with new workflow
- Train team on new process
Comparison: Before vs After
Before (Git Flow)
Day 1, 9am: Create feature branch
Day 1, 10am: Write blog post
Day 1, 11am: PR to develop
Day 1, 2pm: Review & merge to develop
Day 2, 9am: PR develop → main
Day 2, 10am: Review & merge to main
Day 2, 10:05am: Deployed
Total: ~25 hours
After (Fast-Track)
9:00am: Create feature branch
9:30am: Write blog post
10:00am: PR to main with blog-post label
10:01am: Auto-validated & auto-merged
10:06am: Deployed
Total: ~1 hour (6 min automated)
Questions?
- Check workflows:
.github/workflows/ - Review validation:
python3 scripts/create-blog.py validate - Test locally:
python3 scripts/create-blog.py check <slug> - Ask on GitHub: https://github.com/ReScienceLab/opc-skills/issues