← back to Govarbitrage
Deploy approved TK-11249 pricing copy; local source e69a5ea
e3141d057a5817e38ff9a0399eb622240d078aa4 · 2026-09-11 15:36:10 +0000 · Steve Abrams
Files touched
M src/app/pricing/UpgradeButton.tsxM src/app/pricing/page.tsxM src/lib/tiers.ts
Diff
commit e3141d057a5817e38ff9a0399eb622240d078aa4
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Sep 11 15:36:10 2026 +0000
Deploy approved TK-11249 pricing copy; local source e69a5ea
---
src/app/pricing/UpgradeButton.tsx | 2 +-
src/app/pricing/page.tsx | 60 ++++++++++++---------------------------
src/lib/tiers.ts | 30 +++++++++-----------
3 files changed, 33 insertions(+), 59 deletions(-)
diff --git a/src/app/pricing/UpgradeButton.tsx b/src/app/pricing/UpgradeButton.tsx
index fa7231d..f0bee81 100644
--- a/src/app/pricing/UpgradeButton.tsx
+++ b/src/app/pricing/UpgradeButton.tsx
@@ -48,7 +48,7 @@ export default function UpgradeButton({
opacity: loading ? 0.6 : 1,
}}
>
- {loading ? "Redirecting…" : `Upgrade to ${label}`}
+ {loading ? "Redirecting…" : `Try ${label} (test)`}
</button>
{err && <div style={{ color: "#b91c1c", fontSize: 12, marginTop: 6 }}>{err}</div>}
</div>
diff --git a/src/app/pricing/page.tsx b/src/app/pricing/page.tsx
index 62008dd..d849558 100644
--- a/src/app/pricing/page.tsx
+++ b/src/app/pricing/page.tsx
@@ -1,7 +1,6 @@
import type { Metadata } from "next";
import { TIERS, TIER_ORDER } from "@/lib/tiers";
import { getCurrentTier } from "@/lib/current-user";
-import { STRIPE_MODE } from "@/lib/billing";
import UpgradeButton from "./UpgradeButton";
export const dynamic = "force-dynamic";
@@ -9,12 +8,12 @@ export const dynamic = "force-dynamic";
export const metadata: Metadata = {
title: "Pricing",
description:
- "GovArbitrage plans: Free (delayed deals), Standard ($12/mo — real-time + hot-deal alerts), and Premium ($29/mo — unlimited, confidence bands, priority alerts). Cancel anytime.",
+ "Explore GovArbitrage beta access and preview plans. Current listings and full money-math analysis are available on every plan. Checkout uses test or simulated payments.",
alternates: { canonical: "/pricing" },
openGraph: {
title: "Pricing — GovArbitrage",
description:
- "GovArbitrage plans: Free (delayed deals), Standard ($12/mo — real-time + hot-deal alerts), and Premium ($29/mo — unlimited, confidence bands, priority alerts). Cancel anytime.",
+ "Explore GovArbitrage beta access and preview plans. Current listings and full money-math analysis are available on every plan. Checkout uses test or simulated payments.",
url: "/pricing",
type: "website",
},
@@ -22,27 +21,9 @@ export const metadata: Metadata = {
const pricingJsonLd = {
"@context": "https://schema.org",
- "@type": "ItemList",
- name: "GovArbitrage Pricing Plans",
- itemListElement: TIER_ORDER.map((key, idx) => {
- const t = TIERS[key];
- return {
- "@type": "ListItem",
- position: idx + 1,
- item: {
- "@type": "Offer",
- name: t.label,
- description: t.blurb,
- price: t.priceUsd.toString(),
- priceCurrency: "USD",
- eligibleDuration: {
- "@type": "QuantitativeValue",
- value: 1,
- unitCode: "MON",
- },
- },
- };
- }),
+ "@type": "WebPage",
+ name: "GovArbitrage beta access and preview plans",
+ description: metadata.description,
};
export default async function PricingPage() {
@@ -55,40 +36,35 @@ export default async function PricingPage() {
dangerouslySetInnerHTML={{ __html: JSON.stringify(pricingJsonLd) }}
/>
<div className="text-center space-y-2">
- <h1 className="text-3xl font-semibold tracking-tight">Find the deals before everyone else</h1>
+ <h1 className="text-3xl font-semibold tracking-tight">Explore government-surplus deals</h1>
<p className="text-base text-muted-foreground">
- 8 government-surplus auction networks, de-duped and scored — with honest,
- confidence-labeled max-bid math. Cancel anytime.
+ Browse current auction listings and full money-math analysis. Paid-plan
+ features and prices are previews during beta.
+ </p>
+ <p className="rounded-lg bg-warning/20 text-foreground text-sm px-4 py-3" data-testid="beta-notice">
+ Beta access: listing freshness, source access, and money-math analysis are
+ currently available on every plan. Daily newsletter access depends on
+ confirmed subscription, not plan. Checkout uses test or simulated payments;
+ no real charge is made.
</p>
- {STRIPE_MODE !== "test" && (
- <span className="inline-block bg-warning/20 text-warning text-xs px-3 py-1 rounded-full font-medium">
- TEST MODE — no real charges (checkout is simulated)
- </span>
- )}
</div>
<div className="grid grid-cols-1 gap-4 md:grid-cols-3 mt-7">
{TIER_ORDER.map((key) => {
const t = TIERS[key];
const isCurrent = current === key;
- const featured = key === "STANDARD";
return (
<div
key={key}
- className={`relative rounded-xl bg-card text-card-foreground p-5 ${
- featured ? "border-2 border-foreground" : "border"
- }`}
+ className="relative rounded-xl border bg-card text-card-foreground p-5"
+ data-testid={`plan-${key.toLowerCase()}`}
>
- {featured && (
- <div className="absolute -top-3 left-1/2 -translate-x-1/2 bg-foreground text-background text-[11px] font-bold px-3 py-0.5 rounded-full">
- MOST POPULAR
- </div>
- )}
<div className="font-bold text-lg">{t.label}</div>
<div className="my-1.5">
<span className="text-4xl font-extrabold">${t.priceUsd}</span>
<span className="text-muted-foreground">{t.priceUsd > 0 ? "/mo" : ""}</span>
</div>
+ {t.priceUsd > 0 && <div className="text-xs text-muted-foreground">preview price</div>}
<div className="text-muted-foreground text-sm min-h-9">{t.blurb}</div>
<ul className="list-none p-0 my-3.5 space-y-1 text-sm leading-relaxed">
{t.features.map((f) => (
@@ -111,7 +87,7 @@ export default async function PricingPage() {
<p className="text-center text-muted-foreground text-xs leading-relaxed">
Estimates are heuristic and confidence-labeled — always verify comps before bidding.
- Prices shown are introductory and may change.
+ Paid-plan features and prices are previews and may change before launch.
</p>
</main>
);
diff --git a/src/lib/tiers.ts b/src/lib/tiers.ts
index 21461fc..415f47e 100644
--- a/src/lib/tiers.ts
+++ b/src/lib/tiers.ts
@@ -31,13 +31,12 @@ export const TIERS: Record<Tier, TierDef> = {
key: "FREE",
label: "Free",
priceUsd: 0,
- blurb: "See the full analysis on every deal — on a delay.",
+ blurb: "Current listings and full money-math analysis.",
features: [
- "Browse the auction catalog",
+ "Browse current auction listings",
"Full money-math: recommended max bid, ROI, net profit, scores",
- "Deals delayed 24 hours",
- "Up to 25 listings",
- "No email alerts",
+ "Up to 25 listings per page",
+ "Daily newsletter available after subscription confirmation",
],
limits: {
maxListings: 25,
@@ -52,12 +51,12 @@ export const TIERS: Record<Tier, TierDef> = {
key: "STANDARD",
label: "Standard",
priceUsd: price("TIER_PRICE_STANDARD", 19),
- blurb: "Real-time deals + the daily hot-deal alert.",
+ blurb: "Preview plan with up to 500 listings per page.",
features: [
- "Real-time listings (no delay)",
- "🔥 Daily hot-deal email alerts",
- "Up to 500 listings",
- "All 8 auction sources",
+ "Current listings and full money-math analysis",
+ "Up to 500 listings per page",
+ "Available sources are accessible on every plan",
+ "Daily newsletter available after subscription confirmation",
],
limits: {
maxListings: 500,
@@ -72,13 +71,12 @@ export const TIERS: Record<Tier, TierDef> = {
key: "PREMIUM",
label: "Premium",
priceUsd: price("TIER_PRICE_PREMIUM", 49),
- blurb: "Everything, unlimited, with confidence bands + priority.",
+ blurb: "Preview plan with a higher listing page-size allowance.",
features: [
- "Everything in Standard",
- "Unlimited listings",
- "Honesty-Gate confidence bands on every deal",
- "Full dashboard + saved views + exports",
- "Priority hot-deal alerts (sent first)",
+ "Current listings and full money-math analysis",
+ "Higher listing page-size allowance",
+ "Results remain subject to search and sorting limits",
+ "Daily newsletter available after subscription confirmation",
],
limits: {
maxListings: 1_000_000,
← d81ee96 Snapshot live source before approved TK-11249 pricing releas
·
back to Govarbitrage
·
TK-11466 FIX 2: decouple ADMIN mint from wall-disabled state 0442a97 →