Skip to content

Commit fce4717

Browse files
authored
website overhaul phase 1 (#75)
* overhaul phase 1 * fix pricing page * Update call-to-action text across multiple components to emphasize "Free Early Access" and remove redundant phrases about card requirements. * Refine pricing page text for clarity and precision regarding data handling and deletion policies. * small fix * rem stats bar * fix deploy * - verbose * hero * fix lints
1 parent 7e8428e commit fce4717

File tree

9 files changed

+1057
-459
lines changed

9 files changed

+1057
-459
lines changed

.github/workflows/deploy.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ jobs:
4444
4545
cd "$DEPLOY_DIR"
4646
git fetch origin
47+
git checkout -- .
48+
git clean -fd
4749
git checkout "$BRANCH"
4850
git reset --hard "origin/$BRANCH"
4951

website/app/components/WhatsAppWidget.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,19 +72,21 @@ export default function WhatsAppWidget() {
7272
const link = `https://wa.me/${number}?text=${encodeURIComponent(message)}`;
7373

7474
useEffect(() => {
75-
if (isOpen) {
76-
setIsAnimating(false);
77-
}
75+
if (!isOpen) return;
76+
const id = requestAnimationFrame(() => setIsAnimating(false));
77+
return () => cancelAnimationFrame(id);
7878
}, [isOpen]);
7979

8080
// Enter: after panel mounts, trigger transition from opacity-0 to opacity-100
8181
useEffect(() => {
8282
if (!isChatPanelOpen || isPanelClosing) return;
83-
setIsPanelEntered(false);
8483
const id = requestAnimationFrame(() => {
8584
requestAnimationFrame(() => setIsPanelEntered(true));
8685
});
87-
return () => cancelAnimationFrame(id);
86+
return () => {
87+
cancelAnimationFrame(id);
88+
setIsPanelEntered(false);
89+
};
8890
}, [isChatPanelOpen, isPanelClosing]);
8991

9092
// Close: run exit animation then unmount
@@ -101,7 +103,7 @@ export default function WhatsAppWidget() {
101103
return () => {
102104
if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current);
103105
};
104-
}, [isPanelClosing]);
106+
}, [isPanelClosing, closeWidget]);
105107

