Skip to content

Commit d1f9448

Browse files
committed
Add daily briefing wizard
1 parent 029d6d6 commit d1f9448

File tree

1 file changed

+275
-0
lines changed

1 file changed

+275
-0
lines changed

index.html

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Daily Social Briefing Setup</title>
7+
<style>
8+
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
9+
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #f5f4f1; min-height: 100vh; display: flex; align-items: flex-start; justify-content: center; padding: 40px 16px; }
10+
.card { background: #fff; border-radius: 12px; border: 1px solid #e8e6e0; padding: 36px; width: 100%; max-width: 560px; }
11+
.brand { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: #aaa; margin-bottom: 24px; }
12+
.step-bar { display: flex; gap: 5px; margin-bottom: 28px; }
13+
.step-dot { height: 3px; flex: 1; border-radius: 2px; background: #e8e6e0; transition: background 0.3s; }
14+
.step-dot.done { background: #222; }
15+
.step-dot.active { background: #888; }
16+
h2 { font-size: 20px; font-weight: 600; color: #111; margin-bottom: 5px; }
17+
.sub { font-size: 13px; color: #777; line-height: 1.6; margin-bottom: 24px; }
18+
label { font-size: 12px; color: #555; display: block; margin-bottom: 5px; font-weight: 500; }
19+
input, textarea, select { width: 100%; padding: 9px 11px; font-size: 14px; border: 1px solid #ddd; border-radius: 8px; background: #fff; color: #111; margin-bottom: 14px; font-family: inherit; transition: border-color 0.15s; }
20+
input:focus, textarea:focus { outline: none; border-color: #888; }
21+
textarea { min-height: 76px; resize: vertical; line-height: 1.5; }
22+
.tag-group { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
23+
.tag { font-size: 12px; padding: 5px 12px; border-radius: 20px; border: 1px solid #ddd; color: #555; cursor: pointer; background: #fff; transition: all 0.15s; user-select: none; }
24+
.tag:hover { border-color: #aaa; }
25+
.tag.on { background: #111; color: #fff; border-color: #111; }
26+
.btn-row { display: flex; gap: 8px; margin-top: 8px; }
27+
.btn { padding: 9px 20px; border-radius: 8px; font-size: 13px; font-weight: 500; cursor: pointer; border: 1px solid #ddd; background: #fff; color: #333; transition: background 0.15s; font-family: inherit; }
28+
.btn:hover { background: #f5f4f1; }
29+
.btn-primary { background: #111; color: #fff; border-color: #111; }
30+
.btn-primary:hover { background: #333; }
31+
.output-box { background: #f9f8f5; border: 1px solid #e8e6e0; border-radius: 8px; padding: 14px; font-size: 12px; font-family: 'Menlo', 'Monaco', monospace; color: #444; white-space: pre-wrap; line-height: 1.7; max-height: 320px; overflow-y: auto; margin-bottom: 10px; }
32+
.copy-btn { width: 100%; margin-bottom: 20px; }
33+
.setup-block { border: 1px solid #e8e6e0; border-radius: 8px; padding: 12px 14px; margin-bottom: 8px; }
34+
.setup-num { font-size: 11px; font-weight: 600; color: #888; text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 3px; }
35+
.setup-block p { font-size: 13px; color: #555; line-height: 1.6; }
36+
.setup-block strong { color: #111; font-weight: 600; }
37+
.success-icon { width: 40px; height: 40px; border-radius: 50%; background: #f0f9f0; display: flex; align-items: center; justify-content: center; margin-bottom: 14px; }
38+
.note { font-size: 12px; color: #999; line-height: 1.6; margin-top: 16px; padding-top: 16px; border-top: 1px solid #eee; }
39+
.copy-flash { color: #2a7a2a; font-size: 12px; display: none; margin-top: 6px; }
40+
</style>
41+
</head>
42+
<body>
43+
<div class="card">
44+
<div class="brand">Daily Social Briefing</div>
45+
<div id="app"></div>
46+
</div>
47+
48+
<script>
49+
const state = {
50+
step: 0,
51+
name: '', firstName: '', role: '',
52+
linkedin: '', instagram: '', facebook: '', twitter: '', extraAccounts: '',
53+
family: '', friends: '',
54+
platforms: ['LinkedIn','Instagram','Facebook'],
55+
workInterests: '', personalInterests: '',
56+
tone: 'professional',
57+
outputDest: 'Slack DM to myself',
58+
};
59+
60+
const PLATFORMS = ['LinkedIn','Instagram','Facebook','Twitter/X','TikTok','YouTube','Threads'];
61+
const TONES = ['professional','casual and warm','concise and direct','witty and playful'];
62+
const DESTINATIONS = ['Slack DM to myself','Google Doc','Email','Claude chat window'];
63+
const STEPS = ['You','Accounts','People','Interests','Your Prompt'];
64+
65+
function render() {
66+
const app = document.getElementById('app');
67+
68+
const bar = STEPS.map((s,i) =>
69+
`<div class="step-dot${i < state.step ? ' done' : i === state.step ? ' active' : ''}" title="${s}"></div>`
70+
).join('');
71+
72+
let inner = `<div class="step-bar">${bar}</div>`;
73+
74+
if (state.step === 0) {
75+
inner += `
76+
<h2>Who are you?</h2>
77+
<p class="sub">This briefing will be built around your life. A few basics to get started.</p>
78+
<label>Full name</label>
79+
<input id="f-name" placeholder="Katherine Caswell" value="${esc(state.name)}">
80+
<label>What you'd like to be called</label>
81+
<input id="f-fname" placeholder="Kat" value="${esc(state.firstName)}">
82+
<label>Your main role or focus (optional)</label>
83+
<input id="f-role" placeholder="e.g. teacher, entrepreneur, designer..." value="${esc(state.role)}">
84+
<div class="btn-row">
85+
<button class="btn btn-primary" onclick="s0()">Continue</button>
86+
</div>`;
87+
} else if (state.step === 1) {
88+
inner += `
89+
<h2>Your social accounts</h2>
90+
<p class="sub">Paste your profile URLs. The briefing will track your own activity and engagement. Leave blank anything you don't use.</p>
91+
<label>LinkedIn</label>
92+
<input id="f-li" placeholder="https://linkedin.com/in/yourhandle" value="${esc(state.linkedin)}">
93+
<label>Instagram</label>
94+
<input id="f-ig" placeholder="https://instagram.com/yourhandle" value="${esc(state.instagram)}">
95+
<label>Facebook</label>
96+
<input id="f-fb" placeholder="https://facebook.com/yourprofile" value="${esc(state.facebook)}">
97+
<label>Twitter / X</label>
98+
<input id="f-tw" placeholder="https://x.com/yourhandle" value="${esc(state.twitter)}">
99+
<label>Any other accounts (business pages, TikTok, etc)</label>
100+
<textarea id="f-extra" placeholder="One per line...">${esc(state.extraAccounts)}</textarea>
101+
<div class="btn-row">
102+
<button class="btn" onclick="go(0)">Back</button>
103+
<button class="btn btn-primary" onclick="s1()">Continue</button>
104+
</div>`;
105+
} else if (state.step === 2) {
106+
inner += `
107+
<h2>People to track</h2>
108+
<p class="sub">Who do you want the briefing to watch for? The briefing surfaces their public posts and drafts suggested replies for you.</p>
109+
<label>Family members</label>
110+
<textarea id="f-fam" placeholder="e.g. Tom Caswell (brother), Sarah Caswell, Ryan, Jordan, Becca...">${esc(state.family)}</textarea>
111+
<label>Friends and colleagues</label>
112+
<textarea id="f-friends" placeholder="e.g. close friends, work contacts you want to stay in touch with...">${esc(state.friends)}</textarea>
113+
<div class="btn-row">
114+
<button class="btn" onclick="go(1)">Back</button>
115+
<button class="btn btn-primary" onclick="s2()">Continue</button>
116+
</div>`;
117+
} else if (state.step === 3) {
118+
const tagHtml = PLATFORMS.map(p =>
119+
`<span class="tag${state.platforms.includes(p)?' on':''}" onclick="toggleP('${p}')">${p}</span>`
120+
).join('');
121+
const toneHtml = TONES.map(t =>
122+
`<span class="tag${state.tone===t?' on':''}" onclick="setT('${t}')">${t}</span>`
123+
).join('');
124+
inner += `
125+
<h2>Your interests</h2>
126+
<p class="sub">Tell the briefing where to focus its attention each day.</p>
127+
<label>Platforms to scan</label>
128+
<div class="tag-group">${tagHtml}</div>
129+
<label>Work or professional topics</label>
130+
<textarea id="f-work" placeholder="e.g. AI, marketing, real estate, your company, industry news...">${esc(state.workInterests)}</textarea>
131+
<label>Personal interests (optional)</label>
132+
<textarea id="f-personal" placeholder="e.g. travel, food, photography, fitness...">${esc(state.personalInterests)}</textarea>
133+
<label>Tone for suggested replies and post drafts</label>
134+
<div class="tag-group">${toneHtml}</div>
135+
<div class="btn-row">
136+
<button class="btn" onclick="go(2)">Back</button>
137+
<button class="btn btn-primary" onclick="s3()">Continue</button>
138+
</div>`;
139+
} else if (state.step === 4) {
140+
const destHtml = DESTINATIONS.map(d =>
141+
`<span class="tag${state.outputDest===d?' on':''}" onclick="setD('${d}')">${d}</span>`
142+
).join('');
143+
const prompt = buildPrompt();
144+
inner += `
145+
<div class="success-icon">
146+
<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><polyline points="4,10 8,14 16,6" stroke="#2a7a2a" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>
147+
</div>
148+
<h2>Your prompt is ready${state.firstName ? ', ' + state.firstName : ''}</h2>
149+
<p class="sub">Copy this into Claude Cowork as a scheduled daily task. Set it to run at whatever time works for you, with web search turned on.</p>
150+
<label style="margin-bottom:8px">Where do you want results delivered?</label>
151+
<div class="tag-group">${destHtml}</div>
152+
<label>Your personalized prompt</label>
153+
<div class="output-box">${escHtml(prompt)}</div>
154+
<button class="btn btn-primary copy-btn" onclick="copyP()">Copy prompt to clipboard</button>
155+
<div class="copy-flash" id="flash">Copied to clipboard</div>
156+
<div style="margin-top:4px">
157+
<div style="font-size:13px;font-weight:600;color:#111;margin-bottom:10px">Cowork setup steps</div>
158+
<div class="setup-block"><div class="setup-num">Step 1</div><p>Download and open <strong>Claude Cowork</strong> on your desktop. It's free at claude.ai/download.</p></div>
159+
<div class="setup-block"><div class="setup-num">Step 2</div><p>Create a new scheduled task. Paste your prompt into the task prompt field.</p></div>
160+
<div class="setup-block"><div class="setup-num">Step 3</div><p><strong>Turn on web search</strong> in the task settings. This is what lets Claude scan social media and news in real time.</p></div>
161+
<div class="setup-block"><div class="setup-num">Step 4</div><p>Set the schedule to your preferred time (9am works well). Set delivery to <strong>${esc(state.outputDest)}</strong>. Save and activate.</p></div>
162+
</div>
163+
<p class="note">No Cowork yet? You can also run this manually: open Claude.ai, turn on web search, paste the prompt, and hit send. You'll get the full briefing in the chat window.</p>
164+
<div class="btn-row" style="margin-top:16px">
165+
<button class="btn" onclick="go(3)">Back</button>
166+
<button class="btn" onclick="window.print()">Print / Save as PDF</button>
167+
</div>`;
168+
}
169+
170+
app.innerHTML = inner;
171+
}
172+
173+
function esc(s) { return (s||'').replace(/"/g,'&quot;'); }
174+
function escHtml(s) { return (s||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); }
175+
176+
function s0() {
177+
state.name = document.getElementById('f-name').value.trim();
178+
state.firstName = document.getElementById('f-fname').value.trim();
179+
state.role = document.getElementById('f-role').value.trim();
180+
go(1);
181+
}
182+
function s1() {
183+
state.linkedin = document.getElementById('f-li').value.trim();
184+
state.instagram = document.getElementById('f-ig').value.trim();
185+
state.facebook = document.getElementById('f-fb').value.trim();
186+
state.twitter = document.getElementById('f-tw').value.trim();
187+
state.extraAccounts = document.getElementById('f-extra').value.trim();
188+
go(2);
189+
}
190+
function s2() {
191+
state.family = document.getElementById('f-fam').value.trim();
192+
state.friends = document.getElementById('f-friends').value.trim();
193+
go(3);
194+
}
195+
function s3() {
196+
state.workInterests = document.getElementById('f-work').value.trim();
197+
state.personalInterests = document.getElementById('f-personal').value.trim();
198+
go(4);
199+
}
200+
function go(n) { state.step = n; render(); window.scrollTo(0,0); }
201+
function toggleP(p) {
202+
if (state.platforms.includes(p)) state.platforms = state.platforms.filter(x=>x!==p);
203+
else state.platforms.push(p);
204+
render();
205+
}
206+
function setT(t) { state.tone = t; render(); }
207+
function setD(d) { state.outputDest = d; render(); }
208+
209+
function copyP() {
210+
navigator.clipboard.writeText(buildPrompt()).then(() => {
211+
const f = document.getElementById('flash');
212+
if (f) { f.style.display = 'block'; setTimeout(()=>{ f.style.display='none'; }, 2500); }
213+
});
214+
}
215+
216+
function buildPrompt() {
217+
const name = state.name || 'me';
218+
const fname = state.firstName || state.name || 'me';
219+
const role = state.role ? '\nRole: ' + state.role : '';
220+
const accounts = [
221+
state.linkedin && 'LinkedIn: ' + state.linkedin,
222+
state.instagram && 'Instagram: ' + state.instagram,
223+
state.facebook && 'Facebook: ' + state.facebook,
224+
state.twitter && 'Twitter/X: ' + state.twitter,
225+
state.extraAccounts,
226+
].filter(Boolean).join('\n');
227+
228+
return `You are running a daily social media and web intelligence briefing for ${name}.${role}
229+
230+
Today's date is: [today's date]
231+
232+
Use web search to find the most recent public posts, updates, and activity from every source below. If a source has no findable public activity, say so briefly and move on.
233+
234+
===== SOCIAL PROFILES =====
235+
${accounts || 'No accounts specified.'}
236+
237+
===== PEOPLE TO TRACK =====
238+
Family: ${state.family || 'None specified'}
239+
Friends and colleagues: ${state.friends || 'None specified'}
240+
241+
===== PLATFORMS TO SCAN =====
242+
${state.platforms.join(', ')}
243+
244+
===== TOPICS AND INTERESTS =====
245+
Work and professional: ${state.workInterests || 'General industry and professional news'}
246+
Personal: ${state.personalInterests || 'None specified'}
247+
248+
===== OUTPUT FORMAT =====
249+
250+
Produce the briefing in this structure:
251+
252+
DAILY BRIEFING: [today's date]
253+
254+
SECTION 1: FAMILY AND FRIENDS ACTIVITY
255+
For each person with findable public activity, list the platform, approximate post date, and a brief summary. Then write a suggested reply in ${fname}'s voice: ${state.tone}, specific and genuine, no emojis, no hyphens. Flag anything that warrants a personal follow-up with [FOLLOW UP].
256+
257+
SECTION 2: WORK AND INDUSTRY FEED
258+
Top 3 to 5 posts or articles worth engaging with from ${fname}'s professional topics. For each: platform or source, author, brief summary, and a suggested comment or reply in ${fname}'s voice.
259+
260+
SECTION 3: PERSONAL INTEREST UPDATES
261+
Any notable posts or news from personal interest areas. Brief summaries only.
262+
263+
SECTION 4: POST DRAFTS FOR TODAY
264+
Write 1 to 2 ready-to-post updates for ${fname}'s most active platform based on the most timely findings from today's scan. Tone: ${state.tone}. No emojis. No hyphens. Format each as ready to copy and paste.
265+
266+
SECTION 5: FLAGS AND TIME-SENSITIVE ITEMS
267+
Anything requiring action today: replies that should go out soon, news worth amplifying, deadlines. Mark each with [ACTION NEEDED].
268+
269+
Keep the briefing direct and specific. No filler. Lead each section with the most important item.`;
270+
}
271+
272+
render();
273+
</script>
274+
</body>
275+
</html>

0 commit comments

Comments
 (0)