Skip to content

Commit 9ac704e

Browse files
Created 8 program pages
X-Lovable-Edit-ID: edt-f2a33075-819b-4376-a27f-667ca32e604a Co-authored-by: ghostcodedynamics <295822717+ghostcodedynamics@users.noreply.github.com>
2 parents 079a499 + 0e7eb0f commit 9ac704e

6 files changed

Lines changed: 861 additions & 41 deletions

File tree

‎src/components/program-page.tsx‎

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
import type { ReactNode } from "react";
2+
import { motion } from "framer-motion";
3+
import { Reveal, SectionHeader, fadeUp, stagger } from "@/components/section";
4+
import { CtaLink } from "@/components/cta-button";
5+
6+
/**
7+
* Shared building blocks for the "program" surfaces
8+
* (Academy, Careers, Community, Courses, Events, Internships, Labs, Verify).
9+
* Pure presentation — content lives in each route file.
10+
*/
11+
12+
export interface FeatureItem {
13+
icon: ReactNode;
14+
title: string;
15+
desc: string;
16+
}
17+
18+
export function FeatureGrid({
19+
eyebrow,
20+
title,
21+
description,
22+
items,
23+
columns = 3,
24+
}: {
25+
eyebrow?: string;
26+
title: ReactNode;
27+
description?: ReactNode;
28+
items: FeatureItem[];
29+
columns?: 2 | 3 | 4;
30+
}) {
31+
const cols =
32+
columns === 2
33+
? "sm:grid-cols-2"
34+
: columns === 4
35+
? "sm:grid-cols-2 lg:grid-cols-4"
36+
: "sm:grid-cols-2 lg:grid-cols-3";
37+
38+
return (
39+
<section className="relative py-16 md:py-24">
40+
<div className="container-prose">
41+
<SectionHeader eyebrow={eyebrow} title={title} description={description} />
42+
<motion.ul
43+
initial="hidden"
44+
whileInView="show"
45+
viewport={{ once: true, margin: "-80px" }}
46+
variants={stagger}
47+
className={`mt-12 grid gap-5 ${cols}`}
48+
>
49+
{items.map((item) => (
50+
<motion.li
51+
key={item.title}
52+
variants={fadeUp}
53+
className="group rounded-2xl border border-border bg-card/60 p-6 backdrop-blur transition hover:border-primary/40"
54+
>
55+
<span className="inline-flex h-10 w-10 items-center justify-center rounded-xl border border-border bg-surface/60 text-primary">
56+
{item.icon}
57+
</span>
58+
<h3 className="mt-5 font-display text-lg font-semibold tracking-tight text-foreground">
59+
{item.title}
60+
</h3>
61+
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">{item.desc}</p>
62+
</motion.li>
63+
))}
64+
</motion.ul>
65+
</div>
66+
</section>
67+
);
68+
}
69+
70+
export interface TimelineItem {
71+
label: string;
72+
title: string;
73+
desc: string;
74+
}
75+
76+
export function Timeline({
77+
eyebrow,
78+
title,
79+
description,
80+
items,
81+
}: {
82+
eyebrow?: string;
83+
title: ReactNode;
84+
description?: ReactNode;
85+
items: TimelineItem[];
86+
}) {
87+
return (
88+
<section className="relative border-t border-border/60 py-16 md:py-24">
89+
<div className="container-prose">
90+
<SectionHeader eyebrow={eyebrow} title={title} description={description} />
91+
<ol className="mt-12 relative border-l border-border pl-6 sm:pl-8">
92+
{items.map((item, i) => (
93+
<li key={item.title} className="relative pb-10 last:pb-0">
94+
<span
95+
className="absolute -left-[31px] sm:-left-[39px] mt-1.5 flex h-4 w-4 items-center justify-center rounded-full border border-primary/40 bg-background"
96+
aria-hidden
97+
>
98+
<span className="h-1.5 w-1.5 rounded-full bg-primary" />
99+
</span>
100+
<Reveal delay={i * 0.04}>
101+
<p className="font-mono text-[10px] uppercase tracking-[0.3em] text-primary">
102+
{item.label}
103+
</p>
104+
<h3 className="mt-2 font-display text-lg font-semibold tracking-tight text-foreground">
105+
{item.title}
106+
</h3>
107+
<p className="mt-2 max-w-2xl text-sm leading-relaxed text-muted-foreground">
108+
{item.desc}
109+
</p>
110+
</Reveal>
111+
</li>
112+
))}
113+
</ol>
114+
</div>
115+
</section>
116+
);
117+
}
118+
119+
export function Faq({
120+
title = "Questions, answered honestly",
121+
items,
122+
}: {
123+
title?: string;
124+
items: { q: string; a: string }[];
125+
}) {
126+
return (
127+
<section className="relative border-t border-border/60 py-16 md:py-24">
128+
<div className="container-prose">
129+
<SectionHeader title={title} />
130+
<div className="mt-10 grid gap-4 md:grid-cols-2">
131+
{items.map((item) => (
132+
<Reveal key={item.q}>
133+
<details className="group rounded-2xl border border-border bg-card/60 p-5 backdrop-blur transition hover:border-primary/40">
134+
<summary className="cursor-pointer list-none text-sm font-medium text-foreground marker:hidden">
135+
{item.q}
136+
</summary>
137+
<p className="mt-3 text-sm leading-relaxed text-muted-foreground">{item.a}</p>
138+
</details>
139+
</Reveal>
140+
))}
141+
</div>
142+
</div>
143+
</section>
144+
);
145+
}
146+
147+
export function ProgramCta({
148+
title,
149+
description,
150+
primaryLabel = "Get early access",
151+
primaryTo = "/contact",
152+
secondaryLabel,
153+
secondaryTo,
154+
}: {
155+
title: string;
156+
description: string;
157+
primaryLabel?: string;
158+
primaryTo?: string;
159+
secondaryLabel?: string;
160+
secondaryTo?: string;
161+
}) {
162+
return (
163+
<section className="relative border-t border-border/60 py-16 md:py-24">
164+
<div className="container-prose">
165+
<Reveal className="relative overflow-hidden rounded-3xl border border-border bg-card/60 p-8 backdrop-blur sm:p-12">
166+
<div className="absolute inset-0 bg-aurora opacity-50 pointer-events-none" aria-hidden />
167+
<div className="relative">
168+
<h2 className="font-display text-2xl font-semibold tracking-tight text-foreground sm:text-3xl">
169+
{title}
170+
</h2>
171+
<p className="mt-3 max-w-xl text-sm leading-relaxed text-muted-foreground sm:text-base">
172+
{description}
173+
</p>
174+
<div className="mt-8 flex flex-wrap gap-3">
175+
<CtaLink to={primaryTo}>{primaryLabel}</CtaLink>
176+
{secondaryLabel && secondaryTo && (
177+
<CtaLink to={secondaryTo} variant="secondary" icon={false}>
178+
{secondaryLabel}
179+
</CtaLink>
180+
)}
181+
</div>
182+
</div>
183+
</Reveal>
184+
</div>
185+
</section>
186+
);
187+
}
188+
189+
export function StatusNote({ children }: { children: ReactNode }) {
190+
return (
191+
<p className="mt-6 inline-flex items-center gap-2 rounded-full border border-border bg-surface/60 px-3 py-1.5 text-xs text-muted-foreground">
192+
<span className="h-1.5 w-1.5 rounded-full bg-primary animate-pulse-glow" />
193+
{children}
194+
</p>
195+
);
196+
}

