- Middleware now redirects unauthenticated users to /welcome instead of /login - Added /features and /pricing to public paths - Created 8 dedicated feature pages: AI OCR, Scanner Integration, Integrations, Team Collaboration, Collection Days, Multi-Site, Analytics, Security - Created features index page at /features with links to all detail pages - Created standalone pricing page at /pricing with comparison table - Extracted shared MarketingNav (with features dropdown) and MarketingFooter - Created FeaturePageShell for consistent feature page layout - Updated landing page to use shared components and link to feature pages Made-with: Cursor
339 lines
14 KiB
TypeScript
339 lines
14 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import Link from "next/link";
|
|
import { Check, ArrowRight, HelpCircle } from "lucide-react";
|
|
import { MarketingNav } from "@/components/marketing/nav";
|
|
import { MarketingFooter } from "@/components/marketing/footer";
|
|
|
|
const tiers = [
|
|
{
|
|
name: "Free",
|
|
price: "$0",
|
|
period: "forever",
|
|
description: "Perfect for trying Echo with your team.",
|
|
cards: "50 cards/month",
|
|
features: [
|
|
"AI-powered OCR extraction",
|
|
"Web upload (PDF, JPEG, PNG)",
|
|
"2 team members",
|
|
"1 location",
|
|
"CSV export",
|
|
"Community support",
|
|
],
|
|
cta: "Get Started Free",
|
|
ctaHref: "/signup",
|
|
highlighted: false,
|
|
},
|
|
{
|
|
name: "Starter",
|
|
price: "$29",
|
|
period: "/month",
|
|
annualPrice: "$24",
|
|
description: "For churches ready to automate their guest workflow.",
|
|
cards: "250 cards/month",
|
|
features: [
|
|
"Everything in Free, plus:",
|
|
"Email & FTP scanner integration",
|
|
"5 team members",
|
|
"Collection day management",
|
|
"Google Sheets integration",
|
|
"Webhook support",
|
|
"Email support",
|
|
],
|
|
cta: "Start 14-Day Trial",
|
|
ctaHref: "/signup?plan=starter",
|
|
highlighted: false,
|
|
},
|
|
{
|
|
name: "Growth",
|
|
price: "$79",
|
|
period: "/month",
|
|
annualPrice: "$66",
|
|
description: "Full integration power for growing congregations.",
|
|
cards: "1,000 cards/month",
|
|
features: [
|
|
"Everything in Starter, plus:",
|
|
"Planning Center sync",
|
|
"Monday.com & Airtable",
|
|
"15 team members",
|
|
"3 locations",
|
|
"Auto-assign to events",
|
|
"API access",
|
|
"Priority support",
|
|
],
|
|
cta: "Start 14-Day Trial",
|
|
ctaHref: "/signup?plan=growth",
|
|
highlighted: true,
|
|
},
|
|
{
|
|
name: "Enterprise",
|
|
price: "Custom",
|
|
period: "",
|
|
description: "For multi-site churches and denominations.",
|
|
cards: "Unlimited cards",
|
|
features: [
|
|
"Everything in Growth, plus:",
|
|
"Unlimited team members",
|
|
"Unlimited locations",
|
|
"SSO / SAML authentication",
|
|
"Custom integrations",
|
|
"Dedicated account manager",
|
|
"99.9% uptime SLA",
|
|
"Self-hosted deployment option",
|
|
],
|
|
cta: "Contact Sales",
|
|
ctaHref: "mailto:sales@echoocr.com",
|
|
highlighted: false,
|
|
},
|
|
];
|
|
|
|
const comparisonRows = [
|
|
{ feature: "Cards per month", free: "50", starter: "250", growth: "1,000", enterprise: "Unlimited" },
|
|
{ feature: "Team members", free: "2", starter: "5", growth: "15", enterprise: "Unlimited" },
|
|
{ feature: "Locations", free: "1", starter: "1", growth: "3", enterprise: "Unlimited" },
|
|
{ feature: "AI-powered OCR", free: true, starter: true, growth: true, enterprise: true },
|
|
{ feature: "Web upload", free: true, starter: true, growth: true, enterprise: true },
|
|
{ feature: "Email scanning", free: false, starter: true, growth: true, enterprise: true },
|
|
{ feature: "FTP scanning", free: false, starter: true, growth: true, enterprise: true },
|
|
{ feature: "Collection days", free: false, starter: true, growth: true, enterprise: true },
|
|
{ feature: "CSV export", free: true, starter: true, growth: true, enterprise: true },
|
|
{ feature: "Google Sheets", free: false, starter: true, growth: true, enterprise: true },
|
|
{ feature: "Webhooks", free: false, starter: true, growth: true, enterprise: true },
|
|
{ feature: "Planning Center", free: false, starter: false, growth: true, enterprise: true },
|
|
{ feature: "Monday.com", free: false, starter: false, growth: true, enterprise: true },
|
|
{ feature: "Airtable", free: false, starter: false, growth: true, enterprise: true },
|
|
{ feature: "Auto-assign to events", free: false, starter: false, growth: true, enterprise: true },
|
|
{ feature: "API access", free: false, starter: false, growth: true, enterprise: true },
|
|
{ feature: "SSO / SAML", free: false, starter: false, growth: false, enterprise: true },
|
|
{ feature: "Custom integrations", free: false, starter: false, growth: false, enterprise: true },
|
|
{ feature: "Self-hosted option", free: false, starter: false, growth: false, enterprise: true },
|
|
{ feature: "Dedicated account manager", free: false, starter: false, growth: false, enterprise: true },
|
|
{ feature: "Uptime SLA", free: false, starter: false, growth: false, enterprise: true },
|
|
];
|
|
|
|
function CellValue({ value }: { value: boolean | string }) {
|
|
if (typeof value === "string") {
|
|
return <span className="text-sm font-medium">{value}</span>;
|
|
}
|
|
return value ? (
|
|
<Check className="h-4 w-4 text-primary mx-auto" />
|
|
) : (
|
|
<span className="text-muted-foreground/30">—</span>
|
|
);
|
|
}
|
|
|
|
export default function PricingPage() {
|
|
const [annual, setAnnual] = useState(false);
|
|
|
|
return (
|
|
<div className="min-h-screen bg-background">
|
|
<MarketingNav />
|
|
|
|
<section className="relative pt-32 pb-16 sm:pt-40 sm:pb-20 overflow-hidden">
|
|
<div className="absolute inset-0 gradient-mesh pointer-events-none" />
|
|
<div className="relative mx-auto max-w-4xl px-6 text-center">
|
|
<h1 className="text-3xl sm:text-4xl lg:text-5xl font-bold tracking-tight leading-[1.1] mb-6">
|
|
Simple, transparent{" "}
|
|
<span className="bg-gradient-to-r from-primary via-foreground to-primary bg-clip-text text-transparent">
|
|
pricing.
|
|
</span>
|
|
</h1>
|
|
<p className="text-lg text-muted-foreground max-w-2xl mx-auto leading-relaxed mb-8">
|
|
Start free. Upgrade when you’re ready. Every plan saves your team
|
|
hours of manual data entry every single week.
|
|
</p>
|
|
<div className="inline-flex items-center gap-3 rounded-full border border-border/60 bg-card/60 p-1 glass">
|
|
<button
|
|
onClick={() => setAnnual(false)}
|
|
className={`rounded-full px-5 py-2 text-sm font-medium transition-all ${
|
|
!annual
|
|
? "bg-primary text-primary-foreground shadow-sm"
|
|
: "text-muted-foreground hover:text-foreground"
|
|
}`}
|
|
>
|
|
Monthly
|
|
</button>
|
|
<button
|
|
onClick={() => setAnnual(true)}
|
|
className={`rounded-full px-5 py-2 text-sm font-medium transition-all ${
|
|
annual
|
|
? "bg-primary text-primary-foreground shadow-sm"
|
|
: "text-muted-foreground hover:text-foreground"
|
|
}`}
|
|
>
|
|
Annual
|
|
<span className="ml-1.5 text-xs opacity-80">Save 17%</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="pb-16">
|
|
<div className="mx-auto max-w-6xl px-6">
|
|
<div className="grid sm:grid-cols-2 lg:grid-cols-4 gap-5">
|
|
{tiers.map((tier) => (
|
|
<div
|
|
key={tier.name}
|
|
className={`rounded-2xl p-6 flex flex-col ${
|
|
tier.highlighted
|
|
? "glass-card ring-2 ring-primary/30 shadow-xl scale-[1.02]"
|
|
: "glass-card"
|
|
}`}
|
|
>
|
|
{tier.highlighted && (
|
|
<div className="text-[10px] font-bold uppercase tracking-wider text-primary mb-4">
|
|
Most Popular
|
|
</div>
|
|
)}
|
|
<h3 className="text-lg font-semibold">{tier.name}</h3>
|
|
<div className="mt-3 mb-1">
|
|
<span className="text-3xl font-bold">
|
|
{annual && tier.annualPrice ? tier.annualPrice : tier.price}
|
|
</span>
|
|
{tier.period && (
|
|
<span className="text-sm text-muted-foreground ml-1">
|
|
{tier.period}
|
|
</span>
|
|
)}
|
|
</div>
|
|
{annual && tier.annualPrice && (
|
|
<div className="text-xs text-muted-foreground mb-3">
|
|
Billed annually ({tier.annualPrice === "$24" ? "$288" : "$792"}/year)
|
|
</div>
|
|
)}
|
|
<p className="text-sm text-muted-foreground mb-4">
|
|
{tier.description}
|
|
</p>
|
|
<div className="text-sm font-semibold text-foreground mb-4 pb-4 border-b border-border/40">
|
|
{tier.cards}
|
|
</div>
|
|
<ul className="space-y-3 mb-8 flex-1">
|
|
{tier.features.map((feature) => (
|
|
<li key={feature} className="flex items-start gap-2.5 text-sm">
|
|
<Check className="h-4 w-4 text-primary mt-0.5 shrink-0" />
|
|
<span className="text-muted-foreground">{feature}</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
<Link
|
|
href={tier.ctaHref}
|
|
className={`block text-center rounded-lg py-2.5 text-sm font-semibold transition-all ${
|
|
tier.highlighted
|
|
? "bg-primary text-primary-foreground shadow-sm hover:opacity-90"
|
|
: "border border-border/60 bg-card/60 text-foreground hover:bg-accent/40"
|
|
}`}
|
|
>
|
|
{tier.cta}
|
|
</Link>
|
|
</div>
|
|
))}
|
|
</div>
|
|
<p className="text-center text-xs text-muted-foreground mt-8">
|
|
All paid plans include a 14-day free trial. No credit card required to
|
|
start. Need more cards? Overage billed at $0.08/card.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="py-16">
|
|
<div className="mx-auto max-w-5xl px-6">
|
|
<h2 className="text-2xl font-bold tracking-tight text-center mb-10">
|
|
Compare plans
|
|
</h2>
|
|
<div className="glass-card rounded-2xl overflow-hidden">
|
|
<div className="overflow-x-auto">
|
|
<table className="w-full text-sm">
|
|
<thead>
|
|
<tr className="border-b border-border/40">
|
|
<th className="text-left p-4 font-semibold w-[200px]">Feature</th>
|
|
<th className="text-center p-4 font-semibold">Free</th>
|
|
<th className="text-center p-4 font-semibold">Starter</th>
|
|
<th className="text-center p-4 font-semibold bg-primary/5">Growth</th>
|
|
<th className="text-center p-4 font-semibold">Enterprise</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{comparisonRows.map((row) => (
|
|
<tr key={row.feature} className="border-b border-border/20 last:border-0">
|
|
<td className="p-4 text-muted-foreground">{row.feature}</td>
|
|
<td className="p-4 text-center"><CellValue value={row.free} /></td>
|
|
<td className="p-4 text-center"><CellValue value={row.starter} /></td>
|
|
<td className="p-4 text-center bg-primary/5"><CellValue value={row.growth} /></td>
|
|
<td className="p-4 text-center"><CellValue value={row.enterprise} /></td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="py-16">
|
|
<div className="mx-auto max-w-3xl px-6">
|
|
<h2 className="text-2xl font-bold tracking-tight text-center mb-10">
|
|
Common questions about pricing
|
|
</h2>
|
|
<div className="space-y-6">
|
|
{[
|
|
{
|
|
q: "What counts as a \"card\"?",
|
|
a: "Each individual response card extracted from your upload counts as one card. A 10-page duplex PDF with 5 card pairs = 5 cards. A single photo of one card = 1 card.",
|
|
},
|
|
{
|
|
q: "What happens if I exceed my monthly limit?",
|
|
a: "We'll never cut you off mid-month. Overage is billed at $0.08 per card at the end of the billing cycle. If you're consistently over, we'll suggest upgrading to save money.",
|
|
},
|
|
{
|
|
q: "Can I change plans at any time?",
|
|
a: "Yes. Upgrade instantly and we'll prorate the difference. Downgrade at the end of your current billing period. No penalties, no contracts.",
|
|
},
|
|
{
|
|
q: "Do you offer nonprofit discounts?",
|
|
a: "Our pricing is already designed to be accessible for churches and nonprofits. If you're a small church with budget constraints, contact us — we're happy to work something out.",
|
|
},
|
|
{
|
|
q: "Is there really no credit card required?",
|
|
a: "Correct. The Free plan is fully functional with no credit card. Paid plan trials also start without payment — we only ask for billing info when you're ready to continue after the trial.",
|
|
},
|
|
].map((faq) => (
|
|
<div key={faq.q} className="glass-card rounded-xl p-6">
|
|
<div className="flex items-start gap-3">
|
|
<HelpCircle className="h-5 w-5 text-primary mt-0.5 shrink-0" />
|
|
<div>
|
|
<h3 className="font-semibold text-sm mb-2">{faq.q}</h3>
|
|
<p className="text-sm text-muted-foreground leading-relaxed">{faq.a}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="py-16 sm:py-24 relative">
|
|
<div className="absolute inset-0 gradient-mesh pointer-events-none" />
|
|
<div className="relative mx-auto max-w-3xl px-6 text-center">
|
|
<div className="glass-card rounded-2xl p-10 sm:p-14">
|
|
<h2 className="text-2xl sm:text-3xl font-bold tracking-tight mb-4">
|
|
Ready to give your team Sunday evenings back?
|
|
</h2>
|
|
<p className="text-muted-foreground text-lg mb-8 max-w-xl mx-auto">
|
|
Start free. No credit card. No commitment.
|
|
</p>
|
|
<Link
|
|
href="/signup"
|
|
className="inline-flex items-center gap-2 rounded-xl bg-primary px-8 py-3.5 text-base font-semibold text-primary-foreground shadow-lg hover:opacity-90 transition-opacity"
|
|
>
|
|
Get Started Free
|
|
<ArrowRight className="h-4 w-4" />
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<MarketingFooter />
|
|
</div>
|
|
);
|
|
}
|