DEV Community

孫昊
孫昊

Posted on

I Built a Flask Dashboard That Aggregates 60+ Indie Hacker Assets

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
Enter fullscreen mode Exit fullscreen mode

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]  │
└──────────────────┴──────────────────┴──────────────────┘
Enter fullscreen mode Exit fullscreen mode

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))
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)