prelaunch: create launch dashboard + daily cron updates
- 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
This commit is contained in:
@@ -0,0 +1,977 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="robots" content="noindex, nofollow" />
|
||||
<title>Prelaunch Dashboard — Derez.ai</title>
|
||||
<style>
|
||||
/* ═══════════════════════════════════════════════════════════════
|
||||
DESIGN TOKENS (matches derez.ai design system)
|
||||
═══════════════════════════════════════════════════════════════ */
|
||||
:root {
|
||||
--bg: #000810;
|
||||
--bg-card: #010f20;
|
||||
--bg-inner: #000d1a;
|
||||
--bg-hover: #001a30;
|
||||
--bg-input: #000813;
|
||||
--border: #0a3060;
|
||||
--border-hi: rgba(0,245,255,0.45);
|
||||
--accent: #00f5ff;
|
||||
--accent-dim: #002535;
|
||||
--danger: #ff3b3b;
|
||||
--danger-dim: #3b0000;
|
||||
--success: #00ff88;
|
||||
--warning: #ffaa00;
|
||||
--text: #c8f0ff;
|
||||
--text-muted: #2e6a80;
|
||||
--radius: 8px;
|
||||
--radius-card: 18px;
|
||||
--shadow: 0 0 0 1px rgba(0,245,255,0.25), 0 0 60px rgba(0,245,255,0.12), 0 28px 72px rgba(0,0,0,0.9);
|
||||
--max-width: 1200px;
|
||||
}
|
||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
html { scroll-behavior: smooth; -webkit-font-smoothing: antialiased; }
|
||||
body {
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
overflow-x: hidden;
|
||||
padding-top: 70px;
|
||||
}
|
||||
body::before {
|
||||
content: "";
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background:
|
||||
radial-gradient(ellipse 60% 50% at 25% 20%, rgba(0,245,255,0.06) 0%, transparent 70%),
|
||||
radial-gradient(ellipse 50% 60% at 75% 80%, rgba(0,200,255,0.04) 0%, transparent 70%);
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
a { color: var(--accent); text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
|
||||
.container {
|
||||
max-width: var(--max-width);
|
||||
margin: 0 auto;
|
||||
padding: 0 24px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* ── Header ──────────────────────────────── */
|
||||
.site-header {
|
||||
position: fixed;
|
||||
top: 0; left: 0; right: 0;
|
||||
z-index: 100;
|
||||
background: rgba(0,8,16,0.85);
|
||||
backdrop-filter: blur(14px);
|
||||
border-bottom: 1px solid var(--border-hi);
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.site-header .container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
.site-logo { display: flex; align-items: center; flex-shrink: 0; }
|
||||
.site-logo-img { display: block; height: 30px; width: auto; }
|
||||
.nav-links {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
list-style: none;
|
||||
}
|
||||
.nav-links a {
|
||||
padding: 6px 14px;
|
||||
border-radius: var(--radius);
|
||||
color: var(--text-muted);
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
transition: color 0.15s, background 0.15s;
|
||||
}
|
||||
.nav-links a:hover {
|
||||
color: var(--text);
|
||||
background: var(--bg-hover);
|
||||
text-decoration: none;
|
||||
}
|
||||
.nav-links a.active {
|
||||
color: var(--accent);
|
||||
background: var(--accent-dim);
|
||||
}
|
||||
|
||||
/* ── Status Banner ───────────────────────── */
|
||||
.status-banner {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-card);
|
||||
padding: 28px 32px;
|
||||
margin-bottom: 28px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
}
|
||||
.status-banner h1 {
|
||||
font-size: 22px;
|
||||
color: var(--accent);
|
||||
font-weight: 700;
|
||||
}
|
||||
.status-banner .day-indicator {
|
||||
font-size: 13px;
|
||||
color: var(--text-muted);
|
||||
margin-top: 4px;
|
||||
}
|
||||
.status-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 16px;
|
||||
border-radius: 999px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.status-badge.live {
|
||||
background: rgba(0,255,136,0.12);
|
||||
color: var(--success);
|
||||
border: 1px solid rgba(0,255,136,0.3);
|
||||
}
|
||||
.status-badge.paused {
|
||||
background: rgba(255,170,0,0.12);
|
||||
color: var(--warning);
|
||||
border: 1px solid rgba(255,170,0,0.3);
|
||||
}
|
||||
.last-updated {
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* ── Section ─────────────────────────────── */
|
||||
.section {
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
.section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 14px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
.section-header h2 {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.section-header h2 .icon { color: var(--accent); }
|
||||
.section-toggle {
|
||||
color: var(--text-muted);
|
||||
font-size: 18px;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
.section-toggle.collapsed {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
.section-body {
|
||||
transition: max-height 0.3s ease, opacity 0.2s ease;
|
||||
overflow: hidden;
|
||||
max-height: 20000px;
|
||||
opacity: 1;
|
||||
}
|
||||
.section-body.hidden {
|
||||
max-height: 0;
|
||||
opacity: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* ── KPI Grid ────────────────────────────── */
|
||||
.kpi-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
.kpi-card {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-card);
|
||||
padding: 20px;
|
||||
}
|
||||
.kpi-label {
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.kpi-value {
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
}
|
||||
.kpi-value .target {
|
||||
font-size: 16px;
|
||||
color: var(--text-muted);
|
||||
font-weight: 400;
|
||||
}
|
||||
.kpi-bar {
|
||||
margin-top: 10px;
|
||||
height: 4px;
|
||||
background: var(--bg-inner);
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.kpi-bar-fill {
|
||||
height: 100%;
|
||||
border-radius: 2px;
|
||||
transition: width 0.6s ease;
|
||||
}
|
||||
.kpi-bar-fill.green { background: var(--success); }
|
||||
.kpi-bar-fill.blue { background: var(--accent); }
|
||||
.kpi-bar-fill.yellow { background: var(--warning); }
|
||||
.kpi-bar-fill.red { background: var(--danger); }
|
||||
.kpi-sub {
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* ── Action Plan Table ───────────────────── */
|
||||
.action-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-card);
|
||||
overflow: hidden;
|
||||
font-size: 13px;
|
||||
}
|
||||
.action-table th {
|
||||
background: var(--bg-inner);
|
||||
padding: 12px 16px;
|
||||
text-align: left;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--text-muted);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.action-table td {
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
vertical-align: top;
|
||||
}
|
||||
.action-table tr:last-child td { border-bottom: none; }
|
||||
.action-table td.day-col {
|
||||
color: var(--accent);
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
width: 60px;
|
||||
}
|
||||
.action-table td.status-col {
|
||||
white-space: nowrap;
|
||||
width: 110px;
|
||||
}
|
||||
.action-table td.owner-col { white-space: nowrap; width: 80px; }
|
||||
|
||||
.status-tag {
|
||||
display: inline-block;
|
||||
padding: 2px 10px;
|
||||
border-radius: 999px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.status-tag.done { background: rgba(0,255,136,0.12); color: var(--success); border: 1px solid rgba(0,255,136,0.25); }
|
||||
.status-tag.in-progress { background: rgba(0,245,255,0.12); color: var(--accent); border: 1px solid rgba(0,245,255,0.25); }
|
||||
.status-tag.pending { background: rgba(46,106,128,0.15); color: var(--text-muted); border: 1px solid transparent; }
|
||||
.status-tag.blocked { background: rgba(255,59,59,0.12); color: var(--danger); border: 1px solid rgba(255,59,59,0.25); }
|
||||
.status-tag.today { background: rgba(255,170,0,0.15); color: var(--warning); border: 1px solid rgba(255,170,0,0.3); }
|
||||
|
||||
/* ── Card Layout ─────────────────────────── */
|
||||
.grid-2 {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 20px;
|
||||
}
|
||||
.grid-3 {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 20px;
|
||||
}
|
||||
.info-card {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-card);
|
||||
padding: 24px;
|
||||
}
|
||||
.info-card h3 {
|
||||
font-size: 13px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
color: var(--accent);
|
||||
margin-bottom: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.info-card ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
.info-card li {
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid rgba(10,48,96,0.4);
|
||||
font-size: 13px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
}
|
||||
.info-card li:last-child { border-bottom: none; }
|
||||
.info-card li .bullet { color: var(--accent); flex-shrink: 0; }
|
||||
|
||||
.need-checkbox {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 2px solid var(--border);
|
||||
border-radius: 4px;
|
||||
flex-shrink: 0;
|
||||
margin-top: 2px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
.need-checkbox.checked {
|
||||
background: var(--success);
|
||||
border-color: var(--success);
|
||||
}
|
||||
.need-checkbox.checked::after {
|
||||
content: "✓";
|
||||
color: var(--bg);
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.need-item.done .need-text {
|
||||
color: var(--text-muted);
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
/* ── Strategy Section ────────────────────── */
|
||||
.strategy-card {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-card);
|
||||
padding: 24px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.strategy-card h3 {
|
||||
font-size: 14px;
|
||||
color: var(--accent);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.strategy-card p, .strategy-card ul {
|
||||
font-size: 13px;
|
||||
color: var(--text);
|
||||
line-height: 1.7;
|
||||
}
|
||||
.strategy-card ul {
|
||||
padding-left: 20px;
|
||||
list-style: none;
|
||||
}
|
||||
.strategy-card ul li::before {
|
||||
content: "› ";
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
/* ── Cron / Daily Routine ────────────────── */
|
||||
.cron-timeline {
|
||||
position: relative;
|
||||
padding-left: 28px;
|
||||
}
|
||||
.cron-timeline::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
top: 4px;
|
||||
bottom: 4px;
|
||||
width: 2px;
|
||||
background: var(--border);
|
||||
}
|
||||
.cron-item {
|
||||
position: relative;
|
||||
padding: 6px 0 16px;
|
||||
}
|
||||
.cron-item::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: -24px;
|
||||
top: 10px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
background: var(--bg-card);
|
||||
border: 2px solid var(--accent);
|
||||
}
|
||||
.cron-item.daily-hour::before {
|
||||
background: var(--accent);
|
||||
box-shadow: 0 0 12px rgba(0,245,255,0.5);
|
||||
}
|
||||
.cron-time {
|
||||
font-size: 12px;
|
||||
color: var(--accent);
|
||||
font-weight: 600;
|
||||
}
|
||||
.cron-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
}
|
||||
.cron-desc {
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
/* ── Responsive ──────────────────────────── */
|
||||
@media (max-width: 900px) {
|
||||
.grid-2, .grid-3 { grid-template-columns: 1fr; }
|
||||
.kpi-grid { grid-template-columns: repeat(2, 1fr); }
|
||||
.status-banner { flex-direction: column; align-items: flex-start; }
|
||||
.action-table { font-size: 12px; }
|
||||
.action-table th, .action-table td { padding: 8px 10px; }
|
||||
}
|
||||
@media (max-width: 500px) {
|
||||
.kpi-grid { grid-template-columns: 1fr; }
|
||||
.nav-links { display: none; }
|
||||
}
|
||||
|
||||
.tag { color: var(--text-muted); font-size: 12px; }
|
||||
.highlight { color: var(--accent); }
|
||||
.success-text { color: var(--success); }
|
||||
.warn-text { color: var(--warning); }
|
||||
.danger-text { color: var(--danger); }
|
||||
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 8px 20px;
|
||||
border-radius: var(--radius);
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
transition: all 0.15s;
|
||||
font-family: inherit;
|
||||
}
|
||||
.btn-primary {
|
||||
background: var(--accent);
|
||||
color: var(--bg);
|
||||
}
|
||||
.btn-primary:hover { opacity: 0.85; text-decoration: none; }
|
||||
.btn-ghost {
|
||||
background: transparent;
|
||||
color: var(--text);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); text-decoration: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- ── HEADER ──────────────────────────────────── -->
|
||||
<header class="site-header">
|
||||
<div class="container">
|
||||
<a href="/" class="site-logo">
|
||||
<img src="assets/images/logo.svg" alt="Derez.ai" width="132" height="34" class="site-logo-img" />
|
||||
</a>
|
||||
<ul class="nav-links" id="nav-links">
|
||||
<li><a href="/">Home</a></li>
|
||||
<li><a href="/#pricing">Pricing</a></li>
|
||||
<li><a href="/#faq">FAQ</a></li>
|
||||
<li><a href="launch-dashboard.html" class="active">🚀 Launch Dashboard</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<!-- ── STATUS BANNER ─────────────────────────── -->
|
||||
<div class="status-banner" id="status-banner">
|
||||
<div>
|
||||
<h1>🚀 Prelaunch Dashboard</h1>
|
||||
<div class="day-indicator" id="day-indicator">Day 1 of 14 — Counting down to launch</div>
|
||||
</div>
|
||||
<div style="display:flex;align-items:center;gap:14px;flex-wrap:wrap;">
|
||||
<span class="status-badge live" id="campaign-status">● Campaign Active</span>
|
||||
<span class="last-updated" id="last-updated">Updated: just now</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── KPI DASHBOARD ─────────────────────────── -->
|
||||
<div class="section">
|
||||
<div class="section-header" onclick="toggleSection('kpi-section', this)">
|
||||
<h2><span class="icon">📊</span> Key Performance Indicators</h2>
|
||||
<span class="section-toggle">▼</span>
|
||||
</div>
|
||||
<div class="section-body" id="kpi-section">
|
||||
<div class="kpi-grid" id="kpi-grid">
|
||||
<!-- populated by JS -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── ACTION PLAN ───────────────────────────── -->
|
||||
<div class="section">
|
||||
<div class="section-header" onclick="toggleSection('actions-section', this)">
|
||||
<h2><span class="icon">📋</span> 14-Day Action Plan</h2>
|
||||
<span class="section-toggle">▼</span>
|
||||
</div>
|
||||
<div class="section-body" id="actions-section">
|
||||
<table class="action-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Day</th>
|
||||
<th>Action</th>
|
||||
<th>Owner</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="action-rows">
|
||||
<!-- populated by JS -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── STRATEGY SUMMARY ──────────────────────── -->
|
||||
<div class="section">
|
||||
<div class="section-header" onclick="toggleSection('strategy-section', this)">
|
||||
<h2><span class="icon">🎯</span> Strategy Overview</h2>
|
||||
<span class="section-toggle">▼</span>
|
||||
</div>
|
||||
<div class="section-body" id="strategy-section">
|
||||
|
||||
<div class="grid-2">
|
||||
|
||||
<div>
|
||||
<div class="strategy-card">
|
||||
<h3>👨👩👧👦 Friends & Family Program</h3>
|
||||
<p>Invite 20–30 trusted contacts to beta test at discounted rates. Each gets:</p>
|
||||
<ul>
|
||||
<li>50% off first month ($4.75/mo instead of $9.50)</li>
|
||||
<li>$5 OpenRouter credits with referral coupon code</li>
|
||||
<li>Priority support via chat</li>
|
||||
<li>Direct feedback channel (Telegram group)</li>
|
||||
<li>NPS survey after 7 days</li>
|
||||
</ul>
|
||||
<p style="margin-top:8px;"><span class="highlight">Goal:</span> 20 signups, 5 detailed testimonials</p>
|
||||
</div>
|
||||
|
||||
<div class="strategy-card">
|
||||
<h3>🔗 Backlinks & SEO</h3>
|
||||
<p>Three-pronged approach:</p>
|
||||
<ul>
|
||||
<li><strong>Product Hunt / directories:</strong> List on Product Hunt, BetaList, AlternativeTo, G2</li>
|
||||
<li><strong>Guest posts:</strong> Pitch "How to deploy AI agents in 5 minutes" to AI/DevOps blogs</li>
|
||||
<li><strong>HARO / Qwoted:</strong> Respond to journalist queries about AI hosting</li>
|
||||
<li><strong>Open source:</strong> Link back from Hermes Agent docs / GitHub (if accepted)</li>
|
||||
</ul>
|
||||
<p style="margin-top:8px;"><span class="highlight">Goal:</span> 10 quality backlinks, rank in top 5 for "AI agent hosting"</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="strategy-card">
|
||||
<h3>📢 Influencer Outreach</h3>
|
||||
<p>Target micro-influencers in AI/ML/DevOps spaces:</p>
|
||||
<ul>
|
||||
<li><strong>Where to find them:</strong> YouTube (AI channels 5K–50K subs), X/Twitter (AI builders), LinkedIn (DevOps thought leaders), Discord communities (OpenRouter, Nous Research, local LLM)</li>
|
||||
<li><strong>Offer:</strong> Free 3-month agent instance + affiliate commission (10% recurring)</li>
|
||||
<li><strong>Pitch angle:</strong> "Your followers can deploy their own AI agent in 5 minutes — no DevOps needed"</li>
|
||||
<li><strong>Toolkit:</strong> One-pager, demo video, coupon codes, pre-written tweets</li>
|
||||
</ul>
|
||||
<p style="margin-top:8px;"><span class="highlight">Goal:</span> 5 confirmed partnerships, 3 social mentions</p>
|
||||
</div>
|
||||
|
||||
<div class="strategy-card">
|
||||
<h3>📈 Launch Strategy</h3>
|
||||
<ul>
|
||||
<li><strong>Week 1 (Days 1–7):</strong> Friends & Family + SEO foundation + directory listings</li>
|
||||
<li><strong>Week 2 (Days 8–14):</strong> Influencer push + guest posts + social content sprint</li>
|
||||
<li><strong>Launch day:</strong> Product Hunt + email blast + social storm + all influencers post</li>
|
||||
<li><strong>Tracking:</strong> UTM on every link, Google Search Console, weekly KPI review</li>
|
||||
</ul>
|
||||
<p style="margin-top:8px;"><span class="highlight">Goal:</span> 500 unique visitors, 50 email captures, 20 paid signups by launch</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── DAILY ROUTINE & CRON ──────────────────── -->
|
||||
<div class="section">
|
||||
<div class="section-header" onclick="toggleSection('routine-section', this)">
|
||||
<h2><span class="icon">⏰</span> Daily Routine & Cron Schedule</h2>
|
||||
<span class="section-toggle">▼</span>
|
||||
</div>
|
||||
<div class="section-body" id="routine-section">
|
||||
<div class="grid-2">
|
||||
|
||||
<div class="info-card">
|
||||
<h3>⏱ Our Daily 1-Hour Block</h3>
|
||||
<p style="font-size:13px;margin-bottom:12px;">Every day at <strong class="highlight">09:00 PYST</strong> (America/Asuncion) — 60 minutes.</p>
|
||||
<div class="cron-timeline">
|
||||
<div class="cron-item daily-hour">
|
||||
<div class="cron-time">09:00 – 09:05</div>
|
||||
<div class="cron-title">Dashboard review</div>
|
||||
<div class="cron-desc">Read the 03:00 auto-update, review KPIs, see what changed overnight</div>
|
||||
</div>
|
||||
<div class="cron-item daily-hour">
|
||||
<div class="cron-time">09:05 – 09:15</div>
|
||||
<div class="cron-title">Status sync</div>
|
||||
<div class="cron-desc">Reply to dashboard comments, update action statuses, unblock items</div>
|
||||
</div>
|
||||
<div class="cron-item daily-hour">
|
||||
<div class="cron-time">09:15 – 09:45</div>
|
||||
<div class="cron-title">Deep work</div>
|
||||
<div class="cron-desc">Execute today's priority actions (outreach emails, content drafts, influencer DMs)</div>
|
||||
</div>
|
||||
<div class="cron-item daily-hour">
|
||||
<div class="cron-time">09:45 – 10:00</div>
|
||||
<div class="cron-title">Wrap & queue</div>
|
||||
<div class="cron-desc">Set tomorrow's priorities, queue tasks for the cron, log progress</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-card">
|
||||
<h3>🤖 Automated Cron Jobs</h3>
|
||||
<div class="cron-timeline">
|
||||
<div class="cron-item">
|
||||
<div class="cron-time">03:00 PYST</div>
|
||||
<div class="cron-title">📊 Dashboard Update</div>
|
||||
<div class="cron-desc">Auto-generates KPI snapshot: signups, traffic, backlinks, influencer status. Writes to <code>data/launch-status.json</code> for Oliver to review at 09:00.</div>
|
||||
</div>
|
||||
<div class="cron-item">
|
||||
<div class="cron-time">03:10 PYST</div>
|
||||
<div class="cron-title">📈 SEO & Rank Tracker</div>
|
||||
<div class="cron-desc">Check Google Search Console for new impressions/clicks. Log keyword positions for target terms. Alert on +50% change.</div>
|
||||
</div>
|
||||
<div class="cron-item">
|
||||
<div class="cron-time">03:20 PYST</div>
|
||||
<div class="cron-title">🔗 Backlink Monitor</div>
|
||||
<div class="cron-desc">Check Ahrefs/Moz API for new backlinks. Update backlink KPI count. Flag new domains referring.</div>
|
||||
</div>
|
||||
<div class="cron-item">
|
||||
<div class="cron-time">03:30 PYST</div>
|
||||
<div class="cron-title">💬 Social Monitor</div>
|
||||
<div class="cron-desc">Check X/Twitter for brand mentions, reply to inquiries, log sentiment.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── ITEMS NEEDED ──────────────────────────── -->
|
||||
<div class="section">
|
||||
<div class="section-header" onclick="toggleSection('items-section', this)">
|
||||
<h2><span class="icon">📦</span> Items Needed From You</h2>
|
||||
<span class="section-toggle">▼</span>
|
||||
</div>
|
||||
<div class="section-body" id="items-section">
|
||||
<div class="info-card">
|
||||
<p style="margin-bottom:16px;font-size:13px;color:var(--text-muted);">
|
||||
Check off items as you deliver them. This list is saved in your browser.
|
||||
</p>
|
||||
<ul id="needs-list">
|
||||
<!-- populated by JS -->
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── OUTCOME TARGETS ───────────────────────── -->
|
||||
<div class="section">
|
||||
<div class="section-header" onclick="toggleSection('targets-section', this)">
|
||||
<h2><span class="icon">🏆</span> 14-Day Targets</h2>
|
||||
<span class="section-toggle">▼</span>
|
||||
</div>
|
||||
<div class="section-body" id="targets-section">
|
||||
<div class="grid-3">
|
||||
<div class="info-card">
|
||||
<h3>👥 Friends & Family</h3>
|
||||
<ul>
|
||||
<li><span class="bullet">•</span> 20 beta signups</li>
|
||||
<li><span class="bullet">•</span> 5 video testimonials</li>
|
||||
<li><span class="bullet">•</span> 8 NPS responses (target: 8+)</li>
|
||||
<li><span class="bullet">•</span> 3 bug/UX improvement reports</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="info-card">
|
||||
<h3>📣 Reach & Visibility</h3>
|
||||
<ul>
|
||||
<li><span class="bullet">•</span> 5 influencer partnerships</li>
|
||||
<li><span class="bullet">•</span> 10 quality backlinks</li>
|
||||
<li><span class="bullet">•</span> 500 unique landing page visitors</li>
|
||||
<li><span class="bullet">•</span> 50 email list signups</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="info-card">
|
||||
<h3>📈 SEO & Rankings</h3>
|
||||
<ul>
|
||||
<li><span class="bullet">•</span> Indexed in Google (<7 days)</li>
|
||||
<li><span class="bullet">•</span> Top 5 for "AI agent hosting"</li>
|
||||
<li><span class="bullet">•</span> 3 directory listings live</li>
|
||||
<li><span class="bullet">•</span> 2 guest posts published</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<br><br>
|
||||
|
||||
<script>
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
DATA — strategy & action plan
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
|
||||
const DAY_ONE = new Date("2026-06-09T00:00:00-04:00"); // today
|
||||
|
||||
const KPIS = [
|
||||
{ id: "signups", label: "Friends & Family Signups", current: 0, target: 20, unit: "", color: "green" },
|
||||
{ id: "visitors", label: "Landing Page Visitors", current: 0, target: 500, unit: "", color: "blue" },
|
||||
{ id: "emails", label: "Email Captures", current: 0, target: 50, unit: "", color: "blue" },
|
||||
{ id: "backlinks", label: "Quality Backlinks", current: 0, target: 10, unit: "", color: "yellow" },
|
||||
{ id: "influencers", label: "Influencer Partnerships", current: 0, target: 5, unit: "", color: "green" },
|
||||
{ id: "testimonials", label: "Testimonials Collected", current: 0, target: 5, unit: "", color: "green" },
|
||||
{ id: "impressions", label: "Google Impressions (7d)", current: 0, target: 2000, unit: "", color: "blue" },
|
||||
{ id: "directory", label: "Directory Listings", current: 0, target: 3, unit: "", color: "yellow" },
|
||||
];
|
||||
|
||||
const ACTIONS = [
|
||||
// ── Day 1 ──
|
||||
{ day: 1, action: "Set up friends & family invite list (20–30 contacts)", owner: "Oliver", status: "today" },
|
||||
{ day: 1, action: "Generate & configure referral coupon codes in Stripe", owner: "Mint", status: "today" },
|
||||
{ day: 1, action: "Create prelaunch landing page / launch-dashboard", owner: "Mint", status: "done" },
|
||||
{ day: 1, action: "Submit to Google Search Console + Bing Webmaster Tools", owner: "Mint", status: "pending" },
|
||||
{ day: 1, action: "Set up UTM tracking for all campaign links", owner: "Mint", status: "pending" },
|
||||
// ── Day 2 ──
|
||||
{ day: 2, action: "Send friends & family invitation emails", owner: "Oliver", status: "pending" },
|
||||
{ day: 2, action: "Create F&F onboarding docs (1-pager + video)", owner: "Mint", status: "pending" },
|
||||
{ day: 2, action: "Set up dedicated F&F Telegram/Discord group", owner: "Mint", status: "pending" },
|
||||
{ day: 2, action: "Submit to Product Hunt — create draft listing", owner: "Oliver", status: "pending" },
|
||||
// ── Day 3 ──
|
||||
{ day: 3, action: "Start influencer research: compile list of 30 targets", owner: "Oliver", status: "pending" },
|
||||
{ day: 3, action: "Write influencer outreach email template", owner: "Mint", status: "pending" },
|
||||
{ day: 3, action: "Submit to BetaList, AlternativeTo, G2 directories", owner: "Mint", status: "pending" },
|
||||
// ── Day 4 ──
|
||||
{ day: 4, action: "Send first batch of influencer DMs/emails (top 10)", owner: "Oliver", status: "pending" },
|
||||
{ day: 4, action: "Pitch guest post: 'Deploy AI agents in 5 min' to 5 blogs", owner: "Mint", status: "pending" },
|
||||
{ day: 4, action: "Set up HARO / Qwoted / Connectively alerts", owner: "Mint", status: "pending" },
|
||||
{ day: 4, action: "First friends & family onboardings go live", owner: "Oliver", status: "pending" },
|
||||
// ── Day 5 ──
|
||||
{ day: 5, action: "Follow up on influencer DMs (non-responders)", owner: "Oliver", status: "pending" },
|
||||
{ day: 5, action: "Create 3 social posts (X/LinkedIn) about launch", owner: "Mint", status: "pending" },
|
||||
{ day: 5, action: "Send F&F NPS survey #1", owner: "Mint", status: "pending" },
|
||||
// ── Day 6 ──
|
||||
{ day: 6, action: "Publish first social proof tweet: F&F testimonial", owner: "Oliver", status: "pending" },
|
||||
{ day: 6, action: "Write blog post: 'Why I built Derez.ai'", owner: "Oliver", status: "pending" },
|
||||
{ day: 6, action: "Check Google indexing status — escalate if not indexed", owner: "Mint", status: "pending" },
|
||||
// ── Day 7 ──
|
||||
{ day: 7, action: "Mid-campaign review: KPI check vs targets", owner: "Both", status: "pending" },
|
||||
{ day: 7, action: "Second batch influencer outreach (next 10 targets)", owner: "Oliver", status: "pending" },
|
||||
{ day: 7, action: "Polish Product Hunt listing with F&F feedback quotes", owner: "Mint", status: "pending" },
|
||||
// ── Day 8 ──
|
||||
{ day: 8, action: "Guest post #1 published — monitor backlinks", owner: "Mint", status: "pending" },
|
||||
{ day: 8, action: "Send affiliate program details to confirmed influencers", owner: "Oliver", status: "pending" },
|
||||
{ day: 8, action: "Content sprint: write 5 more social posts", owner: "Mint", status: "pending" },
|
||||
// ── Day 9 ──
|
||||
{ day: 9, action: "Follow up guest post pitches — pitch 5 more blogs", owner: "Mint", status: "pending" },
|
||||
{ day: 9, action: "Record demo video (screen recording 3 min)", owner: "Oliver", status: "pending" },
|
||||
{ day: 9, action: "Email list: send first newsletter teaser", owner: "Mint", status: "pending" },
|
||||
// ── Day 10 ──
|
||||
{ day: 10, action: "Launch day prep: schedule Product Hunt live", owner: "Oliver", status: "pending" },
|
||||
{ day: 10, action: "Coordinate influencer posts for launch day", owner: "Both", status: "pending" },
|
||||
{ day: 10, action: "Prepare launch day email blast", owner: "Mint", status: "pending" },
|
||||
// ── Day 11 ──
|
||||
{ day: 11, action: "🚀 LAUNCH DAY — Product Hunt go-live", owner: "Both", status: "pending" },
|
||||
{ day: 11, action: "Social storm: all platforms post simultaneously", owner: "Oliver", status: "pending" },
|
||||
{ day: 11, action: "Influencers publish their content", owner: "Influencers", status: "pending" },
|
||||
// ── Day 12 ──
|
||||
{ day: 12, action: "Post-launch: reply to every Product Hunt comment", owner: "Oliver", status: "pending" },
|
||||
{ day: 12, action: "Monitor signups & traffic spike — adjust messaging", owner: "Mint", status: "pending" },
|
||||
// ── Day 13 ──
|
||||
{ day: 13, action: "Follow up on all pending leads from launch", owner: "Oliver", status: "pending" },
|
||||
{ day: 13, action: "Send thank-you emails to F&F + influencers", owner: "Mint", status: "pending" },
|
||||
// ── Day 14 ──
|
||||
{ day: 14, action: "Final KPI review & retrospective", owner: "Both", status: "pending" },
|
||||
{ day: 14, action: "Compile lessons learned doc", owner: "Mint", status: "pending" },
|
||||
{ day: 14, action: "Decide: full public launch or iterate based on data", owner: "Oliver", status: "pending" },
|
||||
];
|
||||
|
||||
const NEEDS = [
|
||||
{ id: "n1", text: "List of 20–30 friends & family contacts (name + email)", done: false },
|
||||
{ id: "n2", text: "Target influencer list (30 names, handles/emails, niche, follower count)", done: false },
|
||||
{ id: "n3", text: "Influencer partnership budget (free plans? cash? affiliate %?)", done: false },
|
||||
{ id: "n4", text: "OpenRouter coupon codes for referral program (5 needed)", done: false },
|
||||
{ id: "n5", text: "Product demo video (3 min screen recording) or go-ahead to record one", done: false },
|
||||
{ id: "n6", text: "3–5 screenshots of dashboard / agent setup flow", done: false },
|
||||
{ id: "n7", text: "Social media account access (X/Twitter + LinkedIn posting access)", done: false },
|
||||
{ id: "n8", text: "Personal story / 'Why I built Derez.ai' notes for blog post", done: false },
|
||||
{ id: "n9", text: "Competitor list (5–10 names) for backlink gap analysis", done: false },
|
||||
{ id: "n10", text: "Price anchoring: confirm if F&F get special discount or free month", done: false },
|
||||
{ id: "n11", text: "HARO / Qwoted / Connectively account (or credentials to set up)", done: false },
|
||||
{ id: "n12", text: "Google Search Console access for derez.ai", done: true },
|
||||
];
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
RENDER
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
|
||||
function getDayNumber() {
|
||||
const now = new Date();
|
||||
const diff = Math.floor((now - DAY_ONE) / (1000 * 60 * 60 * 24));
|
||||
return Math.max(1, Math.min(14, diff + 1));
|
||||
}
|
||||
|
||||
function renderDay() {
|
||||
const day = getDayNumber();
|
||||
document.getElementById("day-indicator").textContent =
|
||||
`Day ${day} of 14 — ${14 - day} days until launch`;
|
||||
}
|
||||
|
||||
function renderKPIs(kpis) {
|
||||
const grid = document.getElementById("kpi-grid");
|
||||
grid.innerHTML = kpis.map(k => {
|
||||
const pct = k.target > 0 ? Math.min(100, Math.round((k.current / k.target) * 100)) : 0;
|
||||
const barColor = k.color || "blue";
|
||||
return `
|
||||
<div class="kpi-card">
|
||||
<div class="kpi-label">${k.label}</div>
|
||||
<div class="kpi-value">${k.current} <span class="target">/ ${k.target}${k.unit}</span></div>
|
||||
<div class="kpi-bar"><div class="kpi-bar-fill ${barColor}" style="width:${pct}%"></div></div>
|
||||
<div class="kpi-sub">${pct}% of target</div>
|
||||
</div>
|
||||
`;
|
||||
}).join("");
|
||||
}
|
||||
|
||||
function renderActions(actions) {
|
||||
const tbody = document.getElementById("action-rows");
|
||||
const day = getDayNumber();
|
||||
tbody.innerHTML = actions.map(a => {
|
||||
let statusClass = a.status;
|
||||
let statusLabel = a.status.replace("-", " ").replace(/\b\w/g, c => c.toUpperCase());
|
||||
return `
|
||||
<tr>
|
||||
<td class="day-col">Day ${a.day}</td>
|
||||
<td>${a.action}</td>
|
||||
<td class="owner-col">${a.owner}</td>
|
||||
<td class="status-col"><span class="status-tag ${statusClass}">${statusLabel}</span></td>
|
||||
</tr>
|
||||
`;
|
||||
}).join("");
|
||||
}
|
||||
|
||||
function renderNeeds(needs) {
|
||||
const list = document.getElementById("needs-list");
|
||||
list.innerHTML = needs.map(n => `
|
||||
<li class="need-item${n.done ? ' done' : ''}">
|
||||
<span class="need-checkbox${n.done ? ' checked' : ''}" data-id="${n.id}" onclick="toggleNeed('${n.id}')"></span>
|
||||
<span class="need-text">${n.text}</span>
|
||||
</li>
|
||||
`).join("");
|
||||
}
|
||||
|
||||
function toggleNeed(id) {
|
||||
const needs = getNeeds();
|
||||
const idx = needs.findIndex(n => n.id === id);
|
||||
if (idx === -1) return;
|
||||
needs[idx].done = !needs[idx].done;
|
||||
localStorage.setItem("derez-needs", JSON.stringify(needs));
|
||||
renderNeeds(needs);
|
||||
}
|
||||
|
||||
function getNeeds() {
|
||||
try {
|
||||
const saved = localStorage.getItem("derez-needs");
|
||||
if (saved) {
|
||||
const parsed = JSON.parse(saved);
|
||||
// Merge with defaults — keep done states
|
||||
return NEEDS.map(def => {
|
||||
const s = parsed.find(p => p.id === def.id);
|
||||
return s ? { ...def, done: s.done } : def;
|
||||
});
|
||||
}
|
||||
} catch(e) {}
|
||||
return NEEDS;
|
||||
}
|
||||
|
||||
/* ── Toggle sections ─────────────────────────── */
|
||||
function toggleSection(id, header) {
|
||||
const body = document.getElementById(id);
|
||||
const toggle = header.querySelector(".section-toggle");
|
||||
body.classList.toggle("hidden");
|
||||
toggle.classList.toggle("collapsed");
|
||||
}
|
||||
|
||||
/* ── Load data from JSON (if available) ───────── */
|
||||
async function loadData() {
|
||||
try {
|
||||
const res = await fetch("data/launch-status.json?_=" + Date.now());
|
||||
if (!res.ok) throw new Error("No data file yet");
|
||||
const data = await res.json();
|
||||
if (data.kpis) {
|
||||
// Merge server KPIs with our defaults
|
||||
const merged = KPIS.map(k => {
|
||||
const s = data.kpis.find(d => d.id === k.id);
|
||||
return s ? { ...k, current: s.current } : k;
|
||||
});
|
||||
renderKPIs(merged);
|
||||
}
|
||||
if (data.actions) {
|
||||
const merged = ACTIONS.map(a => {
|
||||
const s = data.actions.find(d => d.day === a.day && d.action === a.action);
|
||||
return s ? { ...a, status: s.status } : a;
|
||||
});
|
||||
renderActions(merged);
|
||||
}
|
||||
if (data.updated) {
|
||||
document.getElementById("last-updated").textContent =
|
||||
"Updated: " + new Date(data.updated).toLocaleString("en-US", {
|
||||
month: "short", day: "numeric", hour: "2-digit", minute: "2-digit"
|
||||
});
|
||||
}
|
||||
} catch(e) {
|
||||
// No data file yet — render defaults
|
||||
renderKPIs(KPIS);
|
||||
renderActions(ACTIONS);
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Init ────────────────────────────────────── */
|
||||
renderDay();
|
||||
renderNeeds(getNeeds());
|
||||
loadData();
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user