Tell people which controls spend money before they press them - #29
Merged
Conversation
This app is careful about not spending WITHOUT a click -- `useMeteredQuery`
disables mount/focus/reconnect refetching so a restored page cannot fire a
paid request. This closes the other half: six controls that DO spend and
did not say so.
Look up · up to 1 paid request
Run · 4 paid requests
Build brief · up to 4 paid requests
Fetch reviews · 1 paid request
Update keyword stats · uses credits
Analyze <domain> · may use credits (+ "If not cached: est. $0.85.")
One `meteredActionLabel` helper rather than six hand-written suffixes,
because the wording encodes two facts that are easy to get wrong
independently.
**How much.** A count of upstream requests where that is knowable, a
MEASURED dollar figure where one exists, otherwise just "uses credits".
Never an invented number -- `shared/analysis-costs.ts` already says why:
showing a guessed price immediately before spending someone's money is
worse than showing none. The brand estimate reuses that file's constants
and its markup rule rather than hardcoding the figure Codex quoted.
**Whether it might cost nothing.** Most of these read a server cache first,
so a second press inside the window spends zero. Saying "1 paid request"
there would be a lie in the expensive-sounding direction, which teaches
people to distrust the labels that are accurate. Hence "up to" / "may", and
hence the brand price sitting beside the button as a conditional rather
than on it as a promise.
Counts were verified against the fan-out, not assumed: Prompt Explorer
dedupes models before spending (`new Set(...)`), Local SEO caches a
successful profile for 12h, the brief caches for 7 days over a 6h SERP
read.
Two things NOT changed, on Codex's recommendation and after checking:
* Small rank checks stay as they are. The header already shows a per-check
estimate, and the <50-keyword threshold deliberately avoids modal fatigue.
* No new blocking confirmations. The app reserves those for 50+ keyword
checks and batch analysis; these six are deliberate submits, so an inline
label is proportionate. A modal in front of a cheap cached click trains
people to dismiss modals.
A caught mistake worth recording: knip passed while `meteredEstimateNote`
was exported, tested, and rendered NOWHERE -- the test import satisfied the
unused-export check. A green gate was hiding the fact that the price never
reached a user. It is rendered now, and browser-verified showing
"If not cached: est. $0.85."
Browser-verified: four of the six labels render correctly. Fetch reviews
and Update keyword stats need a business profile and rank data respectively.
7 new tests, 2,129 passing, ci:check clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
flyrocketseo | 3576e7e | Jul 31 2026, 06:45 AM |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This app is careful about not spending without a click —
useMeteredQuerydisables mount/focus/reconnect refetching so a restored page can't fire a paid
request. This closes the other half: six controls that do spend and didn't
say so.
One helper, not six suffixes
The wording encodes two facts that are easy to get wrong independently.
How much. A count of upstream requests where that's knowable, a measured
dollar figure where one exists, otherwise just "uses credits". Never an invented
number —
shared/analysis-costs.tsalready says why: showing a guessed priceimmediately before spending someone's money is worse than showing none. The
brand estimate reuses that file's constants and its markup rule rather than
hardcoding a figure.
Whether it might cost nothing. Most of these read a server cache first, so a
second press inside the window spends zero. Saying "1 paid request" there would
be a lie in the expensive-sounding direction — which teaches people to distrust
the labels that are accurate. Hence "up to" / "may", and hence the brand price
sitting beside the button as a conditional rather than on it as a promise.
Counts were verified against the actual fan-out, not assumed: Prompt Explorer
dedupes models before spending (
new Set(...)), Local SEO caches a successfulprofile for 12h, the brief caches 7 days over a 6h SERP read.
Two things deliberately unchanged
estimate, and the <50-keyword threshold deliberately avoids modal fatigue.
checks and batch analysis. These six are deliberate submits, so an inline label
is proportionate — a modal in front of a cheap, cached click trains people to
dismiss modals.
Both came from the Codex audit, which correctly refuted one of its own
earlier items once it read
RankTrackingDetailHeader.A caught mistake worth recording
knippassed whilemeteredEstimateNotewas exported, tested, and renderednowhere — the test's import satisfied the unused-export check. A green gate
was hiding the fact that the price never reached a user. It's rendered now, and
browser-verified showing
If not cached: est. $0.85.Verification
Browser-verified: four of the six labels render correctly (Local SEO, Prompt
Explorer, Content brief, Brand analyze). Fetch reviews and Update keyword
stats need a business profile and rank data respectively.
7 new tests, 2,129 passing,
pnpm ci:checkclean.🤖 Generated with Claude Code