Files
derez.ai/operations.html
T

1049 lines
43 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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>Daily Brief — Derez.ai Operations</title>
<style>
: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: #e0f4ff;
--text-muted: #3a8aaa;
--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: 1100px;
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; -webkit-font-smoothing: antialiased; }
body {
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", sans-serif;
background: var(--bg);
color: var(--text);
font-size: 14px;
line-height: 1.7;
overflow-x: hidden;
padding: 32px 0;
}
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;
}
code {
font-family: "JetBrains Mono", "Fira Code", "Cascadia Code", "Consolas", monospace;
font-size: 0.9em;
}
/* ── Brief Header ────────────────────────── */
.brief-header {
text-align: center;
margin-bottom: 32px;
padding: 36px 28px 28px;
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius-card);
box-shadow: var(--shadow);
}
.brief-header .date {
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--text-muted);
margin-bottom: 6px;
}
.brief-header h1 {
font-size: 26px;
font-weight: 700;
color: var(--accent);
}
.brief-header .sub {
font-size: 13px;
color: var(--text-muted);
margin-top: 6px;
}
.brief-header .badge-row {
display: flex;
justify-content: center;
gap: 10px;
flex-wrap: wrap;
margin-top: 14px;
}
.brief-header .badge {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 4px 14px;
border-radius: 999px;
font-size: 11px;
font-weight: 600;
}
.badge.live { background: rgba(0,255,136,0.12); color: var(--success); border: 1px solid rgba(0,255,136,0.3); }
.badge.warn { background: rgba(255,170,0,0.12); color: var(--warning); border: 1px solid rgba(255,170,0,0.3); }
.badge.info { background: rgba(0,245,255,0.1); color: var(--accent); border: 1px solid rgba(0,245,255,0.2); }
.updated { font-size: 11px; color: var(--text-muted); margin-top: 12px; opacity: 0.6; }
/* ── Section ─────────────────────────────── */
.section { margin-bottom: 32px; }
.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); font-size: 18px; }
.section-header .count {
font-size: 11px;
color: var(--text-muted);
font-weight: 400;
}
.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; }
/* ── Q2 Goals Grid ───────────────────────── */
.goals-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
gap: 14px;
}
.goal-card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius-card);
padding: 20px;
}
.goal-card .goal-label {
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--text-muted);
margin-bottom: 4px;
}
.goal-card .goal-current {
font-size: 28px;
font-weight: 700;
color: var(--text);
}
.goal-card .goal-target {
font-size: 14px;
color: var(--text-muted);
}
.goal-card .goal-bar {
margin-top: 10px;
height: 4px;
background: var(--bg-inner);
border-radius: 2px;
overflow: hidden;
}
.goal-card .goal-bar-fill {
height: 100%;
border-radius: 2px;
transition: width 0.6s ease;
}
.goal-card .goal-bar-fill.green { background: var(--success); }
.goal-card .goal-bar-fill.blue { background: var(--accent); }
.goal-card .goal-bar-fill.yellow { background: var(--warning); }
.goal-card .goal-bar-fill.red { background: var(--danger); }
.goal-card .goal-sub {
font-size: 11px;
color: var(--text-muted);
margin-top: 4px;
}
/* ── Campaign Cards ──────────────────────── */
.campaign-grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 14px;
}
.campaign-card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius-card);
padding: 20px;
}
.campaign-card h3 {
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--accent);
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 8px;
}
.campaign-card .status-tag {
display: inline-block;
font-size: 10px;
padding: 2px 8px;
border-radius: 4px;
font-weight: 600;
}
.campaign-card .status-tag.active { background: rgba(0,255,136,0.12); color: var(--success); border: 1px solid rgba(0,255,136,0.25); }
.campaign-card .status-tag.paused { background: rgba(255,170,0,0.12); color: var(--warning); border: 1px solid rgba(255,170,0,0.3); }
.campaign-card .status-tag.draft { background: rgba(46,106,128,0.15); color: var(--text-muted); border: 1px solid transparent; }
.campaign-card .stat-row {
display: flex;
gap: 16px;
margin-bottom: 10px;
}
.campaign-card .stat-item {
text-align: center;
flex: 1;
}
.campaign-card .stat-num {
font-size: 24px;
font-weight: 700;
color: var(--text);
}
.campaign-card .stat-label {
font-size: 10px;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.04em;
}
.campaign-card ul {
list-style: none;
margin-top: 6px;
}
.campaign-card li {
font-size: 12px;
padding: 5px 0;
border-bottom: 1px solid rgba(10,48,96,0.3);
display: flex;
align-items: center;
gap: 6px;
}
.campaign-card li:last-child { border-bottom: none; }
.campaign-card li .dot {
width: 6px; height: 6px;
border-radius: 50%;
flex-shrink: 0;
}
.dot.green { background: var(--success); }
.dot.red { background: var(--danger); }
.dot.yellow { background: var(--warning); }
/* ── Action Items ────────────────────────── */
.action-list { list-style: none; }
.action-item {
background: var(--bg-card);
border: 1px solid var(--border);
border-left: 3px solid var(--accent);
border-radius: var(--radius-card);
padding: 20px 24px;
margin-bottom: 12px;
display: flex;
align-items: flex-start;
gap: 14px;
}
.action-item .action-num {
width: 28px; height: 28px;
border-radius: 50%;
background: var(--accent-dim);
border: 1px solid var(--accent);
color: var(--accent);
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: 700;
flex-shrink: 0;
}
.action-item .action-body h4 {
font-size: 14px;
color: var(--text);
margin-bottom: 3px;
}
.action-item .action-body p {
font-size: 12px;
color: var(--text-muted);
}
.action-item .action-owner {
font-size: 11px;
color: var(--accent);
margin-top: 4px;
}
/* ── Items Needed (interactive checkboxes) ── */
.needs-card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius-card);
padding: 24px;
}
.needs-card .needs-intro {
font-size: 13px;
color: var(--text-muted);
margin-bottom: 16px;
}
.needs-list { list-style: none; }
.needs-list li {
display: flex;
align-items: flex-start;
gap: 12px;
padding: 10px 0;
border-bottom: 1px solid rgba(10,48,96,0.3);
}
.needs-list li:last-child { border-bottom: none; }
.need-checkbox {
width: 20px;
height: 20px;
min-width: 20px;
border: 2px solid var(--border);
border-radius: 5px;
flex-shrink: 0;
margin-top: 2px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.15s;
}
.need-checkbox:hover {
border-color: var(--accent);
}
.need-checkbox.checked {
background: var(--success);
border-color: var(--success);
}
.need-checkbox.checked::after {
content: "✓";
color: var(--bg);
font-size: 14px;
font-weight: 700;
}
.need-item.done .need-text {
color: var(--text-muted);
text-decoration: line-through;
}
.need-text {
font-size: 14px;
color: var(--text);
line-height: 1.6;
}
/* ── Strategy ────────────────────────────── */
.strategy-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
}
.strategy-card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius-card);
padding: 22px;
}
.strategy-card h3 {
font-size: 13px;
font-weight: 700;
color: var(--accent);
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 8px;
}
.strategy-card p, .strategy-card li {
font-size: 13px;
color: var(--text);
line-height: 1.7;
}
.strategy-card ul {
list-style: none;
padding: 0;
}
.strategy-card ul li {
padding: 4px 0;
}
.strategy-card ul li::before {
content: " ";
color: var(--accent);
}
.strategy-card .highlight { color: var(--accent); }
/* ── Recommendations ─────────────────────── */
.reco-list { list-style: none; }
.reco-list li {
padding: 10px 16px;
margin-bottom: 8px;
background: var(--bg-card);
border: 1px solid var(--border);
border-left: 3px solid var(--accent);
border-radius: var(--radius-card);
font-size: 13px;
display: flex;
align-items: flex-start;
gap: 10px;
}
.reco-list li .reco-icon {
color: var(--accent);
flex-shrink: 0;
font-weight: 700;
}
/* ── Communications ──────────────────────── */
.comms-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
}
.comms-card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius-card);
padding: 20px;
}
.comms-card h3 {
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--accent);
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 8px;
}
.comms-card .comms-summary {
display: flex;
gap: 20px;
margin-bottom: 12px;
}
.comms-card .comms-stat {
text-align: center;
}
.comms-card .comms-stat-num {
font-size: 24px;
font-weight: 700;
color: var(--text);
}
.comms-card .comms-stat-label {
font-size: 10px;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.04em;
}
.comms-list { list-style: none; }
.comms-list li {
font-size: 12px;
padding: 6px 0;
border-bottom: 1px solid rgba(10,48,96,0.3);
display: flex;
align-items: flex-start;
gap: 8px;
line-height: 1.5;
}
.comms-list li:last-child { border-bottom: none; }
.comms-list .comms-time {
color: var(--text-muted);
font-size: 11px;
white-space: nowrap;
flex-shrink: 0;
min-width: 60px;
}
.comms-list .comms-subj {
color: var(--text);
}
.comms-list .comms-detail {
color: var(--text-muted);
font-size: 11px;
}
.comms-list .comms-from {
color: var(--accent);
font-size: 11px;
}
.comms-alert {
background: var(--bg-card);
border: 1px solid rgba(255,59,59,0.3);
border-left: 3px solid var(--danger);
border-radius: var(--radius-card);
padding: 12px 16px;
margin-top: 10px;
font-size: 12px;
display: flex;
align-items: flex-start;
gap: 8px;
}
.comms-alert .alert-icon { color: var(--danger); flex-shrink: 0; font-size: 14px; }
.comms-alert .alert-body { color: var(--text); }
.comms-alert .alert-detail { color: var(--text-muted); font-size: 11px; margin-top: 2px; }
/* ── Daily Routine (from old dashboard) ──── */
.grid-2 {
display: grid;
grid-template-columns: 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;
}
.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;
line-height: 1.6;
}
/* ── Progress badge ──────────────────────── */
.progress-tag {
display: inline-block;
padding: 2px 10px;
border-radius: 999px;
font-size: 11px;
font-weight: 600;
}
.progress-tag.done { background: rgba(0,255,136,0.12); color: var(--success); border: 1px solid rgba(0,255,136,0.25); }
.progress-tag.in-progress { background: rgba(0,245,255,0.12); color: var(--accent); border: 1px solid rgba(0,245,255,0.25); }
.progress-tag.pending { background: rgba(46,106,128,0.15); color: var(--text-muted); border: 1px solid transparent; }
.progress-tag.blocked { background: rgba(255,59,59,0.12); color: var(--danger); border: 1px solid rgba(255,59,59,0.25); }
.progress-tag.today { background: rgba(255,170,0,0.15); color: var(--warning); border: 1px solid rgba(255,170,0,0.3); }
.highlight { color: var(--accent); }
@media (max-width: 900px) {
.campaign-grid { grid-template-columns: 1fr; }
.comms-grid { grid-template-columns: 1fr; }
.goals-grid { grid-template-columns: repeat(2, 1fr); }
.strategy-grid { grid-template-columns: 1fr; }
.grid-2 { grid-template-columns: 1fr; }
}
@media (max-width: 500px) {
.goals-grid { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="container">
<!-- ═══════════════ BRIEF HEADER ═══════════════ -->
<div class="brief-header">
<div class="date" id="brief-date">Loading...</div>
<h1>☕ Daily Brief &mdash; Q2 2026</h1>
<div class="sub">derez.ai &middot; Operations Dashboard</div>
<div class="badge-row">
<span class="badge live">● Site Live</span>
<span class="badge warn">● Prelaunch</span>
<span class="badge info">◉ 89 CRM Contacts</span>
</div>
<div class="updated" id="brief-updated">Last updated: &mdash;</div>
</div>
<!-- ═══════════════ Q2 GOALS ═══════════════ -->
<div class="section">
<div class="section-header" onclick="toggleSection('goals-section', this)">
<h2><span class="icon">🎯</span> Q2/2026 Goals</h2>
<span class="section-toggle"></span>
</div>
<div class="section-body" id="goals-section">
<div class="goals-grid" id="goals-grid"></div>
</div>
</div>
<!-- ═══════════════ CAMPAIGNS ═══════════════ -->
<div class="section">
<div class="section-header" onclick="toggleSection('campaigns-section', this)">
<h2><span class="icon">📡</span> Campaigns <span class="count">overview</span></h2>
<span class="section-toggle"></span>
</div>
<div class="section-body" id="campaigns-section">
<div class="campaign-grid" id="campaign-grid"></div>
</div>
</div>
<!-- ═══════════════ ACTION ITEMS ═══════════════ -->
<div class="section">
<div class="section-header" onclick="toggleSection('actions-section', this)">
<h2><span class="icon"></span> Action Items <span class="count">needs your attention</span></h2>
<span class="section-toggle"></span>
</div>
<div class="section-body" id="actions-section">
<ul class="action-list" id="action-list"></ul>
</div>
</div>
<!-- ═══════════════ ITEMS NEEDED (INTERACTIVE CHECKBOXES) ═══════════════ -->
<div class="section">
<div class="section-header" onclick="toggleSection('needs-section', this)">
<h2><span class="icon">📦</span> Items Needed From You <span class="count">check off as delivered</span></h2>
<span class="section-toggle"></span>
</div>
<div class="section-body" id="needs-section">
<div class="needs-card">
<p class="needs-intro">
Click a checkbox to mark it done &mdash; saved in your browser.
</p>
<ul class="needs-list" id="needs-list"></ul>
</div>
</div>
</div>
<!-- ═══════════════ COMMUNICATIONS ═══════════════ -->
<div class="section">
<div class="section-header" onclick="toggleSection('comms-section', this)">
<h2><span class="icon"></span> Communications <span class="count">last 35 hours</span></h2>
<span class="section-toggle"></span>
</div>
<div class="section-body" id="comms-section">
<div class="comms-grid" id="comms-grid"></div>
</div>
</div>
<!-- ═══════════════ DAILY ROUTINE ═══════════════ -->
<div class="section">
<div class="section-header" onclick="toggleSection('routine-section', this)">
<h2><span class="icon"></span> Daily Routine &amp; 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) &mdash; 60 minutes.</p>
<div class="cron-timeline">
<div class="cron-item daily-hour">
<div class="cron-time">09:00 &ndash; 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 &ndash; 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 &ndash; 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 &ndash; 10:00</div>
<div class="cron-title">Wrap &amp; 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/operations.json</code> for review at 09:00.</div>
</div>
<div class="cron-item">
<div class="cron-time">03:10 PYST</div>
<div class="cron-title">📈 SEO &amp; Rank Tracker</div>
<div class="cron-desc">Check Google Search Console for new impressions/clicks. Log keyword positions. 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 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>
<!-- ═══════════════ STRATEGY & RECOMMENDATIONS ═══════════════ -->
<div class="section">
<div class="section-header" onclick="toggleSection('strategy-section', this)">
<h2><span class="icon">🧠</span> Strategy Overview &amp; Recommendations</h2>
<span class="section-toggle"></span>
</div>
<div class="section-body" id="strategy-section">
<div class="strategy-grid" id="strategy-grid"></div>
<br>
<ul class="reco-list" id="reco-list"></ul>
</div>
</div>
</div>
<script>
/* ═══════════════ DATA ═══════════════════════ */
const goals = [
{ id: 'active-contacts', label: 'Active Contacts', current: 1, target: 60, note: 'CRM: Cold to Won (88 on Hold excluded)' },
{ id: 'subscriptions', label: 'Subscriptions', current: 0, target: 50, note: 'Paying customers' },
{ id: 'influencers', label: 'Influencers', current: 0, target: 20, note: 'YT creators & affiliates on board' },
{ id: 'visitors', label: 'Page Visitors', current: 0, target: 10000, unit: '/mo', note: 'Monthly unique visitors' },
{ id: 'outreach-sent', label: 'Cold Emails Sent', current: 0, target: 100, note: 'First touch emails' },
{ id: 'crm-contacts', label: 'CRM Contacts', current: 89, target: 200, note: 'Total contacts collected' },
];
const campaigns = [
{
label: '✉ Cold Mail', status: 'draft',
metrics: [{ v: 0, l: 'Drafted' }, { v: 0, l: 'Sent' }, { v: 0, l: 'Replied' }],
items: [
{ t: 'Coupon codes: friends950, creator950', ok: true },
{ t: 'Template signed as Mark — Customer Agent', ok: true },
{ t: 'No Cold contacts with real emails yet', ok: false },
]
},
{
label: '🎙 Influencer', status: 'paused',
metrics: [{ v: 60, l: 'Identified' }, { v: 0, l: 'Contacted' }, { v: 0, l: 'Onboarded' }],
items: [
{ t: '60 YouTube creators on Hold', ok: true },
{ t: 'Need business emails for top 20', ok: false },
{ t: 'Affiliate program TBD', ok: false },
]
},
{
label: '🔗 LinkedIn', status: 'draft',
metrics: [{ v: 0, l: 'Connections' }, { v: 0, l: 'Outreach' }, { v: 0, l: 'Replied' }],
items: [
{ t: 'No outreach started yet', ok: false },
{ t: 'Company page TBD', ok: false },
{ t: 'No content strategy defined', ok: false },
]
}
];
const actions = [
{ num: 1, title: 'Prioritise top 20 YouTube creators for outreach', desc: 'From the 60 YT creators on Hold — pick the most relevant 20 for first-wave influencer outreach.', owner: 'Oliver' },
{ num: 2, title: 'Collect business emails for top 20 creators', desc: 'Research and collect real business emails from the prioritised creators\' websites or social bios.', owner: 'Mint' },
{ num: 3, title: 'Send first cold email batch', desc: 'Using friends950 / creator950 coupons. Draft goes to Telegram for confirmation first.', owner: 'Oliver + Mint' },
];
const NEEDS = [
{ id: "n1", text: "List of 2030 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: "35 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 (510 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 },
];
const strategyCards = [
{
icon: '📢', title: 'Influencer Outreach',
body: 'Target 60 YouTube creators in AI/ML/DevOps. Offer free 3-month agent + affiliate commission (10% recurring). Pitch: "Your followers can deploy AI agents in 5 minutes — no DevOps needed."',
goal: 'Goal: 20 onboarded, 3+ social mentions'
},
{
icon: '👨‍👩‍👧‍👦', title: 'Cold Email',
body: 'Templates and coupons ready (friends950, creator950). Signed as Mark — Customer Success Agent. All drafts reviewed via Telegram before sending.',
goal: 'Goal: 100 emails sent, 10+ replies'
},
{
icon: '🔗', title: 'LinkedIn Presence',
body: 'Zero LinkedIn presence currently. Need company page, connection building, and content strategy before outreach can begin.',
goal: 'Goal: Company page live, 100 connections'
},
{
icon: '📈', title: 'SEO & Analytics',
body: 'Plausible analytics live on derez.ai with 7 custom events tracked. Weekly cron monitors insights. Need Search Console submission and directory listings.',
goal: 'Goal: 10K monthly visitors, top 5 for "AI agent hosting"'
}
];
const comms = {
inbox: {
total: 4,
last35h: 2,
items: [
{ time: 'Jun 09 14:44', from: 'Mail Delivery System', subj: 'Undelivered — the@123.de', detail: '421 Downstream server error — cold email bounced', alert: true },
{ time: 'Jun 08 21:04', from: 'Mail Delivery System', subj: 'Undelivered — the@123.de', detail: '421 Downstream server error', alert: false },
],
alerts: [
{ icon: '⚠', body: 'Cold email to the@123.de bouncing (421 Downstream server error)', detail: 'Check recipient email validity or retry later.' }
]
},
sent: {
total: 8,
last35h: 2,
items: [
{ time: 'Jun 09', to: 'o.arnold@projektbox.de', subj: 'setting up an agent for projektbox' },
{ time: 'Jun 08', to: 'oliver@odoo4projects.com', subj: 'managing your agents without SSH' },
],
top_sent: 'Mark — Customer Success Agent'
},
note: '2 bounce alerts need review. Sending from support@derez.ai as Mark.'
};
const recommendations = [
'Prioritise the top 20 YouTube creators from the 60 collected — these are your most winnable influencer channel.',
'Unlock cold email outreach by populating real business emails for those 20 creators. Templates and coupons are ready.',
'Set up a LinkedIn company page and start building connections — zero presence there currently.',
'Email capturing (newsletter signup or lead magnet) is needed before 10K visitors/mo becomes realistic.',
];
/* ═══════════════ RENDER ═══════════════════════ */
function fmtDate() {
return new Date().toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
}
function pct(cur, target) { return target > 0 ? Math.min(100, Math.round(cur / target * 100)) : 0; }
function barClass(p) { return p >= 80 ? 'green' : p >= 40 ? 'blue' : p >= 20 ? 'yellow' : 'red'; }
function toggleSection(id, header) {
const el = document.getElementById(id);
const toggle = header.querySelector('.section-toggle');
el.classList.toggle('hidden');
toggle.classList.toggle('collapsed');
}
function renderGoals() {
document.getElementById('goals-grid').innerHTML = goals.map(g => {
const p = pct(g.current, g.target);
const bc = barClass(p);
return `<div class="goal-card">
<div class="goal-label">${g.label}</div>
<div class="goal-current">${g.current}<span class="goal-target"> / ${g.target} ${g.unit || ''}</span></div>
<div class="goal-bar"><div class="goal-bar-fill ${bc}" style="width:${p}%"></div></div>
<div class="goal-sub">${g.note}</div>
</div>`;
}).join('');
}
function renderCampaigns() {
document.getElementById('campaign-grid').innerHTML = campaigns.map(c => {
const st = c.status === 'active' ? '<span class="status-tag active">● Active</span>'
: c.status === 'paused' ? '<span class="status-tag paused">● Paused</span>'
: '<span class="status-tag draft">Draft</span>';
return `<div class="campaign-card">
<h3>${c.label} ${st}</h3>
<div class="stat-row">${c.metrics.map(m => `<div class="stat-item"><div class="stat-num">${m.v}</div><div class="stat-label">${m.l}</div></div>`).join('')}</div>
<ul>${c.items.map(i => `<li><span class="dot ${i.ok ? 'green' : 'red'}"></span>${i.t}</li>`).join('')}</ul>
</div>`;
}).join('');
}
function renderActions() {
document.getElementById('action-list').innerHTML = actions.map(a =>
`<li class="action-item">
<div class="action-num">${a.num}</div>
<div class="action-body">
<h4>${a.title}</h4>
<p>${a.desc}</p>
<div class="action-owner">Owner: ${a.owner}</div>
</div>
</li>`
).join('');
}
/* ── Interactive Checkboxes ────────────────── */
function getNeeds() {
try {
const saved = localStorage.getItem("derez-needs");
if (saved) {
const parsed = JSON.parse(saved);
return NEEDS.map(def => {
const s = parsed.find(p => p.id === def.id);
return s ? { ...def, done: s.done } : def;
});
}
} catch(e) {}
return NEEDS;
}
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 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 renderStrategy() {
document.getElementById('strategy-grid').innerHTML = strategyCards.map(s =>
`<div class="strategy-card">
<h3>${s.icon} ${s.title}</h3>
<p>${s.body}</p>
<p style="margin-top:8px;"><span class="highlight">${s.goal}</span></p>
</div>`
).join('');
document.getElementById('reco-list').innerHTML = recommendations.map(r =>
`<li><span class="reco-icon">→</span>${r}</li>`
).join('');
}
function renderCommunications() {
const c = comms;
const inboxItems = c.inbox.items.map(i =>
`<li><span class="comms-time">${i.time}</span><span><span class="comms-from">${i.from}</span><br><span class="comms-subj">${i.subj}</span> <span class="comms-detail">${i.detail}</span></span></li>`
).join('');
const alerts = c.inbox.alerts.map(a =>
`<div class="comms-alert"><span class="alert-icon">${a.icon}</span><div><div class="alert-body">${a.body}</div><div class="alert-detail">${a.detail}</div></div></div>`
).join('');
const sentItems = c.sent.items.map(i =>
`<li><span class="comms-time">${i.time}</span><span><span class="comms-from">${i.to}</span><br><span class="comms-subj">${i.subj}</span></span></li>`
).join('');
document.getElementById('comms-grid').innerHTML =
`<div class="comms-card">
<h3>📥 Inbox</h3>
<div class="comms-summary">
<div class="comms-stat"><div class="comms-stat-num">${c.inbox.total}</div><div class="comms-stat-label">Total</div></div>
<div class="comms-stat"><div class="comms-stat-num">${c.inbox.last35h}</div><div class="comms-stat-label">Last 35h</div></div>
<div class="comms-stat"><div class="comms-stat-num">${c.inbox.alerts.length}</div><div class="comms-stat-label">Alerts</div></div>
</div>
<ul class="comms-list">${inboxItems}</ul>
${alerts}
</div>
<div class="comms-card">
<h3>📤 Sent</h3>
<div class="comms-summary">
<div class="comms-stat"><div class="comms-stat-num">${c.sent.total}</div><div class="comms-stat-label">Total Sent</div></div>
<div class="comms-stat"><div class="comms-stat-num">${c.sent.last35h}</div><div class="comms-stat-label">Last 35h</div></div>
<div class="comms-stat"><div class="comms-stat-num">${c.sent.items.length}</div><div class="comms-stat-label">Recent</div></div>
</div>
<ul class="comms-list">${sentItems}</ul>
<div style="margin-top:8px;font-size:11px;color:var(--text-muted);">
Sender: ${c.sent.top_sent} &middot; ${c.note}
</div>
</div>`;
}
async function fetchLiveData() {
try {
const res = await fetch('data/operations.json?t=' + Date.now());
if (!res.ok) throw new Error('Not found');
const d = await res.json();
if (d.date) document.getElementById('brief-date').textContent = d.date;
if (d.updated) document.getElementById('brief-updated').textContent = 'Last updated: ' + d.updated;
if (d.goals) d.goals.forEach((g, i) => { if (goals[i]) { goals[i].current = g.current; goals[i].note = g.note || goals[i].note; } });
renderGoals();
} catch { /* use defaults */ }
}
/* ── Init ──────────────────────────────────── */
document.getElementById('brief-date').textContent = fmtDate();
renderGoals();
renderCampaigns();
renderActions();
renderNeeds(getNeeds());
renderCommunications();
renderStrategy();
fetchLiveData();
</script>
</body>
</html>