Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 93 additions & 12 deletions src/app/pricing/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { useState } from 'react'

interface PricingTier {
name: string
price: string
monthlyPrice: number
annualPrice: number
tokens: string
description: string
features: string[]
Expand All @@ -15,10 +16,11 @@ interface PricingTier {
perMember?: boolean
}

const individualMonthlyTiers: PricingTier[] = [
const individualTiers: PricingTier[] = [
{
name: 'Free',
price: '0',
monthlyPrice: 0,
annualPrice: 0,
tokens: '240K tokens',
description: 'Start with a free account to speed up your workflow on public projects',
features: [
Expand All @@ -31,7 +33,8 @@ const individualMonthlyTiers: PricingTier[] = [
},
{
name: 'Pro',
price: '20',
monthlyPrice: 20,
annualPrice: 200,,
tokens: '10M tokens',
description: 'Ideal for hobbyists and casual users for light, exploratory use',
features: [
Expand All @@ -44,7 +47,8 @@ const individualMonthlyTiers: PricingTier[] = [
},
{
name: 'Pro 50',
price: '50',
monthlyPrice: 50,
annualPrice: 500,
tokens: '26M tokens',
description: 'Designed for professionals who need to use Bolt a few times per week',
features: [
Expand All @@ -57,7 +61,8 @@ const individualMonthlyTiers: PricingTier[] = [
},
{
name: 'Pro 100',
price: '100',
monthlyPrice: 100,
annualPrice: 1000,
tokens: '55M tokens',
description: 'Perfect for heavy users looking to enhance daily workflows',
features: [
Expand All @@ -70,10 +75,49 @@ const individualMonthlyTiers: PricingTier[] = [
}
]

const teamTiers: PricingTier[] = [
{
name: 'Team Starter',
monthlyPrice: 150,
annualPrice: 1500,
tokens: '200M tokens',
description: 'For small teams looking to collaborate',
features: [
'Up to 10 members',
'Shared environments',
'Team analytics',
'Standard support'
],
bg: 'from-yellow-600 to-orange-500',
button: 'Upgrade Team',
perMember: true
},
{
name: 'Team Pro',
monthlyPrice: 400,
annualPrice: 4000,
tokens: '1B tokens',
description: 'For larger teams with advanced needs',
features: [
'Unlimited members',
'Advanced analytics',
'SSO Integration',
'Priority support'
],
bg: 'from-red-600 to-pink-600',
button: 'Upgrade Team Pro',
perMember: true
}
]

export default function Pricing() {
const router = useRouter()
const [showTeams, setShowTeams] = useState(false)
const [billingCycle, setBillingCycle] = useState('annual')
const isAuthenticated = false
const currentPlan = 'Free'

const tiers = showTeams ? teamTiers : individualTiers


return (
<div className="min-h-screen bg-black py-20 px-4">
Expand All @@ -95,8 +139,42 @@ export default function Pricing() {
Start with a free account to speed up your workflow on public projects or boost your entire team with instantly-opening production environments.
</motion.p>

<div className="grid gap-6 mb-20 md:grid-cols-2 lg:grid-cols-4">
{individualMonthlyTiers.map((tier, index) => (
{/* Billing Cycle Toggle */}
<div className="flex justify-center items-center gap-4 mb-10">
<span className={`text-lg ${billingCycle === 'monthly' ? 'text-white' : 'text-gray-500'}`}>Monthly</span>
<motion.div
className="relative w-14 h-7 bg-gray-700 rounded-full cursor-pointer"
onClick={() => setBillingCycle(billingCycle === 'monthly' ? 'annual' : 'monthly')}
initial={false}
animate={{ backgroundColor: billingCycle === 'annual' ? '#4ade80' : '#374151' }}
>
<motion.div
className="absolute top-0.5 w-6 h-6 bg-white rounded-full shadow-md"
animate={{ x: billingCycle === 'annual' ? 28 : 2 }}
transition={{ type: 'spring', stiffness: 300 }}
/>
</motion.div>
<span className={`text-lg ${billingCycle === 'annual' ? 'text-white' : 'text-gray-500'}`}>Annual</span>
</div>

{/* Toggle between Individual and Teams */}
<div className="flex justify-center gap-6 mb-12">
<button
className={`px-4 py-2 rounded-lg ${!showTeams ? 'bg-cyan-600 text-white' : 'bg-gray-800 text-gray-300'}`}
onClick={() => setShowTeams(false)}
>
Individual
</button>
<button
className={`px-4 py-2 rounded-lg ${showTeams ? 'bg-cyan-600 text-white' : 'bg-gray-800 text-gray-300'}`}
onClick={() => setShowTeams(true)}
>
Teams
</button>
</div>

<div className="grid gap-6 mb-20 md:grid-cols-2 lg:grid-cols-3">
{tiers.map((tier, index) => (
<motion.div
key={`${tier.name}-${index}`}
className={`bg-gradient-to-br ${tier.bg} p-0.5 rounded-2xl shadow-xl`}
Expand All @@ -110,7 +188,8 @@ export default function Pricing() {

<div className="mb-6">
<div className="text-4xl font-bold text-white">
${tier.price}<span className="text-lg">/month</span>
${billingCycle === 'monthly' ? tier.monthlyPrice : tier.annualPrice}
<span className="text-lg">/{billingCycle}</span>
</div>
<div className="text-gray-300">{tier.tokens}</div>
</div>
Expand All @@ -128,7 +207,9 @@ export default function Pricing() {

<button
onClick={() => {
if (tier.name !== 'Free') {
if (!isAuthenticated) {
router.push('/login')
}else if (currentPlan === 'Free' && tier.name !== 'Free') {
router.push('/checkout')
}
}}
Expand All @@ -147,4 +228,4 @@ export default function Pricing() {
</div>
</div>
)
}
}