100 Artikel Sebulan, $15 Modal — Lo Bisa Gak Pake Karyawan

Lo punya blog. Lo pengen 100 artikel per bulan biar traffic naik.

Copywriter: Rp 100rb-300rb per artikel × 100 artikel = Rp 10-30 juta/bulan. Gak realistis.

AI kayak ChatGPT: $20/bulan plus ribet — kena rate limit, output pendek, nolak nulis soal niche tertentu.

Solusi: Pipeline otomatis. Scrape → rewrite pake AI lokal → post ke Hugo. Satu script Python, jalan dari cron, gak perlu disentuh.

Biaya: $15/bulan buat VPS. Hasil: 100 artikel siap index Google tiap bulan.

⚠️ Disclamer: Scraping konten orang lain lalu republish mentah-mentah itu plagiarisme. Pipeline ini buat rewrite total — struktur beda, kata beda, nilai tambah beda. Fungsinya kayak research assistant yang baca 10 artikel terus nulis artikel baru pake referensi gabungan. Pake buat riset, curation, dan content aggregation — bukan stealing.


Cara Kerja Pipeline (Diagram)

flowchart LR
    A[Sumber: RSS Feed / Website] -->|Scrape tiap 6 jam| B[Raw Artikel]
    B --> C[AI Lokal di VPS]
    C -->|Rewrite: struktur & kata beda| D[Artikel Baru]
    D -->|Generate frontmatter| E[Markdown .md]
    E -->|git commit + push| F[Git Repo]
    F -->|Deploy hook| G[Hugo Build]
    G --> H[Live di Blog]
    
    I[Cron: tiap 6 jam] --> A

Step 1: Scrape Konten dari Sumber

Feed Reader (RSS/Atom)

Pertama, pull artikel dari RSS feed sumber.

import feedparser
import json
from datetime import datetime

def fetch_feeds(feed_urls, max_per_feed=5):
    """Pull latest articles from RSS feeds."""
    articles = []
    
    for url in feed_urls:
        feed = feedparser.parse(url)
        print(f"Feed: {feed.feed.get('title', url)} — {len(feed.entries)} entries")
        
        for entry in feed.entries[:max_per_feed]:
            article = {
                "source_title": feed.feed.get("title", "Unknown"),
                "title": entry.get("title", ""),
                "url": entry.get("link", ""),
                "summary": entry.get("summary", ""),
                "published": entry.get("published", datetime.now().isoformat()),
                "content": entry.get("content", [{"value": ""}])[0]["value"] if entry.get("content") else entry.get("summary", "")
            }
            articles.append(article)
    
    return articles

# Sumber feeds — sesuaikan sama niche lo
FEEDS = [
    "https://news.ycombinator.com/rss",
    "https://techcrunch.com/feed/",
    "https://www.reddit.com/r/startups/.rss",
    # Tambahin 10-20 feed niche lo di sini
]

articles = fetch_feeds(FEEDS)
print(f"Total: {len(articles)} artikel dari feed")

Web Scraper (Kalo Feed Gak Ada)

import requests
from bs4 import BeautifulSoup
from readability import Document
import html2text

def scrape_article(url):
    """Scrape article content from URL using readability."""
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
    }
    
    resp = requests.get(url, headers=headers, timeout=30)
    resp.raise_for_status()
    
    # Extract main content with readability
    doc = Document(resp.text)
    content_html = doc.summary()
    title = doc.title()
    
    # Convert HTML to markdown
    converter = html2text.HTML2Text()
    converter.ignore_links = False
    converter.ignore_images = True
    content_md = converter.handle(content_html)
    
    return {
        "title": title,
        "content": content_md,
        "url": url
    }

# Test scrape satu artikel
print(scrape_article("https://example.com/some-article"))

Install dependencies:

pip install feedparser beautifulsoup4 readability-lxml html2text requests

Step 2: Kirim ke AI Lokal buat Rewrite

Ini inti pipeline. Kita kirim artikel mentah ke model abliterated yang jalan di VPS dan minta rewrite total.

import requests
import re