‎src/routes/academy.tsx‎

Lines changed: 122 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,130 @@
1-
import { ComingSoon } from "@/components/coming-soon";
1+
import { BookOpen, Code2, ShieldCheck, Users, Compass, Rocket } from "lucide-react";
2+
import { PageHero } from "@/components/section";
23
import { Seo } from "@/components/seo";
4+
import { Faq, FeatureGrid, ProgramCta, StatusNote, Timeline } from "@/components/program-page";
5+
import { breadcrumbSchema, webPageSchema } from "@/lib/seo";
6+
7+
const title = "GhostCode Academy - GhostCode Dynamics";
8+
const description =
9+
"GhostCode Academy is the education arm of GhostCode Dynamics: structured, project-based learning paths in modern web development and cybersecurity.";
10+
const path = "/academy";
11+
12+
const TRACKS = [
13+
{
14+
icon: <Code2 className="h-5 w-5" />,
15+
title: "Modern Web Track",
16+
desc: "HTML, CSS, JavaScript and React fundamentals taught through one real product you build end to end.",
17+
},
18+
{
19+
icon: <Rocket className="h-5 w-5" />,
20+
title: "Full-Stack MERN Track",
21+
desc: "Node, Express, MongoDB and API design — auth, data modelling, deployment and the boring parts that matter.",
22+
},
23+
{
24+
icon: <ShieldCheck className="h-5 w-5" />,
25+
title: "Security Foundations",
26+
desc: "Web application security basics: the OWASP Top 10, safe auth patterns, and how attacks actually work.",
27+
},
28+
{
29+
icon: <Compass className="h-5 w-5" />,
30+
title: "Career Craft",
31+
desc: "Portfolio, GitHub hygiene, writing about your work, and interviewing without pretending to know everything.",
32+
},
33+
{
34+
icon: <BookOpen className="h-5 w-5" />,
35+
title: "Build Journals",
36+
desc: "Every track ends with a written case study — the artefact that gets you hired, not just a certificate.",
37+
},
38+
{
39+
icon: <Users className="h-5 w-5" />,
40+
title: "Small Cohorts",
41+
desc: "Intentionally small groups so feedback stays personal and questions actually get answered.",
42+
},
43+
];
44+
45+
const PHASES = [
46+
{
47+
label: "Phase 01",
48+
title: "Curriculum in the open",
49+
desc: "Track outlines and project briefs published publicly so you can start learning before any cohort opens.",
50+
},
51+
{
52+
label: "Phase 02",
53+
title: "First pilot cohort",
54+
desc: "A small, invite-based group works through the Modern Web track with direct founder feedback.",
55+
},
56+
{
57+
label: "Phase 03",
58+
title: "Open enrolment",
59+
desc: "Tracks open publicly with self-paced material, live sessions and reviewed project submissions.",
60+
},
61+
];
62+
63+
const FAQS = [
64+
{
65+
q: "Is the Academy running right now?",
66+
a: "Not yet. It is in active development. Joining the list means you hear first when the pilot cohort opens — nothing is being sold today.",
67+
},
68+
{
69+
q: "Who is it for?",
70+
a: "Students and early-career developers who can already write some code and want to build production-grade work rather than follow tutorials.",
71+
},
72+
{
73+
q: "Will it be free?",
74+
a: "Curriculum outlines and a good amount of written material will be free. Reviewed cohorts with direct mentorship will be paid, and priced for students.",
75+
},
76+
{
77+
q: "Do I get a certificate?",
78+
a: "Completed cohorts will issue a verifiable certificate you can check on our verification page. The project you ship matters more.",
79+
},
80+
];
381

