_private/qwestly-hire-docs/plan/job-creation-flow.md

Job creation & matching: user journey (proposed)

This document describes the proposed end-to-end user journey from signup to sharing a job for matching, with a single guiding question to reduce decision fatigue, clearer naming, and a dedicated path for exploratory jobs.


Design principles

  • One question first: "Do you have a job link?" โ€” branch once, then guide along a predefined path.
  • Safety: Draft by default; confirm before publishing. Clear "what happens next" at each step.
  • Efficiency: Prefer URL โ†’ analyze; offer paste as primary alternative and as fallback when URL fails.
  • Dedicated exploratory path: Separate route and flow for "I don't have a role yet" so the experience is tailored and the codebase is easier to reason about.

High-level journey (signup โ†’ sharing a job)

flowchart TB subgraph create["Create job"] H["Create job" CTA] H --> I["/jobs/new"] I --> J{"Do you have a job link?"} J -->|Yes| K["Job link path"] J -->|No| L["Exploratory path"] end subgraph link_path["Job link path (has JD)"] K --> M[Enter URL with option to paste JD] M --> N[Analyze] N --> O{URL OK?} O -->|No| P[Fallback: paste JD โ†’ Analyze] O -->|Yes| STAY P --> STAY["Stay on /jobs/new โ€” draft created"] STAY --> SHOW["Show analysis results on same page"] SHOW --> PROCEED["Proceed / Continue"] PROCEED --> COMPLETE["Navigate to /jobs/[id]/complete"] COMPLETE --> SUB1["Step 1: Confirm details"] SUB1 --> SUB2["Step 2: Anything else? + Generate summary"] SUB2 --> SUB3["Step 3: Show summary; Step 4: Publish inline"] SUB3 --> SUCCESS["Job is live โ€” redirect to dashboard / job"] end subgraph exploratory_path["Exploratory path (no JD) โ€” separate route"] L --> V["/jobs/new/exploratory"] V --> W[Enter role type] W --> SPEECH["Speech text input on same page"] SPEECH --> X[Create draft] X --> Y["Redirect to /jobs/[id]/exploratory/complete"] Y --> E1["Step 1: Confirm role"] E1 --> E2["Step 2: Anything else? / ingest JD"] E2 --> E3["Step 3: Matching summary"] E3 --> E4["Step 4: Publish"] E4 --> SUCCESS end SUCCESS --> MATCH[Job active โ†’ matching] classDef authFill fill:#e3f2fd,stroke:#1976d2,color:#000 classDef createFill fill:#f3e5f5,stroke:#7b1fa2,color:#000 classDef linkFill fill:#e8f5e9,stroke:#2e7d32,color:#000 classDef completeFill fill:#fff3e0,stroke:#e65100,color:#000 classDef exploratoryFill fill:#e1f5fe,stroke:#0277bd,color:#000 classDef successFill fill:#c8e6c9,stroke:#1b5e20,color:#000 class A,B,C,D,E,F,G authFill class H,I,J,K createFill class M,N,O,P,STAY,SHOW linkFill class PROCEED,COMPLETE completeFill class SUB1,SUB2,SUB3 linkFill class L,V,W,SPEECH,X,Y,E1,E2,E3,E4 exploratoryFill class SUCCESS,MATCH successFill

Step-by-step (proposed)

1. Auth & onboarding

Step Route / action Notes
Land / or /signup Unauthenticated โ†’ signup/login.
Signup complete /signup/complete Sync user; if no companies โ†’ company selection.
Select company /companies/new Only when user has no company. After select โ†’ dashboard or jobs/new.
Dashboard / (dashboard) List jobs; "Create job" โ†’ /jobs/new.

2. Create job โ€” single entry, one question

