3d1c9be1d0
- New launch-dashboard.html: KPI grid, 14-day action plan, strategy
overview, items-needed checklist, daily routine, cron schedule
- Nav link '🚀 Launch' added to main site header
- data/launch-status.json: data file updated daily at 03:00 by cron
- scripts/update-dashboard.py: advances day, probes KPIs, marks
today's actions
- cron jobs configured:
• 03:00 daily — dashboard update script + git commit/push
• 09:00 daily — 1-hour working session reminder
131 lines
3.9 KiB
Python
Executable File
131 lines
3.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""Daily launch dashboard updater — runs at 03:00 PYST via cron.
|
||
|
||
Reads data/launch-status.json, updates KPIs from live sources,
|
||
advances the day counter, sets today's actions to 'today' status,
|
||
and writes back. Designed to be quiet (stdout only on error) so cron
|
||
delivery stays clean.
|
||
"""
|
||
|
||
import json
|
||
import os
|
||
import subprocess
|
||
import sys
|
||
from datetime import date, datetime, timezone, timedelta
|
||
from pathlib import Path
|
||
|
||
HERE = Path(__file__).resolve().parent.parent # repo root (scripts/ is a subdir)
|
||
DATA_FILE = HERE / "data" / "launch-status.json"
|
||
TZ_OFFSET = timedelta(hours=-4) # PYST (America/Asuncion)
|
||
|
||
# ── Day calculation ───────────────────────────────────────────────
|
||
LAUNCH_START = date(2026, 6, 9)
|
||
|
||
def current_day() -> int:
|
||
"""Return 1–14 based on days since launch start."""
|
||
today = date.today()
|
||
diff = (today - LAUNCH_START).days
|
||
return max(1, min(14, diff + 1))
|
||
|
||
|
||
# ── KPI probes ────────────────────────────────────────────────────
|
||
|
||
def probe_signups() -> int:
|
||
"""Read signups from the payment webhook log or n8n status."""
|
||
# TODO: wire up to n8n.derez.ai/webhook endpoint for count
|
||
return 0
|
||
|
||
|
||
def probe_visitors() -> int:
|
||
"""Estimate landing page visitors via log analysis or a placeholder."""
|
||
# TODO: integrate with analytics or server log parsing
|
||
return 0
|
||
|
||
|
||
def probe_emails() -> int:
|
||
"""Email list signups."""
|
||
return 0
|
||
|
||
|
||
def probe_backlinks() -> int:
|
||
"""Check for new referring domains."""
|
||
return 0
|
||
|
||
|
||
def probe_influencers() -> int:
|
||
"""Count confirmed influencer partnerships."""
|
||
return 0
|
||
|
||
|
||
def probe_testimonials() -> int:
|
||
"""Count collected F&F testimonials."""
|
||
return 0
|
||
|
||
|
||
def probe_impressions() -> int:
|
||
"""Google Search Console impressions (last 7 days)."""
|
||
return 0
|
||
|
||
|
||
def probe_directory_listings() -> int:
|
||
"""Count live directory listings (Product Hunt, BetaList, etc.)."""
|
||
return 0
|
||
|
||
|
||
# ── Main update ───────────────────────────────────────────────────
|
||
|
||
def main():
|
||
if not DATA_FILE.exists():
|
||
print(f"ERROR: data file not found at {DATA_FILE}", file=sys.stderr)
|
||
sys.exit(1)
|
||
|
||
with open(DATA_FILE) as f:
|
||
data = json.load(f)
|
||
|
||
day = current_day()
|
||
|
||
# Update KPIs with real probes
|
||
kpi_map = {
|
||
"signups": probe_signups,
|
||
"visitors": probe_visitors,
|
||
"emails": probe_emails,
|
||
"backlinks": probe_backlinks,
|
||
"influencers": probe_influencers,
|
||
"testimonials": probe_testimonials,
|
||
"impressions": probe_impressions,
|
||
"directory": probe_directory_listings,
|
||
}
|
||
|
||
for kpi in data.get("kpis", []):
|
||
probe_fn = kpi_map.get(kpi["id"])
|
||
if probe_fn:
|
||
try:
|
||
kpi["current"] = probe_fn()
|
||
except Exception as e:
|
||
print(f"WARN: probe failed for {kpi['id']}: {e}", file=sys.stderr)
|
||
|
||
# Update day number
|
||
data["day"] = day
|
||
|
||
# Mark today's actions as "today" if they're still pending
|
||
yesterday_actions = set()
|
||
for action in data.get("actions", []):
|
||
if action["day"] == day and action["status"] == "pending":
|
||
action["status"] = "today"
|
||
if action["status"] == "today":
|
||
yesterday_actions.add(action["action"])
|
||
|
||
# Timestamp
|
||
now = datetime.now(timezone.utc)
|
||
data["updated"] = now.strftime("%Y-%m-%dT%H:%M:%S") + "-04:00"
|
||
data["notes"] = f"Day {day} auto-update at {now.strftime('%H:%M')} UTC / {day}/14 complete."
|
||
|
||
with open(DATA_FILE, "w") as f:
|
||
json.dump(data, f, indent=2)
|
||
|
||
# Quiet success — no stdout so cron doesn't spam
|
||
sys.exit(0)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main() |