Career Portal
A Bullhorn job board a staffing agency can rebrand without a developer.

41
Live roles from the Bullhorn API
9
Admin screens, no code required
3
Environment variables to deploy
0
Databases
Why this exists at all.
Bullhorn ships an open-source career portal, and every staffing agency running Bullhorn inherits it. It works. It also looks like every other agency's, and changing anything past the logo means forking Angular and owning that fork forever.
So the choice on offer is a portal that looks like everyone else's, or a bespoke build per agency at bespoke prices. Both answers are wrong for a firm of sixty people, which is most firms.
The decisions, and what they rule out.
Rebranding is a screen, not a fork
Nine admin pages — branding, application fields, features, job display, integrations, security — write to a config file. An agency changes its name, palette, logo, which form fields appear and in what order, without touching the repo. The alternative, a fork per client, is the thing that makes this category expensive.
No database, on purpose
Configuration is a JSON file and the jobs live in Bullhorn, which is already the system of record. Adding Postgres would have meant a second source of truth for data the ATS owns, plus a migration story, plus something to back up. Deploying is three environment variables.
Cache by tag, not just by clock
The Bullhorn feed revalidates every 900 seconds, but every fetch is also tagged, so saving a change in the admin clears it immediately instead of leaving the agency staring at a stale board for a quarter of an hour and assuming the save failed.
The things thinking about it did not catch.
Every item below is a real defect, found by measurement, with a commit behind it. They are here because the failures are more informative than the features.
Audited with our own instrument, and it failed twice
Loupe against a live instance: 30 contrast checks found two real AA failures, both in the footer, both at 2.53:1 against the 4.5 required. Everything else held — focus rings on all 15 tab stops, no overflow at 390 or 1440, no truncation, no console errors, LCP 144ms and CLS 0. Then 15 of 30 tap targets came in under 44px: legal under WCAG 2.5.8, under our house standard. Filter selects at 42px, pagination at 36, footer links 20px tall. A board people use on a phone between meetings is the wrong place to be two pixels shy.
The rebuild kept the easy half
A later, cleaner rewrite of this portal dropped the admin panel and kept the job list. The original is the one worth showing, because the admin is the entire product — without it this is a job list, and job lists are free.
- Next.js
- TypeScript
- Tailwind
- Bullhorn Public REST API
- Vercel
- Two AA contrast failures in the footer at 2.53:1, and 15 tap targets under the 44px house standard. Both measured, neither fixed.
- The public deployment is not linked from this page yet.
- Admin screens are password-gated, so this page shows the portal rather than the panel that is the actual product.
Runs inside the studio's own pipeline.