Skip to content

Commit ccae025

Browse files
refactor(web): premium UI/UX overhaul of marketing and auth pages
1 parent be22f65 commit ccae025

16 files changed

Lines changed: 914 additions & 652 deletions

apps/web/app/features/page.tsx

Lines changed: 67 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,155 +1,150 @@
1-
import type { Metadata } from 'next';
2-
import { Activity, Layers, ReceiptText, RefreshCw, ShieldCheck, Users, Zap } from 'lucide-react';
1+
'use client';
2+
3+
import { Activity, Layers, ReceiptText, RefreshCw, ShieldCheck, Zap, Sparkles, Users } from 'lucide-react';
34
import { SectionContainer } from '../../components/layout/SectionContainer';
45
import { CTASection } from '../../components/marketing/CTASection';
56
import { FeatureCard } from '../../components/marketing/FeatureCard';
67
import { PageHeader } from '../../components/marketing/PageHeader';
7-
8-
export const metadata: Metadata = {
9-
title: 'Features | FairShare - Smart Expense Sharing',
10-
description: 'Explore the features that help groups track expenses, keep balances current, and settle up faster.',
11-
};
8+
import { GlassCard } from '../../components/ui/GlassCard';
129

1310
const featureList = [
1411
{
1512
title: 'Flexible split rules',
1613
description: 'Split equally, assign exact amounts, or use percentages when the group did not share costs evenly.',
1714
iconName: 'Zap' as const,
18-
colorClass: 'shadow-yellow-500/20',
15+
eyebrow: 'Dynamic Logic',
1916
},
2017
{
2118
title: 'Dedicated group spaces',
2219
description: 'Separate trips, roommates, and teams so each group has its own members, expenses, and running balance.',
2320
iconName: 'Users' as const,
24-
colorClass: 'shadow-cyan-500/20',
21+
eyebrow: 'Isolated Context',
2522
},
2623
{
2724
title: 'Instant balance updates',
2825
description: 'See balance changes instantly across all members after a new expense or settlement is recorded.',
2926
iconName: 'RefreshCw' as const,
30-
colorClass: 'shadow-purple-500/20',
27+
eyebrow: 'Real-time Sync',
3128
},
3229
{
3330
title: 'Receipts with context',
3431
description: 'Attach receipts to expenses so the group can confirm the details without searching old message threads.',
3532
iconName: 'ShieldCheck' as const,
36-
colorClass: 'shadow-pink-500/20',
33+
eyebrow: 'Transparency',
3734
},
3835
{
3936
title: 'Settlement simplification',
4037
description: 'Reduce multiple debts into the fewest practical payments so the group can settle up with less friction.',
4138
iconName: 'Layers' as const,
42-
colorClass: 'shadow-emerald-500/20',
39+
eyebrow: 'Smart Math',
4340
},
4441
{
4542
title: 'Activity visibility',
4643
description: 'Keep a running feed of what changed, who added it, and when the group balance moved.',
4744
iconName: 'Activity' as const,
48-
colorClass: 'shadow-orange-500/20',
45+
eyebrow: 'Audit Trail',
4946
},
5047
];
5148

