All modules
Module 24 · business · intermediate
Proposal Generator
After this module you can turn a two-minute discovery form into a priced, on-brand proposal page the client can accept online, in under a minute.
What it does
The demo business is Brightline Studio (a small web agency). The service catalog (services, tiers, prices, weeks, deliverables) and pricing rules live in Settings.
| Entry | What happens |
|---|---|
Discovery Form (/form/proposal-intake, separate workflow) or POST /webhook/prop/create |
Validate the intake, pick the best tier of each requested service that fits the budget (bundle discount for 3+ services, tax, deposit, 14-day validity), flag over-budget, no-budget and timeline problems. OpenAI writes summary, understanding, approach and next steps (template if AI fails); guardrails replace any price that isn't in the quote and flag promises like "guaranteed". Builds a hosted proposal page with a private link and emails it with Gmail |
GET /webhook/prop/view?id=…&t=… |
The proposal page (token required). Counts views; shows an expiry or accepted banner |
POST /webhook/prop/accept |
The page's accept form (typed name + checkbox). Records who accepted and emails the owner; 409 if already accepted, 410 if expired |
GET /webhook/prop/status?id=… or ?email=… |
Status, views, flags, quote (no HTML or token) |
Create options: dry_run (returns the page HTML, saves nothing), send_email: false, ai: false, sections (supply your own text, still checked), now (inject the clock).
Flow
learner-form.json: Discovery Form → To API Body → Create Proposal (HTTP POST prop/create)
Create API ─┐
View API ───┤
Accept API ─┼→ Settings → Route ─create→ Build Quote → Valid Intake? → Use AI? ─yes→ Write Sections (OpenAI) ─┐
Status API ─┘ │ └no─────────────────────────────────────┴→ Join Branches → Assemble Proposal
│ → Dry Run? → Email It? → Email Proposal (Gmail) → Record Sent → respond
├view→ Render Proposal → HTML page
├accept→ Accept Proposal → Accepted? → Notify Owner (Gmail) → thank-you page | error page
└status→ Proposal Status → respond
Verification status (n8n 2.43.6)
- 29 behavior checks (55 assertions) without credentials: tier selection against the budget, bundle discount, over-budget/no-budget/timeline flags, service names from form checkboxes, validation, template fallback when AI fails, price and promise guardrails, HTML escaping, private link and token, view counting (preview excluded), accept validation, double accept (409), expiry banner and 410,
send_email: false, Gmail failure reported, and a real n8n Form submission creating a proposal. - Not run with OpenAI or Gmail credentials (
WITH_CREDS=1 TEST_EMAIL=… ./test/test.sh). AI section quality and real email delivery are unverified.
Files
| File | Tier | Purpose |
|---|---|---|
| lesson.md | Free | Step-by-step build |
| workflow/starter.json | Free | Endpoints, Settings, quote builder |
| workflow/learner.json | Learner | Finished workflow |
| workflow/learner-form.json | Learner | Discovery form workflow |
| workflow/code/ | Learner | Readable copies of the Code nodes + AI prompt |
| exercises.md | Learner | Practice tasks |
| solutions.md | Learner | Exercise solutions |
| notes.md | Private | Learning log |
| sell/ | Private | Offer, video script, blog post |