Hack Design Canvas
A one-page canvas that tells you, before anyone opens an editor, whether to build the workflow, buy it, run it by hand, or leave it alone.
- Works in
- Google Sheets · Notion · Zapier · Make · n8n
- Format
- one-page canvas
- Time
- 45–60 min
- For
- founders and RevOps leads about to greenlight an internal GTM build, whoever gets asked "can we just build this ourselves", anyone who has caught themselves scoping a tool on vibes
- Job
- decide whether to build it
Most internal GTM tools get built because someone was annoyed, not because anyone measured what the tool would have to beat. This canvas forces the measurement first. Fill every section before you open an editor — a section you can't fill honestly is telling you the build isn't ready, not that the canvas is too strict.
One tool per canvas. If you're scoping two workflows, run this twice.
A workflow with no named symptom is a hobby, not a build.
- Who feels this, as a seat, not "the team": ____
- What it costs them today, in their own words, quoted, not paraphrased: "____"
- How often: daily / weekly / monthly / event-driven
- If we build nothing at all, what happens in three months: ____
If nobody is named here, nobody runs it in six months.
- Who operates this after it ships — a name, not a role: ____
- What they're already doing instead, that this competes with for their attention: ____
- Hours a week they will actually give it, not the hours it deserves: ____
A seat is not an owner. A name is. If you can't write a name in the first line, stop here — the rest of the canvas will still work, but the build won't survive contact with week three.
The tool has to beat the manual version, not beat nothing.
Before you build anything, write down what happens today with no tool at all. That's the baseline every hour you spend building has to clear.
- The manual process today, in steps: ____
- Time it actually costs per week — measured on a real week, not estimated: ____ hrs
- The number this build has to move, and by how much, to be worth those hours: ____
If you can't measure the baseline, you can't measure whether the build worked. Pick a different metric before you pick a different tool.
Every write to a system outside this one needs an undo before it needs a trigger.
List every external system the tool will touch. For each write, write the exact reverse action before you build the forward one — if you can't write the reverse, you don't understand the forward yet. This is the same discipline behind sandbox-first, idempotent writes, snapshot-before-production: standard practice for anything that touches a CRM, a sheet someone else reads, or a channel someone else watches.
Composite. Not a real client's stack. A lead-routing build, illustrating the shape:
| System | The write | The undo |
|---|---|---|
| CRM | Set icp_score and lifecycle_stage on the contact |
Clear both fields; restore the prior stage from a pre-write snapshot |
| Sheet | Append a routed-lead row | Delete the row by its idempotency key, not by guessing which row |
| Slack | Post an alert to the sales channel | No true undo exists — post a retraction, log that it happened |
| Email tool | Enroll the contact in a sequence | Unenroll by contact ID; log it separately from a natural completion |
Your build:
| System | The write | The undo |
|---|---|---|
Take a snapshot of anything you're about to write to, before the first write runs. Without the snapshot, "undo" is a hope, not a plan.
The cheapest real test of this costs an afternoon, not a sprint.
Before any tooling, name the manual version that would tell you the same thing the finished build would — a human doing the tool's job by hand, once, for real.
- The fake version: ____
- What you'd watch, to know if it's worth automating: ____
- Who runs it, and by when: ____
Write the ending before you write the beginning.
Kill criteria, decided now, while there's no sunk cost yet to defend.
- Kill before building if: no name in section 2, no measured baseline in section 3, or the manual test in section 5 was never actually run.
- Kill mid-build if: one blocker — an API limit, a missing permission, bad source data — doubles the size of what you scoped.
- Kill after launch if: at 30 days the metric from section 3 hasn't moved, and the named owner isn't opening the tool weekly. Unused and flat is dead. It is not "still settling in."
Kill date, on the calendar now: ____
A build should score on more than one axis, or it isn't worth the hours.
- Presence — does this put you somewhere buyers already are?
- Pipeline — does this create, speed up, or protect revenue?
- Learning — does it produce evidence, in the buyer's own words, about who buys and why?
Zero boxes: don't build it. One box: fine, if the hours are genuinely small. Two or three: worth the hours.
Decide in writing, before anyone opens an editor.
| Option | Pick this when |
|---|---|
| Build it | A name exists in section 2, the baseline is measured, every write in section 4 has an undo, and at least one box is ticked above |
| Buy it | A tool already does this, and its monthly cost is less than the hours you'd spend maintaining a homemade copy |
| Do it manually | Volume is low enough that a human doing it by hand beats the time spent automating around it |
| Don't build it | No name, no baseline, or zero boxes ticked. Write the "don't" down — a documented no is worth more than a quiet build nobody asked for |
Decision: ____________ Date: ____________ Reviewed with: ____________
Sheet: tab canvas, one row per tool you considered.
The canvas is the thinking; the row is what survives it — including the ones that ended in "don't."
date,workflow,symptom_seat,owner_name,owner_hours_week,manual_hours_week,baseline_metric,target_move,writes_all_have_undo,fake_version_run,axes_ticked,decision,kill_date,reviewed_with
The lead-routing composite from the undo table above, as one row:
2026-09-06,lead routing,SDR lead,"(a name, not a role)",2,6,"hours/week routing by hand","6 → 1",yes,yes,2,build,2026-10-06,"(reviewer)"
decision ∈ {build, buy, manual, don't}. axes_ticked is the count from the
Presence / Pipeline / Learning boxes (0–3). A row with owner_name empty is a don't,
whatever the other columns say.