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

> Source: <https://dev.to/yan_yan_096c6a71b7657ec65/i-built-an-ai-proposal-writer-in-2-weeks-heres-the-exact-prompt-architecture-that-made-it-286k>
> Published: 2026-07-28 14:18:50+00:00

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**

``` js
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).
