Skip to content

Commit 09e08dd

Browse files
committed
feat(site,courses): rank 2026 courses #1-#4, add YouTube playlist & subscribe CTAs, and fix all 24 typecheck errors
1 parent 3bbc5b6 commit 09e08dd

16 files changed

Lines changed: 154 additions & 62 deletions

File tree

‎apps/site/src/components/Footer.astro‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ const socialLinks = [
5151
path: "M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286ZM5.337 7.433a2.062 2.062 0 1 1 0-4.124 2.062 2.062 0 0 1 0 4.124ZM7.119 20.452H3.555V9h3.564v11.452ZM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003Z",
5252
},
5353
{
54-
href: "https://youtube.com/codingcatdev",
54+
href: "https://www.youtube.com/@codingcatdev?sub_confirmation=1",
5555
label: "YouTube",
5656
path: "M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814ZM9.545 15.568V8.432L15.818 12l-6.273 3.568Z",
5757
},
@@ -91,6 +91,17 @@ const socialLinks = [
9191
))
9292
}
9393
</div>
94+
<a
95+
href="https://www.youtube.com/@codingcatdev?sub_confirmation=1"
96+
target="_blank"
97+
rel="noopener noreferrer"
98+
class="tactile-btn inline-flex items-center gap-2 rounded-xl border-2 border-[#2A1155] bg-[#FF0000] px-3.5 py-2 font-display text-xs font-black text-white shadow-sketch-sm transition hover:bg-[#DC2626] dark:border-white/60"
99+
>
100+
<svg class="size-3.5 fill-current" viewBox="0 0 24 24" aria-hidden="true">
101+
<path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z" />
102+
</svg>
103+
<span>Subscribe on YouTube (62.5K / 100K) →</span>
104+
</a>
94105
</div>
95106

96107
{/* Structured Sitemap Columns */}

‎apps/site/src/components/PodcastListen.astro‎

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,13 @@ const appleUrl =
3939
(src
4040
? "https://podcasts.apple.com/us/podcast/codingcat-dev-podcast/id1491655542"
4141
: null);
42-
const youtubeUrl = cleanLinks.youtube || cleanYoutube || null;
42+
const rawYoutubeUrl = cleanLinks.youtube || cleanYoutube || null;
43+
const youtubeVideoMatch = rawYoutubeUrl?.match(
44+
/(?:youtu\.be\/|youtube\.com\/(?:watch\?v=|embed\/|shorts\/))([A-Za-z0-9_-]{11})/,
45+
);
46+
const youtubeUrl = youtubeVideoMatch?.[1]
47+
? `https://www.youtube.com/watch?v=${youtubeVideoMatch[1]}&list=PLUKgAjyG9B0ZhUEXp9eVa7h4L__FDW3uV`
48+
: rawYoutubeUrl;
4349
const pocketCastsUrl = cleanLinks.pocketCasts || null;
4450
const castboxUrl = cleanLinks.castbox || null;
4551
const castroUrl = cleanLinks.castro || null;
@@ -151,6 +157,19 @@ const buttonClass =
151157
<span>YouTube</span>
152158
</a>
153159
)}
160+
<a
161+
href="https://www.youtube.com/@codingcatdev?sub_confirmation=1"
162+
target="_blank"
163+
rel="noreferrer noopener"
164+
class="tactile-btn inline-flex items-center justify-center gap-1.5 rounded-xl border-2 border-[#2A1155] bg-[#FF0000] px-3.5 py-2 font-display text-xs font-black text-white shadow-sketch-sm transition-all hover:-translate-y-0.5 hover:bg-[#DC2626] dark:border-white/60"
165+
title="Subscribe to CodingCat.dev on YouTube (62.5K / 100K Goal)"
166+
aria-label="Subscribe to CodingCat.dev on YouTube"
167+
data-track="podcast_listen"
168+
data-track-label="youtube_subscribe"
169+
data-track-target="https://www.youtube.com/@codingcatdev?sub_confirmation=1"
170+
>
171+
<span>Subscribe on YouTube (62.5K / 100K) →</span>
172+
</a>
154173
{pocketCastsUrl && (
155174
<a
156175
href={pocketCastsUrl}

‎apps/site/src/components/portable-text/PtYouTube.astro‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ type Props = PtProps<YouTubeNode> & {
1212
};
1313
1414
const { node, coverImage, priority = false } = Astro.props;
15-
const id = youtubeId(stegaClean(node.youtube ?? node.url));
15+
const rawYoutubeUrl = stegaClean(node.youtube ?? node.url) ?? "";
16+
const id = youtubeId(rawYoutubeUrl);
17+
const customListMatch = rawYoutubeUrl.match(/[?&]list=([A-Za-z0-9_-]+)/);
18+
const playlistId = customListMatch?.[1] || "UUnKZ8gEb78zXKMi1ns-IQ2g";
1619
1720
const builder = Astro.locals.sanity.urlForImage(coverImage ?? undefined);
1821
const sanitySrc = builder?.width(1920).height(1080).quality(82).url();
@@ -121,7 +124,7 @@ const alt = rawAlt && rawAlt.trim().length > 0 ? rawAlt : "";
121124

122125
<div class="flex flex-wrap items-center gap-2">
123126
<a
124-
href={`https://www.youtube.com/watch?v=${id}&list=UUnKZ8gEb78zXKMi1ns-IQ2g`}
127+
href={`https://www.youtube.com/watch?v=${id}&list=${playlistId}`}
125128
target="_blank"
126129
rel="noopener noreferrer"
127130
class="inline-flex items-center gap-1.5 rounded-xl border-2 border-[#2A1155] bg-white px-3.5 py-1.5 font-mono text-xs font-extrabold text-[#2A1155] shadow-sketch-sm transition hover:border-[#7C3AED] hover:bg-[#EDE9FE] hover:text-[#7C3AED] dark:border-white/25 dark:bg-[#0B1326] dark:text-white dark:hover:border-[#C084FC] dark:hover:bg-purple-950/60"

‎apps/site/src/pages/api/auth/[...slug].ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@ export const ALL: APIRoute = async ({ request, locals }) => {
4545
token: portalTokenHeader,
4646
privateLeadId: `private.sponsorLead-${portalTokenHeader}`,
4747
leadId: `sponsorLead-${portalTokenHeader}`,
48-
},
48+
} as Record<string, any>,
4949
),
5050
client.fetch<Record<string, any> | null>(
5151
`*[_type == "booking" && (portalToken == $token || legacyPortalToken == $token || _id == $privateBookingId)] | order(_createdAt desc)[0]{ guestEmail, coordinatorEmail, coordinatorEmails, allowedEmails }`,
5252
{
5353
token: portalTokenHeader,
5454
privateBookingId: `private.booking-${portalTokenHeader}`,
55-
},
55+
} as Record<string, any>,
5656
),
5757
]);
5858

