Copy polish: remove jargon, add competitor contrast, fix empty state - #492
Copy polish: remove jargon, add competitor contrast, fix empty state#492manazoid4 wants to merge 7 commits into
Conversation
…st, fix empty state - FindJobsPage: Remove off-brand SVG from empty state; replace corporate alert copy with direct trade language; add Bark/Checkatrade contrast to upgrade nudge; fix scan-limit message from 'Buyer and submission context locked' to plain English; add 'No credit card required' to upgrade CTA; add 'NO SHARED AUCTION' micro-label - PricingPage: Change hero persona from '5-25-person contractors' to electricians/ plumbers/roofers/builders; rename 'FOUNDER-ASSISTED PILOT' label to 'FULL ACCESS — £39/MO'; add Checkatrade/Bark vs JobFilter answer to objections FAQ - DashboardPage: Replace 'PUBLIC-WORKS DECISION TRACKER' with 'YOUR JOB PIPELINE'; replace 'FTS' acronym in badge and quick-action CTA with plain English Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01THrG2vfrtJzJKWZ6zUTuUu
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01THrG2vfrtJzJKWZ6zUTuUu
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
|
✅ Meticulous spotted 0 visual differences across 169 screens tested: view results. Meticulous evaluated ~4 hours of user flows against your PR. Expected differences? Click here. Last updated for commit |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 57e144fd35
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| <p className="micro-label text-[var(--orange)]">SCAN REPORT</p> | ||
| <h2 className="headline mt-2 text-3xl leading-none sm:text-4xl">NO LIVE MATCHES. NO FAKE LEADS.</h2> | ||
| <p className="mt-2 text-sm font-black text-[var(--muted)]"> | ||
| Bark and Checkatrade sell you a lead whether it's real or not. Here, no match means there's genuinely nothing verified for your trade and area right now — check back tomorrow or widen the search. |
There was a problem hiding this comment.
Avoid certifying failed scans as genuinely empty
When any source adapter fails, the lead engine can still return ok: true, zero leads, and populate result.errors/failed source stats; complete 429 or 503 responses also reach this component with count === 0. The results renderer always shows EmptyScanReport for that count, so this new statement tells users there are genuinely no opportunities even while the page reports a failed or incomplete scan, potentially causing them to miss live work. Only make this claim after confirming all relevant sources succeeded, and use an incomplete-scan message otherwise.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in a13e97c. EmptyScanReport now checks result.errors.length > 0 before showing the competitor-contrast copy. When any source errors are present the component renders a neutral "No matches this scan — completed with errors on some sources" message instead of certifying the result as genuinely empty. The confident "NO LIVE MATCHES. NO FAKE LEADS." copy only shows when errors is empty (clean scan).
Generated by Claude Code
| <p className="font-black text-[var(--yellow)] text-sm uppercase tracking-wide">Get notified the moment new jobs come in</p> | ||
| <p className="mt-1 text-sm font-black text-white/80">New verified jobs for your trade and area — sent straight to you. No missed first-mover window. No credit card required.</p> |
There was a problem hiding this comment.
Do not promise immediate alerts without payment
For users following this empty-state offer, the advertised combination is unavailable: /api/alerts allows free users only the weekly frequency, while instant and daily alerts require a paid subscription. The pricing link can lead to paid immediate alerts, but then a card is required; the free no-card alert can take up to a week and cannot guarantee the stated first-mover window. Describe this as a weekly alert or remove the no-card/immediacy claims.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in a13e97c. Removed "No missed first-mover window" and "No credit card required" from the alert CTA. Copy now reads: "Get a weekly alert when new jobs come in" / "New verified jobs for your trade and area — delivered weekly. Upgrade for daily or instant alerts." This accurately reflects the free-tier frequency and surfaces the paid upgrade path without implying immediacy that requires payment.
Generated by Claude Code
| ? `3 free scans this week — no credit card required` | ||
| : `${weeklyScansRemaining} free scan${weeklyScansRemaining === 1 ? '' : 's'} left this week` | ||
| : 'Buyer and submission context locked. Scanning remains free.'} | ||
| : 'Free scans used up — upgrade to see who to call, the value, and the deadline on every lead.'} |
There was a problem hiding this comment.
Keep the exhausted-scan message consistent with enforcement
After the third successful scan, only this local banner changes: the scan form and presets remain enabled, submit() has no quota guard, and its request supplies no bearer token even though the server-side quota resolver only enforces limits for bearer-authenticated users. Consequently the same user can continue receiving successful scans while being told their free scans are used up. Either retain the previous wording that scanning remains free or enforce the quota in the actual submission path.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in a13e97c. Changed "Free scans used up" → "Buyer details locked" so the banner accurately describes what the quota gates (the locked detail fields) rather than implying scanning itself is blocked. The form and submit path are intentionally unchanged — enforcement lives server-side for authenticated users and the scan result still renders with locked fields for free users. The new wording is consistent with that behaviour.
Generated by Claude Code
… fix) nanoid was pinned to ^3.3.16 via postcss/next; bumped to >=3.3.18 to resolve GHSA-2v37-7h3g-55p8. Pre-existing on main — fixed here to unblock CI. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01THrG2vfrtJzJKWZ6zUTuUu
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01THrG2vfrtJzJKWZ6zUTuUu
- EmptyScanReport: competitor-contrast copy now guarded by result.errors check; shows neutral 'scan incomplete' message instead of certifying genuinely empty results when source adapters returned errors - Alert CTA: 'No missed first-mover window / No credit card required' removed; free tier is weekly-only, not instant; copy now says 'weekly alert' and surfaces paid upgrade path for daily/instant - Quota banner: 'Free scans used up' → 'Buyer details locked' to reflect that scanning continues and only the detail fields are enforcement-gated Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a13e97c8d9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| <Link className="jf-button mt-3 inline-block bg-[var(--yellow)] text-[var(--ink)] text-sm" href="/pricing"> | ||
| SET UP YOUR TRADE ALERT → |
There was a problem hiding this comment.
Send the alert CTA to an alert setup flow
Although the corrected copy now advertises a weekly alert, clicking this CTA after an empty scan still navigates to /pricing, which contains checkout controls but no alert setup action. The actual weekly-alert form lives on the dashboard, and AlertQuickSetup already posts the selected trade and postcode to /api/alerts; route or render this CTA through one of those flows so “SET UP” does not strand users on an unrelated sales page.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 526b039. Changed the button label from "SET UP YOUR TRADE ALERT →" to "UNLOCK ALERTS — £39/MO →" so it matches the /pricing destination and accurately signals a paid upgrade action rather than a free alert-setup flow. The link itself stays /pricing — a free alert setup widget in the empty state would require embedding AlertQuickSetup with auth state, which is out of scope for this PR.
Generated by Claude Code
| <p className="mt-2 text-sm font-black text-[var(--ink)]/70"> | ||
| Unlike Checkatrade or Bark, Gold leads show one buyer — your trade, your patch, your timing. Full Access adds the buyer name, published value, deadline and official response route. |
There was a problem hiding this comment.
Qualify the promise of a published value
For leads whose source does not publish a value, normalise() explicitly produces POA, and paid responses do not synthesize an exact value. The previous copy correctly said “published value where available,” but this replacement promises that Full Access adds a published value; users can therefore subscribe from this banner and still receive no value for the displayed Gold lead. Restore the availability qualification.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 526b039. Restored "where available" qualifier: "Full Access adds the buyer name, published value where available, deadline and official response route." Matches the behaviour of normalise() which returns POA when no value is published.
Generated by Claude Code
- Alert CTA in EmptyScanReport: rename 'SET UP YOUR TRADE ALERT' to 'UNLOCK ALERTS — £39/MO' so label matches the /pricing destination; no mismatch between setup language and a checkout page - Upgrade nudge: restore 'where available' qualifier on published value to match normalise() which returns POA when no value is published; Full Access does not synthesize a value for POA leads Co-Authored-By: Claude <noreply@anthropic.com>
Summary
Nightly build agent run — 2026-08-21. Build green, TypeScript clean, no new features required (all Tier 1 already built). Focus: copy polish on 3 pages + site health fixes.
FindJobsPage
PricingPage
DashboardPage
Phase 4 — Site Health
NEEDLE found: 3 issues — paywall jargon at scan limit, pricing page wrong persona, dashboard FTS acronym throughout.
BUILDER fixed: All 3 issues addressed.
CRITIC: All 3 changes read clearly in under 3 seconds. ✓
REVENUE: Yes — removing persona mismatch on pricing page and fixing the scan-limit message directly improves likelihood of paying £39/mo.
Generated by Claude Code