Capture the current CyberLux UI, commerce, messaging, and Tor ops updates so local main can be pushed to the remote. Made-with: Cursor
214 lines
7.9 KiB
TypeScript
214 lines
7.9 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { useState } from "react";
|
|
import ThemedLayout from "@/components/layouts/ThemedLayout";
|
|
import { LINK_GARDEN_INTERNAL } from "@/lib/cyberluxSitemap";
|
|
|
|
type Resource = {
|
|
name: string;
|
|
description: string;
|
|
href: string;
|
|
category: string;
|
|
trust: "internal" | "clearnet" | "onion-required";
|
|
icon: string;
|
|
external: boolean;
|
|
};
|
|
|
|
const RESOURCES: Resource[] = [
|
|
{
|
|
name: "Tor Project",
|
|
description: "Official documentation for the Tor anonymity network and Tor Browser. Start here for anything Tor-related.",
|
|
href: "https://www.torproject.org/",
|
|
category: "Infrastructure",
|
|
trust: "clearnet",
|
|
icon: "🧅",
|
|
external: true,
|
|
},
|
|
{
|
|
name: "EFF — Surveillance Self-Defense",
|
|
description: "Electronic Frontier Foundation's guide to protecting yourself from digital surveillance.",
|
|
href: "https://ssd.eff.org/",
|
|
category: "OPSEC",
|
|
trust: "clearnet",
|
|
icon: "🛡️",
|
|
external: true,
|
|
},
|
|
{
|
|
name: "Tails OS",
|
|
description: "Privacy-focused amnesic operating system that leaves no trace. Runs from a USB drive.",
|
|
href: "https://tails.boum.org/",
|
|
category: "Infrastructure",
|
|
trust: "clearnet",
|
|
icon: "💾",
|
|
external: true,
|
|
},
|
|
{
|
|
name: "Privacy Guides",
|
|
description: "Community-maintained recommendations for privacy software, services, and tools across every category.",
|
|
href: "https://www.privacyguides.org/",
|
|
category: "Reference",
|
|
trust: "clearnet",
|
|
icon: "📚",
|
|
external: true,
|
|
},
|
|
{
|
|
name: "SecureDrop",
|
|
description: "Open-source whistleblower submission platform used by major news organizations.",
|
|
href: "https://securedrop.org/",
|
|
category: "Whistleblowing",
|
|
trust: "clearnet",
|
|
icon: "📮",
|
|
external: true,
|
|
},
|
|
{
|
|
name: "Monero (XMR)",
|
|
description: "Privacy-focused cryptocurrency with ring signatures, stealth addresses, and confidential transactions.",
|
|
href: "https://www.getmonero.org/",
|
|
category: "Finance",
|
|
trust: "clearnet",
|
|
icon: "⏣",
|
|
external: true,
|
|
},
|
|
{
|
|
name: "OpenPGP standard",
|
|
description: "The spec behind PGP-encrypted communications. Essential reading for key hygiene and signing.",
|
|
href: "https://www.openpgp.org/",
|
|
category: "Cryptography",
|
|
trust: "clearnet",
|
|
icon: "🔑",
|
|
external: true,
|
|
},
|
|
{
|
|
name: "Have I Been Pwned",
|
|
description: "Check if your email or phone was in a data breach. Free lookup, no account needed.",
|
|
href: "https://haveibeenpwned.com/",
|
|
category: "Security",
|
|
trust: "clearnet",
|
|
icon: "🔍",
|
|
external: true,
|
|
},
|
|
];
|
|
|
|
const TRUST_LABELS: Record<Resource["trust"], { label: string; color: string }> = {
|
|
internal: { label: "Internal", color: "text-neon-green" },
|
|
clearnet: { label: "Clearnet", color: "text-neon-cyan" },
|
|
"onion-required": { label: "Tor only", color: "text-amber-400" },
|
|
};
|
|
|
|
export default function LinksPage() {
|
|
const [cat, setCat] = useState<string>("All");
|
|
const cats = ["All", ...Array.from(new Set(RESOURCES.map((r) => r.category)))];
|
|
const visible = cat === "All" ? RESOURCES : RESOURCES.filter((r) => r.category === cat);
|
|
|
|
return (
|
|
<ThemedLayout theme="institutional" siteTitle="LINK GARDEN" siteSubtitle="Curated clearnet + internal resources">
|
|
<section className="container mx-auto max-w-6xl px-4 py-12">
|
|
<div className="text-center">
|
|
<h1 className="font-orbitron text-5xl font-bold md:text-6xl">
|
|
LINK <span className="theme-accent">GARDEN</span>
|
|
</h1>
|
|
<p className="mx-auto mt-6 max-w-3xl text-lg opacity-80">
|
|
Curated privacy and security resources. External links go to real clearnet sites. Internal links stay on
|
|
this deployment. Every .onion row in the Atlas requires Tor Browser — these are clearnet-accessible
|
|
references.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="container mx-auto max-w-6xl px-4 py-8">
|
|
<div className="mb-8 flex flex-wrap items-center justify-between gap-4">
|
|
<h2 className="font-orbitron text-3xl font-bold">EXTERNAL RESOURCES</h2>
|
|
<div className="flex flex-wrap gap-2">
|
|
{cats.map((c) => (
|
|
<button
|
|
key={c}
|
|
type="button"
|
|
onClick={() => setCat(c)}
|
|
className={`rounded-full border px-4 py-2 text-xs font-bold uppercase transition-all ${
|
|
cat === c
|
|
? "border-neon-cyan bg-neon-cyan/15 text-neon-cyan"
|
|
: "border-white/15 text-foreground/60 hover:border-white/30"
|
|
}`}
|
|
>
|
|
{c}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 gap-5 md:grid-cols-2 lg:grid-cols-3">
|
|
{visible.map((r) => {
|
|
const trust = TRUST_LABELS[r.trust];
|
|
return (
|
|
<div
|
|
key={r.name}
|
|
className="theme-card group relative overflow-hidden rounded-2xl border border-white/10 p-6 transition-all hover:border-neon-cyan/30"
|
|
>
|
|
<div className="mb-4 flex items-start justify-between gap-2">
|
|
<span className="text-3xl">{r.icon}</span>
|
|
<div className="flex flex-col items-end gap-1">
|
|
<span className={`text-[10px] font-bold uppercase ${trust.color}`}>{trust.label}</span>
|
|
<span className="rounded-full bg-white/5 px-2 py-0.5 text-[10px] text-foreground/50">
|
|
{r.category}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<h3 className="mb-2 text-lg font-bold">{r.name}</h3>
|
|
<p className="mb-4 text-sm leading-relaxed opacity-70">{r.description}</p>
|
|
<a
|
|
href={r.href}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="inline-flex items-center gap-2 text-sm font-bold theme-accent hover:underline"
|
|
>
|
|
Visit ↗
|
|
</a>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</section>
|
|
|
|
<section className="container mx-auto max-w-6xl px-4 py-16">
|
|
<h2 className="mb-8 font-orbitron text-3xl font-bold">INTERNAL ROUTES</h2>
|
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
{LINK_GARDEN_INTERNAL.map((item) => (
|
|
<Link
|
|
key={item.href}
|
|
href={item.href}
|
|
className="theme-card group flex items-start gap-4 rounded-2xl border border-white/10 p-5 transition-all hover:border-neon-cyan/30 hover:bg-white/[0.03]"
|
|
>
|
|
<span className="mt-0.5 text-2xl">{item.icon}</span>
|
|
<div>
|
|
<div className="font-bold">{item.name}</div>
|
|
<p className="mt-1 text-sm opacity-60">{item.description}</p>
|
|
</div>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</section>
|
|
|
|
<section className="container mx-auto max-w-6xl px-4 pb-20">
|
|
<div className="theme-card rounded-2xl border border-white/10 p-8 text-sm">
|
|
<h3 className="mb-4 font-bold text-neon-cyan">Using Tor Browser</h3>
|
|
<p className="leading-relaxed opacity-70">
|
|
The external resources above are clearnet sites — accessible in any browser. For accessing .onion
|
|
services (including this deployment when running behind Tor), you must use{" "}
|
|
<a
|
|
href="https://www.torproject.org/download/"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-neon-cyan underline"
|
|
>
|
|
Tor Browser
|
|
</a>
|
|
. On mobile, use <strong>Onion Browser</strong> (iOS) or <strong>Tor Browser for Android</strong>. Safari
|
|
and Chrome cannot resolve .onion hostnames regardless of settings.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
</ThemedLayout>
|
|
);
|
|
}
|