Skip to content

Commit 9afea6a

Browse files
authored
Merge pull request #763 from CodingCatDev/dev
release: ship Ops App SDK, Guest Profile Magic-Link Portal, and Deal Room to production
2 parents fc49253 + 8d59f76 commit 9afea6a

35 files changed

Lines changed: 11932 additions & 2065 deletions

‎.github/workflows/ci.yml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ jobs:
5757
SANITY_STUDIO_PROJECT_ID: hfh83o0w
5858
SANITY_STUDIO_DATASET: production
5959

60+
- name: Build ops app (Sanity App SDK)
61+
run: pnpm --filter @codingcatdev/ops build
62+
6063
- name: Run E2E Tests
6164
run: pnpm --filter @codingcatdev/site test:e2e
6265

‎.github/workflows/deploy.yml‎

Lines changed: 248 additions & 8 deletions
Large diffs are not rendered by default.

‎apps/ops/package.json‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "@codingcatdev/ops",
3+
"version": "0.1.0",
4+
"private": true,
5+
"type": "module",
6+
"scripts": {
7+
"dev": "sanity dev",
8+
"build": "sanity build",
9+
"deploy": "sanity deploy"
10+
},
11+
"dependencies": {
12+
"@sanity/sdk": "^3.9.1",
13+
"@sanity/sdk-react": "^3.9.1",
14+
"@sanity/ui": "^4.4.9",
15+
"react": "^19.2.4",
16+
"react-dom": "^19.2.4",
17+
"sanity": "^6.20.0",
18+
"styled-components": "^6.3.11"
19+
},
20+
"devDependencies": {
21+
"@types/react": "^19.2.0",
22+
"@types/react-dom": "^19.2.0",
23+
"typescript": "^5.9.3"
24+
}
25+
}

‎apps/ops/sanity.cli.ts‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { defineCliConfig } from "sanity/cli";
2+
3+
const dataset =
4+
process.env.SANITY_APP_DATASET ||
5+
process.env.SANITY_STUDIO_DATASET ||
6+
"production";
7+
const isDev = dataset === "dev";
8+
9+
export default defineCliConfig({
10+
app: {
11+
organizationId: process.env.SANITY_ORGANIZATION_ID || "ovF2qiKSO",
12+
entry: "./src/index.tsx",
13+
title: isDev
14+
? "CodingCat Ops & Revenue OS (Dev)"
15+
: "CodingCat Ops & Revenue OS (Production)",
16+
},
17+
deployment: {
18+
appId:
19+
process.env.SANITY_OPS_APP_ID ||
20+
(isDev ? "yiugiba2sjnhpehqmky6nulc" : undefined),
21+
},
22+
});
23+
24+
25+
26+

