<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Michael Mitrakos</title>
    <description>The latest articles on DEV Community by Michael Mitrakos (@mike_mitrakos).</description>
    <link>https://dev.to/mike_mitrakos</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F248649%2F341ed79a-6e51-4da4-818e-e7caa047b5f2.jpg</url>
      <title>DEV Community: Michael Mitrakos</title>
      <link>https://dev.to/mike_mitrakos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mike_mitrakos"/>
    <language>en</language>
    <item>
      <title>How I stopped an LLM from lying on your resume (grounding, in practice)</title>
      <dc:creator>Michael Mitrakos</dc:creator>
      <pubDate>Sat, 11 Jul 2026 06:46:23 +0000</pubDate>
      <link>https://dev.to/mike_mitrakos/how-i-stopped-an-llm-from-lying-on-your-resume-grounding-in-practice-48dn</link>
      <guid>https://dev.to/mike_mitrakos/how-i-stopped-an-llm-from-lying-on-your-resume-grounding-in-practice-48dn</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Telling an LLM "only use real information" in a system prompt is not a safeguard — it's a suggestion the model will ignore the moment a keyword filter rewards ignoring it. If you need a hard guarantee that generated text only makes &lt;em&gt;sourceable&lt;/em&gt; claims, you have to build it outside the prompt: constrain generation to a fact store, then run a separate verification pass that rejects any claim it can't trace back to a source. Below is the pattern, with code.&lt;/p&gt;




&lt;p&gt;I've been building an AI agent that writes and submits job applications (&lt;a href="https://www.landearly.com" rel="noopener noreferrer"&gt;LandEarly&lt;/a&gt; — that's the context, not the point of this post). The single hardest requirement wasn't scraping job boards or automating Workday's form-from-hell. It was this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The system must never claim the candidate has experience they don't have.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sounds trivial. It is not. And the way most tools "solve" it — a stern line in the system prompt — is exactly why so many auto-apply tools produce resumes that fall apart in the first phone screen.&lt;/p&gt;

&lt;p&gt;Let me walk through why the easy version fails and what actually works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "just tell it not to" doesn't hold
&lt;/h2&gt;

&lt;p&gt;Here's the naive approach almost everyone starts with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;system&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
You are a resume writer. Tailor the candidate's resume to the job.
IMPORTANT: Only use real information. Never invent experience.
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem: the model has two instructions in tension. "Match this job" pulls toward inventing a Kubernetes bullet when the JD screams Kubernetes. "Don't invent" pulls the other way. Which one wins is non-deterministic, and it gets &lt;em&gt;worse&lt;/em&gt; under exactly the conditions you care about — a strong keyword match the candidate doesn't actually have is the most tempting thing for the model to fabricate.&lt;/p&gt;

&lt;p&gt;You cannot audit a vibe. If the guarantee lives only in the prompt, you have no guarantee.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Generation can only see facts, and every fact has an ID
&lt;/h2&gt;

&lt;p&gt;The first move is to stop feeding the model a blob of resume text and start feeding it a structured, addressable set of facts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The candidate's real history, as discrete sourceable units.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;factStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;exp_01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Built a React dashboard used by ~2k internal users at Acme&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;exp_02&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Migrated a REST API to GraphQL, cut payload size ~40%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;skill_01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TypeScript — 4 years, primary language&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now generation is constrained: the model must write each resume bullet &lt;strong&gt;from&lt;/strong&gt; a specific fact, and return the &lt;code&gt;id&lt;/code&gt; it used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;system&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
You tailor resumes. You may ONLY write bullets grounded in the FACTS provided.
For every bullet you output, return the exact id of the fact it is based on.
If no fact supports a requirement in the job description, DO NOT write a bullet
for it. Return JSON only:
{ "bullets": [{ "text": "...", "sourceId": "exp_01" }] }
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;callModel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;system&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;facts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;factStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jobDescription&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;bullets&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This alone changes the shape of the problem. We've gone from "trust the model" to "the model made a &lt;em&gt;claim&lt;/em&gt; about its sources that we can now check."&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Never trust the claimed source — verify it
&lt;/h2&gt;

&lt;p&gt;The model will sometimes cite &lt;code&gt;exp_01&lt;/code&gt; for a bullet &lt;code&gt;exp_01&lt;/code&gt; doesn't actually support. So the citation isn't the guarantee either. It's just a claim to be verified.&lt;/p&gt;

