A live map coaching tool for Escape from Tarkov. Host real-time sessions on interactive maps, draw routes and markers for your squad, and point things out as they happen — all in one clean place.
Primarily built for PC web. Live at https://tacmap-six.vercel.app.
- Live sessions — host a real-time coaching session on any map. Share a short code; players join with no account. Strokes, markers and the coach's viewport sync live (Liveblocks), with a "Follow coach" mode. Sessions are ephemeral.
- Interactive maps — pan/zoom Leaflet maps (
CRS.Simple) for all 10 locations, with toggleable marker layers (extracts, spawns, keys, loot) ingested from the wiki's interactive-map data. - Accounts — register with email + username + password, or sign in with Google (first-time Google users pick a username). Password recovery by email is built in.
- Admin console — hidden
/admindashboard (admin role required): user database with login and hosting stats, live-presence view of active sessions, ban/unban, rename users, and role management. - Quest wiki (currently hidden) — every task grouped by trader, with
objectives, prerequisites and rewards. Disabled for launch behind the
QUESTS_ENABLEDflag insrc/lib/flags.ts; pages remain reachable by direct URL.
All quest and map data is ingested only from the Escape from Tarkov Wiki via its MediaWiki API — no game-mined data and no game/tarkov.dev APIs. Content is licensed CC BY-NC-SA; this project is free and non-commercial, attributes the wiki site-wide and per quest, and is not affiliated with Battlestate Games. See ATTRIBUTION.txt.
- Next.js 16 (App Router) + TypeScript, Tailwind CSS v4 (Tarkov dark theme)
- Drizzle ORM + Postgres (Vercel Postgres / Neon)
- Auth.js v5 — Credentials (username + password) and Google OAuth, JWT sessions, bcrypt hashing
- Resend for transactional email (password reset)
- Leaflet / react-leaflet for maps, Liveblocks for realtime sessions
- Deployed on Vercel
npm install
cp .env.example .env.local # then fill in the variables below
npx auth secret # generates AUTH_SECRET into .env.local
npm run db:migrate # apply DB schema (needs DATABASE_URL)
npm run ingest # pull quest data from the EFT Wiki → content/quests
npm run devOpen http://localhost:3000.
| Variable | Purpose |
|---|---|
AUTH_SECRET |
Auth.js session/JWT signing secret |
DATABASE_URL |
Postgres connection string (Vercel Postgres / Neon) |
LIVEBLOCKS_SECRET_KEY |
Liveblocks secret key (live sessions) |
AUTH_GOOGLE_ID |
Google OAuth client id (login/signup with Google) |
AUTH_GOOGLE_SECRET |
Google OAuth client secret |
RESEND_API_KEY |
Resend API key (password-reset emails) |
EMAIL_FROM |
Sender for reset emails (onboarding@resend.dev until a domain is verified) |
SITE_URL |
Absolute origin used in emailed links (e.g. https://tacmap-six.vercel.app) |
Google OAuth setup: create an OAuth client in Google Cloud Console with the
redirect URI https://<domain>/api/auth/callback/google (and
http://localhost:3000/api/auth/callback/google for dev).
Note: while Resend has no verified domain, reset emails only deliver to the
Resend account owner's inbox (test mode). Verify a domain and update
EMAIL_FROM before relying on it in production.
| Script | Description |
|---|---|
npm run dev |
Start the dev server |
npm run build |
Production build |
npm run ingest |
Ingest quests from the EFT Wiki (--limit, --trader flags) |
npm run ingest:maps |
Ingest map images + marker layers from the wiki (--map flag) |
npm run db:migrate |
Apply Drizzle migrations |
npm run db:generate |
Regenerate migrations after editing the schema |
- Push to GitHub and import the repo in Vercel.
- Add a Vercel Postgres (Neon) integration → it sets
DATABASE_URL. - Add the environment variables listed above.
- Deploy. The build runs
vercel-build(drizzle-kit migrate && next build), so database migrations apply automatically on every deploy — no manual migration step needed.
Quest content is committed in content/, so no DB is needed to render the
wiki — only accounts, progress and sessions use the database.
See ARCHITECTURE.txt for how the pieces fit together.