DEV Community

Cover image for I vibe-coded a Next.js knowledge base that argues with itself
Asuran
Asuran

Posted on

I vibe-coded a Next.js knowledge base that argues with itself

Sanity Challenge Path Two Submission

This is a submission for the Sanity Challenge, Path Two: Vibe-Code Something Strange

What I Built

Still True is a knowledge base about Next.js that keeps itself honest. Instead of storing facts as flat pages it stores them as claims tied to sources, with typed relationships between claims. One claim can supersede another or contradict it. The relationship carries the reason it holds. The public board reads that graph and lays it out by topic. Current claims sit on top. Superseded claims are dimmed and struck through. Wherever two sources disagree the conflict shows side by side with an explanation.

The strange part is that the content is built to disagree with itself on purpose and the app treats that as the signal, not as mess to clean up.

Demo

Live board: https://still-true.vercel.app

The same graph grounds an agent at /ask, which is my Path One entry. On the board you can watch the truth change. The fetch-caching topic shows the current "not cached by default" claim above the superseded "cached by default" one. A time slider replays each topic flipping as newer facts supersede old ones. There is an interactive contradiction graph where every claim is a node and amber links are live disagreements. Every claim has its own page with its source, its confidence and the claims it supports or contradicts.

The contradiction graph: every claim a node, amber links live disagreements

The version time machine: the current answer flips as newer facts supersede old ones

A single claim page with its source and the claims it contradicts

Code

Repo: https://github.com/zkasuran/still-true

Front end is Next.js 16 on the App Router. The Studio in studio/ holds the schema and the workflow. The board reads the dataset with GROQ, following the reference on a claimEdge to both claims it connects. There are 24 unit tests and 4 end-to-end tests running in CI.

My Build Process

I built this with Claude Code as the AI-native IDE. The interesting parts were where the model or the tools pushed back.

The schema was the first real decision. My instinct was to hang a "contradicts" list of references on each claim. That was wrong, because a bare reference has nowhere to store why two claims conflict. The prompt that turned it around was roughly "model the relationship as its own document, not a field", which gave me the claimEdge type: from, to, a relation of supports / contradicts / supersedes and a reason. Once the reason lived on the edge the whole app got simpler, because the board just renders edges.

Sanity Context surprised me. I seeded the Knowledge Base with pairs of documents that disagreed and expected it to flag every pair. It did not. When I labelled the documents by version, Context reconciled them into one timeline-aware entry instead of raising a conflict. That is the behaviour you want most of the time, but it meant my "look, a contradiction" demo produced zero conflicts. The fix was to add one pair that genuinely could not be reconciled, an official default beside a community one that disagree on the same fact with no version to separate them. That rebuild raised exactly one conflict, the one the board and the agent now show.

The Studio schema tooling fought me. sanity schema deploy and sanity schema validate both failed with exports is not defined. They failed on a clean template too, so it was a toolchain issue in this Studio version rather than my schema. sanity build and sanity dev worked fine and the board queries the dataset directly rather than through a deployed schema, so I routed around it and wrote it down instead of fighting it.

Deploying to Vercel hid two gotchas. The first deploy returned 404 on every route because Vercel had not detected the framework as Next.js, so it served the wrong output. The second was a login wall: the project shipped with deployment protection on, which would have shown judges an SSO screen instead of the app. Both were one-line fixes through the Vercel project API, framework: nextjs then ssoProtection: null, followed by a redeploy. I only caught the login wall because I tested the URL logged out, which is the test that actually matters for a submission.

Reaching past the Studio: Workflows and an App SDK app

I modelled the editorial process as data with sanity-plugin-workflow. A claim moves through unverified, sourced and confirmed. The move into confirmed is gated to an administrator role. State lives in a separate metadata document, so the content schema stays clean while the Studio gets a drag-and-drop board, promote and demote actions and colored status badges. A person or an agent can add a claim as unverified and it only becomes confirmed once a human with the right role signs off, the same propose-then-approve shape the challenge suggests.

I also built a real App SDK app in app-sdk/, a contradiction-triage dashboard on @sanity/sdk-react that runs inside the Sanity Dashboard. It reads the open contradictions live and lets a reviewer walk each one, so the "reach past the Studio" bonus is a working custom surface rather than a read-only frontend. The code is in the repo and deploying it to the Dashboard is one command.

Sanity Project Details

  • Project ID: mx12urdz
  • Public dataset: production

The dataset holds the claims, sources and typed edges. You can query it directly. Every contradiction with both statements dereferenced:

*[_type == "claimEdge" && relation == "contradicts"]{
  reason, "from": from->statement, "to": to->statement
}
Enter fullscreen mode Exit fullscreen mode

Agent Session


AI assistance (Claude Code, Anthropic) was used to build this. The design and the decisions were mine and the build was verified live at the URL above. It runs on MiniMax-M3.

Top comments (0)