13.6 KB
billing.html
{{template "app.html" .}}
{{define "title"}}Billing & Plan{{end}}
{{define "content"}}
<div class="max-w-4xl mx-auto px-4 sm:px-6 py-8 sm:py-12">
<h1 class="text-2xl font-bold text-white mb-2">Billing & Plan</h1>
<p class="text-[#888] text-sm mb-8">Each site has its own plan. Upgrade individual sites to unlock more features.</p>
<!-- Success banner -->
{{if eq (query "success") "true"}}
<div class="mb-6 p-4 rounded-xl border border-emerald-500/30 bg-emerald-500/10 flex items-center gap-3">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
<div>
<div class="text-emerald-400 text-sm font-medium">Payment successful!</div>
<div class="text-emerald-400/70 text-xs">Your site has been upgraded. It may take a moment to reflect.</div>
</div>
</div>
{{end}}
<!-- Canceled banner -->
{{if eq (query "canceled") "true"}}
<div class="mb-6 p-4 rounded-xl border border-yellow-500/30 bg-yellow-500/10 flex items-center gap-3">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#f59e0b" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
<div>
<div class="text-yellow-400 text-sm font-medium">Checkout canceled</div>
<div class="text-yellow-400/70 text-xs">No charges were made. You can upgrade anytime.</div>
</div>
</div>
{{end}}
<!-- Current Sites / Plans -->
{{if billing.UserSites}}
<div class="mb-10">
<h2 class="text-sm font-medium text-[#888] uppercase tracking-wider mb-4">Your Sites</h2>
<div class="space-y-3">
{{range $site := billing.UserSites}}
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-3 p-4 rounded-xl border border-white/10 bg-white/[0.02]">
<div class="flex items-center gap-3 min-w-0">
<div class="w-8 h-8 rounded-lg flex items-center justify-center text-xs font-medium flex-shrink-0" style="background: rgba(139,92,246,0.15); color: #a78bfa;">
{{upper (slice $site.Name 0 1)}}
</div>
<div class="min-w-0">
<div class="text-white text-sm font-medium truncate">{{$site.Name}}</div>
<div class="text-[#666] text-xs font-mono truncate">{{$site.Subdomain}}.readysite.app</div>
</div>
</div>
<div class="flex items-center gap-3 flex-shrink-0 pl-11 sm:pl-0">
<span class="text-xs px-2.5 py-0.5 rounded-full font-medium {{if eq $site.Status "active"}}bg-emerald-500/15 text-emerald-400{{else if eq $site.Status "sleeping"}}bg-gray-500/15 text-gray-400{{else}}bg-yellow-500/15 text-yellow-400{{end}}">
{{$site.Status}}
</span>
{{if eq $site.Plan "pro"}}
<span class="text-xs px-2.5 py-0.5 rounded-full font-medium bg-violet-500/15 text-violet-400">Pro</span>
{{if and (billing.StripeEnabled) (billing.HasStripeCustomer)}}
<form method="POST" action="/billing/portal" class="inline">
<button type="submit" class="text-xs px-2.5 py-1 rounded-full font-medium transition-colors cursor-pointer text-[#888] hover:text-white" style="background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.1);">
Manage
</button>
</form>
{{end}}
{{else if eq $site.Plan "hobby"}}
<span class="text-xs px-2.5 py-0.5 rounded-full font-medium bg-emerald-500/15 text-emerald-400">Hobby</span>
{{if and (billing.StripeEnabled) (billing.HasStripeCustomer)}}
<form method="POST" action="/billing/portal" class="inline">
<button type="submit" class="text-xs px-2.5 py-1 rounded-full font-medium transition-colors cursor-pointer text-[#888] hover:text-white" style="background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.1);">
Manage
</button>
</form>
{{end}}
{{else}}
<button
hx-post="/api/sites/{{$site.ID}}/upgrade?plan=hobby"
hx-swap="none"
hx-confirm="Upgrade {{$site.Name}} to Hobby ($5/mo)? Your site will be always on with 500MB storage."
class="text-xs px-2.5 py-1 rounded-full font-medium transition-colors cursor-pointer" style="background: linear-gradient(135deg, rgba(16,185,129,0.2), rgba(34,211,238,0.2)); color: #6ee7b7; border: 1px solid rgba(16,185,129,0.3);">
Upgrade
</button>
{{end}}
</div>
</div>
{{end}}
</div>
</div>
{{end}}
<!-- Pricing Comparison -->
<h2 class="text-sm font-medium text-[#888] uppercase tracking-wider mb-4">Plans</h2>
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4 sm:gap-5 mb-10">
<!-- Free Plan -->
<div class="p-6 rounded-2xl border border-white/10 bg-white/[0.02]">
<div class="flex items-center gap-2 mb-1">
<h3 class="text-white font-semibold text-lg">Free</h3>
<span class="text-xs px-2 py-0.5 rounded-full bg-white/5 text-[#888]">Default</span>
</div>
<div class="text-[#888] text-sm mb-5">Test ReadySite. Sites pause after 30 min of inactivity.</div>
<div class="text-2xl font-bold text-white mb-6">$0 <span class="text-sm font-normal text-[#666]">/ month</span></div>
<ul class="space-y-2.5 text-sm text-[#ccc]">
<li class="flex items-center gap-2">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
50MB persistent database
</li>
<li class="flex items-center gap-2">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
Subdomain hosting
</li>
<li class="flex items-center gap-2 text-[#555]">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#555" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
Pauses after 30min idle
</li>
<li class="flex items-center gap-2 text-[#555]">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#555" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
No custom domains
</li>
</ul>
</div>
<!-- Hobby Plan -->
<div class="p-6 rounded-2xl border border-emerald-500/30 bg-emerald-500/[0.03] relative overflow-hidden">
<div class="absolute top-0 right-0 w-32 h-32 bg-emerald-500/10 rounded-full blur-3xl -mr-10 -mt-10 pointer-events-none"></div>
<div class="flex items-center gap-2 mb-1 relative">
<h3 class="text-white font-semibold text-lg">Hobby</h3>
<span class="text-xs px-2 py-0.5 rounded-full bg-emerald-500/15 text-emerald-400">Popular</span>
</div>
<div class="text-[#888] text-sm mb-5">Always-on hosting for personal sites and side projects.</div>
<div class="text-2xl font-bold text-white mb-6">$5 <span class="text-sm font-normal text-[#666]">/ month</span></div>
<ul class="space-y-2.5 text-sm text-[#ccc] relative">
<li class="flex items-center gap-2">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
500MB persistent database
</li>
<li class="flex items-center gap-2">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
Always on
</li>
<li class="flex items-center gap-2">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
Subdomain hosting
</li>
<li class="flex items-center gap-2 text-[#555]">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#555" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
No custom domains
</li>
</ul>
</div>
<!-- Pro Plan -->
<div class="p-6 rounded-2xl border border-violet-500/30 bg-violet-500/[0.03] relative overflow-hidden">
<div class="absolute top-0 right-0 w-32 h-32 bg-violet-500/10 rounded-full blur-3xl -mr-10 -mt-10 pointer-events-none"></div>
<div class="flex items-center gap-2 mb-1 relative">
<h3 class="text-white font-semibold text-lg">Pro</h3>
<span class="text-xs px-2 py-0.5 rounded-full bg-violet-500/15 text-violet-400">Pro</span>
</div>
<div class="text-[#888] text-sm mb-5">Custom domains, daily backups, and priority support for production sites.</div>
<div class="text-2xl font-bold text-white mb-6">$20 <span class="text-sm font-normal text-[#666]">/ month</span></div>
<ul class="space-y-2.5 text-sm text-[#ccc] relative">
<li class="flex items-center gap-2">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
2GB persistent database
</li>
<li class="flex items-center gap-2">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
Custom domain + SSL
</li>
<li class="flex items-center gap-2">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
Daily backups
</li>
<li class="flex items-center gap-2">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
Priority support
</li>
</ul>
</div>
</div>
<!-- Manage Billing / Upgrade CTA -->
<div class="p-6 rounded-2xl border border-white/10 bg-white/[0.02] text-center">
{{if and (billing.StripeEnabled) (billing.HasStripeCustomer)}}
<h3 class="text-white font-semibold mb-2">Manage your subscription</h3>
<p class="text-[#888] text-sm mb-4">Update payment methods, view invoices, or cancel subscriptions.</p>
<form method="POST" action="/billing/portal" class="inline">
<button type="submit" class="inline-flex items-center gap-2 px-5 py-2.5 rounded-lg text-sm font-medium transition-colors cursor-pointer" style="background: linear-gradient(135deg, rgba(139,92,246,0.3), rgba(34,211,238,0.3)); color: #e0d5ff; border: 1px solid rgba(139,92,246,0.3);">
Manage Subscription
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>
</button>
</form>
{{else}}
<h3 class="text-white font-semibold mb-2">Ready to upgrade?</h3>
<p class="text-[#888] text-sm mb-4">Upgrade individual sites from the site list above or from the site manager.</p>
<a href="/sites" class="inline-flex items-center gap-2 px-5 py-2.5 rounded-lg text-sm font-medium transition-colors" style="background: linear-gradient(135deg, rgba(139,92,246,0.3), rgba(34,211,238,0.3)); color: #e0d5ff; border: 1px solid rgba(139,92,246,0.3);">
Go to Sites
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="M12 5l7 7-7 7"/></svg>
</a>
{{end}}
</div>
</div>
{{end}}