Step Route Notes
Create job /jobs/new Only content: one question: "Do you have a job link?" with two actions: Yes (continue on this page) / No (go to exploratory). No accordion; no three-way choice.
Step Route / action Notes
Input /jobs/new Primary: URL input. Secondary: "Or paste job description" (e.g. tab or link). Single flow: URL first, paste as alternative or fallback.
Analyze /jobs/new Call analyze-url or analyze-text; backend creates job draft. Do not navigate away.
Show results /jobs/new (same page) Show analysis results on same page (like review shows summary): job details card. User reviews and clicks Proceed / Continue.
Complete flow /jobs/[id]/complete Navigate to complete page. Step 1: Confirm details; Step 2: Anything else?; Step 3: Generate matching summary; Step 4: Publish inline. Redirect to dashboard or job after publish.

3b. Exploratory path (user said No)

Step Route Notes
Start exploratory /jobs/new/exploratory Dedicated page. Enter role type.
Speech input /jobs/new/exploratory (same page) Speech text input right after role type (add context via voice/text before creating draft).
Create draft โ€” Submit โ†’ create exploratory job + linked job draft โ†’ redirect to /jobs/[id]/exploratory/complete (separate route).
Complete your role /jobs/[id]/exploratory/complete Separate route from link path. Confirm role, anything else? / ingest JD, generate summary, publish.
Summary & publish /jobs/[id]/exploratory/complete Generate summary, edit if needed, publish; then "Job is live" + CTA.

Route summary (proposed)

Purpose Current Proposed
New job entry /jobs/new (accordion: link / paste / exploratory) /jobs/new โ€” one question: "Do you have a job link?" โ†’ Yes (stay) / No โ†’ /jobs/new/exploratory
Exploratory start (accordion option on /jobs/new) /jobs/new/exploratory โ€” role type + speech text input, then create draft
After analyze (has JD) /jobs/[id]/review Stay on /jobs/new โ€” show analysis results; user clicks Proceed โ†’ navigate to /jobs/[id]/complete for rest of flow (add context, generate summary, publish)
After exploratory create /jobs/[id]/review /jobs/[id]/exploratory/complete โ€” dedicated route for exploratory only

flowchart LR subgraph entry["/jobs/new"] Q1["Do you have a job link?"] Q1 -->|Yes| URL Q1 -->|No| EX["Go to /jobs/new/exploratory"] end subgraph url_flow["Job link flow"] URL[URL input + paste option] URL --> Analyze[Analyze] Analyze --> Stay["Stay on /jobs/new โ€” show analysis results"] Stay --> Results["View analysis results on same page"] Results --> Proceed["Proceed / Continue"] Proceed --> Complete["Navigate to /jobs/[id]/complete"] Complete --> Same["Confirm + add more + generate summary + publish"] Same --> Done["Job is live โ€” redirect"] end subgraph exploratory_flow["Exploratory flow"] EX --> Role[Role type on /jobs/new/exploratory] Role --> Speech["Speech text input on same page"] Speech --> CreateDraft[Create draft] CreateDraft --> ExploratoryComplete["/jobs/[id]/exploratory/complete"] ExploratoryComplete --> E1["1. Confirm role"] E1 --> E2["2. Anything else? / ingest JD"] E2 --> E3["3. Generate matching summary"] E3 --> E4["4. Publish inline"] E4 --> Done end classDef linkNode fill:#e8f5e9,stroke:#2e7d32,color:#000 classDef completeNode fill:#fff3e0,stroke:#e65100,color:#000 classDef exploratoryNode fill:#e1f5fe,stroke:#0277bd,color:#000 class URL,Analyze,Stay,Results linkNode class Proceed,Complete completeNode class EX,Role,Speech,CreateDraft,ExploratoryComplete,E1,E2,E3,E4 exploratoryNode

After Analyze, user stays on /jobs/new and sees analysis results. When they proceed, navigate to /jobs/[id]/complete for the rest of the flow (add context, generate summary, publish).

