You can just ask it
Ask the Archive turns 2,702 indexed chunks into an answer in about four seconds — sources first, prose after, every name a link back to its row.
Across 25 races and 577 km, the half-marathon best is 1:59:57 at NMDC Hyderabad Marathon 2025, and the marathon best is 05:05:53 at Tata Mumbai Marathon 2026.
Six regions, six chapters
One SVG scene with pan, wheel-zoom and pinch. Day and night follow the visitor's own clock.
The whole story, in one walk
A full-stack developer with a wide catchment area
Technology, society, psychology, blogging, design, video editing, digital well-being. Years of exploring taught me what I am good at, what I am not, and what I actually want from a career.
Critically engage with what's new, better myself daily, understand the things happening around me — and enjoy the journey.
And what is he doing right now?
Three commitments, held at the same time
Software Development Engineer
Full-stack, data engineering, CI/CD and DevOps.
NAST Research Fellow
Technology geopolitics, at Takshashila.
Marathons, five days a week
10K through the Tata Ultra 50K.
Eight years of that — how much does it add up to?
Eight years, counted live
Nothing here was collected for a chatbot. It accumulated — then it got a database.
Start with the running — where did 577 kilometres come from?
One coastline, five distances
Personal bests, average paces, most-active city and year — plus a timing certificate on every race.
And when the running stops, where does he go?
Twenty forts, graded by difficulty
Including the night march from Panhala to Pawankhind — 22 hours, and the trek the archive is most often asked about.
What does he do on the days he isn't moving?
Rows that never load wholesale
Micro posts peaked at 535 in 2020; essays exploded in 2026 with 61 of the 104. Every bar is a row a question can now reach.
A generated tsvector column, GIN-indexed, never shipped to a browser.
Stemming Devanagari is worse than not stemming it at all.
A unique key on source and source-id lets the Tumblr rescue re-run safely.
Who built the machinery that holds all this?
One content source, two complete front doors
The Wanderer's Atlas
An illustrated 2.5D world. Every page is a place inside one of six regions, wrapped in a themed biome band with map breadcrumbs.
The Classic Shell
Editorial portfolio layout — translucent nav, sticky bio sidebar, 3D globe homepage. The reduced-motion and accessibility escape hatch.
Resolution order: ?view= → stored preference → prefers-reduced-motion → preview flag → feature flag. And how do you arrive in the Atlas?
Orbit, dive, map — a three-stage entrance
A rotating WebGL globe, four counting-up teasers, one "Enter the World" call. Counts hardcoded on purpose — zero network calls before first paint.
A 3.5-second GSAP timeline: camera plunge, three cloud sheets, a white bloom. The globe is swapped for the map at the bloom frame.
The world hub. Returning visitors land here directly; the intro replays on demand, and reduced motion skips the dive entirely.
And what happens if you just stand still?
The map keeps moving when you don't
Sky and far layers lag the camera, near props lead it, and a fine pointer adds eight pixels of drift.
All of it stops under prefers-reduced-motion — the whole animation layer is opt-out in one media query.
Is there a reason to keep exploring?
A passport, seven quests, five secrets
What are the five secrets hiding?
Four layers, no server to run
On 13 June 2026 the whole site moved into Supabase — and every later feature, the chatbot included, stands on that move.
What stops any of that from lying?
The database, not React, keeps the promises
Drafts stay drafts
The projects read policy is visible or is_owner() — a hidden project never reaches a page, a tag list, a share card, or the search index.
Tags are central
213 tags in one table, linked polymorphically, with a function that replaces a row's whole tag set atomically.
Dates are real
Project dates became a Postgres date; book finish dates carry a precision flag. Sorting stopped lying.
The log is owner-only
Visitors write the conversation log through a definer function and can never read it back.
With all that in place — what happens when you ask a question?
Six stations, about four seconds
But how does it find the right rows at all?
Two searches, one ranking — and a card of facts
So every prompt carries the facts card
“How many books?” would return eight books that feel like the question. The card ships the real aggregates instead — the same numbers /stats shows, from one hourly snapshot.
What stops it inventing a link?
It cannot link to anything it did not retrieve
PB 1:59:57 at [NMDC Hyderabad Marathon 2025](/sports/15). Read more at [this link](https://evil.example/x). 
PB 1:59:57 at NMDC Hyderabad Marathon 2025. Read more at this link.
The words stay; the invented URL and the tracking pixel are gone.
If the quota check is down, the request is refused.
Retrieved rows sit in delimiters the prompt declares inert.
Order, model ids, timeouts and switches are rows in a settings table — when a model was retired mid-build, the fix was editing a field. Every answer logged so far came from rung one.
And when it does get something wrong?
Every verdict becomes a test case
Thirty exchanges logged, two rated — one up, one down. Small numbers, honest signal.
Only the reader who owns the conversation can rate it, and comments cap at 1,000 characters.
→ ingest a new source.
→ tighten the prompt.
The foundation is data, not the model. The next moves are chosen by what readers mark as wrong.
Who turns those dials?
Every dial is a form field
Content · 8 tables
Now · months & meta
Ask · settings & conversations
Résumé · experience, skills
Tags · rename, merge, recolour
The dashboard drops the site's rust accent for indigo — it is a workspace, not a page of the site.
Second brain on/off, Turnstile required, questions per day globally and per visitor, max question length, turns of history sent.
Items retrieved, keyword weight, meaning weight — the ranking is tunable without a deploy.
Label, provider, model, timeout and on/off per rung — reorderable, with a 14-day usage chart by tier.
Fourteen filters, a 30-minute gap that splits chats, three exports, and p50/p95 latency by stage.
How long did all of this take?
A template became an archive
Data first, then the brain. Each step made the next one possible.
Vite, Supabase, storage, the Tumblr import.
The Atlas, the Stats Almanac, the admin workspace.
Image compression, canonical domain.
Central tags, projects, books — then the archive learned to answer.