primary documents, not propaganda प्राथमिक दस्तावेज़, प्रचार नहीं
A bilingual (English · Hindi) factcheck-archive documenting Indian political parties, RSS, government actions, and ongoing movements. Every claim links to a primary source.
Show all failures. Hide no one. Start with the ruling party, but the scope is the system, not one organization.
Every claim is a citation. Every citation is a chip. Every chip is a link to a primary source — court order, statute text, archival material, official notification, or named-publisher news report.
Opinion lives in the marginal notes, marked editor's note. The body is the document.
| Layer | Choice |
|---|---|
| Framework | Next.js 14 (App Router, static export) |
| Language | TypeScript |
| Styling | Tailwind CSS + @tailwindcss/typography |
| Content | MDX via next-mdx-remote |
| Markdown | remark-gfm, rehype-slug, rehype-autolink-headings |
| Icons | lucide-react |
| Fonts | Inter, Source Serif 4, JetBrains Mono (next/font) |
| Hosting | Vercel (primary) + Cloudflare Pages (mirror) |
| Search | FlexSearch (static index, lazy-loaded) |
npm install
npm run dev # http://localhost:3000 (auto-redirects to /en)
npm run build # static export to ./out
npx serve out # preview the built site
npm run lint # eslint
npm run lint:sources # verify every <Source> id exists in src/lib/sources.ts
npm run typecheck # tsc --noEmit
npm run build:search # rebuild public/search-index.json
npm run build:sitemap # rebuild public/sitemap.xml
npm run build:feed # rebuild public/feed.xml (RSS 2.0, en + hi)The prebuild hook automatically runs lint:sources, build:search,
build:sitemap, build:feed, and typecheck before next build, so
npm run build alone keeps the search index, sitemap, and RSS feed in sync.
.
├─ content/
│ ├─ en/
│ │ ├─ stories/ # long-form pieces (/*.mdx)
│ │ ├─ faq/ # debate-aid answers (/*.mdx)
│ │ ├─ people/ # public figures (/*.mdx)
│ │ └─ protests.json # state-by-state protest index
│ ├─ hi/ # Hindi mirrors of /en/
│ └─ _research/ # primary-source archive (gitignored)
│
├─ src/
│ ├─ app/
│ │ ├─ layout.tsx # root layout, fonts, metadata
│ │ ├─ globals.css # tailwind + custom CSS
│ │ ├─ [locale]/
│ │ │ ├─ layout.tsx # locale layout, header/footer, SearchProvider
│ │ │ ├─ page.tsx # home (featured story)
│ │ │ ├─ stories/ # index + [slug]
│ │ │ ├─ faq/ # index + [slug]
│ │ │ ├─ people/ # index + [slug]
│ │ │ ├─ protests/ # state-grouped table
│ │ │ ├─ sources/ # master registry (filters)
│ │ │ ├─ about/ # mission
│ │ │ ├─ editorial/ # editorial policy
│ │ │ ├─ legal/ # disclaimers, warrant canary
│ │ │ ├─ right-to-reply/ # response mechanism
│ │ │ └─ contact/ # PGP, email
│ │ └─ middleware.ts # / → /en
│ ├─ components/
│ │ ├─ SourceChip.tsx # hover-tooltip citation chip
│ │ ├─ SourceCitation.tsx # inline MDX <Source /> renderer
│ │ ├─ SourcePinPanel.tsx # slide-over citation reader
│ │ ├─ SearchProvider.tsx # client context for global search
│ │ ├─ SearchSheet.tsx # Cmd/Ctrl+K full-screen sheet
│ │ ├─ SearchTrigger.tsx # header button
│ │ ├─ FilterChips.tsx # pill buttons with active state
│ │ ├─ Breadcrumbs.tsx # server component
│ │ ├─ TableOfContents.tsx # client, IntersectionObserver
│ │ ├─ ReadingProgress.tsx # fixed top bar
│ │ ├─ ShareBar.tsx # copy link + X + WhatsApp
│ │ ├─ EditorNote.tsx # MDX <EditorNote /> aside
│ │ ├─ StoriesIndex.tsx # client, topic filter wrapper
│ │ ├─ SourcesBrowser.tsx # client, type/orientation filter
│ │ ├─ PeopleIndex.tsx # client, status/party filter
│ │ ├─ LanguageToggle.tsx # client component
│ │ ├─ MobileMenu.tsx # full-height slide-in drawer
│ │ └─ layout/Header.tsx, Footer.tsx
│ └─ lib/
│ ├─ sources.ts # central source registry
│ ├─ content.ts # MDX / JSON loaders
│ ├─ i18n.ts # locale config
│ ├─ edit-link.ts # build GitHub edit URLs
│ └─ utils.ts # cn() helper
│
├─ scripts/
│ ├─ verify-sources.mjs # prebuild: audit <Source> ids
│ ├─ build-search-index.mjs # prebuild: FlexSearch JSON
│ ├─ build-sitemap.mjs # prebuild: sitemap.xml
│ └─ build-feed.mjs # prebuild: RSS 2.0 (en + hi)
│
├─ public/
│ ├─ _redirects # / → /en (Cloudflare Pages)
│ ├─ robots.txt # blocks AI scrapers
│ ├─ sitemap.xml # generated
│ ├─ search-index.json # generated, lazy-loaded by SearchSheet
│ └─ feed.xml # generated, two RSS channels (en, hi)
│
└─ .github/
├─ workflows/ci.yml # typecheck + lint + build + preview deploy
└─ ISSUE_TEMPLATE/ # bug / correction / source
Every factual claim in MDX content uses inline <Source id="..." />. The chip renders as a superscript number that hovers/focuses to show:
- Title
- Publisher · date
- Orientation tag (
mainstream/left/right/judicial/academic) - Notes
- Link to the canonical URL
- Wayback snapshot link (if any)
The /sources page auto-renders the full registry from src/lib/sources.ts.
Add an entry to src/lib/sources.ts. The id you set is what you reference as <Source id="..." /> in MDX. Required fields: id, title, type, orientation. Optional: date, publisher, author, url, archiveUrl, notes.
Create content/en/stories/your-slug.mdx:
---
title: "Your story title"
slug: "your-slug"
date: "2026-01-15"
topic: "rss" # rss | government | individual | movement
summary: "One-sentence summary for the index card."
sources:
- rss-constitution-1949
- britannica-rss
---
Your story text. Use the <Source id="..." /> MDX component
inline to cite. Hover any chip to see the source.Mirror to content/hi/stories/your-slug.mdx.
Same pattern, different frontmatter. See content/en/faq/is-rss-samaj-sevak.mdx, content/en/people/narendra-modi.mdx, and content/en/protests.json for examples.
/→ middleware redirects to/en/- All content lives under
/[locale]/... - English is canonical; if Hindi diverges, EN wins
- Language toggle in the header switches between
/en/...and/hi/...
vercel link --yes
vercel deploy --prod --yesBuild command: npm run build
Output directory: out
Environment variables: none required
Build command: npm run build
Build output directory: out
Environment variables: none required
The public/_redirects file handles / → /en/.
See CONTRIBUTING.md. For corrections, open an issue using the Correction template. For sources, use the Source addition template.
See /editorial. Eight principles. Source over summation. Document over opinion.
Any named individual named in published content may request a published response. See /right-to-reply.
- Source code: MIT
- Original content: CC BY-SA 4.0
- Quoted primary documents: original copyrights, used under fair use for criticism, comment, and news reporting
sacchai editorial collective is a pseudonym used by the contributors. The site is published from a non-Indian jurisdiction. See /legal including the warrant canary.
This is a journalism project. It is not legal advice. It is not a substitute for primary reading. Verify against the source.