Command Palette

Search for a command to run...

All Projects
In developmentPrincipal, Blueprint Marketing Solutions · Product lead

Support Stack Platform

Full product ownership for a contracted client, including reversing my own architecture recommendation.

Next.jsClerkLinear
Role
Principal, Blueprint Marketing Solutions · Product lead
Client
Impact Hub Houston
Timeline
June 2026 – Present
Team
Solo product and development, one AI subconsultant
Status
In developmentPhase 1 complete, pre-launch
Scope
  • Discovery and technical audit
  • PRD and six build specs
  • Scope and architecture decisions
  • Backlog ownership
  • Subconsultant integration contract
Stack
Next.js, AWS, SST, Lambda, Postgres, pgvector, Clerk, Airtable, Linear

The problem

Impact Hub Houston ran a mature operations base with 22 tables, three role-based interfaces, and an AI matching layer already wired in. It had produced zero production matches. The intelligence existed on paper and returned nothing the team could act on.

Three gaps compounded the matching failure. There was no scheduling capability for office hours. There was no volunteer system at all. And data hygiene was degrading, with duplicate person records accumulating across the base and no process to catch them.

The four-person admin team held the operation together by hand, brokering introductions manually for roughly 15 entrepreneurs and 24 supporters. The system built to help them was not the part they leaned on.

Why it mattered

Every match the team made by hand was time not spent on the work only they could do. The matching layer was supposed to remove that load. Instead it added a second surface to check that never returned anything usable.

I did not attach a frequency or a time-saved figure to this, because the team never tracked that cadence and any number would be invented. The honest version is plainer: a small team was doing by hand the exact task the platform was meant to automate.

How the work was won

I scoped the engagement around three pillars. Make the matching produce something actionable, add the missing scheduling and volunteer capabilities, and stop the data hygiene from decaying. The client signed a fixed-fee contract structured across four milestones.

The contract mattered later as more than a commercial document. It became the tie-breaker. When my design instincts and the signed scope disagreed, the contract governed, and I built that rule into how the product was documented.

Discovery

Discovery ran on two tracks at once. The first was interviews. I spoke with all four members of the admin team, the entire internal user base, not a sample. When you can talk to everyone who will touch the product, a representative sample is a downgrade.

The second track was a technical audit of the production base. I worked from documented read access and a single authorized test write, and mapped how the 22 tables, the interfaces, and the existing matching layer actually behaved rather than how the documentation claimed they behaved.

I drove both tracks with a structured set of open questions, so the working sessions produced comparable answers instead of four unrelated conversations.

What I found that I did not expect

The finding that reset the project: the team did not want the product I was planning to build them. They wanted to stay in Airtable.

They valued controlling their own automations and their own schema without a developer in the loop. A custom application would have taken that control away and made them dependent on me for every change. The most impressive architecture on paper was the wrong one for the people who had to live in it every day.

What I chose not to build

The discovery finding turned the scope question into a series of deletions. Most of what a proposal like this would normally include, I decided not to build.

Cut from scope, and why

No custom admin surface. The admins keep working in Airtable, the interface they already control, instead of a new screen that I would own and they would depend on me to change.

No data migration. The system mirrors the base rather than moving it, so the client never loses ownership of their own records.

No general-purpose two-way sync engine. Sync is field-level and one-way, with a single owner per field, which removes an entire category of conflict bugs I would otherwise be debugging for the life of the contract.

The contracted out-of-scope items stay out. I held a build-versus-buy option on sync, with a commercial tool as a documented fallback if the hand-built path proved too costly, rather than committing to either up front.

Multi-chapter reuse is built into the architecture but not over-invested in, because further chapters are contractually gated and speculative work against a gate is waste.

Defining the product

I split the documentation into two layers. A product requirements document carries the why and the what across twelve sections. Six build specs carry the how. The split keeps intent stable while implementation detail changes underneath it.

One rule sits above both. Where any document conflicts with the signed contract, the contract wins. Every pillar in the PRD maps to a specific clause in the statement of work, so scope disputes resolve by reference rather than by opinion.

Each spec follows the same nine-part shape and closes with acceptance criteria written as behavior. A criterion states an input and the observable result it must produce, so a feature is testable rather than merely present. 'The feature exists' is not a criterion. 'Given this input, the system returns this' is.

Execution

The build plan lives in Linear, roughly 55 issues across four phase projects plus one cross-cutting project for the AI work. I restructured the workspace so the phases map one to one to the contract milestones, which lets me show the client the board as the delivery plan without translating it first.

Every issue carries two axes of labels. A phase view for sequencing, and a pillar view for scope. The same board answers what is next and which part of the contract this serves, without a second tracker.

Working with the subconsultant

The matching intelligence is computed by an AI subconsultant, a third-party service. I drew a hard ownership boundary. My application owns the data and the workflow, the subconsultant only computes. That boundary settled every integration question that followed.

I handed the subconsultant a spec written as a proposed API contract, with exact endpoints, payload shapes, authentication, and idempotency behavior, stamped for their confirmation rather than assumed. Where the interface was ambiguous, I tracked the ambiguities as a single numbered open-questions issue with one owner, instead of letting them scatter across messages.

I designed the integration to survive that service failing. Requests queue with a dead-letter path, retries back off exponentially, and if the service stays down the system degrades to raw vector similarity so matching still returns a ranked result rather than nothing.

The hard calls

Three decisions were contested, and one was simply wrong.

Custom application versus keeping everything in Airtable. The contract allowed a custom build unless it bottlenecked the client. Discovery showed the bottleneck was the custom build itself, so the exception turned out to be the rule, and the hybrid won.

AWS versus the contract's reference stack. I chose AWS and logged the deviation explicitly in the PRD with a cost flag, so the client could see the tradeoff rather than find it in an invoice.

The client's vocabulary versus the contract's. I adopted the words the team already used for their own operation, even where the contract used different terms, because a product people describe in their own language is a product they will actually adopt.

Then the reversal. My initial recommendation argued for a single unified custom application and reasoned explicitly against a hybrid. Discovery proved that recommendation wrong. I reversed it, and the hybrid, the architecture I had argued against, became the defining shape of the project.

Success criteria and current status

Success is defined at two levels. Each phase closes on written client sign-off at a gate, and each feature carries behavioral acceptance criteria that either pass or do not. Underneath both sits a non-functional bar: TDPSA compliance, encryption, a database on a private subnet, and accounts owned by the client rather than by me.

Phase 1 is complete at 12 of 14 issues. The two that remain are external blockers, not build work. The platform is pre-launch. It has produced no operational results yet, and I claim none.

What I would do differently

The reversal is the lesson. I wrote an architecture recommendation before testing its core assumption against the people who would use it. The fix is an ordering fix. Test the assumption against users first, then write the recommendation.

Artifacts

  • PRD excerpt

    Redacted, available on request

    Available on request
  • Build spec with acceptance criteria section

    Redacted, available on request

    Available on request
  • Linear board, phase and pillar structure

    Redacted, available on request

    Available on request
  • Architecture diagram

    Available on request

    Available on request