"use client"; import Link from "next/link"; import { useMemo } from "react"; import { useSearchParams } from "next/navigation"; import { formatRingLabel } from "@/lib/forumRings"; import { SHOP_CHATTER_COUNT, getChatterSlice } from "@/lib/shopChatterThreads"; const PAGE_SIZE = 12; function formatAgo(ts: number): string { const s = Math.floor((Date.now() - ts) / 1000); if (s < 60) return `${s}s ago`; const m = Math.floor(s / 60); if (m < 60) return `${m}m ago`; const h = Math.floor(m / 60); if (h < 48) return `${h}h ago`; const d = Math.floor(h / 24); return `${d}d ago`; } export default function HubChatterArchivePage() { const sp = useSearchParams(); const page = Math.max(1, parseInt(sp.get("page") ?? "1", 10) || 1); const { items, totalPages, total } = useMemo( () => getChatterSlice(page, PAGE_SIZE), [page], ); const pages = useMemo(() => { const window = 2; const lo = Math.max(1, page - window); const hi = Math.min(totalPages, page + window); const out: number[] = []; for (let i = lo; i <= hi; i++) out.push(i); return out; }, [page, totalPages]); return (

archive

Hub chatter index

Scraped-style threads about the CyberLux main storefront — mirror checks, checkout banter, UI roasts, class-lab meta. Each row opens in Void Aggregate for full comments.

Showing {(page - 1) * PAGE_SIZE + 1}–{Math.min(page * PAGE_SIZE, total)} of {total} indexed posts ·{" "} {PAGE_SIZE} per page

    {items.map((row) => (
  • {formatRingLabel(row.topicSlug)} {row.author} · {formatAgo(row.ts)}
    {row.title}

    {row.body}

    {row.replies.length} comments score ~{row.baseScore ?? 1} open thread →
  • ))}

Total catalogued: {SHOP_CHATTER_COUNT} threads

); }