flowchart TB subgraph phase1["Phase 1: /jobs/new"] L1["Enter URL or paste JD โ†’ Click Analyze"] L2["Backend: create job draft; return analysis"] L3["Stay on /jobs/new โ€” show analysis results"] L4["Job details card: title, description, specs, responsibilities, must-haves"] L5["User reviews and clicks Proceed / Continue"] L1 --> L2 --> L3 --> L4 --> L5 end subgraph phase2["Phase 2: /jobs/[id]/complete"] C1["Navigate to /jobs/[id]/complete"] C2["Step 1: Confirm details; Edit if needed"] C3["Step 2: Anything else? โ€” HM additional info"] C4["Step 3: Generate matching summary โ†’ show summary"] C5["Step 4: Publish inline โ†’ Job is live"] C1 --> C2 --> C3 --> C4 --> C5 end L5 --> C1 classDef newPage fill:#e8f5e9,stroke:#2e7d32,color:#000 classDef completePage fill:#fff3e0,stroke:#e65100,color:#000 class L1,L2,L3,L4,L5 newPage class C1,C2,C3,C4,C5 completePage

Mermaid: Exploratory path โ€” /jobs/new/exploratory then /jobs/[id]/exploratory/complete

Exploratory uses a different route. On /jobs/new/exploratory: role type then speech text input on the same page; after creating draft, redirect to /jobs/[id]/exploratory/complete.

flowchart TB subgraph exploratory_new["/jobs/new/exploratory"] direction TB E0["User chose No job link"] E1["Enter role type"] E2["Speech text input on same page"] E3["Create draft โ†’ redirect"] E0 --> E1 --> E2 --> E3 end subgraph exploratory_complete["/jobs/[id]/exploratory/complete โ€” separate route"] direction TB H["Complete your role"] subgraph step1["Step 1: Confirm role"] S1A["Role details card: role type, overview, qualifications"] S1B["Edit button"] end subgraph step2["Step 2: Anything else? / Ingest JD"] S2A["HM additional info; optional Have a JD? โ€” ingest URL/paste"] end subgraph step3["Step 3: Matching summary"] S3A["Generate matching summary โ†’ show summary; Edit / Regenerate"] end subgraph step4["Step 4: Publish"] S4A["Checkbox + Publish & start matching"] end subgraph success["After publish"] SUCC["Job is live โ€” CTA to dashboard / matches"] end H --> step1 --> step2 --> step3 --> step4 --> success end E3 --> exploratory_complete classDef exploratoryNewFill fill:#e1f5fe,stroke:#0277bd,color:#000 classDef exploratoryCompleteFill fill:#fff3e0,stroke:#e65100,color:#000 class E0,E1,E2,E3 exploratoryNewFill class H,S1A,S2A,S3A,S4A,SUCC exploratoryCompleteFill

Mermaid: Post-analyze to live โ€” Link path (sequence)

User stays on /jobs/new after Analyze and sees analysis results. When they click Proceed, we navigate to /jobs/[id]/complete; the rest of the flow (add context, generate summary, publish) happens on the complete page.

sequenceDiagram participant U as User participant New as /jobs/new participant Complete as /jobs/[id]/complete participant API as API rect rgb(232, 245, 233) Note over U,API: Phase 1 โ€” /jobs/new U->>New: Enter URL or paste JD U->>New: Click Analyze New->>API: analyze-url or analyze-text API->>API: Create job draft API->>New: jobId + analysis Note over New: Stay on /jobs/new โ€” do not redirect yet New->>U: Show analysis results on same page U->>New: Review results, click Proceed / Continue end New->>Complete: Navigate to /jobs/[id]/complete rect rgb(255, 243, 224) Note over U,API: Phase 2 โ€” /jobs/[id]/complete loop On complete page U->>Complete: Step 1: Confirm details (Edit if needed) U->>Complete: Step 2: Add anything else (optional) U->>Complete: Step 3: Click Generate matching summary Complete->>API: generate-matching-summary API->>Complete: summary content Complete->>U: Show summary; Edit / Regenerate U->>Complete: Step 4: Check consent, Publish & start matching Complete->>API: PATCH job status = active API->>Complete: success end end Complete->>U: Job is live โ€” redirect to dashboard or job

