diff --git a/packages/frontend/src/components/ui/icon.tsx b/packages/frontend/src/components/ui/icon.tsx index c44d843..ff3529e 100644 --- a/packages/frontend/src/components/ui/icon.tsx +++ b/packages/frontend/src/components/ui/icon.tsx @@ -12,10 +12,13 @@ import { Close as PixelClose, MessagePlus as PixelCommentSend, CreditCard as PixelCreditCard, + CreditCardDelete as PixelCreditCardDelete, Dashboard as PixelDashboard, Debug as PixelDebug, DebugOff as PixelDebugOff, Edit as PixelEdit, + EyeClosed as PixelEyeClosed, + AddGrid as PixelGridAdd, Home as PixelHome, InfoBox as PixelInfo, Link as PixelLink, @@ -55,6 +58,7 @@ import { DotsSixVerticalIcon as PhosphorDotsSixVertical, DotsThreeVerticalIcon as PhosphorDotsThreeVertical, PencilSimpleIcon as PhosphorEdit, + EyeClosedIcon as PhosphorEyeClosed, HashIcon as PhosphorHash, HashStraightIcon as PhosphorHashStraight, HouseIcon as PhosphorHome, @@ -73,6 +77,7 @@ import { RocketLaunchIcon as PhosphorRocketLaunch, HardDrivesIcon as PhosphorServer, ShieldCheckIcon as PhosphorShieldCheck, + StackPlusIcon as PhosphorStackPlus, StopIcon as PhosphorStop, SunIcon as PhosphorSun, TimerIcon as PhosphorTimer, @@ -100,6 +105,8 @@ import { CreditCard, Edit, EllipsisVertical, + EyeClosed, + Grid2x2Plus as GridAdd, GripVerticalIcon, Hash, InfoIcon, @@ -155,12 +162,15 @@ const icons = { circleQuestionMark: { lucide: CircleQuestionMark, pixel: PixelNoteDelete, phosphor: PhosphorQuestion }, comment: { lucide: MessageSquarePlus, pixel: PixelCommentSend, phosphor: PhosphorComment }, creditCard: { lucide: CreditCard, pixel: PixelCreditCard, phosphor: PhosphorCreditCard }, + creditCardDelete: { lucide: CreditCard, pixel: PixelCreditCardDelete, phosphor: PhosphorCreditCard }, edit: { lucide: Edit, pixel: PixelEdit, phosphor: PhosphorEdit }, ellipsisVertical: { lucide: EllipsisVertical, pixel: PixelMoreVertical, phosphor: PhosphorDotsThreeVertical, }, + eyeClosed: { lucide: EyeClosed, pixel: PixelEyeClosed, phosphor: PhosphorEyeClosed }, + gridAdd: { lucide: GridAdd, pixel: PixelGridAdd, phosphor: PhosphorStackPlus }, gripVerticalIcon: { lucide: GripVerticalIcon, pixel: PixelViewportWide, diff --git a/packages/frontend/src/components/ui/switch.tsx b/packages/frontend/src/components/ui/switch.tsx index 15f72b1..c2d02a1 100644 --- a/packages/frontend/src/components/ui/switch.tsx +++ b/packages/frontend/src/components/ui/switch.tsx @@ -5,10 +5,12 @@ import { cn } from "@/lib/utils"; function Switch({ className, + thumbClassName, size = "default", ...props }: React.ComponentProps & { - size?: "sm" | "default"; + thumbClassName?: string; + size?: "sm" | "default" | "lg"; }) { return ( diff --git a/packages/frontend/src/main.tsx b/packages/frontend/src/main.tsx index b60a98b..f214187 100644 --- a/packages/frontend/src/main.tsx +++ b/packages/frontend/src/main.tsx @@ -13,7 +13,6 @@ import Issues from "@/pages/Issues"; import Landing from "@/pages/Landing"; import Login from "@/pages/Login"; import NotFound from "@/pages/NotFound"; -import Pricing from "@/pages/Pricing"; import Test from "@/pages/Test"; import Timeline from "@/pages/Timeline"; @@ -28,7 +27,6 @@ ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( {/* public routes */} } /> } /> - } /> } /> {/* authed routes */} diff --git a/packages/frontend/src/pages/Landing.tsx b/packages/frontend/src/pages/Landing.tsx index bacb8c5..2100685 100644 --- a/packages/frontend/src/pages/Landing.tsx +++ b/packages/frontend/src/pages/Landing.tsx @@ -1,32 +1,141 @@ -import { HumanRun } from "@nsmr/pixelart-react"; +import { useState } from "react"; import { Link } from "react-router-dom"; import { useSession } from "@/components/session-provider"; import ThemeToggle from "@/components/theme-toggle"; import { Button } from "@/components/ui/button"; import Icon from "@/components/ui/icon"; +import { Switch } from "@/components/ui/switch"; +import { cn } from "@/lib/utils"; + +const pricingTiers = [ + { + name: "Starter", + price: "£0", + priceAnnual: "£0", + period: "Free forever", + periodAnnual: "Free forever", + description: "Perfect for side projects and solo developers", + tagline: "For solo devs and small projects", + features: [ + "1 organisation (owned or joined)", + "1 project", + "100 issues", + "Up to 5 team members", + "Email support", + ], + cta: "Get started free", + ctaLink: "/login", + highlighted: false, + }, + { + name: "Pro", + price: "£11.99", + priceAnnual: "£9.99", + period: "per user/month", + periodAnnual: "per user/month", + description: "For growing teams and professionals", + tagline: "Most Popular", + features: [ + "Everything in starter", + "Unlimited organisations", + "Unlimited projects", + "Unlimited issues", + "Advanced time tracking & reports", + "Custom issue statuses", + "Priority email support", + ], + cta: "Try pro free for 14 days", + ctaLink: "/login", + highlighted: true, + }, +]; + +const faqs = [ + { + question: "Can I switch plans?", + answer: + "Yes, you can upgrade or downgrade at any time. Changes take effect immediately, and we'll prorate any charges.", + }, + { + question: "Is there a free trial?", + answer: "Yes, pro plan includes a 14-day free trial with full access. No credit card required to start.", + }, + { + question: "What payment methods do you accept?", + answer: "We accept all major credit cards.", + }, + { + question: "What if I need more users?", + answer: + "Pro plan pricing scales with your team. Add or remove users anytime, and we'll adjust your billing automatically.", + }, + { + question: "What happens when my trial ends?", + answer: + "You'll automatically downgrade to the free starter plan. No charges unless you actively upgrade to pro.", + }, + { + question: "Can I cancel anytime?", + answer: + "Absolutely. Cancel anytime with no questions asked. You'll keep access until the end of your billing period.", + }, + { + question: "Do you offer refunds?", + answer: "Yes, we offer a 30-day money-back guarantee. If Sprint isn't right for you, just let us know.", + }, +]; export default function Landing() { const { user, isLoading } = useSession(); + const [billingPeriod, setBillingPeriod] = useState<"monthly" | "annual">("monthly"); return ( -
-
-
Sprint
- +
+
+
+
+ Sprint + Sprint +
+ +
@@ -34,7 +143,7 @@ export default function Landing() { {/* hero section */}
- + Sprint

@@ -57,7 +166,7 @@ export default function Landing() { Start free trial )} @@ -69,38 +178,58 @@ export default function Landing() { {/* problem section */}

- Tired of spending more time managing Jira than building your product? + Tired of spending more time managing Jira than building products?

- +

Wasting hours configuring workflows instead of shipping features

- +

Drowning in features you'll never use while missing the basics

- +

- Context switching kills momentum—your flow state doesn't stand a chance + The software is full of bugs. Your flow state doesn't stand a chance

{/* solution section */} -
+

Everything you need, nothing you don't

- +

See your work at a glance

Beautiful, intuitive issue tracking with customizable statuses. Organize by projects and @@ -109,7 +238,7 @@ export default function Landing() {

- +

Track time without thinking

Built-in time tracking that actually works. Start, pause, resume. See where your time goes @@ -118,7 +247,7 @@ export default function Landing() {

- +

Ship in sprints

Sprint planning that actually works. Set date ranges, assign issues, track velocity. Keep @@ -127,7 +256,7 @@ export default function Landing() {

- +

Only use what you need

Every feature is optional. Sprints, time tracking, and other modules can be enabled or @@ -149,23 +278,165 @@ export default function Landing() { "Customizable issue statuses", "Sprint planning with date ranges", "Built-in time tracking", - "Role-based access control", "Native desktop app (Tauri)", - "Self-hostable on your infrastructure", "Clean, resizable interface", "Issue assignment and collaboration", "Individual feature toggles (org level)", ].map((feature) => (

- + {feature}
))}
+ {/* pricing section */} +
+
+

Simple, transparent pricing

+

+ Choose the plan that fits your team. Scale as you grow. +

+ + {/* billing toggle */} +
+ + setBillingPeriod(checked ? "annual" : "monthly")} + className="bg-border data-[state=checked]:bg-border! data-[state=unchecked]:bg-border!" + thumbClassName="bg-personality dark:bg-personality data-[state=checked]:bg-personality! data-[state=unchecked]:bg-personality!" + aria-label="toggle billing period" + /> + + + Save 17% + +
+
+ +
+ {pricingTiers.map((tier) => ( +
+ {tier.highlighted && ( +
+ {tier.tagline} +
+ )} + +
+

{tier.name}

+
+ + {billingPeriod === "annual" ? tier.priceAnnual : tier.price} + + + {billingPeriod === "annual" ? tier.periodAnnual : tier.period} + +
+

{tier.description}

+
+ +
    + {tier.features.map((feature) => ( +
  • + + {feature} +
  • + ))} +
+ + +
+ ))} +
+ + {/* trust signals */} +
+
+ +

Secure & Encrypted

+

Your data is safe with us

+
+
+ +

No Card Required

+

Start your trial instantly

+
+
+ +

Money Back Guarantee

+

30-day no-risk policy

+
+
+ + {/* faq section */} +
+
+

Frequently Asked Questions

+
+ {faqs.map((faq) => ( +
+

{faq.question}

+

{faq.answer}

+
+ ))} +
+
+
+
+ + {/* TODO:> commented out until we have actual testimonies */} {/* social proof placeholder */} -
+ {/*

Join developers who've escaped Jira

@@ -187,13 +458,13 @@ export default function Landing() {

Early user feedback

-
+
*/} {/* final cta */} -
+

Ready to ship faster?

- Start tracking issues, managing sprints, and shipping product in minutes + Start tracking issues, managing sprints, and shipping products in minutes

{!isLoading && user ? ( diff --git a/packages/frontend/src/pages/Pricing.tsx b/packages/frontend/src/pages/Pricing.tsx deleted file mode 100644 index c43533e..0000000 --- a/packages/frontend/src/pages/Pricing.tsx +++ /dev/null @@ -1,289 +0,0 @@ -import { useState } from "react"; -import { Link } from "react-router-dom"; -import { useSession } from "@/components/session-provider"; -import ThemeToggle from "@/components/theme-toggle"; -import { Button } from "@/components/ui/button"; -import Icon from "@/components/ui/icon"; -import { cn } from "@/lib/utils"; - -const pricingTiers = [ - { - name: "Starter", - price: "£0", - priceAnnual: "£0", - period: "Free forever", - description: "Perfect for side projects and solo developers", - tagline: "For solo devs and small projects", - features: [ - "1 organisation (owned or joined)", - "1 project", - "100 issues", - "Up to 5 team members", - "Basic time tracking", - "Email support", - ], - cta: "Get started free", - ctaLink: "/login", - highlighted: false, - }, - { - name: "Pro", - price: "£11.99", - priceAnnual: "£9.99", - period: "per user/month", - periodAnnual: "per user/month", - description: "For growing teams and professionals", - tagline: "Most Popular", - features: [ - "Everything in starter", - "Unlimited organisations", - "Unlimited projects", - "Unlimited issues", - "Advanced time tracking & reports", - "Sprint velocity tracking", - "Priority email support", - "Custom issue statuses", - "Role-based permissions", - ], - cta: "Try pro free for 14 days", - ctaLink: "/login", - highlighted: true, - }, -]; - -const faqs = [ - { - question: "Can I switch plans?", - answer: - "Yes, you can upgrade or downgrade at any time. Changes take effect immediately, and we'll prorate any charges.", - }, - { - question: "Is there a free trial?", - answer: "Yes, pro plan includes a 14-day free trial with full access. No credit card required to start.", - }, - { - question: "What payment methods do you accept?", - answer: "We accept all major credit cards.", - }, - { - question: "What if I need more users?", - answer: - "Pro plan pricing scales with your team. Add or remove users anytime, and we'll adjust your billing automatically.", - }, - { - question: "What happens when my trial ends?", - answer: - "You'll automatically downgrade to the free starter plan. No charges unless you actively upgrade to pro.", - }, - { - question: "Can I cancel anytime?", - answer: - "Absolutely. Cancel anytime with no questions asked. You'll keep access until the end of your billing period.", - }, - { - question: "Do you offer refunds?", - answer: "Yes, we offer a 30-day money-back guarantee. If Sprint isn't right for you, just let us know.", - }, -]; - -export default function Pricing() { - const { user, isLoading } = useSession(); - const [billingPeriod, setBillingPeriod] = useState<"monthly" | "annual">("monthly"); - - return ( -
-
-
Sprint
- -
- -
-
- {/* header section */} -
-

Simple, transparent pricing

-

- Choose the plan that fits your team. Scale as you grow. -

- - {/* billing toggle */} -
- - - - - Save 17% - -
-
- - {/* pricing tiers */} -
- {pricingTiers.map((tier) => ( -
- {tier.highlighted && ( -
- {tier.tagline} -
- )} - -
-

{tier.name}

- -
-
- - {billingPeriod === "annual" ? tier.priceAnnual : tier.price} - - - {billingPeriod === "annual" ? tier.periodAnnual : tier.period} - -
-
- -

{tier.description}

-
- -
    - {tier.features.map((feature) => ( -
  • - - {feature} -
  • - ))} -
- - -
- ))} -
- - {/* trust signals */} -
-
-
- -

Secure & Encrypted

-

Your data is encrypted and secure

-
-
- -

No Credit Card Required

-

Start your free trial today

-
-
- -

30-day money back

-

Cancel anytime, no questions

-
-
-
- - {/* faq section */} -
-

Frequently Asked Questions

-
- {faqs.map((faq) => ( -
-

{faq.question}

-

{faq.answer}

-
- ))} -
-
- - {/* final cta */} -
-

Still have questions?

-

- We're here to help. Get in touch with any questions. -

- - Contact Us - -
-
-
- - -
- ); -}