106108
const handleToggle = () => {
107109
if (isOpen) {

website/app/features/page.tsx

Lines changed: 74 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"use client";
22
import React from "react";
33
import Image from "next/image";
4+
import { useWhatsAppWidget } from "../contexts/WhatsAppWidgetContext";
45

56
// Channel icons as SVG components
67
const ChannelIcons = {
@@ -193,27 +194,28 @@ function ChannelBadge({ status }: { status: string }) {
193194
}
194195

195196
export default function FeaturesPage() {
197+
const { openWidget } = useWhatsAppWidget();
198+
196199
return (
197200
<main className="min-h-screen pt-32 pb-24 px-6 lg:px-8">
198201
<div className="relative z-10 mx-auto max-w-6xl">
199202

200203
{/* Header */}
201204
<div className="text-center mb-20 animate-slide-up">
202-
<h1 className="text-4xl lg:text-6xl font-bold text-white tracking-tight mb-6">
203-
Built for <span className="text-emerald-500">capturing your journey</span>
205+
<h1 className="text-4xl lg:text-6xl font-bold text-white tracking-tighter mb-6">
206+
Everything under the hood.
204207
</h1>
205208
<p className="text-xl text-slate-400 max-w-2xl mx-auto leading-relaxed">
206-
Voice logging, multi-channel chat, AI-powered insights, and a dashboard that turns
207-
your daily conversations into a visual story of your life.
209+
Channels, integrations, and features that make LogLife work. No app needed.
208210
</p>
209211
</div>
210212

211213
{/* Channels Section */}
212214
<section className="mb-24 animate-slide-up" style={{ animationDelay: "0.1s" }}>
213215
<div className="flex items-center justify-between mb-8">
214216
<div>
215-
<h2 className="text-3xl font-bold text-white mb-2">Channels</h2>
216-
<p className="text-slate-400">Journal from anywhere</p>
217+
<span className="text-emerald-400 tracking-widest text-sm font-semibold uppercase">Channels</span>
218+
<h2 className="text-3xl font-bold text-white mt-1 mb-2">Journal from anywhere</h2>
217219
</div>
218220
<div className="hidden sm:flex items-center gap-4 text-sm">
219221
<div className="flex items-center gap-2">
@@ -255,15 +257,8 @@ export default function FeaturesPage() {
255257
{/* Integrations Section (replaces Skills) */}
256258
<section className="mb-24 animate-slide-up" style={{ animationDelay: "0.2s" }}>
257259
<div className="mb-8">
258-
<div className="flex items-center gap-3 mb-2">
259-
<h2 className="text-3xl font-bold text-white">Integrations</h2>
260-
<span className="px-2.5 py-1 text-xs font-medium bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 rounded-full flex items-center gap-1">
261-
<svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
262-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
263-
</svg>
264-
Life telemetry
265-
</span>
266-
</div>
260+
<span className="text-emerald-400 tracking-widest text-sm font-semibold uppercase">Integrations</span>
261+
<h2 className="text-3xl font-bold text-white mt-1 mb-2">Life telemetry</h2>
267262
<p className="text-slate-400">Transparently collect the info you want documented on your journey</p>
268263
</div>
269264

@@ -290,8 +285,8 @@ export default function FeaturesPage() {
290285
{/* Platform Features */}
291286
<section className="mb-24 animate-slide-up" style={{ animationDelay: "0.3s" }}>
292287
<div className="mb-8">
293-
<h2 className="text-3xl font-bold text-white mb-2">Platform Features</h2>
294-
<p className="text-slate-400">Everything you need to capture, reflect, and grow</p>
288+
<span className="text-emerald-400 tracking-widest text-sm font-semibold uppercase">Platform</span>
289+
<h2 className="text-3xl font-bold text-white mt-1 mb-2">Everything you need to capture, reflect, and grow</h2>
295290
</div>
296291

297292
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-6">
@@ -308,57 +303,59 @@ export default function FeaturesPage() {
308303
</div>
309304
</section>
310305

311-
{/* What LogLife Adds */}
306+
{/* Category Comparison Table */}
312307
<section className="mb-24 animate-slide-up" style={{ animationDelay: "0.4s" }}>
313-
<div className="bg-gradient-to-br from-emerald-500/10 to-slate-900/50 border border-emerald-500/20 rounded-3xl p-8 md:p-12">
314-
<div className="text-center mb-10">
315-
<h2 className="text-3xl font-bold text-white mb-2">What LogLife Adds</h2>
316-
<p className="text-slate-400">On top of your existing chat and voice</p>
317-
</div>
318-
319-
<div className="grid sm:grid-cols-2 lg:grid-cols-5 gap-6">
320-
{[
321-
{ title: "No App Needed", description: "Primary interface is chat-native. E2E encryption built-in. No app to download.", icon: "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" },
322-
{ title: "Privacy by Design", description: "Open-source + self-host/local-first by default. No access by design.", icon: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" },
323-
{ title: "Deep Analytics", description: "D/W/M/Q/Y timeline + dashboard + memory graph as the product.", icon: "M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" },
324-
{ title: "Non-Prescriptive", description: "A capture system, not a coach. Advice only when you ask.", icon: "M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" },
325-
{ title: "Auto-Cancel on Inactivity", description: "Not using it? We\u2019ll cancel your subscription. We only want you paying if you\u2019re getting value.", icon: "M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" },
326-
].map((item, index) => (
327-
<div key={index} className="text-center">
328-
<div className="w-12 h-12 mx-auto mb-4 rounded-xl bg-emerald-500/20 border border-emerald-500/30 flex items-center justify-center">
329-
<svg className="w-6 h-6 text-emerald-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
330-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d={item.icon} />
331-
</svg>
332-
</div>
333-
<h3 className="text-lg font-semibold text-white mb-2">{item.title}</h3>
334-
<p className="text-sm text-slate-400">{item.description}</p>
335-
</div>
336-
))}
337-
</div>
338-
339-
<div className="mt-10 text-center">
340-
<a
341-
href="/signup"
342-
className="inline-flex items-center justify-center px-8 py-4 bg-emerald-600 hover:bg-emerald-500 text-white font-bold rounded-xl shadow-lg shadow-emerald-500/20 transition-all transform hover:scale-105"
343-
>
344-
Start Your Log
345-
<svg className="w-5 h-5 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
346-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 7l5 5m0 0l-5 5m5-5H6" />
347-
</svg>
348-
</a>
349-
</div>
308+
<div className="text-center mb-12">
309+
<span className="text-emerald-400 tracking-widest text-sm font-semibold uppercase">Where LogLife Fits</span>
310+
<h2 className="text-3xl lg:text-4xl font-bold text-white mt-3 mb-4">
311+
One tool to replace four.
312+
</h2>
313+
</div>
314+
315+
<div className="overflow-x-auto rounded-2xl border border-slate-700/50 max-w-3xl mx-auto">
316+
<table className="w-full text-sm">
317+
<thead>
318+
<tr className="bg-slate-800/60">
319+
<th className="text-left p-4 text-slate-300 font-semibold min-w-[180px]">Category</th>
320+
<th className="p-4 text-slate-400 font-medium text-center min-w-[100px]">Life context</th>
321+
<th className="p-4 text-slate-400 font-medium text-center min-w-[120px]">Action-oriented</th>
322+
<th className="p-4 text-slate-400 font-medium text-center min-w-[100px]">Habit record</th>
323+
</tr>
324+
</thead>
325+
<tbody>
326+
{[
327+
{ name: "Habit trackers", context: "x", action: "partial", habit: "check", highlight: false },
328+
{ name: "Health wearables", context: "x", action: "partial", habit: "partial", highlight: false },
329+
{ name: "Digital journaling", context: "check", action: "partial", habit: "partial", highlight: false },
330+
{ name: "AI coaching", context: "check", action: "check", habit: "x", highlight: false },
331+
{ name: "LogLife", context: "check", action: "check", habit: "check", highlight: true },
332+
].map((row, index) => (
333+
<tr
334+
key={index}
335+
className={`border-t border-slate-700/30 transition-colors ${
336+
row.highlight
337+
? "bg-emerald-500/10 border-emerald-500/30"
338+
: index % 2 === 0 ? "bg-slate-900/30" : "bg-slate-900/10"
339+
}`}
340+
>
341+
<td className={`p-4 ${row.highlight ? "text-emerald-400 font-bold" : "text-slate-300"}`}>{row.name}</td>
342+
<td className="p-4"><ComparisonIcon status={row.context} /></td>
343+
<td className="p-4"><ComparisonIcon status={row.action} /></td>
344+
<td className="p-4"><ComparisonIcon status={row.habit} /></td>
345+
</tr>
346+
))}
347+
</tbody>
348+
</table>
350349
</div>
351350
</section>
352351

353352
{/* Competitor Comparison Table */}
354353
<section className="animate-slide-up" style={{ animationDelay: "0.5s" }}>
355354
<div className="text-center mb-12">
356-
<h2 className="text-3xl lg:text-4xl font-bold text-white mb-4">
357-
How LogLife <span className="text-emerald-500">compares</span>
355+
<span className="text-emerald-400 tracking-widest text-sm font-semibold uppercase">How We Compare</span>
356+
<h2 className="text-3xl lg:text-4xl font-bold text-white mt-3 mb-4">
357+
LogLife vs. the leading AI journaling apps
358358
</h2>
359-
<p className="text-lg text-slate-400 max-w-2xl mx-auto">
360-
See how LogLife stacks up against the leading AI journaling apps.
361-
</p>
362359
</div>
363360

364361
<div className="overflow-x-auto rounded-2xl border border-slate-700/50">
@@ -411,6 +408,23 @@ export default function FeaturesPage() {
411408
</div>
412409
</section>
413410

411+
{/* CTA */}
412+
<section className="mt-24 text-center animate-slide-up" style={{ animationDelay: "0.6s" }}>
413+
<div className="bg-gradient-to-br from-emerald-500/10 to-slate-900/50 border border-emerald-500/20 rounded-3xl p-12">
414+
<h3 className="text-3xl font-bold tracking-tighter text-white mb-4">Ready to try it?</h3>
415+
<p className="text-lg text-slate-400 mb-8">No card needed.</p>
416+
<button
417+
onClick={openWidget}
418+
className="inline-flex items-center justify-center px-8 py-4 bg-emerald-600 hover:bg-emerald-500 text-white font-bold rounded-xl shadow-[0_0_24px_rgba(16,185,129,0.3)] transition-all transform hover:scale-105 cursor-pointer"
419+
>
420+
Free Early Access
421+
<svg className="w-5 h-5 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
422+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 7l5 5m0 0l-5 5m5-5H6" />
423+
</svg>
424+
</button>
425+
</div>
426+
</section>
427+
414428
</div>
415429
</main>
416430
);

website/app/globals.css

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,16 @@ body {
4444
font-family: Arial, Helvetica, sans-serif;
4545
}
4646

47-
/* Animation keyframes for hero section */
47+
/* Dot-grid background overlay */
48+
.dot-grid {
49+
background-image: radial-gradient(circle, rgba(148, 163, 184, 0.12) 1px, transparent 1px);
50+
background-size: 24px 24px;
51+
}
52+
53+
/* Animation keyframes */
4854
@keyframes fade-in {
49-
from {
50-
opacity: 0;
51-
}
52-
to {
53-
opacity: 1;
54-
}
55+
from { opacity: 0; }
56+
to { opacity: 1; }
5557
}
5658

5759
@keyframes slide-up {
@@ -89,3 +91,15 @@ body {
8991
animation: fade-in-on-scroll 0.6s ease-out;
9092
animation-fill-mode: both;
9193
}
94+
95+
/* Scroll-triggered reveal */
96+
.reveal {
97+
opacity: 0;
98+
transform: translateY(24px);
99+
transition: opacity 0.7s ease-out, transform 0.7s ease-out;
100+
}
101+
102+
.reveal.visible {
103+
opacity: 1;
104+
transform: translateY(0);
105+
}

0 commit comments

Comments
 (0)