cd /news/artificial-intelligence/i-built-an-ai-proposal-writer-in-2-w… · home topics artificial-intelligence article
[ARTICLE · art-77100] src=dev.to ↗ pub= topic=artificial-intelligence verified=true sentiment=· neutral

I Built an AI Proposal Writer in 2 Weeks. Here's the Exact Prompt Architecture That Made It Work.

A freelance Next.js developer built ProposalAI, a tool that generates tailored Upwork proposals using a two-stage prompt architecture. Instead of a single large prompt, the system first extracts structured data from job posts, then generates proposals based on that data, producing more specific and effective output.

read2 min views1 publishedJul 28, 2026

I'm a freelance Next.js developer. Last month I built ProposalAI — a tool

that reads Upwork job posts and generates tailored proposals. Here's the

technical breakdown of what I learned.

The Problem With Existing AI Proposal Tools

Most tools on the market use a single large prompt:

"Write a proposal for this job post: [POST]. Skills: [SKILLS]. Make it professional."

Plain Text

The result? Generic garbage. It starts with "Hi, I'm interested," talks

about your skills, and ends with "I look forward to hearing from you."

90% of freelancers on Upwork write exactly this.

My First Attempt (And Why It Failed)

I started with the same single-prompt approach. The output was indistinguishable

from every other AI tool. I almost gave up until I had an insight:

The problem isn't the model. It's the prompt architecture.

The Solution: Two-Stage Prompting

Instead of one big prompt, I split it into two stages: Extraction and Generation.

Stage 1: Signal Extraction

const extractionPrompt = ` You are analyzing a freelance job posting. Extract ONLY these fields as JSON:

{ "client_company": "string | null", "specific_problem": "string - the exact pain point described", "desired_outcome": "string - what success looks like", "tone": "formal | casual | urgent", "budget_signal": "string | null - any rate mentioned" }

Job Post: ${jobPost} `;

Plain Text

This pass just pulls structured data. No generation. No creativity. Just facts.

**Stage 2: Proposal Generation**

typescript

const proposalPrompt = ` Write an Upwork proposal using this EXACT structure:

OPEN with: "${extracted.specific_problem || 'Your project sounds interesting'}"

Reference their SPECIFIC problem, not your skills

Do NOT start with "Hi" or "I read your post"

PROVE with one quantified result

Example format: "I helped a client [do X] which resulted in [Y]"

Keep it specific, not generic

MATCH their tone: ${extracted.tone}

END with a specific question about their current setup

Example: "Are you currently using [tool]?"

Keep total word count under 200

NEVER start sentences with "I am," "I have," or "I am a"

Client: ${extracted.client_company || 'not mentioned'} `;

Plain Text

Why This Works

The Tech Stack

What I'd Do Differently

Conclusion

The quality difference between a single-prompt tool and a two-stage extraction

If you're building something that needs to produce specific, tailored output

from unstructured input, the two-stage pattern is the single biggest lever

I found.

Check out the live tool at proposalai.top (free tier available).

── more in #artificial-intelligence 4 stories · sorted by recency
── more on @proposalai 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/i-built-an-ai-propos…] indexed:0 read:2min 2026-07-28 ·