Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/team-hannah.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/team-vetri.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 16 additions & 1 deletion src/app/about/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const metadata: Metadata = {
title: "About Us",
description:
"A student-run nonprofit making tech education free and accessible for everyone, everywhere.",
alternates: { canonical: "/about" },
alternates: { canonical: "/about/" },
};

const founders: TeamMember[] = [
Expand Down Expand Up @@ -139,6 +139,21 @@ const teamMembers: TeamMember[] = [
photo: images.team.bhoumik,
photoClass: "object-[50%_0%] scale-[2.5] translate-y-[45%]",
},
{
name: "Hannah Mauro",
role: "Social Media",
photo: images.team.hannah,
photoClass: "object-[50%_8%]",
instagram: "https://www.instagram.com/hannah_gm.9045/",
bio: "Hi! I assist with media at Code With Purpose. I'm a student researcher interested in neuroscience and abnormal/forensic psychiatry, and have worked with professors from BU and Harvard on research into Parkinson's Disease as well as behavioral economics and neuroscience more broadly. In the future I hope to pursue a career in forensic psychiatry. In my free time I enjoy hanging out with my friends, family, and dogs, playing the violin and guitar, playing volleyball, and dancing.",
},
{
name: "Vetrivel Jagath",
role: "Instructor",
photo: images.team.vetri,
photoClass: "object-[48%_30%] scale-[1.75] -translate-y-[5%]",
bio: "Hi, I'm Vetri, a rising freshman with a strong interest in math and helping others learn.",
},
];

