Sales workflow · Case study
From scattered sales context to a proposal a client can safely open.
Agencies build proposals from calls, emails, pricing sheets and specialist reviews. GetPosals turns that scattered work into one lead-to-signature flow, without pretending that an AI draft or a generated link is trustworthy before the system proves it.
- Product
- Proposal Buddy at CodeBuddy
- Portfolio name
- GetPosals
- Role
- Design and engineering owner
- Timeline
- Feb to Aug 2026
- Users
- Agency sales and review teams
- Scope
- Product design, build direction, QA, deployment

- 01 / Trust stateThe persistent notice says this workspace is stored in the current browser and is not shared with teammates.
- 02 / Working setLeads, proposals, pipeline value and recent activity stay in the first scan.
Real local product capture · fictional workspace data · captured Aug 2026
The proposal problem
A proposal starts before anyone opens an editor. Requirements sit in calls and email. Pricing lives in a separate sheet. Finance, technical and compliance reviewers add decisions in other tools. When those inputs stay disconnected, the sales owner spends more time rebuilding context than shaping the deal.
The product brief asked for one path from lead capture to signed contract. The harder design problem was deciding where the system could accelerate judgement, and where it had to slow down and make responsibility visible.
Inputs arrive in fragments
Discovery notes, files, links and lead history need to become one usable brief before drafting begins.
Review is shared, accountability is not
Specialists can contribute, but one execution owner still needs to move the proposal forward.
A client link has to be real
A convincing success state is harmful when the proposal was not persisted or the client cannot open it.
The product had to compress the work without compressing the judgement around it.
How I framed it
I owned product design and engineering at CodeBuddy. I later renamed the work GetPosals for this portfolio. Where AI helped write code, I designed the behaviour, set the constraints, directed the build and verified the result.
- Start from a lead, never a blank contextEvery proposal stays attached to the company, contact, documents, value and ownership that produced it.
- Separate assisted and manual creationProGenie can structure discovery, while a blank route remains available for confidential or highly custom work.
- Treat generation as a draft, not approvalPricing, scope, internal review and client delivery remain explicit steps after content is produced.
- Make trust states literalThe interface must distinguish Gemini output, guided fallback, local storage and a genuinely persisted public link.
The product decisions
I did not organise the work as a parade of design phases. The useful story is in the choices that changed how the system behaves.
Make the lead the source of proposal context
A proposal cannot exist without a lead. Starting from lead detail carries company, contact, value and attached documents into either the AI-assisted route or a blank draft.
The tradeoff is more structure at the start. I kept it because it removes the more expensive work of reconnecting a proposal to its source later.

Keep AI assistance separate from blank creation
ProGenie collects discovery context through chat, files, pasted text, links and custom instructions. A separate blank path opens the editor without an AI conversation.
Combining both into one smart editor looked simpler, but it made confidential work and direct drafting feel like edge cases. Two explicit starts make the system's behaviour easier to predict.

- 01 / GroundingFiles, pasted notes and links keep source context visible beside the conversation.
- 02 / ProvenanceThe response state distinguishes Gemini output from the guided fallback.
Use one document model with two ways to navigate it
The editor keeps the same proposal sections and controls while letting the author switch between visual thumbnails and a compact list.
Thumbnails help with page shape. The list gives long proposals a faster scan. The content does not move to a different editor, so the user can switch views without losing context.


Make the collection a table by default
Proposal work is comparative. Status, owner, value, score and dates need to line up so a sales owner can scan across records without opening each one.
A card collection would give each proposal more personality, but it would hide the differences that matter in pipeline review. The shipped collection is table-only; the list and thumbnail toggle belongs to the editor.

The client handoff
The proposal is not finished when the editor looks complete. The decisive moment is the handoff: create a persisted share record, explain what the system did, and give the client a focused view that does not expose internal analytics or recipient history.




The production gap
On 10 August 2026 I audited the live site in a browser. The frontend looked finished, and the backend health endpoint worked on its own Worker. But the two were not connected on the production domain. The product's most important actions were failing at the seam.
Client links opened dead pages
Send appeared successful, while PDF export returned 405 and ProGenie silently fell back to scripted content.
I reproduced each path live
I compared browser network traffic, console output, production responses and the source that handled fallback behaviour.
The domain only served static assets
API requests hit the SPA fallback. GET returned HTML; POST and PUT returned 405. The healthy API Worker was never reached.
A route and a stricter trust policy
I restored the API source, bound the Worker route, removed fake offline links and labelled AI fallback honestly.
Source: live production audit, gap analysis and resolution record · 10 Aug 2026
Same-origin API reads returned the app shell. Writes stopped at the static asset handler.
The production domain reached D1, R2 and Gemini through the existing server-side Worker.
Source: same-origin health checks recorded before and after the Aug 2026 deployment
The fix changed the product's honesty
Routing fixed the connection, but it did not fix the product's promises. I also changed the rules around failure. A share link is shown only after persistence. Send confirms link creation, not email delivery. Deterministic fallback is labelled as a guided flow, never Gemini output. Browser-local workspace data is disclosed globally.
What changed
I do not have adoption, revenue or proposal-conversion data for this release. The honest outcome is a working product with a verified client-delivery path, plus clearer limits around what remains local to one browser.
Routing, fallback, proposal mapping and helper behaviour.
Gemini, PDF and internal comment paths after deployment.
Desktop at 1440 by 1000 and mobile at 390 by 844.
Source: testing-and-validation.md and gap-resolution-plan-2026-08-10.md · recorded 10 Aug 2026
What changed in my thinking
I used to treat a polished success state as the end of a flow. This product made the backend receipt part of the interface. If the system cannot prove that a link exists, the design should not congratulate the user.
Owning design and engineering also made tradeoffs harder to hide. A card layout can look calmer while making comparison worse. A single AI route can look simpler while making manual work feel broken. The implementation forced each choice to survive real data, failure and deployment.
The interface, all together
These are real captures from the GetPosals build. The collection has one table view. The separate thumbnail and list states shown here are navigation modes inside the proposal editor.












