TL;DR: A 60-line Python script that emails me a daily indie hacker briefing at 7am. Aggregates: dev.to traffic, Gumroad sales, Apple ASC build state, Substack subs, GitHub stars, scheduled tasks for today. Replaces 30 minutes of "checking state" each morning.
What the briefing looks like
=== AutoApp Daily Briefing — 2026-05-07 ===
CONTENT
- dev.to: 50 articles, 0 published yesterday (target: 5/week)
- Substack: 12 issues, 0 published yesterday (target: 1/week)
REVENUE
- Gumroad sales (24h): 0 / total 0
- iOS IAP (24h): 0 / total 0
- B2B consulting (week): 0 calls booked
- Affiliate commissions (week): $0
iOS APPS
- AutoChoice: build VALID, NOT in App Store
- AltitudeNow: build VALID, NOT in App Store
- DaysUntil: build VALID, NOT in App Store
- PromptVault: build VALID, NOT in App Store
AUDIENCE
- dev.to followers: 12 (+0)
- Substack subscribers: 0 (+0)
- GitHub stars (autoapp-toolkit): 0 (+0)
- Twitter followers: 89 (+0)
LIVE ASSETS
- Site pages: 31 LIVE
- All HTTP 200: ✓ (33/33)
TODAY'S TODOS
- [ ] Reddit r/SideProject post (paste-ready /reports/reddit-toolkit-launch)
- [ ] Substack #24 publish (paste-ready /reports/substack-issue-24)
- [ ] dev.to #51-#56 batch publish
ACTIONS YOU CAN DO IN < 5 MIN
- Open https://dev.to/dashboard → check stats
- Open https://gumroad.com/dashboard → check sales
- Open https://appstoreconnect.apple.com → check Apple Review
The script (~60 lines)
#!/usr/bin/env python3
"""Daily indie hacker briefing — designed to run at 7am via cron."""
import json, requests
from datetime import datetime, timedelta
from pathlib import Path
ROOT = Path(__file__).parent.parent
CONFIG = json.loads((ROOT / "config" / "briefing.json").read_text())
def section(title):
return f"\n{title}\n" + "-" * len(title) + "\n"
def fetch_devto():
api_key = CONFIG["devto_api_key"]
r = requests.get(
"https://dev.to/api/articles/me",
headers={"api-key": api_key},
params={"per_page": 100},
)
if r.ok:
articles = r.json()
published = [a for a in articles if a.get("published")]
return f"- dev.to: {len(published)} articles total"
return "- dev.to: API error"
def fetch_gumroad():
api_key = CONFIG["gumroad_api_key"]
r = requests.get(
"https://api.gumroad.com/v2/sales",
params={"access_token": api_key},
)
if r.ok:
sales = r.json().get("sales", [])
cutoff = datetime.now() - timedelta(hours=24)
recent = [s for s in sales if datetime.fromisoformat(s["created_at"].rstrip("Z")) > cutoff]
return f"- Gumroad sales (24h): {len(recent)} / total {len(sales)}"
return "- Gumroad: API error"
def fetch_asc():
state_path = ROOT / "data" / "asc_status.json"
if state_path.exists():
s = json.loads(state_path.read_text())
lines = []
for app in s.get("apps", []):
status = "VALID" if app.get("build_state") == "VALID" else "BUILDING"
in_store = "in App Store" if app.get("in_app_store") else "NOT in App Store"
lines.append(f"- {app['name']}: build {status}, {in_store}")
return "\n".join(lines)
return "- ASC: status file missing"
def fetch_audit():
state_path = ROOT / "data" / "audit.json"
if state_path.exists():
a = json.loads(state_path.read_text())
return f"- All HTTP 200: {'✓' if a['fail'] == 0 else '✗'} ({a['ok']}/{a['total']})"
return "- Audit: not yet run today"
def main():
today = datetime.now().strftime("%Y-%m-%d")
out = []
out.append(f"=== AutoApp Daily Briefing — {today} ===")
out.append(section("CONTENT"))
out.append(fetch_devto())
out.append(section("REVENUE"))
out.append(fetch_gumroad())
out.append(section("iOS APPS"))
out.append(fetch_asc())
out.append(section("LIVE ASSETS"))
out.append(fetch_audit())
out.append(section("TODAY'S TODOS"))
out.append(check_todos())
print("\n".join(out))
def check_todos():
todo_path = ROOT / "INBOX" / "WEEKLY-CONTENT-PLAN-current.md"
if todo_path.exists():
# Find lines starting with - [ ]
lines = todo_path.read_text().split("\n")
unchecked = [l for l in lines if l.strip().startswith("- [ ]")]
return "\n".join(unchecked[:5]) # top 5
return "- (no plan file found)"
if __name__ == "__main__":
main()
Cron setup (Windows)
Use Windows Task Scheduler:
- Action → Start Program →
python.exe - Args:
C:\path\to\dashboard\daily_briefing.py - Trigger: Daily at 07:00
- Output → save to
C:\path\to\briefing-{date}.txt
Or PowerShell scheduled task:
$action = New-ScheduledTaskAction -Execute "python.exe" -Argument "C:\path\to\daily_briefing.py"
$trigger = New-ScheduledTaskTrigger -Daily -At 07:00
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "DailyBriefing"
Cron setup (Linux/macOS)
crontab -e
# Add:
0 7 * * * cd /path/to/project && python dashboard/daily_briefing.py | mail -s "Daily Briefing" you@example.com
What replaces 30 minutes
Pre-script morning routine:
- Open dev.to dashboard, check article stats: 5 min
- Open Gumroad, check sales: 3 min
- Open ASC, check build states: 4 min
- Open Substack, check subs: 2 min
- Open GitHub, check stars: 1 min
- Look at today's TODO list: 5 min
- Mentally aggregate: "what should I do today?": 10 min
Total: 30 min, every morning.
Post-script: 90 sec to read the briefing email + decide.
Time saved: 28.5 min/day × 365 = 173 hours/year.
What I'd add next
- Twitter follower delta (Twitter API V2)
- Stripe subscriptions (when I add paid tier)
- ConvertKit subscriber delta (if I switch from Substack)
- Apple Search Ads spend + installs
- Google Analytics page views (when I add GA)
All cron-friendly, all stack on the same script.
Source
Full daily briefing script + config + Windows Task Scheduler XML:
AutoApp Dashboard ($39) includes:
-
daily_briefing.py(this article) -
weekly_summary_gen.py(Sunday weekly report) -
monthly_review.py(last day of month) -
cron-setup.md(Windows + Linux + macOS)
If you spend more than 5 minutes/day "checking state," you have a briefing-shaped problem. 60 lines of Python solves it.
Top comments (0)