<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Provieo]]></title><description><![CDATA[Provieo]]></description><link>https://provieo.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>Provieo</title><link>https://provieo.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 09 Sep 2026 01:35:49 GMT</lastBuildDate><atom:link href="https://provieo.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to Turn a Job Description Into a Project You Can Actually Build]]></title><description><![CDATA[Originally published at provieo.com.

💡 Quick Answer A job description is a list of nouns; a project is a list of verbs. Do not ask an AI to jump straight from posting to project idea — you will get ]]></description><link>https://provieo.hashnode.dev/how-to-turn-a-job-description-into-a-project-you-can-actually-build</link><guid isPermaLink="true">https://provieo.hashnode.dev/how-to-turn-a-job-description-into-a-project-you-can-actually-build</guid><category><![CDATA[Career]]></category><category><![CDATA[career advice]]></category><dc:creator><![CDATA[Howard Davner]]></dc:creator><pubDate>Sat, 05 Sep 2026 20:48:06 GMT</pubDate><content:encoded><![CDATA[<p><em>Originally published at <a href="https://www.provieo.com/blog/job-description-to-project-spec">provieo.com</a>.</em></p>
<blockquote>
<p>💡 <strong>Quick Answer</strong> A job description is a list of nouns; a project is a list of verbs. Do not ask an AI to jump straight from posting to project idea — you will get a generic dashboard suggestion that maps to nothing. Instead extract each requirement as a claim you must be able to demonstrate ("Can model relational data for a multi-tenant app"), tag each with the kind of proof it needs (code, deployment, writing, or measurement), then design one deliverable per requirement and check that nothing was dropped.</p>
</blockquote>
<p>Every student gets the same advice: build projects that match the jobs you want. Nobody explains the hard part. A job description is a list of <em>nouns</em> — Postgres, React, "experience with event-driven systems." A project is a list of <em>verbs</em>. Getting from one to the other is the actual work, and it is where most people either freeze or build another todo app and tell themselves it counts.</p>
<p>This is the method that survived contact with real postings — not the clean ones, the ones with three unrelated roles fused into a single req and a paragraph about being a rockstar.</p>
<h2>The Mistake: Asking for a Project</h2>
<p>The obvious move is to paste the posting into an AI tool and ask for project ideas. You get five bullets that sound plausible and mean nothing:</p>
<blockquote>
<p>Build a real-time dashboard using React and WebSockets.</p>
</blockquote>
<p>Match that against the posting and you cannot tell which requirement it satisfies, whether it is a weekend or a month of work, or what a reviewer would look for. The failure is structural, not a matter of prompt wording. You asked for the finished output in one hop while the posting was still unparsed, so the model produced a plausible average of every project it has ever seen.</p>
<p>Split it into two steps: extract first, design second.</p>
<h2>Step One: Extract Claims, Not Keywords</h2>
<p>Keyword extraction gives you <code>["React", "PostgreSQL", "AWS"]</code> — the same thing every resume scanner already does, and it tells you nothing about what to build. What you want is the <em>claim you have to be able to make</em>: the sentence a hiring manager needs to believe about you.</p>
<pre><code class="language-ts">type Requirement = {
  claim: string;          // "Can model relational data for a multi-tenant app"
  evidence_type: "code" | "deployment" | "writing" | "measurement";
  source_line: string;    // verbatim from the posting
  weight: "must" | "nice";
};
</code></pre>
<p>Two of those fields do the heavy lifting.</p>
<p><code>source_line</code> forces the extraction to point at text that actually exists in the posting. It cuts invented requirements sharply, and it means you can always answer "why is this in my project?" by pointing at the sentence.</p>
<p><code>evidence_type</code> is the field people skip, and the one that makes the result buildable. "Familiar with CI/CD" is not satisfied by code — it is satisfied by a deployment with a visible pipeline. "Communicates well with stakeholders" is satisfied by writing, not by another repo. Once every requirement carries the <em>kind of artifact</em> that proves it, project design stops being a guess.</p>
<h2>Step Two: The Extraction Prompt</h2>
<pre><code class="language-text">You are extracting verifiable requirements from a job posting.

For each requirement, output:
- claim: what the candidate must be able to demonstrate, phrased as
  "Can &lt;verb&gt; &lt;object&gt;". Never name a tool in the claim itself.
