Replace remote with local repo
This commit is contained in:
193
app/academy/page.tsx
Normal file
193
app/academy/page.tsx
Normal file
@@ -0,0 +1,193 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import Navbar from "@/components/Navbar";
|
||||
|
||||
const COURSES = [
|
||||
{
|
||||
id: "opsec-foundations",
|
||||
title: "OPSEC Foundations",
|
||||
subtitle: "Zero-to-operational in 6 modules",
|
||||
icon: "🛡️",
|
||||
level: "Beginner",
|
||||
modules: 6,
|
||||
cost: 0,
|
||||
free: true,
|
||||
topics: ["Threat modelling", "Device isolation", "Handle hygiene", "Network compartmentalisation"],
|
||||
},
|
||||
{
|
||||
id: "tor-deep-dive",
|
||||
title: "Tor Architecture",
|
||||
subtitle: "How the onion network actually works",
|
||||
icon: "🌐",
|
||||
level: "Intermediate",
|
||||
modules: 8,
|
||||
cost: 15,
|
||||
free: false,
|
||||
topics: ["Circuit construction", "Hidden service descriptor flow", "Guard node selection", "Fingerprinting resistance"],
|
||||
},
|
||||
{
|
||||
id: "pgp-mastery",
|
||||
title: "PGP & Key Hygiene",
|
||||
subtitle: "Encrypt everything, trust nobody",
|
||||
icon: "🔐",
|
||||
level: "Intermediate",
|
||||
modules: 5,
|
||||
cost: 12,
|
||||
free: false,
|
||||
topics: ["Ed25519 vs RSA", "Web of trust vs TOFU", "Subkey architecture", "Revocation ceremonies"],
|
||||
},
|
||||
{
|
||||
id: "darknet-recon",
|
||||
title: "Darknet OSINT",
|
||||
subtitle: "Gather intelligence without leaving traces",
|
||||
icon: "🔍",
|
||||
level: "Advanced",
|
||||
modules: 10,
|
||||
cost: 25,
|
||||
free: false,
|
||||
topics: ["Passive recon techniques", "Link graph analysis", "Temporal correlation", "Attribution avoidance"],
|
||||
},
|
||||
{
|
||||
id: "btc-privacy",
|
||||
title: "Bitcoin Privacy",
|
||||
subtitle: "Spend and receive without a trail",
|
||||
icon: "₿",
|
||||
level: "Intermediate",
|
||||
modules: 7,
|
||||
cost: 20,
|
||||
free: false,
|
||||
topics: ["UTXO management", "CoinJoin & PayJoin", "Lightning privacy tradeoffs", "Blockchain analysis evasion"],
|
||||
},
|
||||
{
|
||||
id: "hidden-service-ops",
|
||||
title: "Hidden Service Operations",
|
||||
subtitle: "Deploy and harden a Tor v3 site",
|
||||
icon: "🧅",
|
||||
level: "Advanced",
|
||||
modules: 9,
|
||||
cost: 30,
|
||||
free: false,
|
||||
topics: ["Vanity address mining", "nginx hardening", "DoS mitigation", "Key backup & recovery", "Systemd hardening"],
|
||||
},
|
||||
];
|
||||
|
||||
const LEVEL_COLORS: Record<string, string> = {
|
||||
Beginner: "text-neon-green border-neon-green/30 bg-neon-green/10",
|
||||
Intermediate: "text-neon-cyan border-neon-cyan/30 bg-neon-cyan/10",
|
||||
Advanced: "text-neon-purple border-neon-purple/30 bg-neon-purple/10",
|
||||
};
|
||||
|
||||
export default function AcademyPage() {
|
||||
const [open, setOpen] = useState<string | null>(null);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Navbar />
|
||||
<main className="min-h-screen bg-[#0a0a0a] pt-24 pb-20">
|
||||
{/* Header */}
|
||||
<section className="container mx-auto max-w-6xl px-4 mb-14 text-center">
|
||||
<p className="mb-3 font-mono text-[10px] uppercase tracking-[0.35em] text-neon-cyan/70">cipher academy · operational security</p>
|
||||
<h1 className="font-orbitron text-5xl font-bold md:text-6xl">
|
||||
CIPHER<span className="text-neon-cyan"> ACADEMY</span>
|
||||
</h1>
|
||||
<p className="mx-auto mt-5 max-w-xl text-lg text-foreground/60">
|
||||
Structured OPSEC and darknet operations curriculum. Free foundation courses; advanced modules unlocked with VOID credits.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{/* Stats */}
|
||||
<section className="container mx-auto max-w-6xl px-4 mb-12">
|
||||
<div className="flex flex-wrap justify-center gap-8 text-center">
|
||||
{[
|
||||
{ label: "Courses", value: COURSES.length },
|
||||
{ label: "Free modules", value: "6" },
|
||||
{ label: "Total modules", value: COURSES.reduce((a, c) => a + c.modules, 0) },
|
||||
{ label: "Skill levels", value: "3" },
|
||||
].map((s) => (
|
||||
<div key={s.label}>
|
||||
<p className="font-orbitron text-3xl font-black text-neon-cyan">{s.value}</p>
|
||||
<p className="mt-1 text-xs text-foreground/50 uppercase tracking-widest">{s.label}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Course grid */}
|
||||
<section className="container mx-auto max-w-6xl px-4">
|
||||
<div className="grid gap-5 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{COURSES.map((course) => (
|
||||
<div
|
||||
key={course.id}
|
||||
className="rounded-xl border border-zinc-700/40 bg-black/40 p-5 flex flex-col hover:border-zinc-500 transition"
|
||||
>
|
||||
<div className="flex items-start justify-between gap-2 mb-3">
|
||||
<span className="text-3xl">{course.icon}</span>
|
||||
<span className={`rounded-full border px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider ${LEVEL_COLORS[course.level]}`}>
|
||||
{course.level}
|
||||
</span>
|
||||
</div>
|
||||
<h3 className="font-orbitron text-base font-bold">{course.title}</h3>
|
||||
<p className="mt-1 text-xs text-foreground/50">{course.subtitle}</p>
|
||||
<p className="mt-1 text-xs text-foreground/40">{course.modules} modules</p>
|
||||
|
||||
<ul className="mt-4 flex-1 space-y-1">
|
||||
{course.topics.map((t) => (
|
||||
<li key={t} className="text-xs text-foreground/60 flex gap-2">
|
||||
<span className="text-neon-cyan/60">›</span> {t}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<div className="mt-5 flex items-center justify-between">
|
||||
{course.free ? (
|
||||
<span className="rounded-full bg-neon-green/15 border border-neon-green/30 px-3 py-1 text-xs font-bold text-neon-green">
|
||||
FREE
|
||||
</span>
|
||||
) : (
|
||||
<span className="font-mono text-sm font-bold text-neon-purple">✦ {course.cost} VOID</span>
|
||||
)}
|
||||
<button
|
||||
onClick={() => setOpen(open === course.id ? null : course.id)}
|
||||
className="rounded-lg border border-zinc-600 bg-white/5 px-4 py-1.5 text-xs hover:border-zinc-400 transition"
|
||||
>
|
||||
{open === course.id ? "Collapse" : "Preview"}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{open === course.id && (
|
||||
<div className="mt-4 rounded-lg border border-zinc-700/40 bg-black/30 p-4">
|
||||
<p className="text-xs text-foreground/60 mb-3">Module breakdown coming soon. Sign in and unlock to access full curriculum.</p>
|
||||
<Link
|
||||
href={course.free ? "/sign-up" : "/account/add-funds"}
|
||||
className="block text-center rounded-lg bg-neon-cyan/15 border border-neon-cyan/30 px-4 py-2 text-xs font-bold text-neon-cyan hover:bg-neon-cyan/25"
|
||||
>
|
||||
{course.free ? "Start free →" : "Unlock with VOID credits →"}
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA */}
|
||||
<section className="container mx-auto max-w-2xl px-4 mt-20 text-center">
|
||||
<div className="rounded-2xl border border-neon-purple/20 bg-neon-purple/5 p-10">
|
||||
<h2 className="font-orbitron text-2xl font-bold mb-3">Start with the free course</h2>
|
||||
<p className="text-foreground/60 mb-6">OPSEC Foundations is available to all registered users at no cost. No excuses.</p>
|
||||
<div className="flex flex-wrap justify-center gap-3">
|
||||
<Link href="/sign-up" className="rounded-full border border-neon-cyan/40 bg-neon-cyan/10 px-6 py-2.5 text-sm font-bold text-neon-cyan hover:bg-neon-cyan/20">
|
||||
Register →
|
||||
</Link>
|
||||
<Link href="/account/add-funds" className="rounded-full bg-gradient-to-r from-neon-cyan to-neon-purple px-6 py-2.5 text-sm font-bold text-background hover:opacity-90">
|
||||
+ VOID Credits
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user