Update pricing: buttons aligned, competitive pricing (/), USD currency
Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled

This commit is contained in:
yves.gugger
2025-12-09 17:35:59 +01:00
parent 772dd4a5af
commit f7e4c8e6a4
7 changed files with 30 additions and 30 deletions

View File

@ -149,7 +149,7 @@ async def get_subscription_tiers():
"domain_limit": config["domain_limit"], "domain_limit": config["domain_limit"],
"portfolio_limit": config.get("portfolio_limit", 0), "portfolio_limit": config.get("portfolio_limit", 0),
"price": config["price"], "price": config["price"],
"currency": config.get("currency", "EUR"), "currency": config.get("currency", "USD"),
"check_frequency": config["check_frequency"], "check_frequency": config["check_frequency"],
"features": feature_list, "features": feature_list,
"feature_flags": config["features"], "feature_flags": config["features"],

View File

@ -35,7 +35,7 @@ TIER_CONFIG = {
SubscriptionTier.SCOUT: { SubscriptionTier.SCOUT: {
"name": "Scout", "name": "Scout",
"price": 0, "price": 0,
"currency": "EUR", "currency": "USD",
"domain_limit": 5, "domain_limit": 5,
"portfolio_limit": 0, "portfolio_limit": 0,
"check_frequency": "daily", "check_frequency": "daily",
@ -56,8 +56,8 @@ TIER_CONFIG = {
}, },
SubscriptionTier.TRADER: { SubscriptionTier.TRADER: {
"name": "Trader", "name": "Trader",
"price": 19, "price": 9,
"currency": "EUR", "currency": "USD",
"domain_limit": 50, "domain_limit": 50,
"portfolio_limit": 25, "portfolio_limit": 25,
"check_frequency": "hourly", "check_frequency": "hourly",
@ -78,8 +78,8 @@ TIER_CONFIG = {
}, },
SubscriptionTier.TYCOON: { SubscriptionTier.TYCOON: {
"name": "Tycoon", "name": "Tycoon",
"price": 49, "price": 29,
"currency": "EUR", "currency": "USD",
"domain_limit": 500, "domain_limit": 500,
"portfolio_limit": -1, # Unlimited "portfolio_limit": -1, # Unlimited
"check_frequency": "realtime", # Every 10 minutes "check_frequency": "realtime", # Every 10 minutes

View File

@ -42,7 +42,7 @@ TIER_FEATURES = {
"scout": { "scout": {
"name": "Scout", "name": "Scout",
"price": 0, "price": 0,
"currency": "EUR", "currency": "USD",
"max_domains": 5, "max_domains": 5,
"check_frequency": "daily", "check_frequency": "daily",
"portfolio_domains": 0, "portfolio_domains": 0,
@ -50,8 +50,8 @@ TIER_FEATURES = {
}, },
"trader": { "trader": {
"name": "Trader", "name": "Trader",
"price": 19, "price": 9,
"currency": "EUR", "currency": "USD",
"max_domains": 50, "max_domains": 50,
"check_frequency": "hourly", "check_frequency": "hourly",
"portfolio_domains": 25, "portfolio_domains": 25,
@ -66,8 +66,8 @@ TIER_FEATURES = {
}, },
"tycoon": { "tycoon": {
"name": "Tycoon", "name": "Tycoon",
"price": 49, "price": 29,
"currency": "EUR", "currency": "USD",
"max_domains": 500, "max_domains": 500,
"check_frequency": "realtime", "check_frequency": "realtime",
"portfolio_domains": -1, # Unlimited "portfolio_domains": -1, # Unlimited

View File

@ -150,7 +150,7 @@ const jsonLd = {
'@type': 'AggregateOffer', '@type': 'AggregateOffer',
lowPrice: '0', lowPrice: '0',
highPrice: '49', highPrice: '49',
priceCurrency: 'EUR', priceCurrency: 'USD',
offerCount: '3', offerCount: '3',
}, },
featureList: [ featureList: [

View File

@ -33,7 +33,7 @@ const tiers = [
id: 'trader', id: 'trader',
name: 'Trader', name: 'Trader',
icon: TrendingUp, icon: TrendingUp,
price: '19', price: '9',
period: '/mo', period: '/mo',
description: 'Hunt with precision. Daily intel.', description: 'Hunt with precision. Daily intel.',
features: [ features: [
@ -55,7 +55,7 @@ const tiers = [
id: 'tycoon', id: 'tycoon',
name: 'Tycoon', name: 'Tycoon',
icon: Crown, icon: Crown,
price: '49', price: '29',
period: '/mo', period: '/mo',
description: 'Dominate the market. No limits.', description: 'Dominate the market. No limits.',
features: [ features: [
@ -171,12 +171,12 @@ export default function PricingPage() {
</div> </div>
{/* Pricing Cards */} {/* Pricing Cards */}
<div className="grid md:grid-cols-3 gap-6 mb-20 animate-slide-up"> <div className="grid md:grid-cols-3 gap-6 mb-20 animate-slide-up items-stretch">
{tiers.map((tier, index) => ( {tiers.map((tier, index) => (
<div <div
key={tier.id} key={tier.id}
className={clsx( className={clsx(
"group relative p-6 sm:p-8 rounded-2xl border transition-all duration-500", "group relative p-6 sm:p-8 rounded-2xl border transition-all duration-500 flex flex-col",
tier.highlighted tier.highlighted
? "bg-background-secondary border-accent/30 shadow-lg shadow-accent/5" ? "bg-background-secondary border-accent/30 shadow-lg shadow-accent/5"
: "bg-background-secondary/50 border-border hover:border-accent/20 hover:bg-background-secondary" : "bg-background-secondary/50 border-border hover:border-accent/20 hover:bg-background-secondary"
@ -196,7 +196,7 @@ export default function PricingPage() {
</div> </div>
)} )}
<div className="relative"> <div className="relative flex-1 flex flex-col">
{/* Header */} {/* Header */}
<div className="mb-6"> <div className="mb-6">
<div className="flex items-center gap-3 mb-3"> <div className="flex items-center gap-3 mb-3">
@ -226,8 +226,8 @@ export default function PricingPage() {
</div> </div>
</div> </div>
{/* Features */} {/* Features - flex-1 to push button to bottom */}
<ul className="space-y-3 mb-8"> <ul className="space-y-3 mb-8 flex-1">
{tier.features.map((feature) => ( {tier.features.map((feature) => (
<li key={feature.text} className="flex items-start gap-3"> <li key={feature.text} className="flex items-start gap-3">
<Check className="w-4 h-4 mt-0.5 shrink-0 text-accent" strokeWidth={2.5} /> <Check className="w-4 h-4 mt-0.5 shrink-0 text-accent" strokeWidth={2.5} />
@ -238,12 +238,12 @@ export default function PricingPage() {
))} ))}
</ul> </ul>
{/* CTA */} {/* CTA - always at bottom */}
<button <button
onClick={() => handleSelectPlan(tier.id, tier.isPaid)} onClick={() => handleSelectPlan(tier.id, tier.isPaid)}
disabled={loadingPlan === tier.id} disabled={loadingPlan === tier.id}
className={clsx( className={clsx(
"w-full flex items-center justify-center gap-2 py-4 rounded-xl text-ui font-medium transition-all duration-300", "w-full flex items-center justify-center gap-2 py-4 rounded-xl text-ui font-medium transition-all duration-300 mt-auto",
tier.highlighted tier.highlighted
? "bg-accent text-background hover:bg-accent-hover shadow-[0_0_20px_rgba(16,185,129,0.15)]" ? "bg-accent text-background hover:bg-accent-hover shadow-[0_0_20px_rgba(16,185,129,0.15)]"
: "bg-foreground text-background hover:bg-foreground/90" : "bg-foreground text-background hover:bg-foreground/90"

View File

@ -483,7 +483,7 @@ export default function SettingsPage() {
<div> <div>
<p className="text-xl font-semibold text-foreground">{tierName}</p> <p className="text-xl font-semibold text-foreground">{tierName}</p>
<p className="text-body-sm text-foreground-muted"> <p className="text-body-sm text-foreground-muted">
{tierName === 'Scout' ? 'Free forever' : tierName === 'Trader' ? '$19/month' : '$49/month'} {tierName === 'Scout' ? 'Free forever' : tierName === 'Trader' ? '$9/month' : '$29/month'}
</p> </p>
</div> </div>
</div> </div>
@ -617,8 +617,8 @@ export default function SettingsPage() {
<tr className="border-b border-border/50"> <tr className="border-b border-border/50">
<td className="py-3 px-3 text-body-sm text-foreground">Price</td> <td className="py-3 px-3 text-body-sm text-foreground">Price</td>
<td className="py-3 px-3 text-center text-body-sm text-foreground">Free</td> <td className="py-3 px-3 text-center text-body-sm text-foreground">Free</td>
<td className="py-3 px-3 text-center text-body-sm text-foreground">$19/mo</td> <td className="py-3 px-3 text-center text-body-sm text-foreground">$9/mo</td>
<td className="py-3 px-3 text-center text-body-sm text-foreground">$49/mo</td> <td className="py-3 px-3 text-center text-body-sm text-foreground">$29/mo</td>
</tr> </tr>
<tr className="border-b border-border/50"> <tr className="border-b border-border/50">
<td className="py-3 px-3 text-body-sm text-foreground">Watchlist Domains</td> <td className="py-3 px-3 text-body-sm text-foreground">Watchlist Domains</td>

View File

@ -96,7 +96,7 @@ export const webAppSchema = generateStructuredData('WebApplication', {
'@type': 'AggregateOffer', '@type': 'AggregateOffer',
lowPrice: '0', lowPrice: '0',
highPrice: '99', highPrice: '99',
priceCurrency: 'EUR', priceCurrency: 'USD',
offerCount: '3', offerCount: '3',
}, },
featureList: [ featureList: [
@ -154,18 +154,18 @@ export const serviceSchema = generateStructuredData('Service', {
'@type': 'Offer', '@type': 'Offer',
name: 'Scout (Free)', name: 'Scout (Free)',
price: '0', price: '0',
priceCurrency: 'EUR', priceCurrency: 'USD',
description: 'Basic domain monitoring with 5 domains, daily checks', description: 'Basic domain monitoring with 5 domains, daily checks',
}, },
{ {
'@type': 'Offer', '@type': 'Offer',
name: 'Trader', name: 'Trader',
price: '19', price: '19',
priceCurrency: 'EUR', priceCurrency: 'USD',
priceSpecification: { priceSpecification: {
'@type': 'UnitPriceSpecification', '@type': 'UnitPriceSpecification',
price: '19', price: '19',
priceCurrency: 'EUR', priceCurrency: 'USD',
billingDuration: 'P1M', billingDuration: 'P1M',
}, },
description: '50 domains, hourly checks, market insights', description: '50 domains, hourly checks, market insights',
@ -174,11 +174,11 @@ export const serviceSchema = generateStructuredData('Service', {
'@type': 'Offer', '@type': 'Offer',
name: 'Tycoon', name: 'Tycoon',
price: '49', price: '49',
priceCurrency: 'EUR', priceCurrency: 'USD',
priceSpecification: { priceSpecification: {
'@type': 'UnitPriceSpecification', '@type': 'UnitPriceSpecification',
price: '49', price: '49',
priceCurrency: 'EUR', priceCurrency: 'USD',
billingDuration: 'P1M', billingDuration: 'P1M',
}, },
description: '500+ domains, 10-min checks, API access, bulk tools', description: '500+ domains, 10-min checks, API access, bulk tools',