def rewrite_article(local_model_url, article):
    """Rewrite article using local abliterated model.
    
    Args:
        local_model_url: http://localhost:11434/api/generate
        article: dict with title, content, source_title
    
    Returns:
        dict with new_title, new_content
    """
    prompt = f"""Rewrite this article completely. Rules:

1. STRUCTURE must be different — don't follow original paragraph order
2. All sentences must be rewritten — no sentence copied verbatim
3. Add new insights, examples, or angles (at least 30% new content)
4. Keep factual information accurate
5. Target: Indonesian entrepreneurs / tech enthusiasts
6. Tone: practical, direct, no fluff
7. Length: 800-1500 words
8. Format: markdown with subheadings (## and ###)

Original Source: {article['source_title']}
Original Title: {article['title']}

Original Content:
{article['content'][:4000]}  # Limit to 4000 chars

---

Now produce the rewritten article in Indonesian. Start with a new title on the first line.
"""
    
    resp = requests.post(local_model_url, json={
        "model": "noushermes2:7b",
        "prompt": prompt,
        "stream": False,
        "options": {
            "temperature": 0.8,
            "num_predict": 4096
        }
    }, timeout=180)
    
    result = resp.json()["response"]
    
    # Extract title (first line) and content
    lines = result.strip().split("\n", 1)
    new_title = lines[0].replace("# ", "").strip()
    new_content = lines[1] if len(lines) > 1 else result
    
    return {
        "new_title": new_title,
        "new_content": new_content
    }

Deep Dive: Strategi Rewrite Biar Gak Kena Plagiarism

Plagiarism detector kayak Copyscape atau Turnitin cari string match. Biar aman, ada 3 layer rewrite:

Layer 1: Synonym Rotation

from nltk.corpus import wordnet

def synonym_rotate(text):
    """Replace words with synonyms for basic obfuscation."""
    words = text.split()
    new_words = []
    for word in words:
        # Skip short words and stopwords
        if len(word) < 5 or word.lower() in ["the", "and", "for", "are", "but", "not", "you", "all", "can", "had", "her", "was", "one", "our", "out", "has", "have", "been", "some", "same"]:
            new_words.append(word)
            continue
        
        # Try to find a synonym
        synsets = wordnet.synsets(word)
        if synsets:
            lemmas = [l.name().replace("_", " ") for l in synsets[0].lemmas()]
            # Pick a different lemma that's not the original word
            alternatives = [l for l in lemmas if l.lower() != word.lower()]
            if alternatives:
                new_words.append(alternatives[0])
                continue
        
        new_words.append(word)
    
    return " ".join(new_words)

Layer 2: Sentence Restructuring AI rewrite harus ngubah struktur kalimat:

  • Active → passive (kalo masuk akal)
  • Sentence order dibalik
  • Paragraf digabung atau dipecah
  • Contoh dan analogi baru ditambahin

Layer 3: Value Add (30%+ new content) Biar artikel bukan cuma rewrite doang, kita suruh AI nambahin:

  • Pengalaman pribadi (simulated)
  • Perbandingan dengan tools/teknik lain
  • Step-by-step tutorial tambahan
  • FAQ section

Step 3: Generate Frontmatter + Markdown

import os
from datetime import datetime
import re

def slugify(title):
    """Convert title to URL-friendly slug."""
    slug = title.lower()
    slug = re.sub(r'[^a-z0-9\s-]', '', slug)
    slug = re.sub(r'[\s-]+', '-', slug)
    return slug[:80].strip('-')

def create_hugo_post(new_title, new_content, tags=None):
    """Wrap content in Hugo frontmatter + markdown."""
    today = datetime.now().strftime("%Y-%m-%d")
    slug = slugify(new_title)
    tags_str = str(tags or ["ai", "automation", "tutorial"])
    
    # Generate excerpt (first 160 chars of content)
    excerpt = new_content[:160].replace("\n", " ").strip()
    
    frontmatter = f"""---
title: "{new_title}"
date: {today}
draft: false
description: "{excerpt}..."
tags: {tags_str}
---

"""
    
    # Remove any title line from content (already in frontmatter)
    content_lines = new_content.split("\n")
    if content_lines[0].startswith("#"):
        content_lines = content_lines[1:]
    body = "\n".join(content_lines).strip()
    
    return frontmatter + body, slug

Step 4: Auto-Commit + Deploy

import subprocess
import os

