All products

Onward — the owner who is leaving meets the one who is arriving.

onwardlegacy.com · in active development · small-business succession

Most small businesses never change hands. The owner is ready, the business is sound, and there is no mechanism — brokers work the top of the market, and below that line an owner is left asking a question nobody will answer for free: what is this actually worth?

Onward answers it first and asks who you are second. The estimator on the homepage runs without a sign-up, and the data model enforces that promise rather than merely honouring it: estimates are append-only, carry no identifying columns, and none may ever be added. Identity is a separate opt-in written in the same transaction as its consent record. Lead capture is switched off in configuration until there is a backend that can do both halves atomically.

Behind the estimate is the part brokers do: a readiness plan, a listing, buyer qualification, diligence, an LOI, encrypted document exchange, and the messages in between — both sides of the table, in one product.

The engineering decision I’d point at is the triage agent. It reads a Slack channel, investigates each report against the code, files a ticket and answers in thread. It began as a scheduled task inside my own session, holding my credentials, with “read-only” and its circuit breakers written as sentences in a Markdown file. Now every one of those limits is a line of code: a checkout it cannot push from, no shell and no file-writing tool at all, one channel, one project, tokens that are refused if they are broad enough to read a user profile. What the model still owns is judgment. The containment is what bounds the damage when judgment fails — and that is the lesson worth carrying into someone else’s organization.

Visit onwardlegacy.com
Onward’s homepage: “Legacies move forward” over the two entry points, one for an owner and one for a buyer
Onward — the public front door. Two doors, not one: the owner deciding whether to sell and the person who wants to run it are different products wearing one brand.
  • Two surfaces, one product A static marketing site carrying the valuation estimator and its API, and a Next.js 15 marketplace app on Auth.js and Drizzle behind it — separate deployments, one npm workspace, one backlog.
  • A valuation estimator that refuses to guess A three-layer taxonomy — buckets, sectors, hand-curated aliases — matched deterministically with no fuzzy fallback. An unmatched trade returns low confidence and says so; it never quietly lands in a default bucket, because a confident wrong multiple is worse than an honest shrug.
  • A data model that keeps the homepage’s promise The page offers an estimate without asking who you are, so estimates are an append-only table with no PII columns and none may ever be added. Identity is a separate opt-in, written in the same transaction as its consent row — channel, scope, timestamp, and the exact version of the consent language shown.
  • Documents encrypted before they leave the app Ciphertext in Vercel Blob, per-document keys wrapped in Neon under a versioned master key. Rotation rewraps every live key and never touches a blob; without the key the store refuses to work rather than falling back to plaintext.
  • The build refuses to ship without its secrets A preview or production build fails on a missing auth secret, mail key, document master key or blob store — and says what breaks without each, rather than deploying a site whose signed-in routes silently redirect.
  • A seeded demo cast, quarantined Personas confined to one demo domain that reset cleanly, plus a dev sign-in that writes a session row directly — and refuses to run against a production environment or any connection string resolving to the production host.
  • An autonomous triage agent, contained in code It sweeps a Slack channel, investigates each report against the codebase, files a Jira ticket and replies in thread. Every limit is a line of code rather than a sentence in a prompt: a read-only clone whose push URL is disabled, no shell and no file-writing tool at all, one channel and threads only, one Jira project, purpose-scoped tokens checked against a scope canary, and circuit breakers on tickets, turns, dollars and wall clock.
  • Identity verification and payments Stripe Identity on the accounts that need to be real, because the whole market rests on a stranger being who they say they are.
  • 552 tests Across 48 files, run on every branch against a real Postgres.

Register · Onward

Live from Jira, Confluence, GitHub and Vercel · updated 12:43 PM ET

github.com/productdetroit
Days building
30Since 29 August 2026, day one for Onward.
Work items delivered
101Stories and tasks closed Done in Jira, in production.
Median idea → live
17hoursMedian created → resolved, all issue types.
Spec → shipped
2hoursMedian epic lifetime: Confluence spec to production.
Specs written
54Problem, data model, architecture decision — before code.
Epics complete
1/23Done of created. The rest are sequenced, not stalled.
Pull requests merged
75
Production deploys
172
Lines of code
152,740
Reviewed by me
100%
Last shipped
Margaret gets an intro video in the demo (ONWARD-105) 3 days ago

Open to senior product roles in B2B enterprise SaaS.

Thirty years of judgment, now with no queue in front of it.

joe@productdetroit.com