- ChatWidget: remove illegal seeds, real localStorage per-handle chat, honest bot replies about market/forum/funds - ForumBoard: wire to real forumState (loadForum/addThread/vote), kill fake stats and illegal seed posts - Home page: privacy features list reflects reality, footer links real - Links: kill all alert() calls, replace fake onions with real clearnet privacy resources + internal route grid - Support: per-coin copied state, env-driven addresses, real BTC addr - Inner circle: wire to AccountContext, tier system from LUX balance, remove hardcoded admin/shadow credentials and fake trading signals - Drop box: real sealed-note localStorage system, honest about no anonymous upload capability, real file picker with receipt - Messages: fully functional per-handle localStorage chat, AI-style contextual bot replies, clear history, honest about local storage - Wallets: pivot from fake PayPal accounts to Digital Access Passes, wire Buy Now to cart via ShopProduct interface - Testimonials: wire submit form to localStorage, interactive star rating 1-10, display submitted reviews above the fold - Raffle: use real merchant BTC address, real per-handle entry storage, honest LUX-only prize disclaimer, fix 0x address - Drops/Lotto: real number picker 1-49 with Quick Pick, ticket submission, match display against drawn numbers, demo disclaimer - Sanctuary: real 4-4-6-2 breathing timer, meditation passage with timer, candle-lighting with localStorage notes - Game: full playable Void Pong with canvas physics, CPU AI, scoring, rally counter, localStorage high score - Security analysis: honest architecture breakdown with real grades, layer-by-layer analysis, practical OPSEC guide, fiction banner - Trust: compute real scores from actual localStorage data (LUX, USD, forum posts, testimonials), FAQ accordion Made-with: Cursor
190 lines
8.2 KiB
TypeScript
190 lines
8.2 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { useMemo, useState } from "react";
|
|
import {
|
|
DARKNET_ATLAS,
|
|
atlasCategoryMatchesQuery,
|
|
type AtlasCategory,
|
|
} from "@/lib/darknetAtlas";
|
|
|
|
function isClearnet(href: string): boolean {
|
|
if (href.toLowerCase().includes(".onion")) return false;
|
|
return href.startsWith("https://") || href.startsWith("http://");
|
|
}
|
|
|
|
function LinkRow({ href, title, note }: { href: string; title: string; note: string }) {
|
|
const external = !href.startsWith("/");
|
|
const clearnet = isClearnet(href);
|
|
const body = (
|
|
<>
|
|
<span className="font-mono text-sm font-semibold text-[#7eb8ff] group-hover:text-[#a8d4ff]">{title}</span>
|
|
<p className="mt-1 font-serif text-sm text-[#94a8b8]">{note}</p>
|
|
<p className="mt-1.5 font-mono text-[10px] tracking-wider text-[#5a6b82]">
|
|
{clearnet ? <span className="text-[#7cfc9a]/80">clearnet · </span> : null}
|
|
<span className="break-all text-[#6b7c91]">{href}</span>
|
|
</p>
|
|
</>
|
|
);
|
|
if (external) {
|
|
return (
|
|
<a href={href} rel="noopener noreferrer" className="group block">
|
|
{body}
|
|
</a>
|
|
);
|
|
}
|
|
return (
|
|
<Link href={href} className="group block">
|
|
{body}
|
|
</Link>
|
|
);
|
|
}
|
|
|
|
export default function DarknetAtlasPage() {
|
|
const [q, setQ] = useState("");
|
|
const visible = useMemo(
|
|
() => DARKNET_ATLAS.filter((c) => atlasCategoryMatchesQuery(c, q)),
|
|
[q],
|
|
);
|
|
|
|
return (
|
|
<div className="min-h-screen bg-[#05070c] text-[#c4cee0]">
|
|
<div className="pointer-events-none fixed inset-0 z-0 bg-[radial-gradient(ellipse_80%_50%_at_50%_-20%,rgba(59,130,246,0.12),transparent)]" />
|
|
<div
|
|
className="pointer-events-none fixed inset-0 z-0 opacity-[0.04]"
|
|
style={{
|
|
backgroundImage: `linear-gradient(rgba(120,160,255,0.35) 1px, transparent 1px),
|
|
linear-gradient(90deg, rgba(120,160,255,0.2) 1px, transparent 1px)`,
|
|
backgroundSize: "32px 32px",
|
|
}}
|
|
/>
|
|
|
|
<header className="relative z-10 border-b border-[#1e293b] bg-[#0a0f18]/95 px-4 py-8 backdrop-blur-md">
|
|
<div className="mx-auto max-w-6xl">
|
|
<p className="font-mono text-[10px] uppercase tracking-[0.45em] text-[#64748b]">reference · taxonomy</p>
|
|
<h1 className="mt-2 bg-gradient-to-r from-[#94a8ff] to-[#38bdf8] bg-clip-text font-mono text-3xl font-black tracking-tight text-transparent md:text-4xl">
|
|
Darknet Atlas
|
|
</h1>
|
|
<p className="mt-4 max-w-3xl text-sm leading-relaxed text-[#94a3b8]">
|
|
Analyst-facing taxonomy for how underground ecosystems get clustered in threat intel — markets, access brokers, leak blogs,
|
|
whistleblowing rails, opsec boutiques, and rumor boards. In-app rows link to real CyberLux routes (forum, market, checkout, funding,
|
|
etc.); clearnet rows are curated references you should still verify out-of-band.
|
|
</p>
|
|
<div className="mt-6 flex flex-wrap gap-3 font-mono text-xs">
|
|
<Link
|
|
href="/hidden-wiki"
|
|
className="rounded border border-[#334155] px-4 py-2 text-[#94a3b8] hover:border-[#38bdf8]/50 hover:text-[#e2e8f0]"
|
|
>
|
|
← Scrapbook wiki
|
|
</Link>
|
|
<Link href="/" className="rounded border border-[#334155] px-4 py-2 text-[#94a3b8] hover:border-[#38bdf8]/50 hover:text-[#e2e8f0]">
|
|
Hub
|
|
</Link>
|
|
<Link href="/forum" className="rounded border border-[#334155] px-4 py-2 text-[#94a3b8] hover:border-[#38bdf8]/50 hover:text-[#e2e8f0]">
|
|
Forums
|
|
</Link>
|
|
<Link href="/links" className="rounded border border-[#334155] px-4 py-2 text-[#94a3b8] hover:border-[#38bdf8]/50 hover:text-[#e2e8f0]">
|
|
Link garden
|
|
</Link>
|
|
<Link href="/dashboard" className="rounded border border-[#334155] px-4 py-2 text-[#94a3b8] hover:border-[#38bdf8]/50 hover:text-[#e2e8f0]">
|
|
Dashboard
|
|
</Link>
|
|
<Link href="/sign-in" className="rounded border border-[#334155] px-4 py-2 text-[#94a3b8] hover:border-[#38bdf8]/50 hover:text-[#e2e8f0]">
|
|
Sign in
|
|
</Link>
|
|
<Link
|
|
href="/search"
|
|
className="rounded border border-[#14532d]/60 bg-[#052e16]/40 px-4 py-2 text-[#86efac] hover:border-[#22c55e]/50"
|
|
>
|
|
Void crawler
|
|
</Link>
|
|
</div>
|
|
<div className="mt-6">
|
|
<label className="sr-only" htmlFor="atlas-search">
|
|
Filter atlas
|
|
</label>
|
|
<input
|
|
id="atlas-search"
|
|
value={q}
|
|
onChange={(e) => setQ(e.target.value)}
|
|
placeholder="Filter categories, subsections, or link titles…"
|
|
className="w-full max-w-xl rounded border border-[#334155] bg-[#0f172a] px-4 py-3 font-mono text-sm text-[#e2e8f0] placeholder:text-[#475569] focus:border-[#38bdf8]/50 focus:outline-none"
|
|
/>
|
|
<p className="mt-2 font-mono text-[10px] text-[#64748b]">
|
|
{visible.length} / {DARKNET_ATLAS.length} top-level categories visible · internal links resolve inside this deployment.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<div className="relative z-10 mx-auto flex max-w-6xl flex-col gap-10 px-4 pb-24 pt-8 lg:flex-row lg:items-start">
|
|
<nav className="top-24 shrink-0 font-mono text-[11px] text-[#64748b] lg:sticky lg:w-56">
|
|
<p className="mb-3 uppercase tracking-widest text-[#475569]">Jump</p>
|
|
<ul className="max-h-[70vh] space-y-1 overflow-y-auto border border-[#1e293b] bg-[#0a0f18]/80 p-3">
|
|
{DARKNET_ATLAS.map((c) => (
|
|
<li key={c.id}>
|
|
<a href={`#${c.id}`} className="flex gap-2 break-words hover:text-[#38bdf8]">
|
|
<span className="shrink-0 opacity-60">{c.icon}</span>
|
|
<span className="leading-tight">{c.title}</span>
|
|
</a>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</nav>
|
|
|
|
<div className="min-w-0 flex-1 space-y-16">
|
|
{visible.length === 0 ? (
|
|
<p className="font-mono text-sm text-[#64748b]">No sections match that filter.</p>
|
|
) : (
|
|
visible.map((cat) => <AtlasCategorySection key={cat.id} cat={cat} query={q} />)
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function AtlasCategorySection({ cat, query }: { cat: AtlasCategory; query: string }) {
|
|
const subs = useMemo(() => {
|
|
if (!query.trim()) return cat.subsections;
|
|
const s = query.toLowerCase();
|
|
return cat.subsections.filter(
|
|
(sub) =>
|
|
sub.name.toLowerCase().includes(s) ||
|
|
sub.blurb.toLowerCase().includes(s) ||
|
|
sub.links.some((L) => L.title.toLowerCase().includes(s) || L.note.toLowerCase().includes(s)),
|
|
);
|
|
}, [cat.subsections, query]);
|
|
|
|
if (subs.length === 0) return null;
|
|
|
|
return (
|
|
<section id={cat.id} className="scroll-mt-28">
|
|
<div className="flex flex-wrap items-start gap-4 border-b border-[#1e293b] pb-4">
|
|
<span className="font-mono text-2xl text-[#38bdf8]/80">{cat.icon}</span>
|
|
<div>
|
|
<h2 className="font-mono text-xl font-bold text-[#f1f5f9] md:text-2xl">{cat.title}</h2>
|
|
<p className="mt-2 text-sm leading-relaxed text-[#94a3b8]">{cat.overview}</p>
|
|
<p className="mt-3 border-l-2 border-[#38bdf8]/50 pl-3 text-xs leading-relaxed text-[#7dd3fc]/90">{cat.literacy}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-8 space-y-10">
|
|
{subs.map((sub) => (
|
|
<div key={sub.name} className="rounded-lg border border-[#1e293b] bg-[#0a0f18]/60 p-5">
|
|
<h3 className="font-mono text-sm font-bold uppercase tracking-wide text-[#7dd3fc]">{sub.name}</h3>
|
|
<p className="mt-2 text-sm text-[#94a3b8]">{sub.blurb}</p>
|
|
<ul className="mt-5 divide-y divide-[#1e293b] border border-[#1e293b] bg-[#070b12]/80">
|
|
{sub.links.map((link) => (
|
|
<li key={`${sub.name}-${link.title}`} className="p-4 transition-colors hover:bg-[#0f172a]/80">
|
|
<LinkRow href={link.href} title={link.title} note={link.note} />
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|