kevin-wiki / ui

Purpose

The web viewer. A Next.js (App Router) app that renders the wiki/ markdown knowledge base as a browsable site, plus Kevin's /me portfolio and the private local /brief decision surface. Wiki content remains read-only; /brief writes only to the local Daily Brief event store through its gated API. Tailwind owns styling; the public wiki is deployed on Vercel.

Mental model & key files

  • src/app/(wiki)/ — the wiki reader (page rendering, [...slug], assets).
  • src/app/(wiki)/system/ — public brain/system projection.
  • src/app/(wiki)/brief/ — global-password-gated local Daily Brief client.
  • src/app/me/ — the portfolio (about, work, projects, research, lab, photography).
  • src/app/api/ — og (per-article OpenGraph images), search, assets, unlock, public system, public OKF v0.2, private brief, and bearer-authenticated proposal-memory routes.
  • src/app/graph/, src/app/audit/ — graph view + audit surfaces.
  • src/components/, src/lib/, src/contexts/ — shared UI, helpers, providers.
  • src/lib/privacy-policy.json + src/lib/gating.ts — shared fail-closed public/private policy for runtime and bundling.
  • scripts/ — build-time content bundling + citation checks (see ui/scripts/SKILL.md).

Patterns to follow / invariants

  • Tailwind + cn() first; raw CSS only in globals.css. No co-located CSS modules for ordinary UI (see wiki/style/css-ui-enforcement.md).
  • Follow wiki/style/react.md + wiki/style/typescript.md; check vercel-react-best-practices for data fetching / perf.
  • Package manager is pnpm here (the repo root is npm/tsx). Run from ui/.
  • Keep the full-text search index out of server-rendered page props. Public search loads the privacy-filtered /search-index.json static asset; unlocked search uses the bounded /api/search?view=page response.

Common tasks → first action

  • Dev server → pnpm dev (from repo root: npm run dev).
  • Build → npm run build (installs ui deps frozen, then builds).
  • Add a page → App Router segment under src/app/, reuse src/components/.

Gotchas

  • The app reads bundled wiki content — re-run the bundler (ui/scripts) after wiki changes that the viewer must reflect.
  • scripts/export-okf.mjs owns the privacy-filtered .content/okf projection; /api/okf only serves that generated tree and never reads canonical private pages directly.
  • Never add a parallel privacy list. Runtime and bundle-wiki.mjs must read the shared privacy manifest, and protected slugs cannot be force-public through frontmatter.
  • Never expose /api/brief without checking the global gate session. The local PGlite ledger is authoritative for the first Daily Brief slice and must not be serialized into public pages or generated assets.
  • /api/memory is a separate machine credential boundary: derive authority on the server, require idempotency and provenance, enforce KEVIN_WIKI_MEMORY_SOURCE_SCOPES, deny public writes unless explicitly enabled, and require a durable ledger path in production. It stores proposals, not canonical wiki truth.
  • This is a separate pnpm workspace from the tsx scripts at the repo root.