UTKRUSHT / RECRUITER UI SPEC JULY 2026 · DRAFT 1

Showing system-design tasks in the recruiter UI

How the task library, share-task dialog, and mixed-assessment card display a DESIGN_REVIEW whiteboard task — which by design has the same competencies as a coding task, no GitHub repo, and a different task_type.

PrincipleCompetencies say what is measured. The badge says how.

A system-design task deliberately assesses the same competencies as a coding task — that is the product's point, not a display bug. So competency pills can never distinguish the two. The UI needs a second, visually different dimension: a format badge driven by tasks.task_type, which is already fetched and sitting unused on TaskData.taskType (transform-task.ts:124). No new data plumbing is required — this is purely a rendering change.

Mock 1Task library — collapsed cards

Today the collapsed card shows title + skill pills only (task-library-card.tsx:41-81). The single change: render the format badge next to the title when taskType contains a non-BUILD value.

app.utkrusht.ai/tasks
Task Library
Rate-Limiter Middleware for an Express API
Node.js (INTERMEDIATE) Express (INTERMEDIATE)
URL-Shortener Service Design System Design ← new: format badge, only on non-BUILD types
Distributed Systems (INTERMEDIATE) API Design (INTERMEDIATE)
Same competency pills on both cards — the outlined whiteboard badge is the only differentiator, and the only one needed.

Mock 2Share-task dialog — sidebar + detail panel (“the share box”)

The sidebar rows today show title only (task-skills-sidebar.tsx:173) — at the exact moment the recruiter decides what to send, nothing marks the format. Add a small whiteboard glyph on the row, and give the right-hand detail panel (task-detail-panel.tsx) three additions: the badge in the header, a one-line format strip, and a proper “View design board” button that opens a read-only preview of the starter board (Mock 3). This is the design-task equivalent of the coding task's “View starter code” gist button — the recruiter sees exactly what the candidate gets at minute zero, so they can be sure about the problem statement and what's on the board. Everything else stays the same read-only task info a coding task shows — problem statement, time, competencies, outcomes.

app.utkrusht.ai/position/backend-eng-2/share
Share task assessment
Pick tasks where candidates code or debug real code bases build, debug, or design real systems ← copy fix, share-task-dialog.tsx:448
Recommended
Rate-Limiter Middleware for an Express API
URL-Shortener Service Design
Skills
Event-Driven Order Pipeline (Kafka)
N+1 Query Hunt in a Django Admin
URL-Shortener Service Design System Design
Time Limit: 45 mins
Distributed Systems (INTERMEDIATE) API Design (INTERMEDIATE)
Interactive whiteboard task. The candidate designs the architecture on an Excalidraw board — no code, no GitHub repo. Graded against a reference design rubric.
Problem statement
  • Design a URL-shortener serving 100M redirects/day with p99 redirect latency under 100 ms.
  • The starter board contains a flawed single-node design — diagnose it and redesign.
Expected outcomes
  • Justified storage + cache choices for the read-heavy redirect path.
  • A key-generation scheme that avoids collisions at scale.
“View design board” replaces the coding task's “View starter code” gist button (task-detail-panel.tsx:140) for this format. It opens the starter board read-only — exactly what the candidate sees at minute zero — never the reference answer or a candidate's submission.
The share box: badge in the header, format strip with the “View design board” button, and otherwise exactly what a coding task shows — problem statement, time, competencies, outcomes.

Mock 3“View design board” — what opens on click

A read-only preview dialog rendering the task's starter board. The sample below is real data from the url-shortener-service-design task (tasks.task_blob in Supabase dev; same JSON as generated_tasks/system_design/url-shortener-service-design/task.json): the given Functional Requirements arrive locked, three dashed answer zones are empty, and the High-Level Design area holds the given starter context the candidate extends.

Implementation is cheap: task_blob.starter_scene is already fetched by TASK_SELECT (orgTasksOperations.ts:13 selects the whole task_blob) — the dialog lazy-loads @excalidraw/excalidraw in viewModeEnabled and hands it the scene. No new API call, no candidate-side route reuse.