export default function AboutPage() {
Expand Down
2 changes: 1 addition & 1 deletion src/app/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export async function generateMetadata({
return {
title: post.title,
description: post.excerpt,
alternates: { canonical: `/blog/${slug}` },
alternates: { canonical: `/blog/${slug}/` },
openGraph: {
title: post.title,
description: post.excerpt,
Expand Down
2 changes: 1 addition & 1 deletion src/app/contact/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { CONTACT_EMAIL, CONTACT_EMAIL_HREF } from "@/lib/links";
export const metadata: Metadata = {
title: "Contact",
description: "Get in touch with the CodeWithPurpose team.",
alternates: { canonical: "/contact" },
alternates: { canonical: "/contact/" },
};

export default function ContactPage() {
Expand Down
2 changes: 1 addition & 1 deletion src/app/courses/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const metadata: Metadata = {
title: "Free Coding Courses",
description:
"Free courses and interactive lessons for students worldwide. Python, Vibecoding, Machine Learning, Financial Literacy, and Health in Tech.",
alternates: { canonical: "/courses" },
alternates: { canonical: "/courses/" },
};

interface Course {
Expand Down
3 changes: 2 additions & 1 deletion src/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export const metadata: Metadata = {
title: "My Progress",
description:
"Track your progress across every CodeWithPurpose course, earn XP and badges, unlock Koda avatars, and keep a whiteboard — all saved right on your device, no account needed.",
alternates: { canonical: "/dashboard" },
alternates: { canonical: "/dashboard/" },
robots: { index: false, follow: true },
};

export default function DashboardPage() {
Expand Down
2 changes: 1 addition & 1 deletion src/app/donate/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const metadata: Metadata = {
title: "Donate",
description:
"Support CodeWithPurpose. Every dollar helps a student start their coding journey today.",
alternates: { canonical: "/donate" },
alternates: { canonical: "/donate/" },
};

const impactAreas = [
Expand Down
2 changes: 1 addition & 1 deletion src/app/impact/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const metadata: Metadata = {
title: "Impact & Stories",
description:
"4,000+ students across 130+ countries, and the stories behind the numbers.",
alternates: { canonical: "/impact" },
alternates: { canonical: "/impact/" },
};

const stats = [
Expand Down
2 changes: 1 addition & 1 deletion src/app/join/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const metadata: Metadata = {
title: "Join Us",
description:
"Volunteer with CodeWithPurpose. Teach, mentor, and help bring free coding education to students worldwide.",
alternates: { canonical: "/join" },
alternates: { canonical: "/join/" },
};

const roles = [
Expand Down
6 changes: 5 additions & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@ export const metadata: Metadata = {
images: ["/seo/og-image.png"],
},
icons: {
icon: [{ url: "/icon.svg", type: "image/svg+xml" }],
icon: [
{ url: "/icon.svg", type: "image/svg+xml" },
{ url: "/seo/favicon-32.png", sizes: "32x32", type: "image/png" },
],
apple: [{ url: "/seo/apple-touch-icon.png", sizes: "180x180", type: "image/png" }],
},
};

Expand Down
3 changes: 2 additions & 1 deletion src/app/leaderboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export const metadata: Metadata = {
title: "Leaderboard",
description:
"See how CodeWithPurpose students stack up. Earn XP by completing lessons and climb the ranks.",
alternates: { canonical: "/leaderboard" },
alternates: { canonical: "/leaderboard/" },
robots: { index: false, follow: true },
};

export default function LeaderboardPage() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export async function generateMetadata({
return {
title: chapter.title,
description: chapter.description,
alternates: { canonical: `/learn/financial-literacy/${slug}` },
alternates: { canonical: `/learn/financial-literacy/${slug}/` },
};
}

Expand Down
12 changes: 9 additions & 3 deletions src/app/learn/financial-literacy/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { Metadata } from "next";
import { JsonLd } from "@/components/seo/JsonLd";
import { courseJsonLd, breadcrumbJsonLd } from "@/lib/seo";
import Link from "next/link";
import { PageHero, PageSection } from "@/components/PageHero";
import { PageShell } from "@/components/PageShell";
Expand All @@ -15,12 +17,15 @@ export const metadata: Metadata = {
title: "Financial Literacy",
description:
"Free interactive financial literacy lessons from CodeWithPurpose, running from your first budget through investing, taxes, and retirement accounts.",
alternates: { canonical: "/learn/financial-literacy" },
alternates: { canonical: "/learn/financial-literacy/" },
};

export default function LearnFinancialLiteracyPage() {
return (
<PageShell>
<>
<JsonLd data={courseJsonLd({ name: String(metadata.title), description: String(metadata.description), path: "/learn/financial-literacy/" })} />
<JsonLd data={breadcrumbJsonLd([{ name: "Home", path: "/" }, { name: "Courses", path: "/courses/" }, { name: String(metadata.title), path: "/learn/financial-literacy/" }])} />
<PageShell>
<PageHero
title="Money skills, from your first budget to your first plan"
description="CodeWithPurpose lessons that turn personal finance into a set of skills you actually use, not jargon you look up. Twenty-four chapters, no experience required."
Expand Down Expand Up @@ -87,6 +92,7 @@ export default function LearnFinancialLiteracyPage() {
{ href: LEARN_HEALTH_IN_TECH_HREF, label: "Try Health in Tech", variant: "secondary" },
]}
/>
</PageShell>
</PageShell>
</>
);
}
2 changes: 1 addition & 1 deletion src/app/learn/health-in-tech/(chapters)/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export async function generateMetadata({
return {
title: chapter.title,
description: chapter.description,
alternates: { canonical: `/learn/health-in-tech/${slug}` },
alternates: { canonical: `/learn/health-in-tech/${slug}/` },
};
}

Expand Down
12 changes: 9 additions & 3 deletions src/app/learn/health-in-tech/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { Metadata } from "next";
import { JsonLd } from "@/components/seo/JsonLd";
import { courseJsonLd, breadcrumbJsonLd } from "@/lib/seo";
import Link from "next/link";
import { PageHero, PageSection } from "@/components/PageHero";
import { PageShell } from "@/components/PageShell";
Expand All @@ -15,12 +17,15 @@ export const metadata: Metadata = {
title: "Health in Tech",
description:
"Free interactive Health in Tech lessons from CodeWithPurpose, running from what health tech actually is through AI diagnosis bias, cybersecurity, and where it's headed.",
alternates: { canonical: "/learn/health-in-tech" },
alternates: { canonical: "/learn/health-in-tech/" },
};

export default function LearnHealthInTechPage() {
return (
<PageShell>
<>
<JsonLd data={courseJsonLd({ name: String(metadata.title), description: String(metadata.description), path: "/learn/health-in-tech/" })} />
<JsonLd data={breadcrumbJsonLd([{ name: "Home", path: "/" }, { name: "Courses", path: "/courses/" }, { name: String(metadata.title), path: "/learn/health-in-tech/" }])} />
<PageShell>
<PageHero
title="Where healthcare meets technology, chapter by chapter"
description="CodeWithPurpose lessons that turn health tech into a subject you actually understand, not headlines you half-follow. Twenty-four chapters, no medical or coding background required."
Expand Down Expand Up @@ -87,6 +92,7 @@ export default function LearnHealthInTechPage() {
{ href: LEARN_FINANCIAL_LITERACY_HREF, label: "Try Financial Literacy", variant: "secondary" },
]}
/>
</PageShell>
</PageShell>
</>
);
}
2 changes: 1 addition & 1 deletion src/app/learn/ml/(chapters)/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export async function generateMetadata({
return {
title: chapter.title,
description: chapter.description,
alternates: { canonical: `/learn/ml/${slug}` },
alternates: { canonical: `/learn/ml/${slug}/` },
};
}

Expand Down
12 changes: 9 additions & 3 deletions src/app/learn/ml/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { Metadata } from "next";
import { JsonLd } from "@/components/seo/JsonLd";
import { courseJsonLd, breadcrumbJsonLd } from "@/lib/seo";
import Link from "next/link";
import { PageHero, PageSection } from "@/components/PageHero";
import { ContributeBand } from "@/components/learn/cards/ContributeBand";
Expand All @@ -19,7 +21,7 @@ export const metadata: Metadata = {
title: "Machine Learning",
description:
"Free interactive machine learning lessons from CodeWithPurpose. Start from nothing: what ML is, what data has to look like, how a model learns, and how to tell whether it worked.",
alternates: { canonical: "/learn/ml" },
alternates: { canonical: "/learn/ml/" },
};

export default function LearnMlPage() {
Expand All @@ -30,7 +32,10 @@ export default function LearnMlPage() {
const firstLesson = lessons[0];

return (
<PageShell>
<>
<JsonLd data={courseJsonLd({ name: String(metadata.title), description: String(metadata.description), path: "/learn/ml/" })} />
<JsonLd data={breadcrumbJsonLd([{ name: "Home", path: "/" }, { name: "Courses", path: "/courses/" }, { name: String(metadata.title), path: "/learn/ml/" }])} />
<PageShell>
<PageHero
title="Machine learning, made visual"
description="CodeWithPurpose lessons that explain core ML ideas through live demos and clear visuals. Click any topic to explore — no setup required."
Expand Down Expand Up @@ -88,6 +93,7 @@ export default function LearnMlPage() {
{ href: LEARN_VIBECODING_HREF, label: "Try Vibe Coding", variant: "secondary" },
]}
/>
</PageShell>
</PageShell>
</>
);
}
2 changes: 1 addition & 1 deletion src/app/learn/python/(chapters)/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export async function generateMetadata({
return {
title: chapter.title,
description: chapter.description,
alternates: { canonical: `/learn/python/${slug}` },
alternates: { canonical: `/learn/python/${slug}/` },
};
}

Expand Down
12 changes: 9 additions & 3 deletions src/app/learn/python/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { Metadata } from "next";
import { JsonLd } from "@/components/seo/JsonLd";
import { courseJsonLd, breadcrumbJsonLd } from "@/lib/seo";
import Link from "next/link";
import { PageHero, PageSection } from "@/components/PageHero";
import { PageShell } from "@/components/PageShell";
Expand All @@ -15,12 +17,15 @@ export const metadata: Metadata = {
title: "Python",
description:
"Free interactive Python lessons from CodeWithPurpose, running from your first program through decorators, generators, and shipping tested code.",
alternates: { canonical: "/learn/python" },
alternates: { canonical: "/learn/python/" },
};

export default function LearnPythonPage() {
return (
<PageShell>
<>
<JsonLd data={courseJsonLd({ name: String(metadata.title), description: String(metadata.description), path: "/learn/python/" })} />
<JsonLd data={breadcrumbJsonLd([{ name: "Home", path: "/" }, { name: "Courses", path: "/courses/" }, { name: String(metadata.title), path: "/learn/python/" }])} />
<PageShell>
<PageHero
title="Python, from your first line to your first library"
description="CodeWithPurpose lessons that turn Python into a language you actually think in, not one you look up. Twenty-four chapters, no setup required."
Expand Down Expand Up @@ -87,6 +92,7 @@ export default function LearnPythonPage() {
{ href: LEARN_ML_HREF, label: "Try Machine Learning", variant: "secondary" },
]}
/>
</PageShell>
</PageShell>
</>
);
}
2 changes: 1 addition & 1 deletion src/app/learn/vibecoding/(chapters)/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export async function generateMetadata({
return {
title: chapter.title,
description: chapter.description,
alternates: { canonical: `/learn/vibecoding/${slug}` },
alternates: { canonical: `/learn/vibecoding/${slug}/` },
};
}

Expand Down
12 changes: 9 additions & 3 deletions src/app/learn/vibecoding/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { Metadata } from "next";
import { JsonLd } from "@/components/seo/JsonLd";
import { courseJsonLd, breadcrumbJsonLd } from "@/lib/seo";
import Link from "next/link";
import { PageHero, PageSection } from "@/components/PageHero";
import { PageShell } from "@/components/PageShell";
Expand All @@ -19,7 +21,7 @@ export const metadata: Metadata = {
title: "Vibe Coding",
description:
"Free interactive vibe coding lessons from CodeWithPurpose. Learn to prompt, pair-program, debug, and ship real apps with AI.",
alternates: { canonical: "/learn/vibecoding" },
alternates: { canonical: "/learn/vibecoding/" },
};

export default function LearnVibecodingPage() {
Expand All @@ -29,7 +31,10 @@ export default function LearnVibecodingPage() {
const firstLesson = getChapters("vibecoding")[0];

return (
<PageShell>
<>
<JsonLd data={courseJsonLd({ name: String(metadata.title), description: String(metadata.description), path: "/learn/vibecoding/" })} />
<JsonLd data={breadcrumbJsonLd([{ name: "Home", path: "/" }, { name: "Courses", path: "/courses/" }, { name: String(metadata.title), path: "/learn/vibecoding/" }])} />
<PageShell>
<PageHero
title="Vibe coding, one step at a time"
description="CodeWithPurpose lessons that turn AI-assisted coding into a repeatable skill: clear animated walkthroughs, no setup required."
Expand Down Expand Up @@ -115,6 +120,7 @@ export default function LearnVibecodingPage() {
{ href: LEARN_ML_HREF, label: "Try Machine Learning", variant: "secondary" },
]}
/>
</PageShell>
</PageShell>
</>
);
}
3 changes: 2 additions & 1 deletion src/app/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export const metadata: Metadata = {
title: "Log in",
description:
"Sign in to CodeWithPurpose to sync your course progress across devices and compete on the student leaderboard.",
alternates: { canonical: "/login" },
alternates: { canonical: "/login/" },
robots: { index: false, follow: true },
};

export default function LoginPage() {
Expand Down
3 changes: 2 additions & 1 deletion src/app/sign-up/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export const metadata: Metadata = {
title: "Sign up",
description:
"Create a free CodeWithPurpose account to sync your progress across devices and join the student leaderboard.",
alternates: { canonical: "/sign-up" },
alternates: { canonical: "/sign-up/" },
robots: { index: false, follow: true },
};

export default function SignUpPage() {
Expand Down
Loading
Loading