re-design public site
BIN
apps/public/public/demo-2/1.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
apps/public/public/demo-2/2.png
Normal file
|
After Width: | Height: | Size: 105 KiB |
BIN
apps/public/public/demo-2/3.png
Normal file
|
After Width: | Height: | Size: 99 KiB |
BIN
apps/public/public/demo-2/4.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
apps/public/public/demo-2/5.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
apps/public/public/demo-2/6.png
Normal file
|
After Width: | Height: | Size: 145 KiB |
BIN
apps/public/public/demo-2/7.png
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
apps/public/public/logo-white.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
@@ -13,25 +13,23 @@ import Image from 'next/image';
|
|||||||
const images = [
|
const images = [
|
||||||
{
|
{
|
||||||
title: 'Beautiful overview, everything is clickable to get more details',
|
title: 'Beautiful overview, everything is clickable to get more details',
|
||||||
url: '/demo/overview-min.png',
|
url: '/demo-2/1.png',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Histogram, perfect for showing active users',
|
title: 'Histogram, perfect for showing active users',
|
||||||
url: '/demo/histogram-min.png',
|
url: '/demo-2/2.png',
|
||||||
},
|
},
|
||||||
{ title: 'Make your overview public', url: '/demo/overview-share-min.png' },
|
{ title: 'Make your overview public', url: '/demo-2/3.png' },
|
||||||
{
|
{
|
||||||
title: 'See real time events from your users',
|
title: 'See real time events from your users',
|
||||||
url: '/demo/events-min.png',
|
url: '/demo-2/4.png',
|
||||||
},
|
},
|
||||||
{ title: 'The classic line chart', url: '/demo/line-min.png' },
|
{ title: 'The classic line chart', url: '/demo-2/5.png' },
|
||||||
{
|
{
|
||||||
title: 'Bar charts to see your most popular content',
|
title: 'Bar charts to see your most popular content',
|
||||||
url: '/demo/bar-min.png',
|
url: '/demo-2/6.png',
|
||||||
},
|
},
|
||||||
{ title: 'Get nice metric cards with graphs', url: '/demo/metrics-min.png' },
|
{ title: 'Get nice metric cards with graphs', url: '/demo-2/7.png' },
|
||||||
{ title: 'See where your events comes from', url: '/demo/worldmap-min.png' },
|
|
||||||
{ title: 'The classic pie chart', url: '/demo/pie-min.png' },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export function PreviewCarousel() {
|
export function PreviewCarousel() {
|
||||||
@@ -51,13 +49,18 @@ export function PreviewCarousel() {
|
|||||||
key={item.url}
|
key={item.url}
|
||||||
className="flex-[0_0_80%] max-w-3xl pl-8"
|
className="flex-[0_0_80%] max-w-3xl pl-8"
|
||||||
>
|
>
|
||||||
<div className="aspect-video">
|
<div
|
||||||
<div className="p-3 rounded-xl overflow-hidden bg-gradient-to-b from-blue-100/50 to-white/50">
|
style={{
|
||||||
|
aspectRatio: 2982 / 1484,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="p-1 rounded-xl overflow-hidden bg-gradient-to-b from-blue-100/50 to-white/50">
|
||||||
<Image
|
<Image
|
||||||
|
priority
|
||||||
className="w-full h-full object-cover rounded-lg"
|
className="w-full h-full object-cover rounded-lg"
|
||||||
src={item.url}
|
src={item.url}
|
||||||
width={1080}
|
width={2982 * 0.5}
|
||||||
height={608}
|
height={1484 * 0.5}
|
||||||
alt={item.title}
|
alt={item.title}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -26,7 +26,10 @@ export function Paragraph({ children, className }: Props) {
|
|||||||
export function Heading1({ children, className }: Props) {
|
export function Heading1({ children, className }: Props) {
|
||||||
return (
|
return (
|
||||||
<h1
|
<h1
|
||||||
className={cn('text-4xl md:text-5xl font-bold text-slate-800', className)}
|
className={cn(
|
||||||
|
'text-4xl md:text-5xl font-bold text-slate-800 !leading-tight',
|
||||||
|
className
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</h1>
|
</h1>
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ export default function Footer() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="overflow-hidden rounded-xl">
|
<div className="overflow-hidden rounded-xl">
|
||||||
<div className="p-3 bg-white/20">
|
<div className="p-2 bg-white/20">
|
||||||
<Image
|
<Image
|
||||||
src="/demo/overview-min.png"
|
src="/demo-2/1.png"
|
||||||
width={1080}
|
width={1080}
|
||||||
height={608}
|
height={608}
|
||||||
alt="Openpanel overview page"
|
alt="Openpanel overview page"
|
||||||
@@ -31,13 +31,13 @@ export default function Footer() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="absolute bottom-0 left-0 right-0">
|
<div className="-mt-8 relative z-10">
|
||||||
<div className="h-px w-full bg-[radial-gradient(circle,rgba(255,255,255,0.7)_0%,rgba(255,255,255,0.7)_50%,rgba(255,255,255,0)_100%)]"></div>
|
<div className="h-px w-full bg-[radial-gradient(circle,rgba(255,255,255,0.7)_0%,rgba(255,255,255,0.7)_50%,rgba(255,255,255,0)_100%)]"></div>
|
||||||
<div className="p-4 bg-blue-darker">
|
<div className="p-4 bg-blue-darker">
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="flex justify-between items-center text-sm">
|
<div className="flex flex-col gap-4 md:flex-row md:justify-between md:items-center text-sm">
|
||||||
<Logo />
|
<Logo />
|
||||||
<div className="flex gap-4">
|
<div className="flex flex-col md:flex-row gap-4">
|
||||||
<Link className="hover:underline" href="/terms">
|
<Link className="hover:underline" href="/terms">
|
||||||
Terms and Conditions
|
Terms and Conditions
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -1,76 +1,56 @@
|
|||||||
// background-image: radial-gradient(circle at 1px 1px, black 1px, transparent 0);
|
|
||||||
// background-size: 40px 40px;
|
|
||||||
|
|
||||||
import { Logo } from '@/components/Logo';
|
|
||||||
import {
|
|
||||||
BarChart2Icon,
|
|
||||||
CookieIcon,
|
|
||||||
Globe2Icon,
|
|
||||||
LayoutPanelTopIcon,
|
|
||||||
LockIcon,
|
|
||||||
ServerIcon,
|
|
||||||
} from 'lucide-react';
|
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
|
|
||||||
import { Heading1, Lead, Lead2 } from './copy';
|
import { PreviewCarousel } from './carousel';
|
||||||
import { JoinWaitlist } from './join-waitlist';
|
import { Heading1, Lead2 } from './copy';
|
||||||
|
import { JoinWaitlistHero } from './join-waitlist-hero';
|
||||||
|
|
||||||
const features = [
|
const avatars = [
|
||||||
{
|
'https://api.dicebear.com/7.x/adventurer/svg?seed=Chester&backgroundColor=b6e3f4',
|
||||||
title: 'Great overview',
|
'https://api.dicebear.com/7.x/adventurer/svg?seed=Casper&backgroundColor=c0aede',
|
||||||
icon: LayoutPanelTopIcon,
|
'https://api.dicebear.com/7.x/adventurer/svg?seed=Boo&backgroundColor=ffdfbf',
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Beautiful charts',
|
|
||||||
icon: BarChart2Icon,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Privacy focused',
|
|
||||||
icon: LockIcon,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Open-source',
|
|
||||||
icon: Globe2Icon,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'No cookies',
|
|
||||||
icon: CookieIcon,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Self-hosted',
|
|
||||||
icon: ServerIcon,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export function Hero({ waitlistCount }: { waitlistCount: number }) {
|
export function Hero({ waitlistCount }: { waitlistCount: number }) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center w-full text-center text-blue-950">
|
<div className="flex py-32 flex-col items-center w-full text-center bg-[#1F54FF] relative overflow-hidden">
|
||||||
<div className="pt-32 pb-56 p-4 flex flex-col items-center max-w-3xl bg-[radial-gradient(circle,rgba(255,255,255,0.7)_0%,rgba(255,255,255,0.7)_50%,rgba(255,255,255,0)_100%)]">
|
{/* <div className="inset-0 absolute h-full w-full bg-[radial-gradient(circle,rgba(255,255,255,0.1)_0%,rgba(255,255,255,0)_100%)]"></div> */}
|
||||||
<Heading1 className="mb-4">
|
<div className="inset-0 absolute h-full w-full flex items-center justify-center">
|
||||||
|
<div className="w-[600px] h-[600px] ring-1 ring-white/05 rounded-full shrink-0"></div>
|
||||||
|
</div>
|
||||||
|
<div className="inset-0 absolute h-full w-full flex items-center justify-center">
|
||||||
|
<div className="w-[900px] h-[900px] ring-1 ring-white/10 rounded-full shrink-0"></div>
|
||||||
|
</div>
|
||||||
|
<div className="inset-0 absolute h-full w-full flex items-center justify-center">
|
||||||
|
<div className="w-[1200px] h-[1200px] ring-1 ring-white/20 rounded-full shrink-0"></div>
|
||||||
|
</div>
|
||||||
|
<div className="relative flex flex-col items-center max-w-3xl">
|
||||||
|
<Image
|
||||||
|
width={64}
|
||||||
|
height={64}
|
||||||
|
src="/logo-white.png"
|
||||||
|
alt="Openpanel Logo"
|
||||||
|
className="w-16 h-16 mb-8"
|
||||||
|
/>
|
||||||
|
<Heading1 className="mb-4 text-white">
|
||||||
An open-source
|
An open-source
|
||||||
<br />
|
<br />
|
||||||
alternative to Mixpanel
|
alternative to Mixpanel
|
||||||
</Heading1>
|
</Heading1>
|
||||||
<p>
|
<Lead2 className="text-white/70 font-light">
|
||||||
Mixpanel + Plausible ={' '}
|
Mixpanel + Plausible = <span className="text-white">Openpanel!</span>{' '}
|
||||||
<strong className="text-blue-600">Openpanel!</strong> A simple
|
<br />A simple analytics tool that your wallet can afford.
|
||||||
analytics tool that your wallet can afford.
|
</Lead2>
|
||||||
</p>
|
|
||||||
<div className="my-12 w-full flex flex-col items-center">
|
<div className="my-12 w-full flex flex-col items-center">
|
||||||
<JoinWaitlist />
|
<JoinWaitlistHero />
|
||||||
<div className="mt-2">
|
<div className="mt-6 flex justify-center items-center">
|
||||||
<p>{waitlistCount} people have already signed up! 🚀</p>
|
<p className="text-white">
|
||||||
|
{waitlistCount} people have already signed up! 🚀
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-wrap gap-10 max-w-xl justify-center">
|
|
||||||
{features.map(({ icon: Icon, title }) => (
|
|
||||||
<div className="flex gap-2 items-center justify-center">
|
|
||||||
<Icon className="text-blue-light " />
|
|
||||||
{title}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<PreviewCarousel />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
128
apps/public/src/app/join-waitlist-hero.tsx
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from '@/components/ui/dialog';
|
||||||
|
import { cn } from '@/utils/cn';
|
||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
interface JoinWaitlistProps {
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function JoinWaitlistHero({ className }: JoinWaitlistProps) {
|
||||||
|
const [value, setValue] = useState('');
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [success, setSuccess] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (open) {
|
||||||
|
// @ts-ignore
|
||||||
|
window.openpanel.event('waitlist_open');
|
||||||
|
}
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (success) {
|
||||||
|
// @ts-ignore
|
||||||
|
window.openpanel.event('waitlist_success', {
|
||||||
|
email: value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [success]);
|
||||||
|
|
||||||
|
const renderSuccess = () => (
|
||||||
|
<DialogContent className="sm:max-w-[425px]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Thanks so much!</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
You're now on the waiting list. We'll let you know when we're ready.
|
||||||
|
Should be within a month or two 🚀
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
|
||||||
|
<DialogFooter>
|
||||||
|
<Button onClick={() => setOpen(false)}>Got it!</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderForm = () => (
|
||||||
|
<DialogContent className="sm:max-w-[425px]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Almost there!</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Enter your email to join the waiting list. We'll let you know when
|
||||||
|
we're ready.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
fetch('/api/waitlist', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({ email: value }),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.ok) {
|
||||||
|
setSuccess(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="relative w-full">
|
||||||
|
<input
|
||||||
|
placeholder="Enter your email"
|
||||||
|
className={cn(
|
||||||
|
'border border-slate-100 rounded-md shadow-sm bg-white h-12 w-full px-4 outline-none focus:ring-1 ring-black text-blue-darker',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
value={value}
|
||||||
|
onChange={(e) => setValue(e.target.value)}
|
||||||
|
/>
|
||||||
|
<Button type="submit" className="absolute right-1 top-1">
|
||||||
|
Join waitlist
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</DialogContent>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
|
{success ? renderSuccess() : renderForm()}
|
||||||
|
</Dialog>
|
||||||
|
<div className="flex gap-4">
|
||||||
|
<Button
|
||||||
|
size="lg"
|
||||||
|
className="text-lg h-12"
|
||||||
|
onClick={() => {
|
||||||
|
setOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Join waitlist now
|
||||||
|
</Button>
|
||||||
|
<Link
|
||||||
|
href="https://dashboard.openpanel.dev/share/overview/ZQsEhG"
|
||||||
|
target="_blank"
|
||||||
|
rel="nofollow"
|
||||||
|
>
|
||||||
|
<Button size="lg" variant="outline" className="text-lg h-12">
|
||||||
|
Demo
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@ import { cn } from '@/utils/cn';
|
|||||||
|
|
||||||
import '@/styles/globals.css';
|
import '@/styles/globals.css';
|
||||||
|
|
||||||
import { Logo } from '@/components/Logo';
|
|
||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { Bricolage_Grotesque } from 'next/font/google';
|
import { Bricolage_Grotesque } from 'next/font/google';
|
||||||
import Script from 'next/script';
|
import Script from 'next/script';
|
||||||
@@ -36,13 +35,6 @@ export default function RootLayout({
|
|||||||
font.className
|
font.className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="absolute top-0 left-0 right-0 py-6 z-10">
|
|
||||||
<div className="container">
|
|
||||||
<div className="flex justify-between">
|
|
||||||
<Logo />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
className="w-full h-screen text-blue-950 bg-[radial-gradient(circle_at_2px_2px,#D9DEF6_2px,transparent_0)] absolute top-0 left-0 right-0 z-0"
|
className="w-full h-screen text-blue-950 bg-[radial-gradient(circle_at_2px_2px,#D9DEF6_2px,transparent_0)] absolute top-0 left-0 right-0 z-0"
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
|
|
||||||
const title = 'Openpanel.dev | An open-source alternative to Mixpanel';
|
const title = 'An open-source alternative to Mixpanel | Openpanel.dev';
|
||||||
const description =
|
const description =
|
||||||
'Unlock actionable insights effortlessly with Insightful, the open-source analytics library that combines the power of Mixpanel with the simplicity of Plausible. Enjoy a unified overview, predictable pricing, and a vibrant community. Join us in democratizing analytics today!';
|
'Unlock actionable insights effortlessly with Insightful, the open-source analytics library that combines the power of Mixpanel with the simplicity of Plausible. Enjoy a unified overview, predictable pricing, and a vibrant community. Join us in democratizing analytics today!';
|
||||||
|
|
||||||
|
|||||||
@@ -13,13 +13,8 @@ export default async function Page() {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Hero waitlistCount={waitlistCount} />
|
<Hero waitlistCount={waitlistCount} />
|
||||||
<div className="bg-gradient-to-b from-blue-light to-[#FFFFFF] pb-16 text-center">
|
|
||||||
<div className="relative -top-20">
|
|
||||||
<PreviewCarousel />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="mb-24">
|
<div className="my-24">
|
||||||
<Heading2 className="md:text-5xl mb-2 leading-none">
|
<Heading2 className="md:text-5xl mb-2 leading-none">
|
||||||
Analytics should be easy
|
Analytics should be easy
|
||||||
<br />
|
<br />
|
||||||
|
|||||||
@@ -10,29 +10,23 @@ import {
|
|||||||
CheckCircle,
|
CheckCircle,
|
||||||
ClockIcon,
|
ClockIcon,
|
||||||
CloudIcon,
|
CloudIcon,
|
||||||
CloudLightning,
|
|
||||||
CloudLightningIcon,
|
CloudLightningIcon,
|
||||||
CompassIcon,
|
CompassIcon,
|
||||||
ConeIcon,
|
ConeIcon,
|
||||||
DatabaseIcon,
|
DatabaseIcon,
|
||||||
DollarSignIcon,
|
DollarSignIcon,
|
||||||
DownloadIcon,
|
DownloadIcon,
|
||||||
FileIcon,
|
|
||||||
FilterIcon,
|
FilterIcon,
|
||||||
FolderIcon,
|
FolderIcon,
|
||||||
FolderOpenIcon,
|
|
||||||
HandCoinsIcon,
|
HandCoinsIcon,
|
||||||
HandshakeIcon,
|
HandshakeIcon,
|
||||||
KeyIcon,
|
KeyIcon,
|
||||||
PieChartIcon,
|
PieChartIcon,
|
||||||
PointerIcon,
|
|
||||||
RouteIcon,
|
RouteIcon,
|
||||||
ServerIcon,
|
ServerIcon,
|
||||||
ShieldPlusIcon,
|
ShieldPlusIcon,
|
||||||
ShoppingCartIcon,
|
ShoppingCartIcon,
|
||||||
SquareUserRound,
|
|
||||||
StarIcon,
|
StarIcon,
|
||||||
ThumbsUp,
|
|
||||||
ThumbsUpIcon,
|
ThumbsUpIcon,
|
||||||
TrendingUpIcon,
|
TrendingUpIcon,
|
||||||
UserRoundSearchIcon,
|
UserRoundSearchIcon,
|
||||||
@@ -40,23 +34,11 @@ import {
|
|||||||
WebhookIcon,
|
WebhookIcon,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
|
|
||||||
import {
|
|
||||||
Blob1,
|
|
||||||
Blob2,
|
|
||||||
Blob3,
|
|
||||||
Blob4,
|
|
||||||
Blob5,
|
|
||||||
Blob6,
|
|
||||||
Blob7,
|
|
||||||
Blob8,
|
|
||||||
Blob9,
|
|
||||||
} from './blob';
|
|
||||||
import { Heading2, Lead2 } from './copy';
|
|
||||||
import { Widget } from './widget';
|
import { Widget } from './widget';
|
||||||
|
|
||||||
interface SectionItem {
|
interface SectionItem {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string | React.ReactNode;
|
||||||
icon: LucideIcon;
|
icon: LucideIcon;
|
||||||
color: string;
|
color: string;
|
||||||
soon?: string;
|
soon?: string;
|
||||||
@@ -67,8 +49,18 @@ interface SectionItem {
|
|||||||
const sections: SectionItem[] = [
|
const sections: SectionItem[] = [
|
||||||
{
|
{
|
||||||
title: 'Own Your Own Data',
|
title: 'Own Your Own Data',
|
||||||
description:
|
description: (
|
||||||
'Take control of your data privacy and ownership with our platform, ensuring full transparency and security.',
|
<>
|
||||||
|
<p>
|
||||||
|
Take control of your data privacy and ownership with our platform,
|
||||||
|
ensuring full transparency and security.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
All our serveres are hosted in EU (Stockholm) and we are fully GDPR
|
||||||
|
compliant.
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
),
|
||||||
icon: KeyIcon,
|
icon: KeyIcon,
|
||||||
color: '#2563EB',
|
color: '#2563EB',
|
||||||
icons: [FolderIcon, DatabaseIcon, ShieldPlusIcon, KeyIcon],
|
icons: [FolderIcon, DatabaseIcon, ShieldPlusIcon, KeyIcon],
|
||||||
@@ -76,8 +68,12 @@ const sections: SectionItem[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Cloud or Self-Hosting',
|
title: 'Cloud or Self-Hosting',
|
||||||
description:
|
description: (
|
||||||
'Choose between the flexibility of cloud-based hosting or the autonomy of self-hosting to tailor your analytics infrastructure to your needs.',
|
<p>
|
||||||
|
Choose between the flexibility of cloud-based hosting or the autonomy of
|
||||||
|
self-hosting to tailor your analytics infrastructure to your needs.
|
||||||
|
</p>
|
||||||
|
),
|
||||||
icon: CloudIcon,
|
icon: CloudIcon,
|
||||||
color: '#ff7557',
|
color: '#ff7557',
|
||||||
icons: [CloudIcon, CheckCircle, ServerIcon, DownloadIcon],
|
icons: [CloudIcon, CheckCircle, ServerIcon, DownloadIcon],
|
||||||
@@ -85,8 +81,12 @@ const sections: SectionItem[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Real-Time Events',
|
title: 'Real-Time Events',
|
||||||
description:
|
description: (
|
||||||
'Stay up-to-date with real-time event tracking, enabling instant insights into user actions as they happen.',
|
<p>
|
||||||
|
Stay up-to-date with real-time event tracking, enabling instant insights
|
||||||
|
into user actions as they happen.
|
||||||
|
</p>
|
||||||
|
),
|
||||||
icon: ClockIcon,
|
icon: ClockIcon,
|
||||||
color: '#7fe1d8',
|
color: '#7fe1d8',
|
||||||
icons: [CloudLightningIcon, ShoppingCartIcon, ArrowUpFromDotIcon],
|
icons: [CloudLightningIcon, ShoppingCartIcon, ArrowUpFromDotIcon],
|
||||||
@@ -94,8 +94,13 @@ const sections: SectionItem[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Deep Dive into User Behaviors',
|
title: 'Deep Dive into User Behaviors',
|
||||||
description:
|
description: (
|
||||||
"Gain profound insights into user behavior with comprehensive analytics tools, allowing you to understand your audience's actions and preferences.",
|
<p>
|
||||||
|
Gain profound insights into user behavior with comprehensive analytics
|
||||||
|
tools, allowing you to understand your audience's actions and
|
||||||
|
preferences.
|
||||||
|
</p>
|
||||||
|
),
|
||||||
icon: UserRoundSearchIcon,
|
icon: UserRoundSearchIcon,
|
||||||
color: '#f8bc3c',
|
color: '#f8bc3c',
|
||||||
icons: [UsersIcon, RouteIcon, BookmarkIcon],
|
icons: [UsersIcon, RouteIcon, BookmarkIcon],
|
||||||
@@ -103,8 +108,12 @@ const sections: SectionItem[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Powerful Report Explorer',
|
title: 'Powerful Report Explorer',
|
||||||
description:
|
description: (
|
||||||
'Explore and analyze your data effortlessly with our powerful report explorer, simplifying the process of deriving meaningful insights.',
|
<p>
|
||||||
|
Explore and analyze your data effortlessly with our powerful report
|
||||||
|
explorer, simplifying the process of deriving meaningful insights.
|
||||||
|
</p>
|
||||||
|
),
|
||||||
icon: CompassIcon,
|
icon: CompassIcon,
|
||||||
color: '#b3596e',
|
color: '#b3596e',
|
||||||
icons: [ThumbsUpIcon, TrendingUpIcon, PieChartIcon, BarChart2Icon],
|
icons: [ThumbsUpIcon, TrendingUpIcon, PieChartIcon, BarChart2Icon],
|
||||||
@@ -113,8 +122,12 @@ const sections: SectionItem[] = [
|
|||||||
{
|
{
|
||||||
soon: 'Coming soon',
|
soon: 'Coming soon',
|
||||||
title: 'Funnels',
|
title: 'Funnels',
|
||||||
description:
|
description: (
|
||||||
'Track user conversion funnels seamlessly, providing valuable insights into user journey optimization.',
|
<p>
|
||||||
|
Track user conversion funnels seamlessly, providing valuable insights
|
||||||
|
into user journey optimization.
|
||||||
|
</p>
|
||||||
|
),
|
||||||
icon: ConeIcon,
|
icon: ConeIcon,
|
||||||
color: '#72bef4',
|
color: '#72bef4',
|
||||||
icons: [ConeIcon, FilterIcon],
|
icons: [ConeIcon, FilterIcon],
|
||||||
@@ -123,8 +136,13 @@ const sections: SectionItem[] = [
|
|||||||
{
|
{
|
||||||
soon: 'Coming with our native app',
|
soon: 'Coming with our native app',
|
||||||
title: 'Push Notifications',
|
title: 'Push Notifications',
|
||||||
description:
|
description: (
|
||||||
'Stay informed about conversions, events, and peaks with our upcoming push notification tool, empowering you to monitor and respond to critical activities in real-time.',
|
<p>
|
||||||
|
Stay informed about conversions, events, and peaks with our upcoming
|
||||||
|
push notification tool, empowering you to monitor and respond to
|
||||||
|
critical activities in real-time.
|
||||||
|
</p>
|
||||||
|
),
|
||||||
icon: BellIcon,
|
icon: BellIcon,
|
||||||
color: '#ffb27a',
|
color: '#ffb27a',
|
||||||
icons: [WebhookIcon, BellIcon],
|
icons: [WebhookIcon, BellIcon],
|
||||||
@@ -132,8 +150,12 @@ const sections: SectionItem[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Cost-Effective Alternative to Mixpanel',
|
title: 'Cost-Effective Alternative to Mixpanel',
|
||||||
description:
|
description: (
|
||||||
'Enjoy the same powerful analytics capabilities as Mixpanel at a fraction of the cost, ensuring affordability without compromising on quality.',
|
<p>
|
||||||
|
Enjoy the same powerful analytics capabilities as Mixpanel at a fraction
|
||||||
|
of the cost, ensuring affordability without compromising on quality.
|
||||||
|
</p>
|
||||||
|
),
|
||||||
icon: DollarSignIcon,
|
icon: DollarSignIcon,
|
||||||
color: '#0f7ea0',
|
color: '#0f7ea0',
|
||||||
icons: [DollarSignIcon, HandCoinsIcon, HandshakeIcon, StarIcon],
|
icons: [DollarSignIcon, HandCoinsIcon, HandshakeIcon, StarIcon],
|
||||||
@@ -142,8 +164,13 @@ const sections: SectionItem[] = [
|
|||||||
{
|
{
|
||||||
soon: 'Something Plausible lacks',
|
soon: 'Something Plausible lacks',
|
||||||
title: 'Great Support for React Native',
|
title: 'Great Support for React Native',
|
||||||
description:
|
description: (
|
||||||
'Benefit from robust support for React Native, ensuring seamless integration and compatibility for your projects, a feature notably lacking in other platforms like Plausible.',
|
<p>
|
||||||
|
Benefit from robust support for React Native, ensuring seamless
|
||||||
|
integration and compatibility for your projects, a feature notably
|
||||||
|
lacking in other platforms like Plausible.
|
||||||
|
</p>
|
||||||
|
),
|
||||||
icon: (({ className }: LucideProps) => {
|
icon: (({ className }: LucideProps) => {
|
||||||
return (
|
return (
|
||||||
<img src="/react-native.svg" alt="React Native" className={className} />
|
<img src="/react-native.svg" alt="React Native" className={className} />
|
||||||
@@ -151,7 +178,7 @@ const sections: SectionItem[] = [
|
|||||||
}) as unknown as LucideIcon,
|
}) as unknown as LucideIcon,
|
||||||
color: '#3ba974',
|
color: '#3ba974',
|
||||||
icons: [FolderIcon, DatabaseIcon, ShieldPlusIcon, KeyIcon],
|
icons: [FolderIcon, DatabaseIcon, ShieldPlusIcon, KeyIcon],
|
||||||
className: 'bg-[#f8bc3c]',
|
className: 'bg-[#e19900]',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -187,7 +214,7 @@ export function Sections() {
|
|||||||
: ['-top-10 -left-20 rotate-12', 'top-10 -rotate-12', '-right-5'];
|
: ['-top-10 -left-20 rotate-12', 'top-10 -rotate-12', '-right-5'];
|
||||||
|
|
||||||
const className = even
|
const className = even
|
||||||
? cn('text-white [&_h3]:text-white col-span-2', section.className)
|
? cn('[&_*]:text-white/90 col-span-2', section.className)
|
||||||
: cn('border border-border', section.className);
|
: cn('border border-border', section.className);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -198,7 +225,7 @@ export function Sections() {
|
|||||||
icons={section.icons}
|
icons={section.icons}
|
||||||
offsets={offsets}
|
offsets={offsets}
|
||||||
>
|
>
|
||||||
<p>{section.description}</p>
|
{section.description}
|
||||||
</Widget>
|
</Widget>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ export function Widget({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'p-10 rounded-xl relative overflow-hidden flex flex-col hover:scale-105 transition-all duration-300 ease-in-out bg-white hover:shadow min-h-[300px] max-md:col-span-3',
|
'p-10 rounded-xl relative overflow-hidden flex flex-col hover:scale-[101%] transition-all duration-300 ease-in-out bg-white hover:shadow min-h-[300px] max-md:col-span-3',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Heading3 className="mb-4">{title}</Heading3>
|
<Heading3 className="mb-2">{title}</Heading3>
|
||||||
{children}
|
<div className="prose-xl">{children}</div>
|
||||||
<div className="flex justify-between mt-auto">
|
<div className="flex justify-between mt-auto">
|
||||||
{icons.map((Icon, i) => (
|
{icons.map((Icon, i) => (
|
||||||
<Icon
|
<Icon
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const DialogOverlay = React.forwardRef<
|
|||||||
<DialogPrimitive.Overlay
|
<DialogPrimitive.Overlay
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
|
'fixed inset-0 z-50 bg-black/50 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export default async function Page({ params: { id } }: PageProps) {
|
|||||||
<div className="p-4 flex gap-2 justify-between">
|
<div className="p-4 flex gap-2 justify-between">
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<OverviewReportRange />
|
<OverviewReportRange />
|
||||||
<OverviewFiltersDrawer projectId={projectId} mode="events" />
|
{/* <OverviewFiltersDrawer projectId={projectId} mode="events" /> */}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<ServerLiveCounter projectId={projectId} />
|
<ServerLiveCounter projectId={projectId} />
|
||||||
|
|||||||