&lt;p&gt;Two layers here. First, a cheap structural check — does the cited id even exist?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;byId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;factStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;structurallyValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bullet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;byId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bullet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sourceId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the real check: does the source fact &lt;em&gt;entail&lt;/em&gt; the bullet? This is a separate, narrowly-scoped LLM call whose only job is entailment — no creativity, no tailoring, no incentive to please. Small model, temperature 0.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isEntailed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bullet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;byId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bullet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sourceId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
SOURCE FACT: "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"
CLAIM: "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;bullet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"
Does the SOURCE FACT fully support the CLAIM, with no added specifics
(numbers, tools, scope) that aren't in the source? Answer "yes" or "no".
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;callSmallModel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;yes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key insight: &lt;strong&gt;the verifier is a different job than the generator.&lt;/strong&gt; The generator is optimizing to match the JD, which is precisely the pressure that produces fabrication. The verifier has no knowledge of the job at all. It can't be tempted, because it doesn't know what the tempting answer would be.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Reject, don't repair
&lt;/h2&gt;

&lt;p&gt;The last piece is a policy decision, and it's the one people get wrong: when a bullet fails verification, you drop it. You don't ask the model to "fix" it, because "fix" quietly becomes "make it pass," which is fabrication with extra steps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;groundedBullets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;drafted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;draftBullets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;       &lt;span class="c1"&gt;// step 1&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;drafted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;structurallyValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;               &lt;span class="c1"&gt;// fake id → drop&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;isEntailed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;              &lt;span class="c1"&gt;// unsupported → drop&lt;/span&gt;
    &lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;byId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sourceId&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// every survivor is traceable to a real fact&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that leaves the resume thin against a role, that's not a bug to paper over — it's &lt;em&gt;signal&lt;/em&gt;. It means the candidate is a weak match for that requirement, and the honest product move is to surface that ("this role wants 5 years of Go; you have none") rather than fake it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part users actually see
&lt;/h2&gt;

&lt;p&gt;Because every surviving bullet carries its &lt;code&gt;source&lt;/code&gt;, the UI can show, next to each line, exactly which piece of the person's real history it came from. That turns "trust our AI" into "check our work" — the reviewer can see the receipts. It's also the single biggest trust feature we shipped, and it fell out of the architecture for free once grounding was in place.&lt;/p&gt;

&lt;h2&gt;
  
  
  What generalizes beyond resumes
&lt;/h2&gt;

&lt;p&gt;Strip out the domain and this is a reusable pattern for any LLM feature where being wrong is expensive:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Make the source material addressable.&lt;/strong&gt; Discrete units with IDs, not a text blob.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Force the generator to cite.&lt;/strong&gt; Output must reference which unit it used.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify with a separate, incentive-free pass.&lt;/strong&gt; The checker must not share the generator's goal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On failure, drop — never auto-repair.&lt;/strong&gt; Repair pressure is fabrication pressure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expose the sources to the user.&lt;/strong&gt; Traceability is a feature, not plumbing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's the same instinct behind good RAG, just pointed at &lt;em&gt;self&lt;/em&gt;-consistency instead of retrieval accuracy. And it's a lot more work than one line in a system prompt — but "don't make things up" is a requirement you either build for or you don't actually have.&lt;/p&gt;




&lt;p&gt;If you want to see the end result in the wild, it's what runs under &lt;a href="https://www.landearly.com" rel="noopener noreferrer"&gt;LandEarly&lt;/a&gt;. But mostly I wanted to write up the pattern, because there's shockingly little honest writing about the gap between "the prompt says don't hallucinate" and "the system provably doesn't."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How are you handling this in your own LLM features?&lt;/strong&gt; Especially curious how others approach the verifier step — separate model, same model with a fresh context, or something structured like constrained decoding. Tell me in the comments.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>webdev</category>
      <category>career</category>
    </item>
    <item>
      <title>Web Design Awards Has Rebranded — Built for Websites That Look Great and Perform Even Better</title>
      <dc:creator>Michael Mitrakos</dc:creator>
      <pubDate>Fri, 03 Jul 2026 07:30:16 +0000</pubDate>
      <link>https://dev.to/mike_mitrakos/web-design-awards-has-rebranded-built-for-websites-that-look-great-and-perform-even-better-5c0m</link>
      <guid>https://dev.to/mike_mitrakos/web-design-awards-has-rebranded-built-for-websites-that-look-great-and-perform-even-better-5c0m</guid>
      <description>&lt;p&gt;I’m excited to announce the rebrand of &lt;a href="https://www.webdesignawards.io" rel="noopener noreferrer"&gt;Web Design Awards&lt;/a&gt;, a platform built to recognize the websites, agencies, designers, developers, and brands pushing digital experiences forward. This rebrand is more than a visual refresh. It represents a clearer point of view on what great web design actually means today.&lt;/p&gt;

