A personal knowledge base you can read and write from two clients: a Next.js web app and a
terminal app (lexicon-tui). Ask a question, get a
clear explanation, and it lands here as a browsable topic — with home-page Posts, a chat-style
Journal, a shared Todo list, full-text search, and a public submission queue moderated
from the website or the terminal.
Live: lexxicon.vercel.app ·
Terminal client: npm install -g lexicon-tui
┌────────────────────────────────────┬──────────────────┐
│ rendered markdown reader / │ Lexicon │
│ website-style composer │ Context │
│ │ server · counts│
│ (topics · posts · journal · │ auth state │
│ search · pending submissions) │ Todo │
│ │ [ ] [~] [x] │
├────────────────────────────────────┴──────────────────┤
│ > search topics, or : for commands │
└────────────────────────────────────────────────────────┘
the TUI — same content, same API, OpenCode-style
- Topics — long-form explainers authored as MDX in
content/, grouped by category, with a table of contents, scroll-spy, and a knowledge graph (/graph). - Posts — flowing, readable notes on the home page. Admin composes at
/compose(Ctrl+Enterflows each draft into one document); the public submits at/submit→ email confirmation → the admin approves or rejects from the moderation queue. - Journal (
/journal) — open, chat-style notes: eachCtrl+Enteradds an entry to a feed. - Todos — a clipboard icon in the navbar with an open-count badge; the dropdown cycles each item todo → in progress → finished. Same list the TUI shows.
- Full-text search (
⌘K) — titles and body content across topics, posts, and journal. - SEO & sharing — generated OG images, sitemap, robots, RSS (
/feed.xml), JSON-LD, PDF export for posts, PWA manifest + offline service worker. - Theming — dark by default; all colors are CSS variables in
globals.css.
Built with Ink 7 + React 19, published as lexicon-tui.
It's a pure API client — point it at any Lexicon instance.
- Read everything — the topic/post tree in the center pane, rendered as ANSI markdown
(coral headings, highlighted code);
j/kscroll,/fuzzy search,Ctrl+Ppalette. - Write everything — composers mirror the website: the note builds up as a readable preview
on top, you type in a box pinned at the bottom,
Ctrl+Entersends the draft up,Ctrl+Ssaves. Posts publish (admin), journal entries append,:todo <text>quick-adds. - Moderate from the terminal — a coral
N pending submissionsbadge appears in the right rail (polled every 60 s);:inboxlists the queue,Enterpreviews,ypublishes,nrejects. - Todo rail —
Tabto focus,spacecycles[ ]→[~]→[x],aadds,ddeletes. - Config persists in
~/.lexicon/config.json(server,editToken,adminToken).
lexicon-tui ──HTTP──▶ Next.js route handlers ──service role──▶ Supabase (Postgres)
browser ──HTTP──▶ /api/tui/* (reads) RLS: public read,
/api/{posts,journal,todos} (writes) no public writes
/api/admin/* (moderation)
- Content — curated topics are MDX files in the repo; posts/journal/todos live in Supabase.
The TUI reads through JSON endpoints (
/api/tui/tree,/api/tui/topic/[slug], …) so the two clients can never disagree. - Writes are never made from a client directly: every mutation goes through a route handler that validates auth, then writes with the server-only service-role key. Tables have public read RLS and no public write policies.
- Auth cascade (
getEditSession): edit-token cookie →Authorization: Bearer <edit token>→ADMIN_API_TOKENbearer → signed-in admin session. Edit tokens are 24-hour, requested at/edit-accessand approved by the admin; the admin API token is a long-lived server secret for non-browser clients (the TUI) and implies edit rights. Only sha256 hashes of edit tokens are stored.
npm install
npm run dev # web app on http://localhost:3002
npm run tui # build + launch the terminal clientThe curated topics work with no setup. Journal, Posts, todos, search, editing, and email need
Supabase (and optionally Resend) — see SETUP-SUPABASE.md and run the SQL
files in supabase/ (schema, journal-schema, posts-schema, posts-moderation,
edit-tokens-schema, todos-schema, storage). Environment variables:
NEXT_PUBLIC_SUPABASE_URL=...
NEXT_PUBLIC_SUPABASE_ANON_KEY=...
SUPABASE_SERVICE_ROLE_KEY=... # server-only; bypasses RLS for token-validated writes
ADMIN_EMAIL=you@example.com # gates /admin
ADMIN_API_TOKEN=<long random> # lets the TUI act as admin via Bearer header
RESEND_API_KEY=re_... # optional; without it, tokens are shown on /admin to send manually
EDIT_FROM_EMAIL=Lexicon <you@yourdomain> # optional; defaults to Resend's test sender
NEXT_PUBLIC_SITE_URL=https://yourdomain # canonical URL for sitemap/RSS/OG (defaults to localhost)
npm install -g lexicon-tui
lexicon-tui # defaults to the deployed site
lexicon-tui --server http://localhost:3002 # local devInside: / search · : commands (:open, :journal, :new post, :todo, :inbox,
:server, :token, :quit) · Ctrl+P palette · Tab cycles focus. Unlock writes with
:token <edit token> or :token admin <ADMIN_API_TOKEN>. Full reference in
tui/README.md.
Drop a .mdx file in content/<anything>/<slug>.mdx with frontmatter — it renders at
/notes/<slug> and appears in the sidebar (and the TUI tree). See ADDING-TOPICS.md.
src/ Next.js app (App Router) — pages, components, API route handlers
content/ curated MDX topics (one file per topic)
supabase/ SQL to run in the Supabase SQL editor (idempotent)
tui/ lexicon-tui — the Ink terminal client (own package, published to npm)
docs/plans/ design documents
npm run dev # web dev server (port 3002)
npm run build # production build
npm run tui # build + run the terminal client from source
npm run lint # eslint
# in tui/
npm run smoke # drives the real TUI against localhost:3002 with fake keystrokes- Web — deploys to Vercel. Set the env vars above (including
ADMIN_API_TOKENandNEXT_PUBLIC_SITE_URL). Note:tui/is excluded from the web app'stsconfig.jsonso the Next build doesn't try to type-check the terminal client. - TUI — from
tui/: bumpversion,npm publish(builds automatically viaprepublishOnly; ships onlydist/).
Next.js 16 (App Router, Turbopack) · React 19 · TypeScript · Tailwind CSS v4 ·
next-mdx-remote + react-markdown (rehype/remark) · Supabase (Postgres + Auth + Storage) ·
Resend (email) · next/og · Ink 7 + marked-terminal (TUI).