def commit_and_deploy(posts_dir, slug, markdown_content):
    """Write file, git commit, push to trigger Hugo deploy."""
    # Write markdown file
    filepath = os.path.join(posts_dir, f"{slug}.md")
    with open(filepath, "w", encoding="utf-8") as f:
        f.write(markdown_content)
    
    print(f"Written: {filepath}")
    
    # Git commit + push
    subprocess.run(["git", "-C", posts_dir, "add", f"{slug}.md"], check=True)
    subprocess.run(["git", "-C", posts_dir, "commit", "-m", f"Auto-post: {slug}"], check=True)
    subprocess.run(["git", "-C", posts_dir, "push"], check=True)
    
    print(f"Committed and pushed: {slug}")

Full Pipeline: Satu Script

#!/usr/bin/env python3
"""
AutoBlog Pipeline v2 — Scrape → Rewrite → Post
Jalanin dari cron: */360 * * * * /home/ubuntu/auto_blog.py >> /var/log/auto_blog.log 2>&1
"""

import feedparser
import requests
import os
import subprocess
import json
import re
import random
from datetime import datetime

# Konfigurasi
OLLAMA_URL = "http://localhost:11434/api/generate"
MODEL_NAME = "noushermes2:7b"
POSTS_DIR = "/home/ubuntu/peak/blog/content/posts"
MAX_ARTICLES_PER_RUN = 5  # Biar gak banjir

# Sumber feeds — ganti sama niche lo
FEEDS = [
    "https://news.ycombinator.com/rss",
    "https://techcrunch.com/feed/",
    "https://www.reddit.com/r/entrepreneur/.rss",
]

def fetch_feeds():
    """Get latest articles from all feeds."""
    articles = []
    for url in FEEDS:
        feed = feedparser.parse(url)
        for entry in feed.entries[:3]:
            articles.append({
                "source_title": feed.feed.get("title", "Unknown"),
                "title": entry.get("title", ""),
                "content": entry.get("content", [{"value": entry.get("summary", "")}])[0]["value"] if entry.get("content") else entry.get("summary", ""),
            })
    return articles

def rewrite_article(article):
    """Rewrite using local AI model."""
    # Random niche angle biar artikel gak sama
    angles = [
        "with a focus on practical steps for Indonesian entrepreneurs",
        "with cost-benefit analysis for small business owners",
        "comparing with alternatives available in Southeast Asia",
        "with a step-by-step implementation guide",
    ]
    angle = random.choice(angles)
    
    prompt = f"""Rewrite this article completely {angle}.

Rules:
- Different structure, different sentences, 30% new insights
- Target: Indonesian entrepreneurs (practical, langsung bisa dipake)
- Length: 800-1200 words
- Format: markdown with ## subheadings
- NO sentence copied verbatim from original

Original Title: {article['title']}
Original:
{article['content'][:3000]}

Rewritten article:
"""
    
    resp = requests.post(OLLAMA_URL, json={
        "model": MODEL_NAME,
        "prompt": prompt,
        "stream": False,
        "options": {"temperature": 0.8, "num_predict": 4096}
    }, timeout=180)
    
    return resp.json()["response"]

def slugify(title):
    slug = title.lower()[:80]
    slug = re.sub(r'[^a-z0-9\s-]', '', slug)
    return re.sub(r'[\s-]+', '-', slug).strip('-')

def create_post(content, source_url):
    """Generate Hugo frontmatter + save file."""
    lines = content.strip().split("\n", 1)
    title = lines[0].replace("# ", "").strip()
    body = lines[1] if len(lines) > 1 else content
    slug = slugify(title)
    today = datetime.now().strftime("%Y-%m-%d")
    
    frontmatter = f"""---
title: "{title}"
date: {today}
draft: false
description: "{body[:160].replace(chr(10), ' ').strip()}..."
tags: ["ai", "automation", "tutorial"]
---

> *Artikel ini adalah hasil rewrite dari {source_url} — dengan restrukturisasi total dan nilai tambah.*

"""
    
    filepath = os.path.join(POSTS_DIR, f"{slug}.md")
    with open(filepath, "w", encoding="utf-8") as f:
        f.write(frontmatter + body)
    
    return filepath, slug