52-
const detailSections = [
49+
const deepDiveSections = [
5350
{
54-
title: 'Capture the expense clearly',
55-
description:
56-
'FairShare helps the payer add the amount, choose the split method, and attach supporting details so everyone understands the record the first time.',
51+
title: 'Capture clearly',
52+
description: 'FairShare helps the payer add the amount, choose the split method, and attach supporting details instantly.',
5753
icon: ReceiptText,
54+
label: 'Step 01',
5855
},
5956
{
60-
title: 'Keep everyone in sync',
61-
description:
62-
'As expenses or settlements are added, balances update for the group right away. Members do not need to refresh a spreadsheet or ask for the latest total.',
57+
title: 'Stay in sync',
58+
description: 'As expenses land, balances update for the group right away. No more "who paid already?" questions.',
6359
icon: RefreshCw,
60+
label: 'Step 02',
6461
},
6562
{
66-
title: 'Close the loop faster',
67-
description:
68-
'Instead of manually tracing who owes whom, settlement suggestions turn a complicated set of debts into a smaller set of actions that are easy to complete.',
63+
title: 'Close the loop',
64+
description: 'Settlement suggestions turn a complicated set of debts into a small set of easy actions.',
6965
icon: Layers,
66+
label: 'Step 03',
7067
},
7168
];
7269

7370
export default function FeaturesPage() {
7471
return (
7572
<main className="min-h-screen overflow-hidden bg-[#030303] text-white">
7673
<div className="pointer-events-none fixed inset-0 grid-bg opacity-10" />
74+
<div className="pointer-events-none fixed top-0 left-1/4 h-[500px] w-full max-w-4xl bg-purple-600/5 blur-[120px]" />
7775

78-
<SectionContainer size="spacious" className="relative pt-10 sm:pt-14">
76+
<SectionContainer size="spacious" className="relative pt-20">
7977
<PageHeader
80-
eyebrow="Features"
81-
title="Everything your group needs to split expenses clearly."
82-
description="FairShare keeps shared spending organized with practical tools for logging expenses, tracking balances, and settling up without extra back-and-forth."
78+
eyebrow="Product Features"
79+
title="Everything your group needs to split bills clearly."
80+
description="FairShare keeps shared spending organized with practical tools for logging expenses, tracking balances, and settling up faster than ever."
81+
centered
8382
/>
8483
</SectionContainer>
8584

8685
<SectionContainer size="compact">
87-
<div className="grid gap-5 md:grid-cols-2 xl:grid-cols-3">
86+
<div className="grid gap-6 md:grid-cols-2 xl:grid-cols-3">
8887
{featureList.map((feature) => (
8988
<FeatureCard key={feature.title} {...feature} />
9089
))}
9190
</div>
9291
</SectionContainer>
9392

94-
<SectionContainer size="compact">
95-
<div className="grid gap-5 lg:grid-cols-3">
96-
{detailSections.map((section) => (
97-
<div key={section.title} className="marketing-card p-6 sm:p-7">
98-
<section.icon size={22} className="text-purple-300" />
99-
<h2 className="mt-5 text-2xl font-bold tracking-tight text-white">{section.title}</h2>
100-
<p className="mt-3 text-sm leading-6 text-zinc-300 sm:text-base sm:leading-7">{section.description}</p>
93+
<SectionContainer size="default">
94+
<div className="grid gap-12 lg:grid-cols-3">
95+
{deepDiveSections.map((section) => (
96+
<div key={section.title} className="relative group">
97+
<div className="text-[10px] font-bold uppercase tracking-[0.3em] text-zinc-600 mb-6 flex items-center gap-4">
98+
<div className="h-px flex-1 bg-white/5" />
99+
<span>{section.label}</span>
100+
<div className="h-px flex-1 bg-white/5" />
101+
</div>
102+
<section.icon size={32} className="text-purple-400 mb-6 transition-transform group-hover:scale-110" />
103+
<h2 className="text-2xl font-extrabold tracking-tight text-white mb-4">{section.title}</h2>
104+
<p className="text-sm leading-8 text-zinc-400 group-hover:text-zinc-300 transition-colors">{section.description}</p>
101105
</div>
102106
))}
103107
</div>
104108
</SectionContainer>
105109

106110
<SectionContainer size="compact">
107-
<div className="marketing-card p-6 sm:p-8 lg:p-10">
108-
<div className="grid gap-8 lg:grid-cols-[0.9fr_1.1fr] lg:items-start">
111+
<GlassCard className="p-10 sm:p-16 lg:p-20 border-white/10 bg-black/40">
112+
<div className="grid gap-12 lg:grid-cols-[0.9fr_1.1fr] lg:items-center">
109113
<div>
110-
<p className="text-sm font-semibold uppercase tracking-[0.22em] text-zinc-400">Why it works</p>
111-
<h2 className="mt-3 text-3xl font-bold tracking-tight text-white sm:text-4xl">
112-
Clear records, live balances, and less ambiguity for everyone involved.
114+
<span className="eyebrow-label mb-6">Versatility</span>
115+
<h2 className="text-4xl font-extrabold tracking-tight text-white sm:text-5xl">
116+
One app for every group situation.
113117
</h2>
114-
<p className="mt-4 text-base leading-7 text-zinc-300">
115-
Each part of the product is designed to reduce one of the common breakdowns in shared expense tracking: missing context, stale numbers, or unclear next steps.
118+
<p className="mt-8 text-lg leading-8 text-zinc-400">
119+
Each part of the product is designed to reduce common breakdowns: missing context, stale numbers, or unclear next steps.
116120
</p>
117121
</div>
118122
<div className="grid gap-4 sm:grid-cols-2">
119-
<div className="rounded-[1.75rem] border border-white/10 bg-white/[0.04] p-5">
120-
<h3 className="text-lg font-semibold text-white">For trips and events</h3>
121-
<p className="mt-2 text-sm leading-6 text-zinc-300">
122-
Track shared bookings, meals, rides, and one-off purchases without losing sight of who covered what.
123-
</p>
124-
</div>
125-
<div className="rounded-[1.75rem] border border-white/10 bg-white/[0.04] p-5">
126-
<h3 className="text-lg font-semibold text-white">For roommates</h3>
127-
<p className="mt-2 text-sm leading-6 text-zinc-300">
128-
Keep recurring household spending visible so rent add-ons, groceries, and utilities stay easy to reconcile.
129-
</p>
130-
</div>
131-
<div className="rounded-[1.75rem] border border-white/10 bg-white/[0.04] p-5 sm:col-span-2">
132-
<h3 className="text-lg font-semibold text-white">For teams and clubs</h3>
133-
<p className="mt-2 text-sm leading-6 text-zinc-300">
134-
Maintain a shared record for reimbursements and group purchases when multiple people are contributing across the same budget.
135-
</p>
136-
</div>
123+
{[
124+
{ title: 'For trips', desc: 'Track meals, rides, and one-off bookings easily.' },
125+
{ title: 'For roommates', desc: 'Keep rent, groceries, and utilities in check.' },
126+
{ title: 'For teams', desc: 'Maintain shared records for reimbursements.' },
127+
{ title: 'For clubs', desc: 'Manage budget contributions across members.' }
128+
].map((item, idx) => (
129+
<div key={idx} className="rounded-2xl border border-white/5 bg-white/[0.02] p-6 hover:bg-white/[0.04] transition-colors">
130+
<h3 className="font-bold text-white mb-2">{item.title}</h3>
131+
<p className="text-sm text-zinc-500">{item.desc}</p>
132+
</div>
133+
))}
137134
</div>
138135
</div>
139-
</div>
136+
</GlassCard>
140137
</SectionContainer>
141138

142-
<SectionContainer size="compact">
143-
<CTASection
144-
eyebrow="See FairShare in action"
145-
title="Start splitting expenses with a workflow people can actually follow."
146-
description="Create a group, add the first expense, and let FairShare keep the balances readable from there."
147-
primaryHref="/login"
148-
primaryLabel="Start Splitting"
149-
secondaryHref="/how-it-works"
150-
secondaryLabel="See How It Works"
151-
/>
152-
</SectionContainer>
139+
<CTASection
140+
eyebrow="Power your group spending"
141+
title="Stop guessing who owes what."
142+
description="Join thousands of users who trust FairShare to keep their group ledgers accurate and their settlements simple."
143+
primaryHref="/register"
144+
primaryLabel="Start Splitting"
145+
secondaryHref="/"
146+
secondaryLabel="Learn More"
147+
/>
153148
</main>
154149
);
155150
}

apps/web/app/globals.css

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,25 +48,25 @@
4848
.brutal-accent-line { border-left: 4px solid var(--fs-primary); }
4949

5050
.btn-royal {
51-
@apply rounded-xl px-6 py-3 font-bold transition-all duration-200 active:scale-95;
51+
@apply rounded-xl px-7 py-3.5 font-bold transition-all duration-200 active:scale-95;
5252
background: linear-gradient(135deg, var(--fs-primary), var(--fs-primary-hover));
5353
color: white;
54-
box-shadow: var(--fs-shadow-soft);
54+
box-shadow: 0 4px 15px -5px var(--fs-primary);
5555
position: relative;
5656
overflow: hidden;
5757
}
5858

5959
.btn-royal::after {
6060
content: '';
61-
@apply absolute left-1 right-1 top-0 h-px rounded-full bg-white opacity-30;
61+
@apply absolute left-1 right-1 top-px h-px rounded-full bg-white opacity-40;
6262
}
6363

6464
.btn-secondary {
65-
@apply inline-flex items-center justify-center rounded-xl border border-white/10 bg-white/[0.04] px-6 py-3 font-semibold text-white transition-all duration-200 hover:border-white/20 hover:bg-white/[0.08];
65+
@apply inline-flex items-center justify-center rounded-xl border border-white/5 bg-white/[0.03] px-7 py-3.5 font-bold text-white transition-all duration-200 hover:border-white/15 hover:bg-white/[0.08] backdrop-blur-xl;
6666
}
6767

6868
.eyebrow-label {
69-
@apply inline-flex items-center gap-2 rounded-full border border-white/10 bg-white/[0.04] px-4 py-2 text-[0.7rem] font-semibold uppercase tracking-[0.24em] text-zinc-300;
69+
@apply inline-flex items-center gap-2 rounded-full border border-purple-500/20 bg-purple-500/5 px-4 py-2 text-[0.65rem] font-bold uppercase tracking-[0.25em] text-purple-400;
7070
}
7171

7272
.neo-border {

apps/web/app/login/page.tsx

Lines changed: 70 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import Link from 'next/link';
44
import { useRouter, useSearchParams } from 'next/navigation';
55
import { FormEvent, useState } from 'react';
6+
import { ArrowRight } from 'lucide-react';
67
import { useAuth } from '../../src/components/auth/AuthProvider';
78

89
export default function LoginPage() {
@@ -31,67 +32,81 @@ export default function LoginPage() {
3132
};
3233

3334
return (
34-
<main className="mx-auto max-w-lg px-6 min-h-screen flex flex-col justify-center">
35-
<div className="text-center mb-10">
36-
<div className="w-16 h-16 bg-[var(--fs-primary)] rounded-2xl flex items-center justify-center mx-auto mb-6 shadow-xl relative overflow-hidden">
37-
<span className="text-white font-black text-3xl">FS</span>
38-
<div className="absolute top-0 left-0 right-0 h-px bg-white/30" />
39-
</div>
40-
<h1 className="text-4xl font-extrabold tracking-tight text-[var(--fs-text-primary)] mb-3">
41-
FairShare
42-
</h1>
43-
<p className="text-[var(--fs-text-secondary)] font-medium">
44-
Sign in to your royal SaaS dashboard
45-
</p>
46-
</div>
35+
<main className="relative min-h-screen overflow-hidden bg-[#030303] text-white flex flex-col justify-center px-6">
36+
{/* Background Ambience */}
37+
<div className="pointer-events-none absolute inset-0 grid-bg opacity-10" />
38+
<div className="pointer-events-none absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 h-[600px] w-full max-w-4xl bg-purple-600/5 blur-[120px]" />
4739

48-
<div className="card-royal p-10 bg-[var(--fs-surface)]">
49-
<form className="space-y-6" onSubmit={onSubmit}>
50-
<div className="space-y-2">
51-
<label className="text-sm font-bold text-[var(--fs-text-primary)]">Email Address</label>
52-
<input
53-
className="w-full bg-[var(--fs-background)] border border-[var(--fs-border)] rounded-xl p-4 font-medium text-[var(--fs-text-primary)] outline-none focus:border-[var(--fs-primary)] transition-all"
54-
placeholder="name@company.com"
55-
type="email"
56-
value={email}
57-
onChange={(event) => setEmail(event.target.value)}
58-
required
59-
/>
60-
</div>
40+
<div className="relative z-10 mx-auto w-full max-w-lg">
41+
<div className="text-center mb-10">
42+
<Link href="/" className="inline-flex h-16 w-16 items-center justify-center rounded-2xl bg-gradient-to-br from-purple-500 to-purple-700 shadow-xl shadow-purple-500/20 mb-6 group transition-transform hover:scale-105 active:scale-95">
43+
<span className="text-white font-black text-3xl">FS</span>
44+
</Link>
45+
<h1 className="text-4xl font-extrabold tracking-tight text-white mb-3">
46+
Welcome Back
47+
</h1>
48+
<p className="text-zinc-400 font-medium tracking-wide uppercase text-[10px] tracking-[0.2em]">
49+
Sign in to your FairShare account
50+
</p>
51+
</div>
6152

62-
<div className="space-y-2">
63-
<label className="text-sm font-bold text-[var(--fs-text-primary)]">Password</label>
64-
<input
65-
className="w-full bg-[var(--fs-background)] border border-[var(--fs-border)] rounded-xl p-4 font-medium text-[var(--fs-text-primary)] outline-none focus:border-[var(--fs-primary)] transition-all"
66-
placeholder="••••••••"
67-
type="password"
68-
value={password}
69-
onChange={(event) => setPassword(event.target.value)}
70-
required
71-
/>
72-
</div>
53+
<div className="relative overflow-hidden rounded-[2.5rem] border border-white/5 bg-white/[0.03] backdrop-blur-2xl p-8 sm:p-12 shadow-2xl">
54+
{/* Internal Glow */}
55+
<div className="absolute inset-0 bg-gradient-to-br from-purple-500/5 via-transparent to-transparent pointer-events-none" />
56+
57+
<form className="relative z-10 space-y-6" onSubmit={onSubmit}>
58+
<div className="space-y-2">
59+
<label className="text-[10px] font-bold uppercase tracking-[0.2em] text-zinc-500 ml-1">Email Address</label>
60+
<input
61+
className="w-full bg-white/5 border border-white/10 rounded-2xl p-4 font-medium text-white outline-none focus:border-purple-500/50 focus:bg-white/[0.08] transition-all"
62+
placeholder="name@company.com"
63+
type="email"
64+
value={email}
65+
onChange={(event) => setEmail(event.target.value)}
66+
required
67+
/>
68+
</div>
7369

74-
{error ? (
75-
<div className="bg-rose-500/10 border border-rose-500/20 p-4 rounded-xl text-rose-600 dark:text-rose-400 font-bold text-sm text-center">
76-
{error}
70+
<div className="space-y-2">
71+
<label className="text-[10px] font-bold uppercase tracking-[0.2em] text-zinc-500 ml-1">Password</label>
72+
<input
73+
className="w-full bg-white/5 border border-white/10 rounded-2xl p-4 font-medium text-white outline-none focus:border-purple-500/50 focus:bg-white/[0.08] transition-all"
74+
placeholder="••••••••"
75+
type="password"
76+
value={password}
77+
onChange={(event) => setPassword(event.target.value)}
78+
required
79+
/>
7780
</div>
78-
) : null}
7981

80-
<button
81-
className="btn-royal w-full"
82-
disabled={loading}
83-
type="submit"
84-
>
85-
{loading ? 'Signing in...' : 'Sign In'}
86-
</button>
82+
{error ? (
83+
<div className="bg-red-500/10 border border-red-500/20 p-4 rounded-xl text-red-400 font-bold text-sm text-center">
84+
{error}
85+
</div>
86+
) : null}
8787

88-
<p className="text-center text-sm font-bold text-[var(--fs-text-secondary)]">
89-
New here?{' '}
90-
<Link className="text-[var(--fs-primary)] hover:underline decoration-2 underline-offset-4" href="/register">
91-
Create account
92-
</Link>
93-
</p>
94-
</form>
88+
<button
89+
className="btn-royal w-full group py-4 h-14"
90+
disabled={loading}
91+
type="submit"
92+
>
93+
<span className="flex items-center justify-center gap-2">
94+
{loading ? 'Authenticating...' : 'Sign In'}
95+
{!loading && <ArrowRight size={18} className="transition-transform group-hover:translate-x-1" />}
96+
</span>
97+
</button>
98+
99+
<p className="text-center text-sm font-medium text-zinc-500">
100+
New to FairShare?{' '}
101+
<Link className="text-purple-400 hover:text-purple-300 transition-colors font-bold underline decoration-purple-500/30 underline-offset-8 decoration-2" href="/register">
102+
Create account
103+
</Link>
104+
</p>
105+
</form>
106+
107+
{/* Top light leak */}
108+
<div className="absolute top-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-white/15 to-transparent" />
109+
</div>
95110
</div>
96111
</main>
97112
);

0 commit comments

Comments
 (0)