logicsrc/prd/0002-hourly-hire-us-rate.md
Anthony Ettinger eaf0a6162b
feat(web): move Hire Us pricing to $400/hour metered billing (PRD 0002) (#102)
* feat(web): move Hire Us pricing to $400/hour metered billing (PRD 0002)

Replaces the $250/week retainer with a $400/hour rate billed against actual
hours, invoiced through CoinPay after the client approves them. A 10-hour
minimum engagement replaces the week as the unit of commitment.

The weekly price lived in 12 places, not the 3 the PRD listed: the front-page
Hire Us section, the Top-Level Pages list, /hire-us metadata, /pricing
(metadata, two FAQ answers, rate bullet), /about, llms.txt, skill.md, and the
Hire Us form success message.

Metered billing rather than a committed weekly block, because the old
"recurring CoinPay invoice" copy documented a mechanic that never existed:
/api/payments/create makes a single one-shot payment, not a subscription.

- coinpay-checkout derives amount_usd from hours x 400 instead of a hardcoded
  250, validates hours as quarter-hour increments at or above the minimum, and
  returns 422 before calling CoinPay on bad input. Payment metadata carries
  billing/hours/rate_usd_per_hour in place of interval.
- project-request returns a rate, billing mode, and minimum; no amount exists
  until hours are approved.
- CoinPay config block documents COINPAY_RATE_USD_PER_HOUR / COINPAY_BILLING /
  COINPAY_MINIMUM_HOURS instead of a weekly amount and interval.
- New real /terms route replacing the SPA stub: what is billable, the
  approve-then-invoice flow, the minimum, cancellation on one week's notice,
  and an explicit clause that existing engagements keep their terms until both
  sides agree in writing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(mcp): advance prd_next_id expectation to 0003 for PRD 0002

The standards test asserts prd_next_id against the live prd/ directory, so
adding prd/0002-hourly-hire-us-rate.md moves the next free id to 0003. This
assertion advances with every PRD added to the repo.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 10:34:49 -07:00

7.7 KiB
Raw Permalink Blame History

openprd id title status authors created updated repo implementation tags
0.2 0002 Move Hire Us pricing from a weekly retainer to an hourly rate Accepted
anthony@profullstack.com
2026-07-28 2026-07-28 https://github.com/profullstack/logicsrc apps/logicsrc-web
pricing
site
billing

Problem

The Hire Us surface on logicsrc.com prices standards work at $250/week, paid through a recurring CoinPay invoice after project acceptance. That number reads as a token retainer rather than a rate for senior open-spec implementation work — schemas, CLIs, SDKs, MCP resources, and provider-neutral plugin surfaces. It anchors every inbound conversation at a price that cannot cover the work, and it selects for clients who are shopping on price rather than on the standard.

The replacement is $400/hour. This is not a bump to an existing hourly number; it is a change of pricing model, which touches page copy, the payment configuration, and the invoicing mechanics that currently assume a fixed weekly amount.

Goals

  • Every public price on logicsrc.com states one rate, in one unit, with no stale $250/week copy left behind on any surface.
  • Inbound Hire Us inquiries arrive already anchored to a senior rate, so the pricing conversation is about scope rather than about the number.
  • Billing can actually execute the new model: an accepted project produces a correct invoice without manual repair.
  • The change is reversible and auditable — the reasoning survives in the repo, not in a Slack thread.

Non-Goals

  • Repricing the standard itself. LogicSRC schemas, specs, and reference implementations stay open and free; this covers implementation services only.
  • Building time tracking. Hourly billing needs hours captured, but that is an operational process for now, not a product to build.
  • Replacing CoinPay or adding a second payment provider.
  • Publishing a rate card with tiers, discounts, or role-based pricing. One rate, one line.
  • Migrating anyone currently engaged at $250/week. Handled case by case, not by this PRD.

Users

  • Prospective clients evaluating whether to hire Profullstack for LogicSRC work — mostly founders and engineering leads arriving from the spec pages, who read the price before they read anything else.
  • Profullstack, as the party quoting, invoicing, and collecting.
  • Existing clients on the weekly plan, who must not be silently repriced.

Decisions

Two questions blocked this PRD at drafting time. Both were resolved before implementation:

  • The rate is $400/hour, confirmed deliberately. Against $250/week this is roughly a 64x change at a 40-hour week. The magnitude is the point: the weekly figure was a token retainer, not a rate, and the new number is intended to filter out engagements too small to scope.
  • Billing is metered against actual hours, not a committed weekly block. This matches how the code already works — /api/payments/create creates a single one-shot payment, never a recurring subscription, so the previous "recurring invoice" copy documented a mechanic that did not exist. Metered billing also avoids the committed-block failure mode, which is a weekly rate wearing an hourly label. A 10-hour minimum engagement replaces the week as the unit of commitment.

Requirements

  • R1 [P0] The Hire Us section heading states the new rate and unit, replacing "$250/week for accepted LogicSRC work".
  • R2 [P0] The price display block shows $400 with the unit "per hour".
  • R3 [P0] The /hire-us entry in the Top-Level Pages list is updated; it repeated the weekly figure independently of the section above it.
  • R4 [P0] The /hire-us page body and its meta description are updated.
  • R5 [P0] The CoinPay configuration block reflects the new model. COINPAY_AMOUNT_USD=250 and COINPAY_INTERVAL=week are both wrong under hourly pricing and are replaced by a rate, a billing mode, and a minimum rather than renumbered.
  • R6 [P0] A repo-wide search for 250, per week, and /week returns no remaining pricing references before the change is considered done.
  • R7 [P1] The site states what an hour is billed against — metered actual hours, invoiced after the client approves them — so the invoice mechanic is legible before a client asks.
  • R8 [P1] Minimum engagement and cancellation terms are stated, since removing the weekly cadence also removes the implicit unit of commitment.
  • R9 [P2] Terms of engagement are documented at /terms rather than only in marketing copy.

Surfaces the original draft did not list, but which carried the weekly price and were therefore in scope for R6: /pricing (metadata, two FAQ answers, and the rate bullet), /about, llms.txt, skill.md, the Hire Us form's success message, and both the contract and e2e tests.

UX Notes

The price appears in several places across the front page, /pricing, /about, and the machine-readable surfaces; they are separate strings and will drift if edited one at a time. Treat the set as one change.

The CoinPay block is rendered as example configuration, so it reads as documentation of how billing actually works. A weekly interval next to an hourly rate is worse than a stale price — it looks like the system does not do what the copy says.

The stated rate sits next to what it buys. The existing four capability cards (workflow specs, reference implementations, integration hardening, open infrastructure) already do that work and are unchanged.

Implementation Notes

  • src/lib/page-markup.ts — section heading, price row, a new .price-terms line carrying the minimum and cancellation summary, the CoinPay config block, and the Top-Level Pages entries for both Hire Us and Terms.
  • src/app/api/hire-us/coinpay-checkout/route.ts — the amount is now derived as hours × $400 rather than hardcoded. Hours are validated as quarter-hour increments at or above the 10-hour minimum, defaulting to the minimum when omitted; invalid hours return 422 before any call to CoinPay. Payment metadata carries billing, hours, and rate_usd_per_hour in place of interval.
  • src/app/api/hire-us/project-request/route.ts — returns a rate, billing mode, and minimum instead of a fixed amount_usd/interval pair, since no amount exists until hours are approved.
  • src/app/terms/page.tsx — new real route, replacing the /terms stub that rendered the homepage SPA. The stub's entry was removed from the catch-all's ROUTE_META.

Success Metrics

  • Zero occurrences of the weekly price across the site and repo after the change, verified by grep rather than by reading.
  • First accepted project under the new model invoices correctly on the first attempt, with no manual adjustment to the CoinPay invoice.
  • Inbound inquiries that reach a scoping conversation do not open by disputing the rate.
  • No existing engagement is repriced without explicit agreement.

Risks & Open Questions

  • Hours are not currently tracked. Metered billing won, and there is no capture mechanism. /terms now defines what is billable (project work, meetings, and written communication in quarter-hour increments; not scoping calls, invoicing, or warranty fixes), so the definition is settled even though the tooling is not. Capturing hours is an operational process until it is worth building.
  • Client mix will change. An hourly rate at this level filters out the small experimental engagements the weekly price attracted. This is the intent, recorded here as a decision rather than left to be discovered.
  • Existing weekly clients keep their terms until both sides agree in writing to move, per /terms. Whether any active weekly engagements exist is still unknown.
  • Author attribution is assumed from the CoinPay org configuration and should be corrected if wrong.