Mermaid: Exploratory path (sequence)

Role type + speech input on /jobs/new/exploratory; then redirect to /jobs/[id]/exploratory/complete.

sequenceDiagram participant U as User participant ExploratoryNew as /jobs/new/exploratory participant API as API participant ExploratoryComplete as /jobs/[id]/exploratory/complete rect rgb(225, 245, 254) Note over U,API: /jobs/new/exploratory U->>ExploratoryNew: Enter role type ExploratoryNew->>U: Show speech text input on same page U->>ExploratoryNew: Add context via voice/text U->>ExploratoryNew: Submit (create draft) ExploratoryNew->>API: Create exploratory job + job draft API->>ExploratoryNew: jobId ExploratoryNew->>ExploratoryComplete: Redirect to exploratory/complete end rect rgb(255, 243, 224) Note over U,API: /jobs/[id]/exploratory/complete loop On complete page U->>ExploratoryComplete: Step 1: Confirm role (Edit if needed) U->>ExploratoryComplete: Step 2: Anything else? / optional ingest JD U->>ExploratoryComplete: Step 3: Generate matching summary ExploratoryComplete->>API: generate-matching-summary API->>ExploratoryComplete: summary content U->>ExploratoryComplete: Step 4: Publish & start matching ExploratoryComplete->>API: PATCH job status = active end end ExploratoryComplete->>U: Job is live โ€” CTA to dashboard/matches

Architectural changes (summary)

To implement the flow in the diagram above, the following architectural changes are needed.

1. Routes (App Router)

Change Detail
/jobs/new Same route; behavior and UI change. No longer an accordion (link / paste / exploratory). Render a single question first; then either link input + analyze + results view, or redirect to exploratory.
/jobs/new/exploratory New route. Add app/jobs/new/exploratory/page.tsx (and client component). Content: role type input + speech text input; submit creates exploratory job + job draft, then redirect to /jobs/[id]/exploratory/complete.
/jobs/[id]/complete New or renamed route. Add app/jobs/[id]/complete/page.tsx (or rename existing review โ†’ complete). Used only for the link path after the user clicks Proceed on jobs/new. Load job by id (expect non-exploratory); render 4-step flow (confirm, add more, generate summary, publish).
/jobs/[id]/exploratory/complete New route. Add app/jobs/[id]/exploratory/complete/page.tsx. Used only for the exploratory path after draft creation. Load job + exploratory job by id (expect exploratory_job_id); render 4-step exploratory flow.

2. /jobs/new page and client behavior

  • State: Introduce a clear โ€œmodeโ€ or step: question | link_input | post_analyze. When post_analyze, hold jobId (and optionally analysis or job) so the same page can render the analysis results and a โ€œProceedโ€ CTA without a full reload.
  • Analyze flow: Keep calling the same analyze + create-draft API (e.g. analyze-url or analyze-text, then POST jobs with analysis). On success, do not call router.push(/jobs/[id]/review). Instead, store jobId (and the job/analysis payload) in state and switch the view to โ€œanalysis resultsโ€ (job details card + โ€œProceedโ€).
  • Proceed: Single CTA that runs router.push(/jobs/[jobId]/complete).
  • UI: Replace the current accordion with: (1) one question + โ€œYesโ€ / โ€œNoโ€; (2) if Yes, URL (and paste fallback) + Analyze; (3) if No, router.push('/jobs/new/exploratory'); (4) after analyze, render results using the same kind of layout as the current review page (e.g. reuse or mirror JobDetailsCard with the analysis/job data).

