Build Careerflow
YESreplaces $23.99/mosaves $287.88/yrback to the verdict
A local job search workspace whose hard problems are keeping a tailored document traceable to approved evidence, treating imported document text as an approximate suggestion rather than fact, and reporting requirement coverage instead of inventing a score.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Runs the application and the document rendering.
Get it nodejs.org, or nvm install 22. open ↗
Verify
node --version prints v22 or higher - have readyfree
Why Coverage and extraction are only meaningful against a description you might actually apply to, and a seeded example will pass every test that matters.
Get it Your current CV as a PDF, and two descriptions saved as text or PDF.
Verify
Both import, and the requirements list needs only small edits - have readyfree
Why The column interleaving warning is the one extraction behaviour most likely to be missed, and it needs a document that actually has the problem.
Get it Any CV or leaflet laid out in two columns, saved as a PDF and kept in the fixtures.
Verify
Extraction of it raises the interleaving warning with a page number - installfree
Why Documents are rendered from structured data, so the renderer is a dependency rather than a browser print dialogue.
Get it Any maintained library that renders from structured content and can be run headless.
Verify
It renders a fixture document whose text extracts back in the right order - API keypennies per document
Why Only for rephrasing approved text, and the tool is designed to stay useful when it is absent.
Get it Create a key in your provider's console and put it in .env, or leave it unset.
Verify
With it unset, everything except rephrasing still works
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- evidence(id, kind, title, organisation, start_date, end_date, body, metrics_json, source_note, approved_at) · nothing is usable until it is approved - imports(id, kind, filename, extracted_text, warnings_json, approved_at) · an import is a draft until a person confirms it line by line - roles(id, company, title, description_text, source_url, imported_at) · the job, kept as text you can quote from - requirements(role_id, ordinal, text, kind) · extracted from the description and editable, because the extraction is a suggestion - coverage(role_id, requirement_ordinal, evidence_id, strength, note) · no rows means not covered, which is a perfectly good answer - variants(id, role_id, name, created_at) and variant_items(variant_id, ordinal, evidence_id, rendered_text) · every rendered line points at one evidence row - applications(id, role_id, variant_id, stage, applied_at, next_action_at, outcome, notes) · contacts and activity hang off this row
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
DATABASE_PATH | required | ./data/career.db | Evidence, roles, variants and applications. |
DOCUMENTS_DIR | required | ./data/documents | Rendered CVs and letters. Deleted with their application. |
BIND_ADDRESS | required | 127.0.0.1 | Loopback. This folder holds your salary history and your rejections. |
USER_TIMEZONE | required | Europe/London | The due view depends on it, and follow ups are the point of the tracker. |
EXPORT_DIR | required | ./exports | JSON and CSV exports, which are how you leave. |
MODEL_MODE | required | rephrase-only | The only permitted mode. There is no generate mode to switch to. |
OPENAI_API_KEYsecret | optional | sk-...redacted | Optional. Unset disables rephrasing and nothing else. |
The build, in order
An evidence bank you actually wrote
Every fact about your career exists once, dated, with a note on where it came from.
Unapproved rows are invisible to every document query.
Files
src/evidence.tstests/approval-gate.test.tsOne sentence about how you know it, which is also what you will say in the interview.
Files
src/db/schema.tsThe same job entered twice produces two truths.
Files
src/evidence/dedupe.ts
done when · tick each as it passeswatch out- Letting a resume import become evidence directly means every later document is tailored from an approximate parse of your own history, complete with a metric that was mangled and a date that slipped, and you will not notice because it looks like something you wrote. Imports land as drafts and become evidence only when a person approves each row.
Extracted text is a suggestion
Nothing imported becomes data until a person has seen what came out.
Two panes, and the failure becomes obvious in a second.
Files
src/imports/review.tsxDetect short alternating fragments and say which page.
Files
src/imports/extract.tstests/two-column.test.tsSo a bad import can be understood later rather than repeated.
Files
src/imports/approve.ts
done when · tick each as it passeswatch out- Text pulled out of a PDF arrives in the order the document's structure gives, not the order the eye follows: the W3C technique on PDF reading order notes that if a two column document is not properly tagged a reader goes straight across both columns and treats them as one, so an untagged two column CV extracts as interleaved half sentences that look like a typing error rather than a parsing failure. Show the extraction for approval and mark the pages where the order looks wrong.
Coverage, not a score
A role shows which requirements you can evidence and which you cannot.
Extraction proposes; the person applying decides.
Files
src/requirements.tsStrength is a judgement, recorded as one.
Files
src/coverage.tsThere is no function that does it, not a setting that hides it.
Files
src/coverage.tstests/no-score.test.ts
done when · tick each as it passeswatch out- A single match percentage is the number everybody wants and the one thing here that cannot be honest, because it implies knowledge of a process you cannot observe and it hides which specific requirement has nothing behind it. Show the three states per requirement with the evidence attached, and leave the summarising to the person applying.
A document assembled from approved rows
Every rendered line traces to an evidence row and adds nothing to it.
A token level comparison against the source row catches the common cases.
Files
src/rephrase/guard.tstests/no-invention.test.tsThe person approves the change, not the idea of the change.
Files
src/rephrase/review.tsxSo what you send is what the data says, in an order you chose.
Files
src/render/document.ts
done when · tick each as it passeswatch out- A model asked to make a bullet sound stronger will quietly add 'by 40 percent' because that is what strong bullets look like, and the invented figure then gets defended in an interview by somebody who believes they wrote it. Compare the rephrasing against the source row, block any new number, date or proper noun, and show the difference before saving.
The tracker, the export and the day you stopproduct builder
Follow ups happen, everything leaves in an open format, and it all runs without a model.
Not a note, because notes are not queryable and do not nag.
Files
src/applications.tsThe model is an improvement, never a dependency.
Files
src/model/optional.tsRendered CVs on disk outlive the row that explains them.
Files
src/delete.tstests/delete-documents.test.ts
done when · tick each as it passeswatch out- A tracker where the follow up lives in a free text note means the follow up does not happen, and the whole reason to keep a tracker was the fortnight between an interview and the silence. Make the next action date a column with a due view, and make an application without one visible as an omission.
That is the whole plan for Careerflow. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- Mass applying.
- Live interview assistance.
- Any screening score or rejection probability.
- Proprietary recruiter and salary databases.
- browser tooling, templates, coaching content, AI workflows, and hosted sync
- proprietary recruiter data
- job-board distribution
- human coaching
- automated application networks
- Interview question practice with your own answers stored against evidence rows, reviewed by you rather than scored
- A second document type, such as a covering letter, assembled by the same evidence rules
- A record of which variants led to interviews, which is the only signal here worth collecting
Need the files? The project pack on the verdict page hands your agent the whole brief · more career.