Open-source Applicant Tracking System designed for small recruiting teams that want a simple, self-hostable alternative to complex enterprise ATS platforms.
Hire Gnome focuses on practical hiring workflows — candidate pipelines, structured evaluation, and lightweight reporting — while remaining easy to deploy, customize, and extend.
Built for teams that want full control of their hiring stack without the cost or complexity of traditional recruiting software.
Try the public demo environment: https://demo.hiregnome.com
When demo mode is enabled, authenticated demo users see a one-time welcome modal with quick guidance. Forwarding a message to demo@hiregnome.com triggers the Postmark inbound workflow in the demo environment, but the forwarded message must include an email address that matches an existing candidate or contact record for processing to occur.
- Features
- Changelog
- User Documentation
- Quick Start
- Onboarding And First Login
- Configuration Model
- Environment Reference
- Scripts
- Operations
- Production Checklist
- Troubleshooting
- Contributing
- Security
- Authentication with first-run onboarding
- Role and division access model (
Administrator,Director,Recruiter) - Core modules: Candidates, Clients, Contacts, Job Orders, Submissions, Interviews, Placements
- Action-oriented dashboard with KPI drill-through, 7-day activity strip, smart needs-attention alerts, upcoming interviews, recent candidates, recent job orders, and fixed-height section paging
- Operational Reporting module with scoped KPIs, pipeline totals, drill-through detail, daily trend, owner performance, and Excel export with summary + entity tabs that mirror report-modal detail
- List + Kanban pipeline views for Candidates and Job Orders with drag-and-drop status updates
- Admin-defined custom fields for Candidates, Clients, Contacts, Job Orders, Submissions, Interviews, and Placements
- AI-assisted resume parsing with fallback parsing if AI is unavailable
- AI candidate summaries opened from a dedicated sparkles button on candidate detail, with first-run auto-generation from profile, resume, history, skills, and recent notes
- Candidate detail snapshot card with title, location, status, top skills, AI summary snippet, last activity, and profile-completeness guidance
- Candidate list profile-completeness chips plus soft submission warnings when recruiters try to submit thin profiles
- AI-generated submission write-ups for polished client-facing candidate introductions
- AI-generated interview question sets stored on the interview record and refreshable on demand
- AI match explanations on candidate/job-order match lists with cached, refreshable fit analysis that auto-generates on first open
- AI email drafting from candidate and contact actions menus with purpose/tone controls and copy-to-clipboard
- AI editor actions use the shared sparkles icon pattern for consistency across candidate and job-order detail views
- AI-specific controls stay visible but are disabled with an inline hint when no OpenAI key is configured in system settings
- Job-order submission workspaces support recruiter priority ordering with persisted drag-and-drop ranking
- Client review portal with persistent magic links per job-order contact, allowing external review of submitted candidates without a login
- Career-site web responses stay differentiated from recruiter-curated submissions and remain hidden from the client portal until a recruiter promotes them
- Candidate file attachments with object storage (
s3) and local fallback - Candidate file workspace supports explicit resume labeling so internal users and the client portal can identify the primary resume document
- Public career site (toggleable in Admin settings) with quick apply + resume upload
- Candidate and job-order match workspaces (top matches, sortable/paged)
- Administrator-only audit trails on records plus admin diagnostics
- Admin diagnostics includes recent inbound email webhook visibility
- Admin data export module with
JSON,NDJSON, andZIP (per-entity)Hire Gnome output + a Bullhorn API batch ZIP exporter for bounded migration samples - Admin data import module:
- Hire Gnome export re-import (
JSON,NDJSON,ZIP) - Generic CSV migration batches with per-column field mapping (
Clients,Contacts,Candidates,Job Orders,Submissions,Interviews,Placements) - Restores
customFieldDefinitionsfrom Hire Gnome exports before importing dependent records - Bullhorn CSV migration batches (
Custom Fields,Clients,Contacts,Candidates,Job Orders,Submissions,Interviews,Placements) - Zoho Recruit CSV migration batches (
Clients,Contacts,Candidates,Job Orders,Submissions,Interviews,Placements) - Built-in CSV template downloads per profile plus auto-mapping suggestions for generic CSV headers
- Generic CSV, Bullhorn CSV, and Zoho Recruit CSV batches run in dependency order so related records can be linked during migration
- Hire Gnome export re-import (
- Global search with cross-entity results
- In-app notifications, unsaved-change navigation guard, archive/restore flows
- Per-list column chooser with per-user persisted visibility/order preferences, hidden-by-default optional columns, drag-and-drop ordering, and cross-device continuity
- Per-list saved views with named filter/sort/column layouts and personal defaults that persist per user across devices
- Mobile-aware list/detail layouts
- Changelog:
CHANGELOG.md - End-user guide:
docs/USER_GUIDE.md - Module guides:
docs/modules - Operations runbook:
docs/OPERATIONS.md - In-app help route:
/helpand/help/[module] - Reports access rules:
Administrator: all dataDirector: division-scoped dataRecruiter: own data only
- See
CHANGELOG.mdfor dated release notes and daily change summaries.
- Node.js
20.x(see.nvmrc) - npm
10+ - MySQL
8+(local install or Docker)
git clone <your-repo-url> hire-gnome-ats
cd hire-gnome-ats
nvm use || true
npm install
cp .env.example .envDATABASE_URL="mysql://root:password@localhost:3306/ats"
AUTH_SESSION_SECRET="replace-with-a-long-random-secret"
AUTH_APP_BASE_URL="http://localhost:3000"Local MySQL:
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS ats;"Docker MySQL:
npm run db:upThen set:
DATABASE_URL="mysql://ats:ats@localhost:3307/ats"npm run bootstrap
npm run devOpen http://localhost:3000.
On a fresh DB you are redirected to /setup.
If you are upgrading an existing DB, apply migrations first:
npx prisma migrate deploy- There is no hardcoded seeded default admin user.
- Optional bootstrap provisioning can create a default admin from
.envwhen DB has zero users. - First user is created in onboarding (
/setup) and becomesAdministrator. - Onboarding sets initial branding and theme.
Quick smoke test after first login:
- Open
Admin Area > System Settings > System Diagnosticsand run diagnostics. - Create a Client.
- Create a Contact linked to that Client.
- Create a Job Order linked to that Client/Contact.
- Create a Candidate.
- Create a Submission for Candidate + Job Order.
Use Admin Area > System Settings for:
- Site name, logo, theme
- Public careers hero headline/body copy
- Career site enabled/disabled
- Client review portal enabled/disabled
- Google Maps API key
- OpenAI API key
- Bullhorn API credentials for background export jobs
- SMTP settings
- Object storage settings (
s3or local mode) - API error log retention days
- Operational-data purge with typed confirmation in the
Diagnosticstab
When DEMO_MODE is enabled:
- administrators can still save the full branding card
- integrations, SMTP, and object storage settings remain read-only
System settings are split into:
BrandingPlatform Settings
Use Admin Area > Custom Fields for:
- Module-scoped custom fields on Candidates, Clients, Contacts, Job Orders, Submissions, Interviews, and Placements
- Field-level validation (
text,long text,number,date,yes/no,select) - Required field enforcement on create/update forms
Use Admin Area > Data Export for:
- Export format selection (
JSON,NDJSON,ZIP) - Optional inclusion of audit trail and API error logs
- Incremental date-range exports using
updatedAt(fallbackcreatedAt) - Export payload includes
customFieldDefinitionsso custom schema can be moved across instances - Bullhorn API batch ZIP export for custom field definitions, clients, contacts, contact notes, candidates (including structured candidate skills), candidate notes, candidate education, candidate work history, candidate files/resumes, job orders, submissions, interviews, and placements
- Bullhorn export filters by created/updated date range and expands upstream dependencies so the exported batch stays importable
- Bullhorn export now also supports a preflight window estimate so administrators can see changed core-row counts by entity before starting a background job
- Bullhorn export keeps the run sample-sized with a per-entity changed-row limit before dependency expansion
- Bullhorn exports now run as background jobs in the admin UI, notify the requesting user when ready, and can be downloaded or opened in the import preview flow from the completed job
- Saved Bullhorn credentials can be managed in
Admin Area > System Settings > Platform Settingsso administrators do not have to re-enter them for each export - Completed, cancelled, or failed Bullhorn export jobs can be deleted from the exports screen after confirmation
Submission workflows include a print-friendly Submission Packet from submission detail for internal review or browser PDF export. The packet compiles the recruiter write-up, primary resume link, candidate snapshot, cached match explanation, and recent interview prep/questions.
Use Admin Area > Data Import for:
- Source selection:
- Hire Gnome export (
JSON,NDJSON,ZIP) - Generic CSV migration batch with field mapping
- Bullhorn CSV migration batch
- Zoho Recruit CSV batch
- Hire Gnome export (
- Hire Gnome import applies
customFieldDefinitionsfirst, then entity records - Entity profile selection for CSV imports
- Generic CSV batch upload with per-file entity selection, auto-suggested field matches, and ordered apply
- Bullhorn batch upload with per-file entity review and ordered apply
- Bullhorn import/export preserves Bullhorn custom field definitions and record-level custom field values when the source includes them
- Bullhorn import/export now also carries candidate notes, candidate education, candidate work history, contact notes, and structured candidate skills inside the batch flow
- Bullhorn export/import now also carries candidate attachment files, including resumes, inside the ZIP batch when Bullhorn exposes downloadable candidate files
- Zoho Recruit batch upload with per-file entity review and ordered apply
- Generic CSV preview now acts as a safety check with per-entity create/update/skip counts, relationship warnings, row-level actions, match-reason visibility, and tabbed inspection before apply
- Every import source type now includes an in-app sample download link, including ZIP-ready sample batches for Generic CSV, Bullhorn, Zoho Recruit, and Hire Gnome export testing
docs/import-samples/bullhorn-batch/contains a clean Bullhorn-style sample batch withcustomFieldDefinitions, the core entity CSVs, note/education/work-history metadata CSVs, and a candidate resume/file payload for ZIP/manual importer demosdocs/import-samples/zoho-recruit-batch/contains a clean seven-file Zoho Recruit-style sample batch for ZIP/manual importer demos- Import preview before apply
- Profile template CSV download from the UI
Use .env for:
- Core runtime (
DATABASE_URL, auth/session settings) - Rate limits and security throttles
- Email safety routing (
EMAIL_TEST_MODE,EMAIL_TEST_RECIPIENT) - Ops and diagnostics knobs (backup/logging/alerts/preflight)
- If object storage settings are missing or invalid, file upload falls back to local storage.
EMAIL_TEST_MODE=trueroutes outgoing emails toEMAIL_TEST_RECIPIENT.- For socket-based MySQL, include socket in
DATABASE_URL, for example:mysql://root:password@localhost:3306/ats?socket=/tmp/mysql.sock
| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
Yes | Prisma/MySQL connection string. |
AUTH_SESSION_SECRET |
Yes | Secret used to sign auth session cookies/tokens. Use a strong random value. |
AUTH_APP_BASE_URL |
Yes | Absolute app URL used for auth/reset links. |
| Variable | Default | Purpose |
|---|---|---|
SKIP_SYSTEM_SETTINGS_DB_DURING_BUILD |
true |
Skips DB reads for system settings during production build to avoid SSG build-time DB coupling. |
LOG_LEVEL |
info |
App log level (debug, info, warn, error). |
API_ERROR_LOG_RETENTION_DAYS |
90 |
Baseline retention window for API error logs. Admin UI can override in DB. |
| Variable | Default | Purpose |
|---|---|---|
AUTH_DEFAULT_PASSWORD |
Welcome123! |
Temporary default password marker for change-password enforcement flows. |
AUTH_SESSION_MAX_AGE_SECONDS |
43200 |
Session lifetime in seconds (12 hours by default). |
AUTH_LOGIN_MAX_ATTEMPTS |
5 |
Max failed login attempts before lockout. |
AUTH_LOGIN_LOCKOUT_MINUTES |
15 |
Lockout duration after failed login threshold. |
AUTH_LOGIN_RATE_LIMIT_MAX_REQUESTS |
20 |
Login endpoint requests allowed in window. |
AUTH_LOGIN_RATE_LIMIT_WINDOW_SECONDS |
900 |
Login endpoint rate-limit window size. |
AUTH_PASSWORD_RESET_TOKEN_TTL_MINUTES |
60 |
Password reset token expiration window. |
AUTH_FORGOT_PASSWORD_RATE_LIMIT_MAX_REQUESTS |
6 |
Forgot-password requests allowed in window. |
AUTH_FORGOT_PASSWORD_RATE_LIMIT_WINDOW_SECONDS |
900 |
Forgot-password rate-limit window size. |
AUTH_RESET_PASSWORD_RATE_LIMIT_MAX_REQUESTS |
10 |
Reset-password submission attempts allowed in window. |
AUTH_RESET_PASSWORD_RATE_LIMIT_WINDOW_SECONDS |
900 |
Reset-password rate-limit window size. |
CLIENT_PORTAL_SECRET |
falls back to AUTH_SESSION_SECRET |
Optional dedicated secret for client-review portal magic links. |
| Variable | Default | Purpose |
|---|---|---|
RATE_LIMIT_SECRET |
falls back to AUTH_SESSION_SECRET |
Secret salt for hashing requester IPs in throttle tables. |
CAREERS_APPLY_RATE_LIMIT_MAX_REQUESTS |
6 |
Public career apply requests allowed per window. |
CAREERS_APPLY_RATE_LIMIT_WINDOW_SECONDS |
900 |
Career apply rate-limit window size. |
CAREERS_APPLY_MIN_FORM_FILL_SECONDS |
2 |
Minimum client-side form fill time accepted for public apply (anti-bot guard). |
LOOKUP_RATE_LIMIT_MAX_REQUESTS |
80 |
Max lookup/typeahead requests per window. |
LOOKUP_RATE_LIMIT_WINDOW_SECONDS |
60 |
Lookup/typeahead rate-limit window size. |
GLOBAL_SEARCH_RATE_LIMIT_MAX_REQUESTS |
30 |
Max global search requests per window. |
GLOBAL_SEARCH_RATE_LIMIT_WINDOW_SECONDS |
60 |
Global search rate-limit window size. |
CANDIDATE_MATCH_RATE_LIMIT_MAX_REQUESTS |
20 |
Candidate-match endpoint max requests per window. |
CANDIDATE_MATCH_RATE_LIMIT_WINDOW_SECONDS |
60 |
Candidate-match rate-limit window size. |
JOB_ORDER_MATCH_RATE_LIMIT_MAX_REQUESTS |
20 |
Job-order-match endpoint max requests per window. |
JOB_ORDER_MATCH_RATE_LIMIT_WINDOW_SECONDS |
60 |
Job-order-match rate-limit window size. |
MUTATION_RATE_LIMIT_MAX_REQUESTS |
120 |
Max mutation (create/update/delete-like) requests per window. |
MUTATION_RATE_LIMIT_WINDOW_SECONDS |
60 |
Mutation rate-limit window size. |
RESUME_PARSE_RATE_LIMIT_MAX_REQUESTS |
30 |
Resume parsing requests allowed per window. |
RESUME_PARSE_RATE_LIMIT_WINDOW_SECONDS |
600 |
Resume parsing rate-limit window size. |
REQUEST_THROTTLE_GLOBAL_CLEANUP_INTERVAL_SECONDS |
300 |
Frequency for global throttle cleanup sweeps. |
REQUEST_THROTTLE_GLOBAL_CLEANUP_SECONDS |
3600 |
Minimum age threshold for throttle-event cleanup candidates. |
| Variable | Default | Purpose |
|---|---|---|
EMAIL_TEST_MODE |
true |
If true, all outbound emails are redirected to test recipient. |
EMAIL_TEST_RECIPIENT |
empty | Address that receives all emails when test mode is on. |
| Variable | Default | Purpose |
|---|---|---|
OPENAI_RESUME_MODEL |
gpt-4o-mini |
Model used for resume parsing/enrichment calls when OpenAI key exists in system settings. |
| Variable | Default | Purpose |
|---|---|---|
LOCAL_STORAGE_ROOT |
.local-storage under project root |
Local fallback storage path when object storage is not configured/available. |
| Variable | Default | Purpose |
|---|---|---|
DB_BACKUP_DIR |
.backups |
Directory used by backup scripts and diagnostics checks. |
DB_BACKUP_RETENTION_DAYS |
14 |
Retention policy for scheduled backup cleanup. |
POSTMARK_INBOUND_WEBHOOK_SECRET |
empty | Optional shared secret for /api/inbound/postmark via query string or header. |
ERROR_ALERT_WEBHOOK_URL |
empty | Webhook endpoint for runtime/API error alerts. |
ERROR_ALERT_MIN_LEVEL |
error |
Minimum log severity that triggers error webhook alert. |
ERROR_ALERT_COOLDOWN_SECONDS |
300 |
Alert cooldown period to suppress webhook spam. |
ERROR_ALERT_SOURCE |
hire-gnome-ats |
Source label included in error alert payloads. |
HEALTH_ALERT_WEBHOOK_URL |
empty | Webhook endpoint for health-check failures. |
HEALTH_ALERT_SOURCE |
hire-gnome-ats |
Source label included in health alert payloads. |
| Variable | Default | Purpose |
|---|---|---|
PAPERTRAIL_HOST |
empty | Papertrail syslog host. When empty, Papertrail shipping is disabled. |
PAPERTRAIL_PORT |
empty | Papertrail UDP syslog port. Required with PAPERTRAIL_HOST to enable shipping. |
PAPERTRAIL_MIN_LEVEL |
info |
Minimum log level forwarded to Papertrail (debug, info, warn, error). |
PAPERTRAIL_APP_NAME |
hire-gnome-ats |
App name tag in Papertrail log lines. |
PAPERTRAIL_FACILITY |
16 |
Syslog facility code (0-23), defaults to local0 (16). |
| Variable | Default | Purpose |
|---|---|---|
PREFLIGHT_SKIP_DB_CONNECTIVITY |
false |
Skips DB connectivity test in npm run ci:preflight when true. |
PREFLIGHT_DB_RETRIES |
1 |
Number of retries for DB connectivity check in preflight. |
PREFLIGHT_DB_RETRY_DELAY_MS |
2500 |
Delay between DB connectivity retries in preflight. |
| Variable | Default | Purpose |
|---|---|---|
DEMO_MODE |
false |
Enables demo UI behavior (system settings read-only + demo credentials shown on login). |
DEMO_ADMIN_EMAIL |
admin@demoats.com |
Demo admin email shown on login when demo mode is enabled. |
DEMO_RECRUITER_EMAIL |
recruiter@demoats.com |
Demo recruiter email shown on login when demo mode is enabled. |
DEMO_LOGIN_PASSWORD |
Welcome123! |
Demo login password shown on login when demo mode is enabled. |
DEMO_RESET_INTERVAL_MINUTES |
360 |
Interval used by npm run demo:reset:loop. |
DEMO_RESET_RUN_ON_START |
true |
If true, the loop script runs one reset immediately on boot. |
DEMO_RESET_MODE |
seed |
Mode used by demo:reset:loop (seed recommended, full is heavier and can show onboarding during reset). |
| Variable | Default | Purpose |
|---|---|---|
BOOTSTRAP_ADMIN_ENABLED |
false |
If true, bootstrap creates a default admin when user count is zero. |
BOOTSTRAP_ADMIN_FIRST_NAME |
System |
First name for bootstrap-provisioned admin. |
BOOTSTRAP_ADMIN_LAST_NAME |
Administrator |
Last name for bootstrap-provisioned admin. |
BOOTSTRAP_ADMIN_EMAIL |
empty | Email for bootstrap-provisioned admin (required when enabled). |
BOOTSTRAP_ADMIN_PASSWORD |
empty | Password for bootstrap-provisioned admin (required when enabled, min 8 chars). |
| Variable | Default | Purpose |
|---|---|---|
BILLING_ENABLED |
false |
Enables hosted billing seat synchronization. |
BILLING_PROVIDER |
stripe |
Billing provider (stripe currently supported). |
BILLING_STRIPE_SECRET_KEY |
empty | Stripe API secret key used for billing sync. |
BILLING_STRIPE_CUSTOMER_ID |
empty | Stripe customer id (cus_...). |
BILLING_STRIPE_SUBSCRIPTION_ID |
empty | Stripe subscription id (sub_...) containing base + seat items. |
BILLING_BASE_PRICE_ID |
empty | Stripe base recurring price id (price_...). |
BILLING_SEAT_PRICE_ID |
empty | Stripe per-seat recurring price id (price_...). |
BILLING_STRIPE_SEAT_SUBSCRIPTION_ITEM_ID |
empty | Optional explicit seat subscription item id (si_...) for quantity updates. |
BILLING_STRIPE_BASE_SUBSCRIPTION_ITEM_ID |
empty | Optional explicit base subscription item id (si_...). |
BILLING_STRIPE_PRORATION_BEHAVIOR |
create_prorations |
Seat-change proration behavior (create_prorations, always_invoice, none). |
BILLING_CURRENCY |
usd |
Fallback currency display when Stripe pricing data is unavailable. |
| Variable | Default | Purpose |
|---|---|---|
BULLHORN_OPERATIONS_ENABLED |
true |
Enables Bullhorn import/export operations in both admin UI and APIs. |
ZOHO_RECRUIT_OPERATIONS_ENABLED |
true |
Enables Zoho Recruit import operations in both admin UI and APIs. |
These are not in .env.example and are only used as fallback link sources:
APP_BASE_URLNEXT_PUBLIC_APP_URL
AUTH_APP_BASE_URL remains the primary setting.
All Node operational scripts in scripts/ auto-load .env (and .env.local if present), so manual source .env is not required.
| Script | Purpose |
|---|---|
npm run dev |
Run Next.js in development mode |
npm run build |
Production app build only |
npm run build:deploy |
Apply production migrations, then build the app |
npm run start |
Start production server |
npm run bootstrap |
Validate environment + migration status + deploy migrations |
npm run bootstrap:admin |
Provision default admin from bootstrap env vars (only when no users exist) |
npm run prisma:migrate |
Create/apply dev migration |
npm run db:up |
Start Docker MySQL (docker-compose.dev.yml) |
npm run db:down |
Stop Docker MySQL |
npm run db:logs |
Stream Docker MySQL logs |
npm run db:reset |
Stop + remove Docker MySQL volume |
npm run db:backup |
One-off DB backup |
npm run db:backup:scheduled |
Backup + retention cleanup |
npm run db:restore -- --input <file> --drop-first |
Restore SQL backup |
npm run demo:seed |
Seed realistic linked demo data (non-destructive to unrelated records) |
npm run demo:reset |
Full DB reset + migration + realistic demo reseed |
npm run demo:reset:seed-only |
Reseed demo data without full DB reset |
npm run demo:reset:loop |
Run automatic periodic demo resets |
npm run db:clear:operational |
Clear operational ATS data while preserving users, settings, skills, custom fields, and zip codes |
npm run ci:preflight |
Env/DB/backup-path checks |
npm run ci:build |
Build wrapper for CI |
npm run ci:smoke |
Permission/API smoke checks |
npm run ci:test |
Preflight + build composite |
npm run health |
Run health-check script |
- Runbook:
docs/OPERATIONS.md - Health endpoint:
GET /api/health - Admin diagnostics:
Admin Area > System Settings > System Diagnostics - Data export:
Admin Area > Data Export(orGET /api/admin/data-exportfor Hire Gnome snapshots,POST /api/admin/bullhorn-export-jobsto queue a Bullhorn export job,GET /api/admin/bullhorn-export-jobsto poll job status,PATCH /api/admin/bullhorn-export-jobs/[recordId]to cancel a queued/running Bullhorn export job,DELETE /api/admin/bullhorn-export-jobs/[recordId]to remove a completed, cancelled, or failed Bullhorn export job) - Data import:
Admin Area > Data Import(orPOST /api/admin/data-import) - Client review portal management:
Job Order Detail > Actions > Client Review Portal
Data export query options:
format:json|ndjson|zipincludeAuditLogs:true/falseincludeApiErrorLogs:true/falsedateFrom: ISO datetime (optional)dateTo: ISO datetime (optional)
Data import form fields:
mode:preview|applysourceType:hire_gnome_export|generic_csv|generic_csv_manual|generic_csv_zip|bullhorn_csv|bullhorn_csv_manual|bullhorn_csv_zip|zoho_recruit_csv|zoho_recruit_manual|zoho_recruit_zipfile: upload file (.json,.ndjson,.zip, or.csvbased on source)genericBatch: JSON array of CSV-batch entries containingentity,mapping, and file field keys (preferred whensourceType=generic_csv)genericEntity: legacy single-file generic entity selector (still accepted whengenericBatchis not provided)genericMapping: legacy single-file generic mapping object (still accepted whengenericBatchis not provided)bullhornEntity:customFieldDefinitions|clients|contacts|candidates|jobOrders|submissions|interviews|placements(required whensourceType=bullhorn_csv)zohoEntity:clients|contacts|candidates|jobOrders|submissions|interviews|placements(required whensourceType=zoho_recruit_csv)
Sample generic migration batch:
docs/import-samples/generic-migration-batch/- Includes a clean seven-file CSV set in dependency order for demos and importer testing.
docs/import-samples/generic-migration-batch-messy/- Includes a second seven-file batch with messier legacy column names for mapping demos.
Kanban status update endpoints:
PATCH /api/candidates/[id]/statuswith{ "status": "...", "reason": "..." }PATCH /api/job-orders/[id]/statuswith{ "status": "open|on_hold|closed" }
Hire Gnome export/import coverage:
- Export includes
customFieldDefinitions, core entities, and related child records. - Import upserts
customFieldDefinitionsbyrecordIdor(moduleKey, fieldKey)before entity rows. - Import applies
customFieldspayload values on supported entities, including Submissions, Interviews, and Placements.
Archive behavior:
- Archive is soft-delete and reversible through the Archive module.
- Certain archive actions can optionally cascade to related records via UI selections during archive flow.
Demo instance reset behavior:
demo:resetpreservesSystem Settings(branding/theme/integration keys) by default.- If no
System Settingsrow exists, demo seeding creates one with default branding and enables the public career site. - Seed creates realistic linked records across all core modules.
- Seeded public job postings include richer, role-aligned career-site descriptions.
- Seed avoids duplicate human-readable names across seeded users, contacts, and candidates.
- Seed-mode reset clears all
customFieldDefinitionsso custom fields do not persist between demo reset cycles. - Default seeded login users use
AUTH_DEFAULT_PASSWORD. - For interval resets, either:
- run
npm run demo:reset:loop(usesDEMO_RESET_INTERVAL_MINUTES), or - schedule
npm run demo:resetwith cron/systemd (for example every 6 hours).
- run
Inbound email webhook:
- Postmark inbound webhook endpoint:
/api/inbound/postmark - The route extracts email addresses from the payload, matches
Candidate.emailandContact.email, creates cleanedEmailnotes on matches, and saves supported attachments to matched candidates only. - Contact matches receive notes only. Attachments are not saved to contacts.
- Duplicate inbound processing is suppressed by Postmark
MessageID. - Matching is based on any email addresses found in the inbound JSON payload, including common reply/forward content.
- Candidate attachments are saved only when the inbound payload includes attachment bytes, not just metadata.
- Recent inbound events and attachment skip reasons are visible in
Admin Area > System Settings > System Diagnostics.
Client review portal:
- The client portal can be disabled globally from
Admin Area > System Settings. - Internal users can issue a persistent magic link from
Job Order Detail > Actions > Client Review Portal. - Portal access is scoped to the job order's assigned client contact and remains valid for the life of the job unless revoked.
- Internal users can copy, open, email, revoke, or restore the portal link from the job-order modal.
- Portal email sends use a branded HTML invite that follows the selected admin theme, with a direct CTA, job title context, and a plain-text fallback.
- Portal management shows lifecycle analytics for sent, opened, last viewed, acted on, and total client actions logged on job order detail and in the modal.
- Clients can review submitted candidates, read the recruiter write-up, download only the candidate's labeled primary resume, complete a simple scorecard (
Communication,Technical Fit,Culture Fit,Overall Recommendation), leave comments, request interviews, or pass. - Client responses are written back to
Submission Detail > Client Feedbackwith the structured scorecard and generate in-app plus email notifications for users who keepClient Feedback Notificationsenabled inAccount Settings. - If
POSTMARK_INBOUND_WEBHOOK_SECRETis set, include it either as?secret=...on the webhook URL or as thex-webhook-secretheader.
- Set strong unique values for:
AUTH_SESSION_SECRETDATABASE_URLAUTH_APP_BASE_URL
- Set
EMAIL_TEST_MODE=trueduring staging/testing. - Set
EMAIL_TEST_MODE=falseonly after SMTP and recipient routing are validated. - Configure system integrations in Admin settings:
- SMTP
- Object storage
- Google/OpenAI keys as needed
- Run:
npm run ci:preflightnpm run build:deploy
- Validate backup and restore before go-live:
npm run db:backupnpm run db:restore -- --input <backup-file> --drop-first
You are running an old Node version. Use Node 20.x, reinstall dependencies, rerun command.
Your local migration history drifted. For local development only:
npx prisma migrate resetSchema and database are out of sync. Apply latest migrations:
npx prisma migrate deployEnsure SKIP_SYSTEM_SETTINGS_DB_DURING_BUILD=true (default) so system settings are not read during static build phases.
This is usually stale auth cookies after a deploy or secret/session changes.
- Refresh once and retry login.
- If needed, clear site cookies for the app domain (
ats-session,ats-acting-user-id) or open/api/session/logout. - New private/incognito windows are typically unaffected because no stale cookies exist.
Verify:
- MySQL is running
DATABASE_URLis correct- database
atsexists - socket path is set when using local socket-based MySQL
- Read
CONTRIBUTING.md - Use issue templates for bugs and feature work
- Use PR template and include migration notes
- Read
SECURITY.md - Do not open public issues for vulnerabilities
This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0-only).
- Full text:
LICENSE - SPDX identifier:
AGPL-3.0-only
