AI-powered resume analysis and cover-letter generation built with Next.js, Stack Auth, Convex, and Google Gemini.
@google/generative-ai)git clone https://github.com/Aditya190803/application-tracking-system.git
cd application-tracking-system
bun install --frozen-lockfile
cp .env.example .env.local
.env.local# Gemini
GOOGLE_API_KEY=""
# Convex
NEXT_PUBLIC_CONVEX_URL=""
# Stack Auth
NEXT_PUBLIC_STACK_PROJECT_ID=""
NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY=""
STACK_SECRET_SERVER_KEY=""
# Optional
NEXT_PUBLIC_APP_URL="http://localhost:3000"
MODEL_NAME="gemini-2.5-flash"
AI_TIMEOUT_MS="30000"
PDF_PARSE_TIMEOUT_MS="12000"
COVER_LETTER_ROUTE_TIMEOUT_MS="35000"
RESUME_ROUTE_TIMEOUT_MS="45000"
LATEX_RENDER_API_BASE="https://latexonline.cc"
UPSTASH_REDIS_REST_URL=""
UPSTASH_REDIS_REST_TOKEN=""
# Only set true for local emergency fallback; keep false/empty in production
ALLOW_IN_MEMORY_RATE_LIMIT=""
# Axiom (production logging)
AXIOM_TOKEN=""
AXIOM_DATASET=""
AXIOM_SERVICE="ats"
LOG_OBS_ERROR_DETAILS=""
bunx convex dev
bun run dev
App runs at http://localhost:3000.
Server routes emit structured JSON logs ([obs] prefix) via src/lib/observability.ts.
ats-prod)..env.local for dev ingest):AXIOM_TOKEN — bearer token (never commit)AXIOM_DATASET — e.g. ats-prodAXIOM_EDGE — optional, e.g. us-east-1.aws.edge.axiom.co (matches your ingest URL region)Useful Axiom queries
['your-dataset']
| where event == "pdf.parse_failed" or event == "pdf.parse_no_text"
| sort by _time desc
['your-dataset']
| where requestId == "paste-ref-from-user"
PDF upload failures include requestId in the API error; the upload UI shows it as (ref: …) so users can share it with support.
Set LOG_OBS_ERROR_DETAILS=true temporarily to include sanitized errorMessage on failure events (never resume or job description content).
$ claude mcp add Application-Tracking-System \
-- python -m otcore.mcp_server <graph>