Internal Asana-style project & task tracker (projects, tasks, subtasks, Kanban board, status updates, My Tasks, notifications). Google login gated by an allowlist you manage in-app. Next.js 16 · Auth.js v5 · Neon Postgres · Drizzle.
- GitHub — hosts the code. (github.com)
- Vercel — hosting; sign in with GitHub. (vercel.com)
- Neon — the Postgres database. (neon.tech)
- Google Cloud — for Google sign-in. (console.cloud.google.com)
1. Push this repo to GitHub (create an empty repo, then):
git remote add origin https://github.com/<you>/vlg-tracker.git
git push -u origin main2. Create the Neon database. In Neon, create a project and copy two connection strings from the dashboard:
- the Pooled one (host has
-pooler) → used asDATABASE_URL - the Direct one → used as
DIRECT_URL
3. Create Google sign-in credentials. In Google Cloud → APIs & Services → Credentials → Create OAuth client ID → Web application. Under Authorized redirect URIs add (use your real Vercel domain — you can fill this in after step 4 and edit it):
https://<your-app>.vercel.app/api/auth/callback/google
Copy the Client ID and Client secret.
4. Import the repo in Vercel (Add New → Project → pick the GitHub repo). Before deploying, set:
-
Build Command (Settings → General):
npm run db:migrate && npm run db:seed && next build(auto-applies the database schema and seeds the first admin on every deploy) -
Environment Variables (Settings → Environment Variables):
Name Value AUTH_SECRETa random secret — run openssl rand -base64 32AUTH_GOOGLE_IDGoogle Client ID (step 3) AUTH_GOOGLE_SECRETGoogle Client secret (step 3) AUTH_TRUST_HOSTtrueDATABASE_URLNeon pooled string (step 2) DIRECT_URLNeon direct string (step 2) BOOTSTRAP_ADMIN_EMAILfirst admin email (default vlg.acm@iitr.ac.in)RESEND_API_KEY(optional) set to also email project status updates (resend.com) EMAIL_FROM(optional) from-address, e.g. VLG Tracker <updates@yourdomain>SLACK_BOT_TOKEN(optional) Slack bot token ( xoxb-…) — see Slack section belowCRON_SECRET(optional) guards the reminders cron; openssl rand -hex 16
5. Deploy. When it's live, make sure the Google redirect URI (step 3) matches your real Vercel domain, then open the site and sign in with the bootstrap admin's Google account. Go to Admin in the sidebar to add teammates.
That's it — every future git push redeploys and applies new migrations
automatically.
Run locally (optional)
export PATH="$HOME/.local/node/bin:$PATH" # Node is at ~/.local/node
cp .env.example .env.local # fill in the same vars as above
npm install
npm run db:migrate && npm run db:seed
npm run dev # http://localhost:3000Add http://localhost:3000/api/auth/callback/google as a redirect URI in Google
Cloud for local sign-in. See CLAUDE.md for architecture notes.
Self-hosting on an on-prem / admin-provisioned server
The app isn't tied to Neon. To run the whole thing on your own server against a standard Postgres:
- Point
DATABASE_URLandDIRECT_URLat your Postgres instance. - Set
DB_DRIVER=pg(switches the driver from Neon's WebSocket driver to a normal TCP Postgres connection). npm run db:migrate && npm run db:seed, thennpm run build && npm startbehind your reverse proxy. Add that host's/api/auth/callback/googleto the Google OAuth redirect URIs, and keep the other env vars the same.
The schema and migrations are plain Postgres, so no code changes are needed.
Slack notifications & reminders (optional, free)
Powers: posting project status updates to a channel, and daily discussion / meeting / "post your updates" reminders. Slack apps + the Web API are free.
Create the bot (one-time):
- https://api.slack.com/apps → Create New App → From scratch → pick your workspace.
- OAuth & Permissions → Bot Token Scopes → add
chat:write. - Install to Workspace, then copy the Bot User OAuth Token (
xoxb-…) → set it asSLACK_BOT_TOKEN(Vercel env + local.env). - Invite the bot to each channel it should post in: in Slack, run
/invite @your-botin that channel.
Wire it up in the app:
- Members: each person opens Settings and pastes their Slack member ID (Slack → your profile → ⋯ → Copy member ID) so reminders can @-mention them.
- Admin → Integrations: set the reminders channel ID (for discussions/meetings).
- Per project → ⋯ → Slack & reminders: set that project's channel ID (status updates post there) and optional daily "post your updates" reminders.
- Get a channel ID from Slack → channel name → View channel details → bottom.
Reminders schedule: vercel.json runs /api/cron/reminders daily at
15:30 UTC (9 PM IST). Set CRON_SECRET in Vercel env; Vercel sends it to the
job automatically. (Vercel Hobby allows one daily cron — this fits.)
Docs images need no external storage — they're resized and stored in the DB, and cleaned up when removed.