Harden onion boot flow and deepen site surfaces

Add persistent onion key backup and restore, improve startup resilience, and flesh out the major site verticals with richer navigation, search coverage, and operator documentation.

Made-with: Cursor
This commit is contained in:
drjones
2026-04-07 21:35:52 -07:00
parent 52432dccfa
commit 78a071ba02
162 changed files with 21692 additions and 39 deletions

View File

@@ -0,0 +1,64 @@
"use client";
import { useCallback, useState } from "react";
import type { ForumThread } from "@/lib/forumState";
import {
displayScore,
getVoteForThread,
setVoteForThread,
type VoteChoice,
} from "@/lib/forumState";
export function ThreadVoteColumn({
thread,
dense,
onVoteChange,
}: {
thread: ForumThread;
dense?: boolean;
onVoteChange?: () => void;
}) {
const [tick, setTick] = useState(0);
const choice = getVoteForThread(thread.id);
const score = displayScore(thread);
const apply = useCallback(
(dir: 1 | -1) => {
const cur = getVoteForThread(thread.id);
let next: VoteChoice = dir;
if (cur === dir) next = 0;
setVoteForThread(thread.id, next);
setTick((t) => t + 1);
onVoteChange?.();
},
[thread.id, onVoteChange],
);
void tick;
const btn = dense ? "px-1 py-0.5 text-[10px]" : "px-1.5 py-1 text-xs";
return (
<div
className={`flex flex-col items-center rounded border border-[#3d3228] bg-[#0d0a07] font-mono ${dense ? "min-w-[44px] py-1" : "min-w-[52px] py-2"}`}
>
<button
type="button"
aria-label="Upvote"
onClick={() => apply(1)}
className={`${btn} leading-none text-[#8a7d6b] hover:text-[#ff9a3c] ${choice === 1 ? "text-[#ff9a3c]" : ""}`}
>
</button>
<span className="text-[11px] font-bold tabular-nums text-[#ffcb8a]">{score}</span>
<button
type="button"
aria-label="Downvote"
onClick={() => apply(-1)}
className={`${btn} leading-none text-[#8a7d6b] hover:text-[#6b9fff] ${choice === -1 ? "text-[#6b9fff]" : ""}`}
>
</button>
</div>
);
}