Instrument x Seth Akkerman
Projects AI-Powered Careers Chatbot

AI-Powered Careers Chatbot

A conversational candidate screening tool built into a careers page that collects candidate profiles through natural dialogue, matches them to open roles, and submits structured data directly into Lever — complete with source tagging, deduplication, and a live data console.

The idea

Recruiting teams spend a lot of time on early-stage phone screens — calls that often end quickly because the candidate simply isn’t a fit. This prototype explores a different model: what if a careers page could do that first-pass qualification conversationally, while simultaneously making candidates feel helped rather than filtered out? The framing matters. This isn’t a bot that replaces human contact — it’s a career coach that helps candidates put their best foot forward before they ever talk to a recruiter.

How it works

The chatbot lives as an overlay on the careers page — a glassmorphism chat panel in the bottom-right corner, with a real-time data console in the bottom-left showing exactly what’s being collected. The conversation flow collects name, email, skills, salary expectations, and location through natural dialogue. An OpenAI API integration handles skill extraction and job matching, with graceful keyword-based fallbacks if the LLM isn’t available.

The real trick is the Lever API integration. When a candidate completes the conversation, their profile is formatted into Lever-compatible data — skills become structured tags (skill:javascript, category:design), experience levels are extracted, salary ranges are preserved in custom fields, and every submission is tagged source:ai-chatbot so recruiters can filter by acquisition channel. A Netlify serverless function handles the API proxy to avoid CORS issues, and a duplicate-check endpoint prevents the same email from creating multiple records.

The returning candidate flow

One of the more interesting moments in the demo is what happens when a known email is entered. The chatbot recognizes the candidate and surfaces what it already knows about them — a check-in moment that feels genuinely personal. “Hey, I recognize you, welcome back” hits differently than a static FAQ page. That recognition layer, pulling from existing Lever records, opens up use cases around candidate re-engagement and pipeline warm-up that most careers pages don’t even attempt.

Why it matters

This is a proof of concept for how recruiting infrastructure can be designed, not just configured. The same pattern applies well beyond hiring: onboarding flows that read from and write to a CRM in real time, waitlist tools that qualify leads conversationally before a sales call, or intake forms for agencies that capture structured client data through chat. The key architectural insight — LLM for understanding, serverless functions for secure API proxying, and a structured data layer for downstream tooling — is reusable across a lot of contexts. The chatbot just happens to be the most human-feeling entry point into what is otherwise a data pipeline.

Applying this to your project

  1. Clone the whole ai-careers-chatbot/ folder as-is — there’s no build step to strip out beyond build.js, and no node_modules since it’s plain HTML/CSS/JS. Discard test-lever-connection.html, WARP.md, and VERIFY-LEVER.md — those were internal debugging aids, not part of the working app. Keep README.md, LEVER-INTEGRATION.md, LEVER-SETUP.md, and NETLIFY-DEPLOY.md as setup references.

  2. Environment variables are set in the Netlify dashboard (Site Settings → Environment Variables), not committed to the repo:

    • OPENAI_API_KEY — from platform.openai.com, optional (the bot degrades gracefully to keyword matching in js/chatbot.js if this is missing)
    • LEVER_API_KEY — from your Lever account’s API settings, required only if you want real ATS submission
    • LEVER_PERFORM_AS_USER — a Lever user ID, fetched via curl -u YOUR_KEY: https://api.lever.co/v1/users (see LEVER-SETUP.md)
    • For local testing without Netlify, copy config/llm-config-example.js to config/llm-config-local.js and paste a real key there — it’s gitignored so it won’t leak.
  3. Swap out to make it your own:

    • assets/careers-page-screenshot.png — replace with your own careers page screenshot; it’s just a static background image, not a live page.
    • this.availableJobs array in js/chatbot.js — currently hardcodes a single “Production Designer” role with a keyword list; replace with your own open roles and their matching keywords.
    • The bot’s opening line and copy live in index.html (chat-messages block) and throughout js/chatbot.js’s conversation states.
    • config/lever-config.js → jobOpportunityMapping — map your job titles to real Lever opportunity IDs if you want auto-application instead of just roster collection.
    • css/styles.css — glassmorphism theme, colors, and positioning of the two floating panels.
  4. Critical integration points where your data plugs in:

    • netlify/functions/submit-to-lever.js and check-lever-candidate.js are the only places that touch your ATS credentials — if you use a different ATS (Greenhouse, Ashby, etc.), rewrite these two functions and the calling code in js/lever-integration.js’s submitCandidate()/checkExistingCandidate().
    • js/llm-service.js’s extractSkills() and evaluateJobMatch() prompts define what the model is asked to return as JSON — adapt the system prompts here if you change what data you collect.
    • netlify.toml’s [build] command = "node build.js" is what injects your API keys into config/llm-config-prod.js and config/lever-config-prod.js at deploy time — any new secret needs a matching block added to build.js.
  5. Gotchas found while reading the code:

    • The OpenAI key is injected into a client-side, publicly-readable JS file (config/llm-config-prod.js) by build.js — it is not server-side-only, so treat it as a low-privilege/rate-limited key, unlike the Lever key which stays server-side in the Netlify Function’s process.env.
    • netlify/functions/case-studies.js reads from a hardcoded public Google Doc ID and appears to be an unrelated, half-finished experiment sitting in the same functions folder — don’t assume everything in netlify/functions/ is part of the chatbot flow.
    • Lever’s perform_as user ID isn’t optional in practice — omitting LEVER_PERFORM_AS_USER causes submissions to fail with a permissions error even though the code technically runs without it.
    • submitCandidate() always calls checkExistingCandidate() first and silently falls back to “doesn’t exist” on any network error, so a flaky Lever API call could create duplicate candidates instead of updating existing ones.

Other ways to repurpose this

Product Design

Web Design

Marketing

Branding

Dependencies

openai-chat-completions-api v1 (gpt-3.5-turbo) Called directly from the browser in js/llm-service.js to extract structured skills/experience from free-text chat replies and score candidates against open roles, with a keyword-matching fallback when no key is present.
lever-hire-api v1 Applicant tracking system that receives completed candidate profiles; js/lever-integration.js formats chatbot data into Lever's candidate schema (tags, headline, notes) and posts it through a serverless proxy.
netlify-functions AWS Lambda runtime, Node 18 Serverless functions (netlify/functions/submit-to-lever.js, check-lever-candidate.js) that hold the Lever API key server-side and proxy requests to avoid exposing it to the browser and to sidestep CORS.
google-docs-export-endpoint n/a (public export URL) netlify/functions/case-studies.js fetches a public Google Doc as plain text/JSON to serve as a lightweight, editable CMS for case study data — appears to be a leftover/unrelated experiment bundled in the same functions folder.
node 18 (pinned in netlify.toml) Runtime for the Netlify build step (build.js) and for executing the two serverless functions; the site itself ships zero npm packages.
Role
Creative Technologist
Tools
OpenAI API Lever API Netlify Functions Vanilla JavaScript HTML CSS Netlify
Metrics
End-to-end candidate submission pipeline: chat to Lever CRM in under two minutes, with source tracking and duplicate detection built in.
URL
https://instrument-careers-page.netlify.app
Video thumbnail for AI-Powered Careers Chatbot