NXT

Credentials

Every account, every secret, where each lives

A complete inventory of services + secrets the app depends on.

All credential values live in Bitwarden under the nxt-app@outlook.com collection. This document lists what exists; values stay in Bitwarden.

Identity owner

Every third-party service below is registered to nxt-app@outlook.com. Bitwarden seats are scoped to it.

Service inventory

Code + infrastructure

ServicePurposeNotes
GitHub (wearenxt org)Source codeOrg-owner seat required for admin
ConvexBackend (production + dev deployments)Dashboard at dashboard.convex.dev
VercelWeb + docs hosting + analytics + Speed InsightsOne Vercel team, multiple projects
Expo / EASMobile build + OTATied to the Expo organization

Identity + auth

ServicePurposeNotes
WorkOSAuthKit tenant — accounts, OAuth, magic linkOne tenant covers mobile + web + docs
Apple Developer ProgramiOS distribution$99/yr renewal
Google Play ConsoleAndroid distribution$25 one-time fee paid

AI + data

ServicePurposeNotes
OpenAIPer-school AI blurb (gpt-5.4-nano)Org-level cost limit configured
College Scorecard APIFederal college dataFree, public, single API key for usage tracking
logo.devSchool logosFree tier; attribution required
SerperGoogle-image proxy for hero imagesPay-as-you-go, ~$0.30/1K queries

Observability + product

ServicePurposeNotes
PostHogProduct analytics + GDPR erasureHosted EU tier (configurable)
SentryError trackingWired in @sentry/nextjs + @sentry/react-native; DSN currently blank (off by default)
Vercel AnalyticsWeb trafficFree tier
Vercel Speed InsightsWeb Core Web VitalsFree tier

Optional / not-yet-active

ServicePurposeStatus
ResendTransactional emailProvisioned; not actively sending mail today
Cloudflare R2Object storageProvisioned; no active buckets yet

Files that live on disk (gitignored)

These three files are not in GitHub. They live in Bitwarden so they can be dropped into place on a fresh checkout.

PathPurpose
apps/mobile/keys/AuthKey_68Y3V9WSG7.p8Apple ASC API key for non-interactive App Store submissions
apps/mobile/keys/google-service-account.jsonGoogle Play service account for non-interactive Play Store submissions
apps/mobile/google-services.jsonFirebase config for Android push notifications

Server-side environment variables

Stored on the Convex deployment via npx convex env set <key> <value>. Inventory:

KeyPurpose
WORKOS_CLIENT_IDWorkOS public client ID
WORKOS_API_KEYWorkOS server-side API key
WORKOS_COOKIE_PASSWORD32+ char random string for cookie encryption
WORKOS_REDIRECT_URIOAuth callback URL
WORKOS_WEBHOOK_SECRET(Optional) webhook signature verification
OPENAI_API_KEYOpenAI key for the per-school blurb
SCORECARD_API_KEYFederal Scorecard usage key
LOGO_DEV_PUBLISHABLE_KEYlogo.dev API key
SERPER_API_KEYSerper.dev key for hero images
POSTHOG_API_HOSTPostHog host (region-specific)
POSTHOG_PROJECT_IDPostHog project ID
POSTHOG_PERSONAL_API_KEYPostHog personal API key — used for GDPR erasure path
REPORT_ADMIN_EMAIL(Optional) address notified on new content reports
REVIEW_LOGIN_EMAILSApp Store / Play Store reviewer test accounts

A full inventory with inline comments is at .env.example in the repo root.

Client-side environment variables

Set in each Vercel project's Environment Variables UI (web + docs) and via EAS secrets for mobile.

KeyWherePurpose
NEXT_PUBLIC_CONVEX_URLweb, docsConvex public URL for the React client
NEXT_PUBLIC_WORKOS_REDIRECT_URIweb, docsOAuth callback (NEXT_PUBLIC variant for middleware time)
NEXT_PUBLIC_SITE_URLwebCanonical URL for sitemap + opengraph
EXPO_PUBLIC_CONVEX_URLmobileConvex URL for the React Native client
EXPO_PUBLIC_WORKOS_CLIENT_IDmobilePublic WorkOS client ID
EXPO_PUBLIC_SITE_URLmobileCanonical web URL for deep linking
NEXT_PUBLIC_SENTRY_DSN / EXPO_PUBLIC_SENTRY_DSNallSentry DSN (blank = off)

Rotation

No rotation policy is in place. Recommended cadence: WorkOS API key, OpenAI key, Serper key, and the Apple ASC API key on a six-month schedule.

Technical detail

Why one Bitwarden collection

Single-collection prevents the "where did I put the X key" tax. The trade-off: anyone who can see the collection can see every key.

Why no Doppler / Vault / 1Password

Considered. Bitwarden was chosen for (a) lowest add-friction for non-technical readers, (b) matching the existing operator setup. Migrating to another manager later doesn't require any code changes — env vars themselves live on Convex / Vercel / EAS, not in a secret manager NXT runs.

Webhook signing

WORKOS_WEBHOOK_SECRET enables HMAC verification of incoming WorkOS webhooks (webhook_events table dedupes by event ID). Unset = webhooks not verified. Today the secret is set; rotate at the WorkOS Dashboard → Webhooks UI if compromised.

Token storage on mobile

WorkOS session tokens are stored in expo-secure-store (Keychain on iOS, EncryptedSharedPreferences on Android). The mobile app never sees the user's password.

On this page