From e3faab75884c944137f2e406d5a605fc63e5de7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl-Gerhard=20Lindesva=CC=88rd?= Date: Tue, 17 Feb 2026 00:16:08 +0100 Subject: [PATCH] public: new page and copy improvements --- .../features/_components/feature-card.tsx | 17 +- .../src/app/(content)/features/page.tsx | 55 +- .../(content)/open-source-analytics/page.tsx | 574 ++++++++++++++++++ .../(home)/_sections/analytics-insights.tsx | 34 +- .../src/app/(home)/_sections/data-privacy.tsx | 35 +- apps/public/src/app/(home)/_sections/faq.tsx | 13 +- apps/public/src/app/(home)/_sections/hero.tsx | 84 ++- .../src/app/(home)/_sections/pricing.tsx | 86 +-- apps/public/src/app/og/[...og]/route.tsx | 27 +- apps/public/src/app/sitemap.ts | 8 +- apps/public/src/components/feature-card.tsx | 25 +- apps/public/src/components/footer.tsx | 56 +- .../src/components/get-started-button.tsx | 8 +- .../illustrations/data-ownership.tsx | 0 .../illustrations/privacy.tsx | 0 .../illustrations/product-analytics.tsx | 0 .../illustrations/web-analytics.tsx | 0 apps/public/src/components/navbar.tsx | 8 +- apps/public/src/components/testimonial.tsx | 22 + apps/start/src/routes/__root.tsx | 311 +++++----- apps/start/src/routes/api/config.tsx | 10 +- apps/start/src/server/get-envs.ts | 5 +- 22 files changed, 1026 insertions(+), 352 deletions(-) create mode 100644 apps/public/src/app/(content)/open-source-analytics/page.tsx rename apps/public/src/{app/(home)/_sections => components}/illustrations/data-ownership.tsx (100%) rename apps/public/src/{app/(home)/_sections => components}/illustrations/privacy.tsx (100%) rename apps/public/src/{app/(home)/_sections => components}/illustrations/product-analytics.tsx (100%) rename apps/public/src/{app/(home)/_sections => components}/illustrations/web-analytics.tsx (100%) create mode 100644 apps/public/src/components/testimonial.tsx diff --git a/apps/public/src/app/(content)/features/_components/feature-card.tsx b/apps/public/src/app/(content)/features/_components/feature-card.tsx index b9378a9c..c5d59219 100644 --- a/apps/public/src/app/(content)/features/_components/feature-card.tsx +++ b/apps/public/src/app/(content)/features/_components/feature-card.tsx @@ -1,31 +1,34 @@ -import { FeatureCardContainer } from '@/components/feature-card'; -import { ArrowRightIcon } from 'lucide-react'; +import { ArrowRightIcon, type LucideIcon } from 'lucide-react'; import Link from 'next/link'; +import { FeatureCardContainer } from '@/components/feature-card'; interface FeatureCardLinkProps { url: string; title: string; description: string; + icon?: LucideIcon; } export function FeatureCardLink({ url, title, description, + icon: Icon, }: FeatureCardLinkProps) { return ( -
-
-

+
+
+ {Icon && } +

{title}

-

+

{description}

- +
diff --git a/apps/public/src/app/(content)/features/page.tsx b/apps/public/src/app/(content)/features/page.tsx index 3aacf597..d0de9271 100644 --- a/apps/public/src/app/(content)/features/page.tsx +++ b/apps/public/src/app/(content)/features/page.tsx @@ -1,3 +1,20 @@ +import type { LucideIcon } from 'lucide-react'; +import { + BellIcon, + ConeIcon, + DollarSignIcon, + FilterIcon, + GlobeIcon, + MonitorIcon, + MousePointerClickIcon, + PieChartIcon, + RefreshCwIcon, + ShareIcon, + UserIcon, + WorkflowIcon, +} from 'lucide-react'; +import type { Metadata } from 'next'; +import { FeatureCardLink } from './_components/feature-card'; import { FeatureHero } from '@/app/(content)/features/[slug]/_components/feature-hero'; import { CtaBanner } from '@/app/(home)/_sections/cta-banner'; import { Section, SectionHeader } from '@/components/section'; @@ -5,8 +22,21 @@ import { WindowImage } from '@/components/window-image'; import { url } from '@/lib/layout.shared'; import { getOgImageUrl, getPageMetadata } from '@/lib/metadata'; import { featureSource } from '@/lib/source'; -import type { Metadata } from 'next'; -import { FeatureCardLink } from './_components/feature-card'; + +const featureIcons: Record = { + conversion: FilterIcon, + 'data-visualization': PieChartIcon, + 'event-tracking': MousePointerClickIcon, + funnels: ConeIcon, + 'identify-users': UserIcon, + integrations: WorkflowIcon, + notifications: BellIcon, + retention: RefreshCwIcon, + 'revenue-tracking': DollarSignIcon, + 'session-tracking': MonitorIcon, + 'share-and-collaborate': ShareIcon, + 'web-analytics': GlobeIcon, +}; export const metadata: Metadata = getPageMetadata({ title: 'Product analytics features', @@ -32,36 +62,37 @@ export default async function FeaturesIndexPage() {
-
+
{features.map((feature) => ( ))}

); diff --git a/apps/public/src/app/(content)/open-source-analytics/page.tsx b/apps/public/src/app/(content)/open-source-analytics/page.tsx new file mode 100644 index 00000000..8352c9da --- /dev/null +++ b/apps/public/src/app/(content)/open-source-analytics/page.tsx @@ -0,0 +1,574 @@ +import { + ArrowRightIcon, + BarChart3Icon, + CalendarIcon, + CookieIcon, + GithubIcon, + InfinityIcon, + LayersIcon, + LineChartIcon, + RefreshCwIcon, + RocketIcon, + ServerIcon, + ShieldCheckIcon, + UnlockIcon, + UserIcon, + UsersIcon, +} from 'lucide-react'; +import type { Metadata } from 'next'; +import Link from 'next/link'; +import Script from 'next/script'; +import { CtaBanner } from '@/app/(home)/_sections/cta-banner'; +import { HeroContainer } from '@/app/(home)/_sections/hero'; +import { FaqItem, Faqs } from '@/components/faq'; +import { FeatureCard } from '@/components/feature-card'; +import { GetStartedButton } from '@/components/get-started-button'; +import { DataOwnershipIllustration } from '@/components/illustrations/data-ownership'; +import { PrivacyIllustration } from '@/components/illustrations/privacy'; +import { ProductAnalyticsIllustration } from '@/components/illustrations/product-analytics'; +import { WebAnalyticsIllustration } from '@/components/illustrations/web-analytics'; +import { Perks } from '@/components/perks'; +import { Section, SectionHeader } from '@/components/section'; +import { Testimonial } from '@/components/testimonial'; +import { Button } from '@/components/ui/button'; +import { WindowImage } from '@/components/window-image'; +import { url } from '@/lib/layout.shared'; +import { getOgImageUrl, getPageMetadata } from '@/lib/metadata'; +import { cn } from '@/lib/utils'; + +export const metadata: Metadata = getPageMetadata({ + title: 'Open Source Analytics | Web & Product Analytics Platform', + description: + 'OpenPanel is an open source analytics platform for web and product teams. Privacy-first, cookieless, self-hostable. Combine web analytics and product analytics in one tool. Free trial.', + url: url('/open-source-analytics'), + image: getOgImageUrl('/open-source-analytics'), +}); + +const jsonLd = { + '@context': 'https://schema.org', + '@type': 'WebPage', + name: 'Open Source Analytics | Web & Product Analytics Platform | OpenPanel', + description: + 'OpenPanel is an open source analytics platform for web and product teams. Privacy-first, cookieless, self-hostable. Combine web analytics and product analytics in one tool.', + url: url('/open-source-analytics'), + publisher: { + '@type': 'Organization', + name: 'OpenPanel', + logo: { + '@type': 'ImageObject', + url: url('/logo.png'), + }, + }, + mainEntity: { + '@type': 'SoftwareApplication', + name: 'OpenPanel', + applicationCategory: 'AnalyticsApplication', + operatingSystem: 'Web', + url: url('/'), + offers: { + '@type': 'Offer', + price: '0', + priceCurrency: 'USD', + description: 'Free 30-day trial, self-host for free', + }, + }, +}; + +const heroPerks = [ + { text: 'Open source (AGPL-3.0)', icon: GithubIcon }, + { text: 'Self-hostable', icon: ServerIcon }, + { text: 'Cookieless tracking', icon: CookieIcon }, + { text: 'GDPR compliant', icon: ShieldCheckIcon }, + { text: 'Web + product analytics', icon: BarChart3Icon }, + { text: '30-day free trial', icon: CalendarIcon }, +]; + +export default function OpenSourceAnalyticsPage() { + return ( +
+