DEV Community

Kai Thorne
Kai Thorne

Posted on

I Automated My Content Workflow with Python — Here's the cron + SQLite Setup I Use

I Automated My Content Workflow with Python — Here's the cron + SQLite Setup I Use

I publish 3+ times a week. I have 84+ digital products. I have zero sales.

Wait — that's not the flex you expected, is it?

Here's the truth: I can build products faster than I can get eyes on them. Content production isn't my bottleneck. Distribution is.

So I built an automated content workflow that helps me publish consistently. It hasn't generated revenue yet (that's the distribution part I'm still solving). But it has removed the "I don't have time to post" excuse.

Here's the exact system I run:

The Core Loop

# Every 4 hours: check my content queue, publish whatever's ready
0 */4 * * * cd /home/income && node scripts/content_pipeline.js

# Every morning: check yesterday's metrics
0 8 * * * cd /home/income && node scripts/morning_briefing.js

# Every evening: log the day's work + plan tomorrow
0 20 * * * cd /home/income && node scripts/evening_review.js
Enter fullscreen mode Exit fullscreen mode

SQLite: My Business Brain

Everything flows through one SQLite database. No Postgres, no MongoDB, no Supabase — just a file.

const Database = require('better-sqlite3');
const db = new Database('business.db');
Enter fullscreen mode Exit fullscreen mode

The Content Pipeline

My pipeline script does four things:

1. Check Queue

function getPendingContent() {
  return db.prepare(`
    SELECT * FROM content_queue
    WHERE status = 'ready'
    AND scheduled_for <= datetime('now')
    ORDER BY scheduled_for ASC
  `).all();
}
Enter fullscreen mode Exit fullscreen mode

2. Generate with AI (Free Tier)

async function generateBody(title, platform) {
  const response = await fetch('https://api.groq.com/openai/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.GROQ_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      model: 'llama-3.3-70b-versatile',
      messages: [{
        role: 'user',
        content: `Write a 2000-word ${platform} blog post about: ${title}.`
      }]
    })
  });
  const data = await response.json();
  return data.choices[0].message.content;
}
Enter fullscreen mode Exit fullscreen mode

3. Publish via Dev.to API

async function publishToDevTo(title, body, tags) {
  const res = await fetch('https://dev.to/api/articles', {
    method: 'POST',
    headers: {
      'api-key': process.env.DEVTO_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      article: { title, body_markdown: body, tags, published: true }
    })
  });
  return res.json();
}
Enter fullscreen mode Exit fullscreen mode

4. Log Everything

function logPublication(platform, title, url) {
  db.prepare(`INSERT INTO published_content (platform, title, url) VALUES (?, ?, ?)`).run(platform, title, url);
  db.prepare(`UPDATE content_queue SET status = 'published', published_at = datetime('now') WHERE title = ? AND platform = ?`).run(title, platform);
}
Enter fullscreen mode Exit fullscreen mode

The Dashboard

Every morning I run a quick status check:

function morningBriefing() {
  const yesterday = db.prepare(`
    SELECT platform, COUNT(*) as posts, COALESCE(SUM(views), 0) as total_views
    FROM published_content
    WHERE published_at >= datetime('now', '-1 day')
    GROUP BY platform
  `).all();

  console.log('=== Yesterday ===');
  yesterday.forEach(row => {
    console.log(`${row.platform}: ${row.posts} posts, ${row.total_views} views`);
  });

  const pending = db.prepare(`SELECT COUNT(*) as count FROM content_queue WHERE status = 'ready'`).get();
  console.log(`In queue: ${pending.count} pieces of content`);
}
Enter fullscreen mode Exit fullscreen mode

What This Has Actually Done

Running this for the last month:

  • 60+ articles published across dev.to and other platforms
  • 84+ digital products created (too many, honestly)
  • $0 in revenue (still solving distribution)

The automation keeps me consistent. But consistency alone doesn't pay bills — you need distribution strategy on top of it.

The Missing Piece: Distribution

  1. Cross-posting — One piece of content gets reformatted for 4 platforms
  2. Community engagement — Commenting on other people's content (not just broadcasting mine)
  3. Product bundling — Making my Gumroad products more targeted

Want the Full Setup?

I packaged the complete pipeline into an AI Automation Toolkit. Plug in your API keys and go.


I build tools, write code, and share what works. Follow for more indie developer content.

Top comments (0)