An unofficial transfer credit lookup tool for Southern New Hampshire University students.
The SNHU Transfer Equivalency List helps students search and browse transfer credit equivalencies from providers such as AP Exams, Sophia Learning, Study.com, and other organizations. It is designed to make it easier to explore which outside learning experiences may transfer into SNHU as credit while planning a degree path.
I built this site as a proud SNHU graduate who understands how valuable transfer credits can be when planning a degree.
During my time at Southern New Hampshire University, transfer credits helped shape my academic path and made it easier to move through my program efficiently. But finding and comparing transfer equivalencies can be time-consuming, especially when checking multiple providers, course codes, academic levels, and eligibility windows.
This tool was designed to give SNHU students a simpler way to explore transfer options in one searchable place. Search by course, provider, or title; browse equivalencies by subject, organization, or academic level; and use the results as a planning aid before confirming details with SNHU.
This site is unofficial and is intended for informational purposes only.
Transfer evaluations, eligibility windows, course mappings, provider offerings, and SNHU policies can change. Always confirm transfer eligibility on the official SNHU website and with your academic advisor before making academic or financial decisions.
This project is not affiliated with, endorsed by, or operated by Southern New Hampshire University.
I also built SNHU Course Prerequisites Tool, another tool for SNHU students that makes it easier to search courses and visualize prerequisite relationships while planning a degree path.
Optional course pages can link to that app for prerequisite details via NEXT_PUBLIC_COURSES_URL. The transfer site does not require the courses app to be running, and sync does not call it over HTTP or join its tables for core pages.
- Search SNHU transfer equivalencies by course code, title, or organization
- Browse results by subject, provider organization, or academic level
- View transfer titles, eligibility timeframes, and academic levels
- Link to official SNHU transfer experience pages when available
- Optional deep links to course prerequisite pages
- Refresh transfer data from SNHU's public Kuali transfer-experience API
- Public read-only transfer-coverage API for bounded course-code batches
- Include basic SEO support through metadata,
robots.txt, andsitemap.xml
Unofficial public endpoint for checking live transfer-equivalency coverage for a bounded list of SNHU course codes. Full contract: docs/transfer-coverage-api.md.
curl "https://snhu-transfers.vercel.app/api/v1/transfer-coverage?courses=CS110,CS210,MAT140"- Maximum 100 unique course codes per request
- Returns explicit unmatched-course objects (not omissions)
dataLastUpdatedAtcomes from the last successful transfer sync- Treat HTTP 503 as unavailable data, not zero coverage
- Not an official SNHU API; listings do not guarantee acceptance
- Next.js App Router
- React
- TypeScript
- Tailwind CSS
- Drizzle ORM for database queries
- Neon / PostgreSQL for transfer equivalency data
- Vercel for hosting and analytics
- Honeybadger for error monitoring
- Lucide React for icons
This project is a Next.js application hosted on Vercel.
At a high level, the app is organized around a server-rendered data load from PostgreSQL, followed by a client-side search and browsing interface:
src/
app/
api/
revalidate/
route.ts
v1/
transfer-coverage/
route.ts
ClientPage.tsx
layout.tsx
page.tsx
robots.ts
sitemap.ts
db/
index.ts
schema.ts
lib/
transfer-sync/
index.ts
fetch.ts
parse.ts
persist.ts
promote.ts
scripts/
migrate.ts
transfer-bootstrap.ts
- Transfer sync fetches public transfer experience data from SNHU's Kuali API (experiences only — not the full course catalog).
- On refresh start, experience PIDs are snapshotted into
transfer_sync_items. Later sync resumes from that immutable list instead of re-downloading and re-slicing the live Kuali response. The previous successfulcompleted_attimestamp is preserved until promote finishes. - Course mappings are parsed from the experience achievement criteria using SNHU course codes (e.g.
CS499) as the cross-project identifier. - Rows are written to
transfer_courses_stage. A failed experience-detail fetch fails the batch without advancing the cursor (successful details with zero mappings are valid and contribute zero rows). - When the snapshot cursor reaches
expected_count, staging is validated and atomically promoted intotransfer_courses. Promote requirescursor === expected_count,failed_experience_count === 0, matching snapshot size, nonempty staging, and that staging is at least 75% of the current live row count (bootstrap can pass--allow-large-shrinkto override). - The homepage and landing pages load from
transfer_coursesonly (no catalog join required). - The client UI lets users search, group, and expand transfer equivalency results.
- After a successful promote, the external sync environment calls
POST /api/revalidateto invalidate thetransfer-datacache tag.
Install dependencies:
npm installCreate a .env file (see .env.example):
POSTGRES_URL=postgresql://...
REVALIDATE_SECRET=your-random-revalidation-secret
NEXT_PUBLIC_SITE_URL=http://localhost:3000
NEXT_PUBLIC_COURSES_URL=https://snhu-courses.vercel.app
HONEYBADGER_API_KEY=
NEXT_PUBLIC_HONEYBADGER_API_KEY=This application uses a dedicated Neon project for transfer data; the prior shared
database is not needed. The local migration and synchronization scripts explicitly
load .env, where POSTGRES_URL should be the direct Neon connection. Do not put
operator credentials such as NEON_API_KEY or VERCEL_API_KEY in Vercel or GitHub.
Initialize the database:
npm run db:migratePopulate transfer course data:
npm run transfer:bootstrapStart the development server:
npm run devOpen http://localhost:3000 with your browser.
npm run dev- Start the development servernpm run build- Create a production buildnpm run start- Run the production servernpm run lint- Run ESLintnpm test- Run testsnpm run test:watch- Run tests in watch modenpm run db:migrate- Create transfer tables and sync state (idempotent)npm run transfer:bootstrap- Full local transfer sync into staging, then promote (--allow-large-shrinkoverrides the 25% live shrink guard)npm run transfer:sync- Run an incremental transfer refresh to completion. Pass-- --ignore-leaseonly to deliberately take over an expired/stuck lease, or-- --allow-large-shrinkonly after reviewing an intentional large data reduction.
The site can deploy on Vercel, but the preferred quota-conscious update model is a weekly CircleCI job (or a trusted desktop machine). Those environments run the full sync to completion without consuming Vercel function time.
Set the following environment variables in the site deployment and in the trusted sync environment as applicable:
POSTGRES_URL(the Vercel Production runtime uses the Neon integration-provided pooled connection; local migration, bootstrap, and external synchronization use a direct connection)REVALIDATE_SECRET(required by the external cache-revalidation endpoint)NEXT_PUBLIC_SITE_URL(optional — defaults tohttps://snhu-transfers.vercel.app)NEXT_PUBLIC_COURSES_URL(optional — enables "View prerequisites" links)HONEYBADGER_API_KEY(server-side error reporting)NEXT_PUBLIC_HONEYBADGER_API_KEY(optional — browser/error-boundary reporting; the app builds and runs when unset)
Database credentials are scoped to Vercel Production only. Preview and Development deployments do not receive production database credentials.
On a trusted machine or CircleCI, keep POSTGRES_URL and REVALIDATE_SECRET in its encrypted secret store. Do not print either value in CI logs. After installing dependencies, run:
npm run db:migrate
npm run transfer:sync
curl --fail --request POST "$SITE_URL/api/revalidate" \
--header "Authorization: Bearer $REVALIDATE_SECRET"transfer:sync preserves the existing lease, staging validation, 25% shrink guard, and atomic promotion. Schedule it weekly in CircleCI with pipeline parameter run_transfer_sync=true on master (default false so ordinary pushes do not sync). Invoke the revalidation endpoint only after a successful promotion. POST /api/revalidate fails closed when REVALIDATE_SECRET is absent or the bearer token is invalid; it invalidates the transfer-data cache tag. Transfer refresh is independent of the course catalog sync.
Also configure a Vercel Firewall rate limit for GET /api/v1/transfer-coverage (dashboard; not in-repo).
- Server errors are reported with
HONEYBADGER_API_KEY(never expose this key to the browser or throughnext.configenv). - Browser / App Router error UI reporting is optional via
NEXT_PUBLIC_HONEYBADGER_API_KEY. - Caught transfer-sync failures (which would otherwise become
{ action: "error" }results) notify Honeybadger once from the sync library with safe job context and tagscron/transfer-sync. - Source map uploading is intentionally disabled (
disableSourceMapUpload: true). - Honeybadger skips reporting in development and test environments by default.
Do not add a permanently public failure route. Prefer one of:
- From a machine with Production env loaded (never commit secrets):
npx tsx -e "
import { reportServerError } from './src/lib/monitoring/honeybadger.ts';
await reportServerError(new Error('Honeybadger test from snhu-transfers'));
console.log('notified');
"- Use Honeybadger’s project UI to send a test notice after keys are configured.
This project is provided as an unofficial educational planning aid. It is not affiliated with Southern New Hampshire University.