&lt;p&gt;TLDR: Check out the new site, and get a 25% DISCOUNT on your website nomination or any purchase using the code REBRAND — valid till the end of July.&lt;/p&gt;

&lt;p&gt;For a long time, web design recognition has been heavily focused on aesthetics. A beautiful homepage, an impressive animation, a striking color palette, or a clever interaction can capture attention quickly. Those things matter, and they always will. But a website is not just a visual artifact. A website is a business tool. It has a job to do, whether that job is generating leads, selling products, building trust, increasing signups, educating customers, or turning a visitor into a buyer.&lt;/p&gt;

&lt;p&gt;That is the idea behind the new Web Design Awards. We believe the best websites are not just beautiful. They are strategic, discoverable, fast, persuasive, technically sound, and built around the user. They combine strong design with strong execution. They look good, but more importantly, they work.&lt;/p&gt;

&lt;p&gt;The web has changed dramatically. Search is more competitive. AI is reshaping discovery. Users make trust decisions in seconds. Businesses expect their websites to contribute directly to growth. In this environment, great design cannot be separated from SEO, performance, accessibility, content strategy, user experience, and conversion optimization. A website that looks incredible but loads slowly, ranks poorly, confuses visitors, or hides the next step is only solving part of the problem.&lt;/p&gt;

&lt;p&gt;With this rebrand, Web Design Awards is expanding the standard for what deserves recognition. We want to showcase websites that balance creativity with commercial impact. That means celebrating visual design, but also the deeper work behind effective digital experiences: clear messaging, intuitive navigation, technical SEO, mobile performance, accessibility, conversion paths, content structure, and the small details that make a website feel effortless to use.&lt;/p&gt;

&lt;p&gt;This matters because recognition should create real value. For an agency, an award can help build credibility, strengthen proposals, support premium pricing, and give prospective clients another reason to trust the team behind the work. For a freelancer, it can become proof of quality and a way to stand out in a crowded market. For a startup or brand, it can signal polish, seriousness, and momentum. A strong feature is not just a badge to place in a footer. It is a credibility asset that can support sales, marketing, SEO, social proof, and brand authority.&lt;/p&gt;

&lt;p&gt;That SEO component is especially important to us. Great work deserves to be discoverable long after launch week. When a project is featured on Web Design Awards, it has the opportunity to become part of a larger ecosystem of search-visible, category-driven recognition. Buyers, founders, marketers, and creative teams are constantly researching agencies, websites, inspiration, and examples of effective digital execution. We want Web Design Awards to become one of the places they find that work.&lt;/p&gt;

&lt;p&gt;The conversion side is just as important. People rarely convert because of one isolated design element. They convert because enough trust has been built and enough friction has been removed. Awards, case studies, testimonials, press, client logos, performance, copy, and user experience all contribute to that decision. Our goal is to help strong websites earn recognition that can be used as leverage across the entire customer journey, from first impression to final proposal.&lt;/p&gt;

&lt;p&gt;The new Web Design Awards has been redesigned with that broader mission in mind. The brand is cleaner, sharper, and more focused. The platform is built to make great work easier to discover and easier to understand. As we continue to grow, we’ll be expanding categories, improving project pages, adding more editorial depth, and creating better ways to highlight the strategy, performance, and people behind exceptional websites.&lt;/p&gt;

&lt;p&gt;To celebrate the rebrand, we’re offering 25% off all products until the end of July. Use the code REBRAND at checkout to claim the discount.&lt;/p&gt;

&lt;p&gt;If you’ve recently launched a website that deserves recognition, this is the right time to submit it. We’re especially interested in projects that go beyond surface-level design and show what modern websites should be: beautiful, fast, search-friendly, conversion-focused, and built with a clear understanding of the user.&lt;/p&gt;

&lt;p&gt;The internet does not need another gallery of pretty screenshots. It needs stronger examples of websites that combine creativity with results. That is what we’re building with Web Design Awards: a platform for digital work that looks great, performs well, earns trust, and deserves to be found.&lt;/p&gt;

&lt;p&gt;Explore the rebrand and submit your work at webdesignawards.io. Until the end of July, use REBRAND for 25% off any purchase.&lt;/p&gt;

</description>
      <category>webdesign</category>
      <category>webawards</category>
      <category>designawards</category>
      <category>awards</category>
    </item>
  </channel>
</rss>