3. Hooks and API usage

  • useJobAnalysis (or equivalent): When createDraft is true and the create step succeeds, return jobId (and job/analysis) to the caller and do not perform navigation. The caller (e.g. CreateJobFormContainer or jobs/new client) is responsible for updating state and rendering the โ€œanalysis resultsโ€ view; it also handles โ€œProceedโ€ โ†’ navigate to /jobs/[id]/complete.
  • APIs: No change to analyze-url / analyze-text or job-creation payloads; they already return the data needed. Optional: ensure the job-creation response includes jobId and enough job/analysis data for the results view so the client does not have to refetch before showing results (or allow a refetch by jobId if preferred).
  • /jobs/[id]/complete: Server: load job by id, enforce auth and โ€œcan editโ€. If the job has exploratory_job_id, redirect to /jobs/[id]/exploratory/complete or show an error so this route is link-path only. Client: 4-step flow (confirm details, add anything else, generate summary, publish). Can be implemented by reusing or copying the non-exploratory branch of the current review client (e.g. client-wrapper.tsx), and optionally deprecating or narrowing the current /jobs/[id]/review to redirect to complete for link-path jobs.
  • /jobs/[id]/exploratory/complete: Server: load job and exploratory job by id; enforce auth and โ€œcan editโ€; expect exploratory_job_id to be set. Client: 4-step exploratory flow (confirm role, anything else / ingest JD, generate summary, publish). Implement by reusing or moving the exploratory branch of the current review client into this route.

5. Shared components and duplication

  • Reuse existing components where possible: JobDetailsCard, JobAdditionalInfoInput, generate-summary and publish logic, bottom sheet or inline publish. The main split is where they render: jobs/new (results view only), /jobs/[id]/complete (link path), /jobs/[id]/exploratory/complete (exploratory path). Avoid three separate implementations by extracting shared โ€œcompleteโ€ steps into components or a shared layout used by both complete routes.
  • Dashboard and any โ€œCreate jobโ€ CTA: keep linking to /jobs/new.
  • After creating an exploratory draft: redirect to /jobs/[id]/exploratory/complete (not review).
  • After the user clicks Proceed on jobs/new (link path): navigate to /jobs/[id]/complete.
  • Any existing links to /jobs/[id]/review (e.g. from jobs list, edit page) need a rule: for exploratory jobs, link to /jobs/[id]/exploratory/complete; for non-exploratory, link to /jobs/[id]/complete (or keep review as an alias that redirects based on job type).

7. Auth and permissions

  • /jobs/new and /jobs/new/exploratory: reuse the same auth and โ€œuser has companyโ€ checks as today.
  • /jobs/[id]/complete and /jobs/[id]/exploratory/complete: enforce the same job access as the current review page (e.g. canEditJob, redirect to /unauthorized if not allowed).

Implementation notes

  • Link path โ€” show results on jobs/new, then navigate to complete: After analyze-url/analyze-text completes, create job draft and stay on /jobs/new; show analysis results (job details card). When user clicks Proceed / Continue, navigate to /jobs/[id]/complete for the rest of the flow (confirm details, add anything else, generate summary, publish).
  • Exploratory โ€” separate route: Add app/jobs/[id]/exploratory/complete/page.tsx for the exploratory complete-your-role flow. After creating draft from /jobs/new/exploratory, redirect to /jobs/[id]/exploratory/complete (not a shared complete route).
  • Exploratory on jobs/new: On /jobs/new/exploratory, show role type input then speech text input on the same page (so user can add context via voice before creating draft); on submit, create draft and redirect to /jobs/[id]/exploratory/complete.
  • jobs/new redesign: Replace accordion with a single screen: headline, "Do you have a job link?", primary "Yes" (stay, show URL + paste), secondary "No" โ†’ router.push('/jobs/new/exploratory').
  • URL-first with paste fallback: On "Yes", show URL input first; below or as tab, "Or paste job description". If analyze-url fails, suggest pasting JD and use analyze-text.

This file is the source of truth for the proposed journey; update it when the flow or routes change.