_private/qwestly-hire-docs/plan/job-creation-flow.md
Table of Contents
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. |
3a. Job link path (user said Yes)
| 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 |
Mermaid: detailed flow (job link vs exploratory)
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
Mermaid: Link path โ /jobs/new then navigate to /jobs/[id]/complete
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. Whenpost_analyze, holdjobId(and optionallyanalysisorjob) 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, storejobId(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 mirrorJobDetailsCardwith the analysis/job data).
3. Hooks and API usage
- useJobAnalysis (or equivalent): When
createDraftis true and the create step succeeds, returnjobId(and job/analysis) to the caller and do not perform navigation. The caller (e.g.CreateJobFormContaineror 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
jobIdand 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).
4. Complete pages (link vs exploratory)
/jobs/[id]/complete: Server: load job by id, enforce auth and โcan editโ. If the job hasexploratory_job_id, redirect to/jobs/[id]/exploratory/completeor 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]/reviewto redirect tocompletefor link-path jobs./jobs/[id]/exploratory/complete: Server: load job and exploratory job by id; enforce auth and โcan editโ; expectexploratory_job_idto 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.
6. Navigation and links
- 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/newand/jobs/new/exploratory: reuse the same auth and โuser has companyโ checks as today./jobs/[id]/completeand/jobs/[id]/exploratory/complete: enforce the same job access as the current review page (e.g.canEditJob, redirect to/unauthorizedif 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]/completefor the rest of the flow (confirm details, add anything else, generate summary, publish). - Exploratory โ separate route: Add
app/jobs/[id]/exploratory/complete/page.tsxfor 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.