‎apps/ops/src/App.tsx‎

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
import { useDocuments } from "@sanity/sdk-react";
2+
import { useState } from "react";
3+
4+
type WorkspaceTab = "crm" | "bookings" | "billing";
5+
6+
interface SeededGmailDraft {
7+
companyName: string;
8+
contact: string;
9+
threadId: string;
10+
draftId: string;
11+
tier: string;
12+
totalUsd: number;
13+
depositUsd: number;
14+
status: string;
15+
}
16+
17+
const ACTIVE_GMAIL_DEALS: SeededGmailDraft[] = [
18+
{
19+
companyName: "StreamLapel",
20+
contact: "hello@streamlapel.com",
21+
threadId: "1a140656cb9a4be1",
22+
draftId: "r8880837980856049603",
23+
tier: "Integrated 60s Mid-Roll Ad (Oct 26 - Nov 6)",
24+
totalUsd: 1800,
25+
depositUsd: 900,
26+
status: "Reply Draft Ready in Gmail",
27+
},
28+
{
29+
companyName: "Tessen ZERO",
30+
contact: "Yannick Parfait <hello@tessen.ai>",
31+
threadId: "1a126242f701063b",
32+
draftId: "r4979210524997526110",
33+
tier: "Full-Stack Launch Bundle",
34+
totalUsd: 3500,
35+
depositUsd: 1750,
36+
status: "Reply Draft Ready in Gmail",
37+
},
38+
{
39+
companyName: "Influencer Laboratory",
40+
contact: "john@influencerlaboratoryinc.com",
41+
threadId: "1a15468638753504",
42+
draftId: "r3892744900021531970",
43+
tier: "Full-Stack Launch Bundle (21.1% US/CA/UK/AU Geo Sent)",
44+
totalUsd: 3500,
45+
depositUsd: 1750,
46+
status: "Reply Draft Ready in Gmail",
47+
},
48+
{
49+
companyName: "Typeless",
50+
contact: "qia@typeless.com",
51+
threadId: "1a13b726a4593e01",
52+
draftId: "r5723240746882402069",
53+
tier: "Oct 26 Launch + 7-Platform Shorts Pack",
54+
totalUsd: 2000,
55+
depositUsd: 1000,
56+
status: "Reply Draft Ready in Gmail",
57+
},
58+
{
59+
companyName: "SuperPlane",
60+
contact: "larisa@superplane.com",
61+
threadId: "1a13b7352b2a713e",
62+
draftId: "r1343316162270961096",
63+
tier: "Full-Stack Launch Bundle (Oct 26-30 GA)",
64+
totalUsd: 3500,
65+
depositUsd: 1750,
66+
status: "Reply Draft Ready in Gmail",
67+
},
68+
{
69+
companyName: "MiniMax (EezyCollab)",
70+
contact: "talent@eezycollab.xyz",
71+
threadId: "1a0d8c55420283dc",
72+
draftId: "r-7977440252907745009",
73+
tier: "Full-Stack Launch Bundle / Dedicated Video",
74+
totalUsd: 3500,
75+
depositUsd: 1750,
76+
status: "Reply Draft Ready in Gmail",
77+
},
78+
{
79+
companyName: "Kolect (AI 3D Platform)",
80+
contact: "sophia.nguyen@kolect.ai",
81+
threadId: "1a138ebfcd7f64c0",
82+
draftId: "r-3575370967009126686",
83+
tier: "Full-Stack Launch Bundle",
84+
totalUsd: 3500,
85+
depositUsd: 1750,
86+
status: "Reply Draft Ready in Gmail",
87+
},
88+
{
89+
companyName: "Kolect (Flova)",
90+
contact: "sophia.nguyen@kolect.ai",
91+
threadId: "1a15878e1da6781e",
92+
draftId: "r7006830561667617324",
93+
tier: "Organic YouTube Feature (Ad Rights Excluded)",
94+
totalUsd: 950,
95+
depositUsd: 475,
96+
status: "Reply Draft Ready in Gmail",
97+
},
98+
];
99+
100+
export function App() {
101+
const projectId = process.env.SANITY_APP_PROJECT_ID || "hfh83o0w";
102+
const dataset = process.env.SANITY_APP_DATASET || "production";
103+
const isDev = dataset === "dev";
104+
const envLabel = isDev ? "Dev" : "Production";
105+
const siteOrigin = isDev ? "https://dev.codingcat.dev" : "https://codingcat.dev";
106+
107+
const [activeTab, setActiveTab] = useState<WorkspaceTab>("crm");
108+
const [discovering, setDiscovering] = useState(false);
109+
const [discoveredProspects, setDiscoveredProspects] = useState<Array<any>>([]);
110+
111+
const sponsorLeads = useDocuments({ documentType: "sponsorLead" });
112+
const sponsorPool = useDocuments({ documentType: "sponsorPool" });
113+
const bookings = useDocuments({ documentType: "booking" });
114+
115+
const handleDiscoverOutbound = async () => {
116+
setDiscovering(true);
117+
try {
118+
const res = await fetch(`${siteOrigin}/api/sponsors/outbound`);
119+
if (res.ok) {
120+
const data = await res.json();
121+
setDiscoveredProspects(data.prospects || []);
122+
}
123+
} catch {
124+
// Fallback
125+
} finally {
126+
setDiscovering(false);
127+
}
128+
};
129+
130+
return (
131+
<div style={{ padding: 24, fontFamily: "system-ui, sans-serif", maxWidth: 1200, margin: "0 auto" }}>
132+
<header style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 24 }}>
133+
<div>
134+
<h1 style={{ margin: 0, fontSize: 28 }}>
135+
CodingCat.dev Revenue &amp; Booking OS ({envLabel})
136+
</h1>
137+
<p style={{ margin: "4px 0 0", color: "#666", fontSize: 14 }}>
138+
Unified Sanity App SDK Workspace &middot; Project <code>{projectId}</code> &middot; Dataset{" "}
139+
<code>{dataset}</code> ({envLabel})
140+
</p>
141+
</div>
142+
<div style={{ display: "flex", gap: 8 }}>
143+
<button
144+
type="button"
145+
onClick={() => setActiveTab("crm")}
146+
style={{
147+
padding: "8px 16px",
148+
borderRadius: 8,
149+
border: "1px solid #ccc",
150+
background: activeTab === "crm" ? "#111" : "#fff",
151+
color: activeTab === "crm" ? "#fff" : "#111",
152+
fontWeight: 600,
153+
cursor: "pointer",
154+
}}
155+
>
156+
1. Sponsor CRM &amp; Outbound ({sponsorLeads.data?.length || ACTIVE_GMAIL_DEALS.length})
157+
</button>
158+
<button
159+
type="button"
160+
onClick={() => setActiveTab("bookings")}
161+
style={{
162+
padding: "8px 16px",
163+
borderRadius: 8,
164+
border: "1px solid #ccc",
165+
background: activeTab === "bookings" ? "#111" : "#fff",
166+
color: activeTab === "bookings" ? "#fff" : "#111",
167+
fontWeight: 600,
168+
cursor: "pointer",
169+
}}
170+
>
171+
2. Calendar Bookings &amp; E-SIGN ({bookings.data?.length || 7})
172+
</button>
173+
<button
174+
type="button"
175+
onClick={() => setActiveTab("billing")}
176+
style={{
177+
padding: "8px 16px",
178+
borderRadius: 8,
179+
border: "1px solid #ccc",
180+
background: activeTab === "billing" ? "#111" : "#fff",
181+
color: activeTab === "billing" ? "#fff" : "#111",
182+
fontWeight: 600,
183+
cursor: "pointer",
184+
}}
185+
>
186+
3. Stripe 50/50 Billing &amp; Deal Rooms
187+
</button>
188+
</div>
189+
</header>
190+
191+
{activeTab === "crm" && (
192+
<div style={{ display: "flex", flexDirection: "column", gap: 24 }}>
193+
<section style={{ padding: 20, border: "1px solid #ddd", borderRadius: 12 }}>
194+
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }}>
195+
<div>
196+
<h2 style={{ margin: 0, fontSize: 18 }}>Active Inbound Sponsor Threads (Gmail + Sanity)</h2>
197+
<p style={{ margin: "4px 0 0", color: "#666", fontSize: 13 }}>
198+
Threaded Gmail reply drafts are staged in <code>alex.patterson@gmail.com</code> with verified 21.1% US/CA/UK/AU geography metrics.
199+
</p>
200+
</div>
201+
</div>
202+
<table style={{ width: "100%", borderCollapse: "collapse", fontSize: 13 }}>
203+
<thead>
204+
<tr style={{ textAlign: "left", borderBottom: "1px solid #eee" }}>
205+
<th style={{ padding: 8 }}>Company</th>
206+
<th style={{ padding: 8 }}>Contact</th>
207+
<th style={{ padding: 8 }}>Recommended Package</th>
208+
<th style={{ padding: 8 }}>Total / 50% Deposit</th>
209+
<th style={{ padding: 8 }}>Status</th>
210+
</tr>
211+
</thead>
212+
<tbody>
213+
{ACTIVE_GMAIL_DEALS.map((deal) => (
214+
<tr key={deal.threadId} style={{ borderBottom: "1px solid #f4f4f4" }}>
215+
<td style={{ padding: 8, fontWeight: 600 }}>{deal.companyName}</td>
216+
<td style={{ padding: 8 }}>{deal.contact}</td>
217+
<td style={{ padding: 8 }}>{deal.tier}</td>
218+
<td style={{ padding: 8 }}>
219+
${deal.totalUsd.toLocaleString()} (${deal.depositUsd.toLocaleString()} deposit)
220+
</td>
221+
<td style={{ padding: 8 }}>{deal.status}</td>
222+
</tr>
223+
))}
224+
</tbody>
225+
</table>
226+
</section>
227+
228+
<section style={{ padding: 20, border: "1px solid #ddd", borderRadius: 12 }}>
229+
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }}>
230+
<div>
231+
<h2 style={{ margin: 0, fontSize: 18 }}>
232+
Outbound Funded AI &amp; YC Startup Scraper ({sponsorPool.data?.length || discoveredProspects.length})
233+
</h2>
234+
<p style={{ margin: "4px 0 0", color: "#666", fontSize: 13 }}>
235+
Automatically generates 2 tailored CodingCat.dev video concepts per startup + Cloudflare Email Routing outreach.
236+
</p>
237+
</div>
238+
<button
239+
type="button"
240+
onClick={handleDiscoverOutbound}
241+
disabled={discovering}
242+
style={{
243+
padding: "8px 14px",
244+
borderRadius: 8,
245+
background: "#2563eb",
246+
color: "#fff",
247+
border: "none",
248+
fontWeight: 600,
249+
cursor: "pointer",
250+
}}
251+
>
252+
{discovering ? "Scanning Launch HN & YC..." : "Scan Launch HN & Generate 2 Video Concepts"}
253+
</button>
254+
</div>
255+
256+
{discoveredProspects.length > 0 && (
257+
<div style={{ display: "grid", gap: 12 }}>
258+
{discoveredProspects.map((p) => (
259+
<div key={p.companyName} style={{ padding: 14, border: "1px solid #eee", borderRadius: 8 }}>
260+
<div style={{ display: "flex", justifyContent: "space-between" }}>
261+
<strong>
262+
{p.companyName} ({p.fundingRound}) — {p.category}
263+
</strong>
264+
<span>Score: {p.relevanceScore}/100</span>
265+
</div>
266+
<ul style={{ margin: "8px 0", paddingLeft: 18, fontSize: 13 }}>
267+
{p.videoConcepts?.map((vc: any, i: number) => (
268+
<li key={i}>
269+
<strong>{vc.title}</strong> — {vc.angle}
270+
</li>
271+
))}
272+
</ul>
273+
</div>
274+
))}
275+
</div>
276+
)}
277+
</section>
278+
</div>
279+
)}
280+
281+
{activeTab === "bookings" && (
282+
<section style={{ padding: 20, border: "1px solid #ddd", borderRadius: 12 }}>
283+
<h2 style={{ marginTop: 0 }}>Two-Track Podcast &amp; Sponsor Calendar Bookings</h2>
284+
<p style={{ color: "#666", fontSize: 14 }}>
285+
All recording sessions enforce 8:00 AM - 5:00 PM PT/ET business hours and E-SIGN digital media release capture at <code>codingcat.dev/book</code>.
286+
</p>
287+
<div style={{ display: "flex", gap: 12, marginTop: 16 }}>
288+
<a
289+
href="https://calendar.app.google/s3B6PEqbVsGcY81MA"
290+
target="_blank"
291+
rel="noreferrer"
292+
style={{ padding: "10px 16px", background: "#111", color: "#fff", borderRadius: 8, textDecoration: "none", fontSize: 13, fontWeight: 600 }}
293+
>
294+
Open Podcast Recording Schedule &nearr;
295+
</a>
296+
<a
297+
href="https://calendar.app.google/tyGiF6dGFQeaVrN66"
298+
target="_blank"
299+
rel="noreferrer"
300+
style={{ padding: "10px 16px", border: "1px solid #ccc", color: "#111", borderRadius: 8, textDecoration: "none", fontSize: 13, fontWeight: 600 }}
301+
>
302+
Open Sponsor Discovery Schedule &nearr;
303+
</a>
304+
</div>
305+
</section>
306+
)}
307+
308+
{activeTab === "billing" && (
309+
<section style={{ padding: 20, border: "1px solid #ddd", borderRadius: 12 }}>
310+
<h2 style={{ marginTop: 0 }}>50% Upfront Deposit + 50% on Publish Milestone Billing</h2>
311+
<p style={{ color: "#666", fontSize: 14 }}>
312+
Every Sponsor Deal Room at <code>codingcat.dev/portal/[token]</code> supports both instant Stripe Checkout (Card / ACH) and Net-15 Corporate Hosted Invoices.
313+
</p>
314+
<ul style={{ fontSize: 14, lineHeight: 1.7 }}>
315+
<li><strong>Full-Stack Launch Bundle ($3,500)</strong>: $1,750 upfront deposit + $1,750 on publish</li>
316+
<li><strong>Sponsored Podcast &amp; Multi-Channel Showcase ($2,000)</strong>: $1,000 upfront deposit + $1,000 on publish</li>
317+
<li><strong>Ecosystem Integration ($950)</strong>: $475 upfront deposit + $475 on publish</li>
318+
</ul>
319+
</section>
320+
)}
321+
</div>
322+
);
323+
}

0 commit comments

Comments
 (0)