- evidence_type: code | deployment | writing | measurement
- source_line: the exact sentence from the posting. Copy it verbatim.
  If no single sentence supports the requirement, omit the requirement.
- weight: must | nice

Rules:
- Tools belong in a separate `stack` array, not in claims. "React" is not
  a skill; "Can build a UI that stays responsive while data streams in" is.
- Merge duplicates. Postings repeat themselves in the bullets and again
  in the "About you" section.
- Ignore compensation, EEO statements, and culture language entirely.
- Aim for 5-9 requirements. If you have more, you are splitting too finely.

Job posting:
"""
{posting}
"""
</code></pre>
<p>Three of those constraints earn their place:</p>
<p><strong>"Never name a tool in the claim itself."</strong> Without it, every claim collapses back to "Experience with React" and you are doing keyword extraction with extra steps. Forcing verb-object phrasing produces something you can build toward — and it survives the posting's tool list being different from the one you know.</p>
<p><strong>"If no single sentence supports the requirement, omit it."</strong> This is the anti-invention clamp. Models love adding Docker to anything that mentions a backend. Requiring a verbatim source line leaves an invented requirement nowhere to attach.</p>
<p><strong>"Ignore compensation, EEO statements, and culture language."</strong> Not for tidiness. Those sections are long and repetitive, and they drag the extraction toward soft-skill requirements no project can demonstrate. You end up with "Can collaborate cross-functionally" as a must-have and no way to build it.</p>
<h2>Step Three: One Artifact Per Requirement</h2>
<p>Now the design step has real input. The rule that matters: <strong>every must-have maps to exactly one artifact, and every artifact names its reviewer-visible proof.</strong></p>
<pre><code class="language-ts">type Artifact = {
  satisfies: string[];     // requirement claims, by exact text
  deliverable: string;     // "A /health endpoint with a documented SLO"
  proof: string;           // what a reviewer clicks to verify it
  est_hours: number;
};
</code></pre>
<p><code>proof</code> is the field that separates a project from a project <em>idea</em>. "Handles concurrent writes safely" is not proven by having written the code — it is proven by a test that fails without the transaction and passes with it, linked from the README. If a requirement cannot produce a proof, it does not belong in the build. It belongs in your cover letter.</p>
<p>And because coverage is mechanical, it is checkable:</p>
<pre><code class="language-ts">function uncovered(reqs: Requirement[], artifacts: Artifact[]): string[] {
  const covered = new Set(artifacts.flatMap((a) =&gt; a.satisfies));
  return reqs
    .filter((r) =&gt; r.weight === "must" &amp;&amp; !covered.has(r.claim))
    .map((r) =&gt; r.claim);
}
</code></pre>
<p>Run that every time. When it returns a non-empty array, you are holding a plan that quietly drops a hard requirement — the exact failure nobody catches by reading, because a plausible-looking plan reads fine.</p>
<h2>What Still Breaks</h2>
<p><strong>Fused postings.</strong> One req, three jobs: data engineer, ML engineer, and analyst. Extraction returns fifteen requirements and no coherent project. Decide which role you are actually applying for and re-run against that half of the posting.</p>
<p><strong>Seniority blindness.</strong> "Can design a service that degrades gracefully" is a legitimate extraction from a senior posting and a useless target for a student. The claim is right; the scope is wrong. Better extraction will not fix this — you have to supply your level as a separate input.</p>
<p><strong>Proof inflation.</strong> Ask for proof and you will get "comprehensive test suite demonstrating reliability." Constrain it to a single clickable thing: a file path, a URL, a specific test name.</p>
<h2>Why This Matters More Than the Project Itself</h2>
<p>The reason this method works in interviews is not that it produces impressive projects. It is that every decision in the build traces back to a line in the posting. When someone asks why you added a caching layer, you have an actual answer: because the posting said the service handles heavy read traffic, and here is the sentence.</p>
<p>That traceability is what a tutorial project can never give you, no matter how polished it looks.</p>
<hr />
<p>Provieo does this end to end — job description in, scoped project out, built and deployed to a live URL with the application package around it. <a href="https://www.provieo.com">Start free at provieo.com</a>.</p>
]]></content:encoded></item></channel></rss>