482
export default function Page() {
583
return (
684
<>
7-
<Seo title={"GhostCode Academy - GhostCode Dynamics"} description={"A future education arm for structured learning paths in modern web development and cybersecurity."} path={"/academy"} robots="noindex, follow" />
8-
<ComingSoon
9-
module="Academy"
10-
title="GhostCode Academy."
11-
description="A future education arm — structured learning paths in modern web development and security, built around real projects."
12-
/>
85+
<Seo
86+
title={title}
87+
description={description}
88+
path={path}
89+
schemas={[
90+
webPageSchema(title, description, path),
91+
breadcrumbSchema([
92+
{ name: "Home", path: "/" },
93+
{ name: "Academy", path },
94+
]),
95+
]}
96+
/>
97+
<PageHero
98+
eyebrow="Academy · In development"
99+
title="Learn by shipping, not by watching."
100+
description="GhostCode Academy is the education arm of GhostCode Dynamics — structured learning paths in modern web development and security, built around real projects instead of passive video."
101+
>
102+
<StatusNote>Curriculum in progress · Pilot cohort planned</StatusNote>
103+
</PageHero>
104+
105+
<FeatureGrid
106+
eyebrow="Tracks"
107+
title="What we're building"
108+
description="Each track is a sequence of briefs, not lectures. You finish with something deployed and documented."
109+
items={TRACKS}
110+
/>
111+
112+
<Timeline
113+
eyebrow="Roadmap"
114+
title="How the Academy rolls out"
115+
description="We would rather launch one track properly than ten badly."
116+
items={PHASES}
117+
/>
118+
119+
<Faq items={FAQS} />
120+
121+
<ProgramCta
122+
title="Be in the first cohort"
123+
description="Tell us what you want to learn and we'll shape the pilot around real demand. No spam, no drip funnel."
124+
primaryLabel="Join the Academy list"
125+
secondaryLabel="Browse Insights"
126+
secondaryTo="/blog"
127+
/>
13128
</>
14129
);
15130
}

0 commit comments

Comments
 (0)