app.utkrusht.ai/position/backend-eng-2/share — design board preview
URL-Shortener Service Design — Starter Board Read-only
Functional Requirements · given
  • Accept a long URL, return a 6–8 char short code / short link.
  • Redirect a visitor hitting a short link to the destination URL.
  • Handle duplicate submissions of the same URL gracefully.
  • Record referrer, timestamp, country on each redirect.
+ 2 more (analytics endpoint, 1-year click retention)
Non-Functional Requirements
Empty — candidate fills this in
Core Entities
Empty — candidate fills this in
API Routes
Empty — candidate fills this in
High-Level Design · starter context, candidate extends
Email Recipient / Marketing UI
URL Shortener Service
MongoDB
Design space
Shortening logic, redirect path, click-analytics flow, caching — not yet designed
80%+
preview · starter scene · not editable
Exactly what the candidate sees at minute zero — locked givens, empty answer zones, starter diagram. Never the reference answer, never a candidate's submission.

Mock 4Invite step — duration cards

Duration cards (task-duration-cards.tsx:87-116) currently show title + skill pills + duration select. The badge carries through so the format stays visible at the final confirmation step.

app.utkrusht.ai/position/backend-eng-2/share — step 2 of 2
Rate-Limiter Middleware for an Express API
Node.js (INTERMEDIATE)
60 mins
URL-Shortener Service Design System Design
Distributed Systems (INTERMEDIATE)
45 mins
Badge repeats on the confirmation step — the recruiter never loses sight of what kind of session they are scheduling.

Mock 5Mixed assessment card — type-aware phase copy

MixedTestCard hardcodes “coding task(s)” (mixed-test-card.tsx:12-16, 39), which misdescribes a design task. Since taskType is on hand for the badge anyway, make the phrase type-aware by counting selected tasks per format.

app.utkrusht.ai/position/backend-eng-2/share-mixed
1
Phase 1 · Test
Proctored MCQ test for the position's competencies
2
Phase 2 · Task
Before2 coding tasks After1 coding task + 1 system-design task
Cheapest acceptable fix is the neutral “2 task(s)”; the counted, type-aware phrase is better and nearly free.

ScaleHow this survives ten more task types

The format list is open-ended — prompts, UI/UX design, more coding variants are already on the horizon. The rule that keeps this from decaying into per-type switch statements: task types are open-ended, but the things the UI branches on stay a small closed set of capabilities. No recruiter surface ever branches on a type name. Every surface renders a display contract that every type — present or future — must fill. The candidate app already proves the pattern: SandboxLayout renders whatever interaction_surfaces.ports[] the backend returns, and new types cost zero frontend code there. This section applies the same philosophy to the recruiter side.

The display contract — what any task must be able to answer

FieldRecruiter question it answersSystem designPrompts (future)UI/UX design (future)
Format label + icon What kind of assessment is this? System Design · whiteboard Prompt Engineering · chat UI/UX Review · frame
“Candidate does…” line What will my candidate experience? Designs the architecture on an interactive whiteboard Writes and iterates prompts against a live model Critiques a seeded design file and proposes fixes
Deliverable What comes back to me? Architecture board + filled answer zones Final prompt set + model outputs Annotated frames + written rationale
Short problem statement + time Is the content right for my role? short_overview + time_for_task_mins — identical treatment for every type
Competencies + proficiency Does it measure the right skills? criterias — identical for every type; never the differentiator
Preview pointer Can I see what the candidate gets? excalidraw-scenestarter_scene document → prompt brief figma-link → seeded file

The closed capability sets — the only things UI code branches on

CapabilityValues todayWhat consumes it
preview_kind code-gist · excalidraw-scene · document · pr-diff · none The preview dialog picks a renderer. A new type reuses one; only a genuinely new modality needs a new renderer — an honest, unavoidable cost.
submission_kind git-push · zip-upload · board-scene · text Mixed-card phase phrasing, submission expectations, report entry point.
Workspace surface (candidate side, shipped) interaction_surfaces.ports[] SandboxLayout tabs — already fully data-driven; the precedent this model copies.

