A web platform for OSINT/GEOINT analysts to archive, reference, and visualize geolocations of armed-conflict events. Interactive map, structured submission flow (coords + source + media + Tiptap proof + tags), community requests, and analyst profiles.
Live at vidit.app (beta).
Work reaches the map through one of four doors. Three of them read an analyst's own X posts and produce machine detections; the fourth is the submit form. Nothing is published until a person vouches for it.
flowchart LR
classDef spec fill:#eef1fb,stroke:#4a5fa5,color:#33417a
classDef shared fill:#e3f2f1,stroke:#0f7b7a,color:#0b5c5b
classDef core fill:#0f7b7a,stroke:#083f3e,stroke-width:3px,color:#ffffff
classDef store fill:#0b5c5b,stroke:#083f3e,color:#ffffff
subgraph legend [Legend]
direction LR
l1["`what an analyst does`"]:::spec
l2["`what the machine does`"]:::shared
l3["`the moment a person vouches`"]:::core
l4[("`the catalog`")]:::store
l1 ~~~ l2 ~~~ l3 ~~~ l4
end
subgraph doors [Four ways work comes in]
direction TB
hand["`**/submit**
one form: coordinates, source, media, tags, and a Tiptap proof`"]:::spec
bot["`**tag @ViditBot on X**`"]:::spec
paste["`**paste one of your own posts**`"]:::spec
arch["`**bulk import your X export**`"]:::spec
end
engine["`**one detection engine, three entries**
reads the coordinate, the source and the media out of the post`"]:::shared
det["`**a detection**
public from the moment it lands, badged as machine output`"]:::shared
review["`**your review**
complete it and publish, or reject it`"]:::core
ev[("`**events**
one row per geolocation; a published row is corrected by versions, never overwritten`")]:::store
read["`**/map, /search, /requests, /profile/{username}**
open to anonymous readers`"]:::spec
hand --> ev
bot --> engine
paste --> engine
arch --> engine
engine --> det --> review --> ev
ev --> read
The detection engine is documented in docs/ingestion.md, the row and its statuses in docs/data-model.md.
100% open source under AGPL-3.0, nothing proprietary. Anyone can self-host the platform; modifications deployed as a network service must publish their source under the same license. Today nothing on the maintainer's hosted instance (vidit.app) is paid. The analyst-facing platform is, and will stay, free; if the hosted instance ever charges for anything, it will be surfaces aimed at consumers of the community's work (alert webhooks, larger exports), never at the analysts producing it. Details in planning/roadmap.md → Openness & transparency.
promo-readme.mp4
| Layer | Choice |
|---|---|
| Backend | FastAPI (Python 3.12) + SQLAlchemy 2 + GeoAlchemy2 + Alembic |
| Database | PostgreSQL + PostGIS 3 (16 in prod, 18 locally) |
| Auth | Cookie session + double-submit CSRF (JWT payload, PyJWT) + bcrypt + invite codes |
| Storage | AWS S3 + CloudFront (media) |
| Frontend | Next.js 16 (App Router) + TypeScript + Tailwind |
| Map | MapLibre GL JS + CARTO Dark Matter tiles, client-side clustering |
| Editor | Tiptap (rich proof) |
| Hosting | Railway (API + DB) + Vercel (frontend) |
| Package mgmt | uv (backend) + npm (frontend) |
Details and rationale: docs/engineering.md.
vidit/
├── backend/ FastAPI service (uv)
│ ├── app/ routers → services → models, Pydantic schemas
│ ├── alembic/ migrations
│ ├── scripts/ one-off ops scripts (mock admin, detection seeder, prod import)
│ └── tests/
├── frontend/ Next.js 16 app (npm)
│ └── src/
│ ├── app/ App Router pages
│ ├── components/
│ ├── contexts/ React context providers (auth, map state)
│ ├── hooks/
│ ├── lib/
│ ├── types/
│ └── proxy.ts default-deny auth + host canonicalisation
├── video/ promo-as-code pipeline (Playwright capture + Remotion render, `make promo`)
├── docs/ api, backups, data-model, design, engineering (technical reference)
├── planning/ roadmap + next (project planning, not user docs)
├── docker/ daily backup cron image
├── AGENTS.md project context for AI tools (CLAUDE.md is a one-line `@AGENTS.md` pointer for Claude Code)
├── CHANGELOG.md release history
├── CODE_OF_CONDUCT.md Contributor Covenant 2.1
├── CONTRIBUTING.md PR flow + commits + doc-sync rule
├── LICENSE AGPL-3.0
├── SECURITY.md vulnerability reporting
├── docker-compose.yml PostgreSQL + PostGIS for local dev
├── Makefile init / dev / seed / test entry points
└── .github/workflows/ backend + frontend CI + manual deploy
More detail: docs/engineering.md.
The technical reference is also hosted at docs.vidit.app (MkDocs Material build of docs/).
make init # install + env + db-up + migrate (one-shot bootstrap)
make seed # mock-admin + machine detections from the committed synthetic archive
make import-prod # replace the local DB with the latest production backup (see docs/backups.md)
make dev # FastAPI :8000 + Next.js :3000 in parallel
make dev-worker # archive-import worker (optional; without it, archive uploads stay queued)
make test # backend pytestmake help lists every target individually.
- Docker (for PostgreSQL + PostGIS; local and prod both run
postgis/postgis:16-3.4, seedocs/backups.md) - Python 3.12+ and uv
- Node.js 20+ and npm
make init copies .env.example → .env (backend) and .env.local.example → .env.local (frontend). Defaults are wired for localhost; every var is documented inline in backend/.env.example and frontend/.env.local.example. API docs auto-served at http://localhost:8000/docs.
make seed (or make mock-admin) creates admin@vidit.app / admin directly. To exercise the real invite + registration flow:
- Set
ADMIN_EMAILS=<your-email>inbackend/.envso your account auto-promotes to admin on first login. - Get an invite code: once an admin exists, the
/adminpanel mints them; for the very first one runmake mock-adminto get one. - Register at http://localhost:3000/register with the code.
EMAIL_PROVIDER=console(the local default) prints the confirmation link to backend stdout.
- Database connection failed: ensure
docker-compose up -dis running and nothing else holds port 5432. - Frontend can't reach the API: check
NEXT_PUBLIC_API_URLinfrontend/.env.localishttp://localhost:8000/api/v1. - "Module not found": re-run
uv sync(backend) /npm install(frontend), ormake installfor both.
cd backend
uv run pytest # run tests
uv run ruff check . # lint
uv run ruff format . # format
uv run alembic revision --autogenerate -m "..." # new migrationcd frontend
npm run lint
npm run buildSee AGENTS.md → Conventions.
Licensed under the GNU Affero General Public License v3.0. See CONTRIBUTING.md, SECURITY.md, and CODE_OF_CONDUCT.md.
The content shown in the landing video uses real geolocation work from @geo27752, reproduced with their consent. Thanks for letting Vidit show the platform the way analysts actually use it.