‎apps/site/src/pages/api/booking.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ export const POST: APIRoute = async ({ request, url }) => {
115115
privId,
116116
stripped,
117117
token: existingToken || "",
118-
},
118+
} as Record<string, any>,
119119
);
120120
} catch {
121121
// Non-fatal

‎apps/site/src/pages/api/ops/daily-digest.ts‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,11 +316,15 @@ async function buildAndOptionallySendDigest(opts: {
316316
provider: `skipped-already-sent-${todayEtStr}`,
317317
};
318318
} else {
319-
emailResult = await sendCodingCatEmail({
319+
const sentOk = await sendCodingCatEmail({
320320
to: opts.recipientEmail || "alex@codingcat.dev",
321321
subject: `[CodingCat.dev Today] ${todayEtStr}: ${pendingHolds.length} Holds, ${upcoming72hBookings.length} Upcoming Recordings, ${actionLeads.length} Deals`,
322322
text: emailText,
323323
});
324+
emailResult = {
325+
sent: Boolean(sentOk),
326+
provider: sentOk ? "gmail-or-resend" : "failed",
327+
};
324328
if (emailResult.sent) {
325329
try {
326330
await client.createOrReplace({

‎apps/site/src/pages/api/portal/assets.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export const GET: APIRoute = async ({ request, url }) => {
8484
allowedEmails,
8585
sharedAssets
8686
}`,
87-
{ token },
87+
{ token } as Record<string, any>,
8888
);
8989

9090
if (!ownerDoc) {
@@ -305,7 +305,7 @@ export const POST: APIRoute = async ({ request, url }) => {
305305
source,
306306
bookingSource
307307
}`,
308-
{ token, docId },
308+
{ token, docId } as Record<string, any>,
309309
);
310310

311311
if (!targetDocs || targetDocs.length === 0) {

‎apps/site/src/pages/api/portal/guest-profile.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export const POST: APIRoute = async ({ request, url }) => {
9696
guestSlug,
9797
guestDocId
9898
}`,
99-
{ token },
99+
{ token } as Record<string, any>,
100100
);
101101

102102
if (!targetDocs || targetDocs.length === 0) {

‎apps/site/src/pages/api/portal/notes.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export const POST: APIRoute = async ({ request, url }) => {
9292
coordinatorEmails,
9393
allowedEmails
9494
}`,
95-
{ token, docId },
95+
{ token, docId } as Record<string, any>,
9696
);
9797

9898
if (!targetDocs || targetDocs.length === 0) {

‎apps/site/src/pages/api/portal/sign-release.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export const POST: APIRoute = async ({ request, url }) => {
9292
coordinatorEmails,
9393
allowedEmails
9494
}`,
95-
{ token },
95+
{ token } as Record<string, any>,
9696
);
9797

9898
if (!targetDocs || targetDocs.length === 0) {

0 commit comments

Comments
 (0)