Where the contract lives

A task_formats registry — one row per task type: task_type, label, icon, “candidate does” copy, deliverable copy, preview_kind, submission_kind. Per-task specifics (the preview source, e.g. task_blob.starter_scene) stay on the task row. Launching a new type then means: one registry row + the generator filling the contract — zero recruiter-UI deploys, and copy stays consistent across every task of the type. A client-side config map is an acceptable v1 of the same idea (one file, one entry per type), upgraded to the table when type launches decouple from frontend releases. The registry is enforced at the pipeline: the DAO's validate-and-insert rejects a task whose type has no registry entry — growth stays safe because an undisplayable task cannot be stored.

Graceful-degradation rule. An unknown task_type must still render: title, competencies, time, problem statement, a neutral badge showing the humanized type name, and no preview button. The recruiter UI never crashes on — and never hides — a task whose type it hasn't heard of. This is what actually decouples UI releases from new-type launches.

Badge-rule expiry. “Badge only non-BUILD types” (Principle, above) is right at 2–3 formats and wrong at 5+. Trigger to revisit: once three or more formats carry real volume, badge everything — including “Coding” — and add a format facet next to the competency rails. The library's grouping stays competency-first; format becomes a secondary filter, never the primary hierarchy, because recruiters hire for skills, not formats.

Trade-offsWhat we show in the share box — and what we deliberately don't

ValueVerdictTrade-off
Format badge + stripShowOne per-type copy map (2–3 entries). Prevents “where's the starter code — is this broken?”
Problem statement, time, competencies, outcomesShow (unchanged)Identical treatment reinforces “same skills, different format”.
“View design board” button → read-only starter-board previewShowThe format's equivalent of “View starter code” — the starter board is exactly what the candidate sees at minute zero, so previewing it leaks nothing the candidate doesn't get anyway. Cost: the Excalidraw bundle — lazy-load it inside the dialog only.
Deliverable chips (board_spec answer-zone titles)SkipRedundant once the preview exists — the empty zones are visible on the board itself.
Reference answer, candidate submissions, hints, rubric detailNeverThe preview renders starter_scene only. The answer key lives in the top-level answer column and must never reach this dialog; submission review belongs to the task report.
Format filter/tab in libraryLaterCompetency rails stay primary; revisit when non-code formats have volume.

GotchasFix alongside, or the mocks above render wrong

Problem-statement fallback dumps the whole brief. transformTaskRow reads short_overview → falls back to full question (transform-task.ts:90-97), but the system-design generator writes task_overview into the blob instead. Until fixed, design tasks show the entire multi-paragraph brief as the “problem statement”. Preferred fix: write short_overview from the generator (system-design repo, payload.py) — one line, no UI change. Alternative: teach the transform to also read task_overview.

task_type is not copied into the session blob. build_task_session_task_blob (Utkrushta/flask_service/routes/v2/task_sessions.py:79-135) omits it, while FastAPI task_sessions.py:551 reads it from that per-entry blob. Candidate-side provisioning works today only because sessions.py:922 re-fetches the full task row. Copy it through for reliability before more type-branching lands.

Badge style must not look like a skill pill. Keep it squared + outlined + icon-led (see mocks). If it ships as another filled green pill, recruiters will read “System Design” as a competency — recreating the exact confusion this spec exists to remove.


Companion docs: the candidate-side whiteboard delivery is specified in system-design/page.html (Whiteboard System-Design Assessment — Design Doc); task storage shape in system-design/flows/non_tech/system_design/payload.py; recruiter report treatment TBD in a follow-up to docs/task-report-v2-frontend.html.

UTKRUSHT · RECRUITER UI SPEC · SYSTEM-DESIGN TASK DISPLAY · DRAFT 1 · JULY 2026