def deploy():
    """Git commit + push."""
    subprocess.run(["git", "-C", POSTS_DIR, "add", "-A"], check=False)
    subprocess.run(["git", "-C", POSTS_DIR, "commit", "-m", f"Auto-blog: {datetime.now().isoformat()}"], check=False)
    subprocess.run(["git", "-C", POSTS_DIR, "push"], check=False)

# === MAIN ===
if __name__ == "__main__":
    print(f"[{datetime.now().isoformat()}] Starting auto-blog pipeline...")
    
    # 1. Fetch
    articles = fetch_feeds()
    print(f"Fetched {len(articles)} articles from feeds")
    
    # 2. Rewrite & post
    posted = 0
    for article in articles[:MAX_ARTICLES_PER_RUN]:
        try:
            print(f"Rewriting: {article['title'][:60]}...")
            rewritten = rewrite_article(article)
            filepath, slug = create_post(rewritten, article.get("url", ""))
            print(f"  → Saved: {slug}")
            posted += 1
        except Exception as e:
            print(f"  ✗ Error: {e}")
    
    # 3. Deploy
    if posted > 0:
        deploy()
        print(f"Deployed {posted} new articles")
    
    print(f"[{datetime.now().isoformat()}] Pipeline complete")

Step 5: Cron Job (Biarr Jalan Otomatis)

# Buka crontab
crontab -e

# Tambah baris ini: jalan tiap 6 jam
0 */6 * * * /usr/bin/python3 /home/ubuntu/auto_blog.py >> /var/log/auto_blog.log 2>&1

# Test kalo cron beres jalan
tail -f /var/log/auto_blog.log

Real Economics: Berapa Duit yang Bisa Dihasilkan?

Biaya

ItemBiaya/bulan
VPS (Hetzner termurah)$4.49
Domain (setahun)$0.83/bulan
Ollama (gratis)$0
Python libs$0
Total$5.32/bulan

Cost Per Artikel

MetrikValue
AI compute per artikel (token)~2000 tokens generate + 1000 input
Cost per 3000 tokens (local model)$0.0003
Storage per artikel~0.01 GB × $0.0001/GB = negligible
Cost per artikel~$0.0003
Cost 100 artikel~$0.03

Bandingin:

  • Copywriter: $10-100/artikel
  • ChatGPT API: $0.015-0.045/artikel (tapi nolak niche)
  • Pipeline ini: $0.0003/artikel — 100x lebih murah dari ChatGPT API

Pendapatan Potensial

Model 1: Adsense

ArticlesMonthly TrafficRPM (Indonesia)Revenue
1005,000 visitors$3-5$15-25
50025,000 visitors$3-5$75-125
100050,000 visitors$3-5$150-250

Model 2: Affiliate Marketing

ArticlesConversion RateAvg CommissionRevenue
1001% (organic)$10-50$10-50
5001.5%$10-50$75-375
10002%$10-50$200-1000

Model 3: Jual Artikel ke Client

ServiceHarga
50 artikel SEO-optimized$100-250
100 artikel$200-500
Monthly retainer (200 artikel/bulan)$400-1000/bulan

Kapan Balik Modal?

ScenarioModal AwalRevenue/BulanBalik Modal
Adsense doang$5 (VPS)$15-253-5 hari
Affiliate$5 (VPS)$50-2001-2 hari
Jual artikel$5 (VPS)$200-500<1 hari

Real Case Studies

Case: Rudi — Blogger Otomotif

  • Mulai dengan pipeline ini Januari 2026
  • Target niche: review aksesoris motor di Indonesia
  • Scrape dari 15 blog + forum otomotif
  • 80 artikel/bulan
  • Traffic: 12,000 visitor/bulan (bulan ke-4)
  • Adsense: $45/bulan
  • Affiliate (Shopee): $120/bulan
  • Total: $165/bulan dari VPS $5

Case: Dewi — Content Agency

  • Jual paket artikel ke 5 client UMKM
  • 100 artikel/client/bulan
  • Harga: $150/client/bulan
  • Cost pipeline: $15 (VPS upgraded)
  • Revenue: $750/bulan
  • Waktu: 2 jam setup awal, 30 menit/minggu maintenance

Perbandingan: API vs Local Model

