VOOZH about

URL: https://dev.to/snake_sun/i-built-a-flask-dashboard-that-aggregates-60-indie-hacker-assets-3g2o

⇱ I Built a Flask Dashboard That Aggregates 60+ Indie Hacker Assets - DEV Community


TL;DR: Single-pane view of every indie hacker asset (paste-ready content, products, roadmaps, audit results, revenue, ASC build state) auto-generated from filesystem + APIs. ~600 lines of Flask. Saves 30+ min/day of "what's the state of things" overhead.


The problem: too many silos

By Day 60 of my indie experiment I had:

  • 50+ paste-ready dev.to articles in reports/
  • 23+ Substack newsletters
  • 6 Gumroad SKUs
  • 4 iOS apps with build state in ASC API
  • 9 LIVE site pages
  • 12 ops scripts
  • 30+ commits across week
  • 33 LIVE URLs to verify

Looking at all this required: 5 terminal windows, 3 browser tabs, 2 API calls, manual mental aggregation. ~30 min/day "checking state."

So I built a dashboard.

Architecture

Single Flask app, ~600 lines:

dashboard/
├── app.py # Flask routes
├── manifest_scan.py # YAML frontmatter aggregator
├── asc_api.py # Apple ASC JWT helper
├── gumroad_api.py # Gumroad REST client
├── verify_urls.py # HTTP 200 audit
├── revenue_state.py # cross-channel revenue aggregator
├── templates/
│ ├── index.html # 3-pane main view
│ ├── audit.html # URL audit table
│ └── revenue.html # revenue dashboard
└── data/
 ├── asc_status.json # cached, refreshed hourly
 └── audit.json # cached, refreshed daily

The 3-pane main view

┌──────────────────┬──────────────────┬──────────────────┐
│ TODO │ User check items │ Quick run scripts│
│ (pending tasks) │ (manual actions) │ (run via button) │
├──────────────────┼──────────────────┼──────────────────┤
│ [Publish #51-56] │ [✓ Apple email?] │ [▶ daily_brief] │
│ [Reddit post] │ [✓ Gumroad sale?]│ [▶ asc_status] │
│ [B2B outreach] │ [✓ DM reply?] │ [▶ verify_urls] │
└──────────────────┴──────────────────┴──────────────────┘

3 panels, 3 actions. Not a Markdown viewer — it's a control panel.

Key endpoints

@app.route('/api/audit')
def audit_urls():
 """HTTP 200 verifier — runs across all LIVE assets"""
 urls = scan_for_live_urls() # finds Gumroad/Substack/dev.to/Site URLs
 results = []
 for url in urls:
 try:
 r = requests.head(url, timeout=10, allow_redirects=True)
 results.append({'url': url, 'status': r.status_code, 'ok': r.status_code == 200})
 except Exception as e:
 results.append({'url': url, 'status': 'ERR', 'ok': False, 'error': str(e)[:80]})
 ok = sum(1 for r in results if r['ok'])
 return jsonify({'total': len(results), 'ok': ok, 'fail': len(results) - ok, 'details': results})

@app.route('/api/revenue')
def revenue():
 """Aggregate revenue across all channels"""
 return jsonify({
 'gumroad': gumroad_total(),
 'asc_iaps': asc_iap_total(),
 'b2b_consulting': b2b_revenue_csv(),
 'affiliates': affiliate_revenue(),
 'total': sum_all(),
 })

@app.route('/api/asc-status')
def asc_status():
 """Cached Apple ASC build state — refreshed hourly via cron"""
 with open('data/asc_status.json') as f:
 return jsonify(json.load(f))

Caching strategy

  • Audit cache: 24h TTL (URLs rarely break in 24h)
  • ASC build state cache: 1h TTL (build state refreshes via hourly cron)
  • Gumroad sales cache: 5 min TTL (real-time enough for indie scale)
  • Manifest scan: no cache, scans on every request (fast — 60 files in <100ms)

What this lets you do in 30 sec/morning

  1. Open dashboard
  2. Glance at 3 panes
  3. Click 1 button (e.g. "▶ daily_brief")
  4. See: "5 Gumroad SKUs LIVE, all 4 apps build VALID, 33/33 URLs OK, 0 stale assets, 1 user action pending: paste Reddit"

You don't need to remember. You don't need to check 5 different places. The dashboard is the truth.

What I'd skip if rebuilding

  • Real-time WebSockets for revenue (overkill — polling is fine)
  • Per-asset detail pages (just link to the file directly)
  • Authentication (it's localhost — useless)
  • Service-worker offline support (you'll always have wifi when you check)

What I'd keep:

  • 3-pane layout (TODO / user / scripts)
  • Frontmatter-driven asset list
  • Click-to-run script buttons
  • Caching for slow APIs

Source

Full Flask dashboard with all 6 endpoints + 3-pane view + caching:

AutoApp Dashboard ($39) is literally this dashboard. Drop-in for any indie hacker workflow with markdown content + API-aggregated state.


If you spend 30+ min/day "checking state" across silos, you have a dashboard-shaped problem. Cost: 4 hours of dev. Payback: 30 min/day = 4 hours / week.