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