
Overview
Lexicon is my personal knowledge platform, live at lexicon.kalyangopalam.com. It started as a place to turn questions into permanent, well-written topic pages and grew into a full study environment: public guides and notes, a private library of books and PDFs with its own reader, a private journal, and a public questions board. The distinguishing feature is Ask-a-Reader — a peer-help system that pairs a stuck reader with someone who has read the same topic for a short live chat, falling back to a persistent public thread when nobody is around. Everything is built on Next.js 16 and Supabase, with owner-only row-level security applied as the default rather than an afterthought.
The hardest problems here were not visual. They were access control across a content model where the same record can be private, shared with one reader, or fully public; keeping a rich editing experience from corrupting a plain-Markdown source of truth; and making a PDF reader that stays responsive on a three-thousand-page document.
Technologies
- - Next.js 16 (App Router) + React 19
- - TypeScript, Tailwind CSS
- - Supabase — Postgres, Auth, Storage, Realtime
- - Postgres row-level security (owner-scoped)
- - MDX + remark/rehype content pipeline
- - Tiptap block editor (Markdown-backed)
- - react-pdf / pdf.js
- - Ink + React (terminal client)
- - Vitest, Vercel

Content Model & Features
- - Guides — curated long-form MDX topic pages, public
- - Notes — published posts plus private drafts, multi-author
- - Library — private books, chapters and pages with a per-book public toggle
- - PDF reader — spread view, outline, zoom, resume, highlights
- - Journal — private, owner-only
- - Questions — public nested threads, follow / save / mark helpful
- - Ask-a-Reader — live peer help with an asynchronous fallback
- - lexicon-tui — a terminal client published to npm
Ask-a-Reader
A reader stuck on a topic can request help from the page they are reading. The request is anchored to that topic, so matching is by subject rather than by a global queue, and an accepted match opens a short ephemeral chat carried over Supabase Realtime — no Redis, no message persistence, no extra infrastructure to run.
The interesting half is what happens when nobody answers. Rather than failing, the request becomes a public question thread; answers persist, and a later helper can claim it and convert the thread into a live session. Session state moves through an explicit transition table rather than ad-hoc status flags, which is what made the abandoned-session and rate-limit edge cases tractable.

Year
2026
Type
Personal Platform (Live)
Role
Solo Developer
Site
lexicon.kalyangopalam.com
Engineering Decisions
Security model: every table is owner-scoped with row-level security, and writes go through the server with the author identity derived server-side rather than trusted from the request body. Uploaded PDFs live in a private bucket with no anonymous storage policy at all — even a publicly shared book is served through a short-lived signed URL, so revoking access is instant and no file ever has to be moved between buckets. Reader highlights stay private on a public book.
Markdown stays the source of truth: the block editor is a nicer way to produce Markdown, not a replacement format. Content is stored as Markdown in the database, so the reading views, search index, PDF and EPUB export, and the terminal client all keep working untouched. That puts the entire risk on the serializer, which is pure and covered by round-trip unit tests.
Paged PDF rendering: the reader mounts only the pages currently in view instead of virtualising a long scroll, so a three-thousand-page document costs the same as a ten-page one — no long placeholder list and no thousands of observer targets.

Surface
33 pages · 90 API routes
Auth
Google OAuth + magic link
Verification
Because the whole point of the platform is that private material stays private, I ran a full access sweep across the site rather than trusting the policies by inspection: every public page, every gated page checked for content leaking into its signed-out shell, and every API route exercised anonymously to confirm it answered with an authentication error rather than data or a server error.
Private books were verified against real production data — an anonymous request for a private document returns nothing and no signed URL, and the private title appears nowhere in the response.
The project also carries a unit test suite covering the Markdown round trip, the help-session state machine, and the zoom-invariance property of PDF highlight coordinates — the parts where a silent regression would be expensive and invisible.