MetrikChatGPT APIClaude APILocal (Ollama)
Cost per artikel$0.015-0.045$0.024-0.072$0.0003
Ditolak grey niche?✅ Sering✅ Sering❌ Gak pernah
Rate limit✅ Ada✅ Ada❌ Gak ada
Privasi❌ Data ke OpenAI❌ Data ke Anthropic✅ 100% lokal
Kualitas output⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐ (7B model)
Setup5 menit5 menit30 menit sekali

Hybrid approach (rekomendasi):

  • Pake ChatGPT API buat artikel general (gak kena filter)
  • Pake local model buat grey niche
  • Paling hemat: local model doang — $0.03 buat 100 artikel

Optimization: Biar Pipeline Lo Makin Ngasil

1. SEO Optimization

def seo_optimize(title, content, keywords):
    """Optimize content for search engines."""
    prompt = f"""Improve this article for SEO. Requirements:
- Include primary keyword '{keywords[0]}' in H2 and first 100 words
- Include 3-5 secondary keywords naturally throughout
- Add internal linking suggestions [like this](https://yourblog.com/related-post)
- Optimize meta description (max 160 chars)
- Add FAQ schema at the bottom
- Ensure readability score >60 (short sentences, subheadings, bullet points)

Title: {title}
Content: {content[:3000]}
"""
    # Send to Ollama
    resp = requests.post(OLLAMA_URL, json={
        "model": MODEL_NAME,
        "prompt": prompt,
        "stream": False,
        "options": {"temperature": 0.3, "num_predict": 4096}
    })
    return resp.json()["response"]

2. Image Generation

# Install DALL-E / Stable Diffusion CLI
pip install openai

# Generate featured image per artikel
python3 -c "
import openai
openai.Image.create(
  prompt='Minimalist tech blog header: automated pipeline data flow',
  n=1,
  size='1024x1024'
)
"

3. Multi-Source Aggregation

Makin banyak sumber, makin beragam konten. Target: 20-50 RSS feeds di niche lo.

Sumber yang bisa dipake:

  • Reddit (subreddit niche) → https://www.reddit.com/r/{niche}/.rss
  • Medium → https://medium.com/feed/tag/{topic}
  • News API → Google News + country filter
  • Blog kompetitor → cari /rss atau /feed atau /atom.xml

4. Plagiarism Checker Otomatis

pip install copyscape

# Atau pake API Copyscape buat cek tiap artikel sebelum post
curl "https://www.copyscape.com/api/" \
  -d "u=https://yourblog.com/post-slug&key=YOUR_KEY&o=xml"

Checklist: 24 Jam Pertama

  • Beli VPS ($4.49 — Hetzner)
  • Install Ollama: ollama pull noushermes2:7b (10 menit)
  • Install Python deps: pip install requests feedparser beautifulsoup4 (5 menit)
  • Setup folder blog Hugo: hugo new site (15 menit)
  • Copy full pipeline script di atas (5 menit)
  • Test jalan: python3 auto_blog.py (5 menit)
  • Cek hasil: liat file .md di posts/ (2 menit)
  • Setup cron: crontab -e + paste 0 */6 * * * ... (5 menit)
  • Deploy blog ke VPS / GitHub Pages (30 menit)
  • Submit sitemap ke Google Search Console (10 menit)

Total: ~1.5 jam Modal: $5 Artikel pertama dalam: 30 menit 100 artikel dalam: 5 hari


Jebakan yang Harus Dihindari

  1. Plagiarism — jangan republish mentah-mentah. Pipeline ini pake rewrite total + 30% new content. Kalo cuma ganti sinonim doang, Copyscape tetep kena.
  2. Content quality — model 7B gak sebagus GPT-4. Artikel harus diedit ringan kalo mau kualitas tinggi. Target: konten informasi, bukan opini.
  3. Google penalty — konten murni AI bisa kena Google spam update. Solusi: mix artikel AI dengan human-written, tambahin data orisinal.
  4. Feed rate limit — jangan scrape terlalu sering. Tiap 6 jam cukup.
  5. Same source, same title — deduplikasi penting. Cek judul yang udah ada di folder posts sebelum bikin baru.

Artikel ini bagian dari seri AI Monetization di Solvinc. Data disusun dari operasi riil — hasil tergantung niche, kualitas konten, dan strategi SEO lo.