← Back to history

Pipeline run

d6c35e6e-fb0d-4299-9ee2-59d7a5bec9c0

Pipeline LLM cost (USD)
API 1: $0.0010 API 2: $0.0000 API 3: $0.0000 Total: $0.0010

Client output enrichment

v2 Skill cluster · Nature of work · AI index · Tech stack maturity · Evidence · KRA description
SPARSE JD
Nature of work
—
no_db_connection
Tech stack maturity
Mainstream Modern
AI index (0 = no AI use, 5 = totally AI-dependent · v2.1)
0.00 / 5
· Title match
· Has AI skill
· AI skill (primary)
· AI skill (secondary)
· On AI team
· Builds AI products
vocab breakdown (legacy)
Assistants (×1): —
Frameworks (×2): —
Models / concepts (×3): —
Evidence — skills matched in JD (0)
No skills extracted
Skill cluster (0 dimension groups, role-scoped)
No dimension groups computed for this JD.
Status: extract_from_jd_done Created: 2026-08-20T15:33:56.490025Z Updated: 2026-08-20T15:35:23.530426Z
Flow Current 3-step pipeline

1 POST /skills/extract-from-jd

2 POST /skills/extract-details

3 POST /skills/final-role-output

Role Chosen role & resolution

No chosen role stored for this run.

Job description

Fix candidate photos disappearing on ranked list and route candidate avatars through Next image optimizer
Photo CDN was returning 429s when all candidate rows remounted at once after
navigating back from the detailed candidate page. Google and LinkedIn serve
profile pictures no-cache and throttle repeated bursts, so the browser was
re-requesting every single photo fresh on each mount and hitting the rate
limit. The img error handler would fire, fall through to initials, and stay
there because the browser cached the failed 429 response.

Switched CandidatePhoto from a plain img element to Next's built-in image
optimizer. The optimizer fetches each URL once server-side, caches it under
our origin for a week (minimumCacheTTL in next.config.ts), and serves it from
there — so going back to the ranked list is a local cache hit and the CDN is
never hit again. Verified: first request MISS, second request HIT with
Cache-Control max-age=604800.

Also unified the fallback. When a photo genuinely fails, it now shows the
same deterministic gradient avatar (keyed to the candidate's name) that
candidates without any photo get — so rows never flip between two different
avatar styles and the same person always gets the same colour.

Updated candidate-row-wide, candidate-profile and app-rail to pass the name
prop so the fallback gradient is consistent everywhere.

Library artifacts (this run)

No artifact rows for this run.
nano JD Parser — gpt-4.1-nano click to toggle
JD type fail
Show raw JSON
{
  "JD_type": "fail"
}
API 1 — extract-from-jd click to toggle
{
  "final_skills": [],
  "jd_parameters": null,
  "jd_role": {
    "display_name": "\u2014",
    "rationale": "Stage 1 marked JD_type=fail (unparseable); body has only 0 canonical-skill mentions and 0 tech-marker hits \u2014 insufficient evidence",
    "role_aliases": [],
    "role_archetype": "\u2014",
    "slug": ""
  },
  "nano_parsed": {
    "JD_type": "fail"
  },
  "rejected": true,
  "rejection_reason": "Stage 1 marked JD_type=fail (unparseable); body has only 0 canonical-skill mentions and 0 tech-marker hits \u2014 insufficient evidence",
  "role": null,
  "run_id": null,
  "secondary_skills": [],
  "skill_layers": null,
  "stage3_signals": null,
  "stage4_decision": null,
  "stage5_updates": null
}
API 2 — extract-details
{}
API 3 — final-role-output
{}

LLM Calls

Every model call made for this run, in pipeline order. Click a card to see the model's response.

Loading…