diff --git a/app/about/page.tsx b/app/about/page.tsx index d88875e..de0fd59 100644 --- a/app/about/page.tsx +++ b/app/about/page.tsx @@ -1,5 +1,6 @@ 'use client' +import { motion } from 'framer-motion' import { CheckCircleIcon, XIcon } from '@ciphera-net/ui' function ComparisonTable({ title, competitors }: { title: string, competitors: { name: string, isPulse: boolean, features: Record }[] }) { @@ -68,7 +69,12 @@ export default function AboutPage() {
-
+

Why Pulse?

@@ -76,14 +82,19 @@ export default function AboutPage() { We built Pulse because we were tired of complex, invasive analytics tools. Here is how we stack up against the giants.

-
+ -
+

Most analytics tools are overkill. They track everything, slow down your site, and require annoying cookie banners. Pulse is different. We focus on the metrics that actually matter—visitors, pageviews, and sources—while respecting user privacy.

-
+ {/* * Comparison: Pulse vs Google Analytics */} -
+

What about Plausible?

We love Plausible! They paved the way for privacy-friendly analytics. Pulse offers a similar philosophy but with a focus on even deeper integration with the Ciphera ecosystem and more flexible pricing for developers.

-
+
diff --git a/app/integrations/page.tsx b/app/integrations/page.tsx index b372bb3..3932ebc 100644 --- a/app/integrations/page.tsx +++ b/app/integrations/page.tsx @@ -1,6 +1,7 @@ 'use client' import Link from 'next/link' +import { motion } from 'framer-motion' import { ArrowRightIcon } from '@ciphera-net/ui' const integrations = [ @@ -62,22 +63,33 @@ export default function IntegrationsPage() {
-
+

Integrations

Connect Pulse with your favorite frameworks and platforms in minutes.

-
+
- {integrations.map((integration) => ( - ( + +
{integration.icon} @@ -111,7 +123,7 @@ export default function IntegrationsPage() { > Request Integration -
+
diff --git a/app/page.tsx b/app/page.tsx index 12068fd..fbbc409 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react' import Link from 'next/link' +import { motion } from 'framer-motion' import { useAuth } from '@/lib/auth/context' import { initiateOAuthFlow, initiateSignupFlow } from '@/lib/api/oauth' import { listSites, deleteSite, type Site } from '@/lib/api/sites' @@ -172,16 +173,26 @@ export default function HomePage() {
{/* * --- 2. BADGE --- */} -
+ Privacy-First Analytics -
+ {/* * --- 3. HEADLINE --- */}
-

+ Simple analytics for
privacy-conscious @@ -191,22 +202,32 @@ export default function HomePage() { {' '}apps. -

+ -

+ Respect your users' privacy while getting the insights you need. No cookies, no IP tracking, fully GDPR compliant. -

+ {/* * --- 4. CTAs --- */} -
+ -
+
{/* * NEW: DASHBOARD PREVIEW */} @@ -219,7 +240,14 @@ export default function HomePage() { { icon: BarChartIcon, title: "Simple Insights", desc: "Get the metrics that matter without the clutter. Page views, visitors, and sources." }, { icon: ZapIcon, title: "Lightweight", desc: "Our script is less than 1kb. It won't slow down your site or affect your SEO." } ].map((feature, i) => ( -
+
@@ -227,7 +255,7 @@ export default function HomePage() {

{feature.desc}

-
+ ))}
@@ -235,13 +263,19 @@ export default function HomePage() { {/* * NEW: CTA BOTTOM */} -
+

Ready to switch?

No credit card required • Cancel anytime

-
+ diff --git a/app/sites/[id]/page.tsx b/app/sites/[id]/page.tsx index c10d051..0cc200c 100644 --- a/app/sites/[id]/page.tsx +++ b/app/sites/[id]/page.tsx @@ -3,6 +3,7 @@ import { useAuth } from '@/lib/auth/context' import { useEffect, useState } from 'react' import { useParams, useRouter } from 'next/navigation' +import { motion } from 'framer-motion' import { getSite, type Site } from '@/lib/api/sites' import { getStats, getRealtime, getDailyStats, getTopPages, getTopReferrers, getCountries, getCities, getRegions, getBrowsers, getOS, getDevices, getScreenResolutions, getEntryPages, getExitPages, getDashboard, getPerformanceByPage, type Stats, type DailyStat, type PerformanceByPageStat } from '@/lib/api/stats' import { formatNumber, formatDuration, getDateRange } from '@/lib/utils/format' @@ -225,7 +226,12 @@ export default function SiteDashboardPage() { } return ( -
+
@@ -417,6 +423,6 @@ export default function SiteDashboardPage() { topPages={topPages} topReferrers={topReferrers} /> -
+ ) } diff --git a/app/sites/[id]/realtime/page.tsx b/app/sites/[id]/realtime/page.tsx index 671986b..40e9351 100644 --- a/app/sites/[id]/realtime/page.tsx +++ b/app/sites/[id]/realtime/page.tsx @@ -7,6 +7,7 @@ import { getRealtimeVisitors, getSessionDetails, type Visitor, type SessionEvent import { toast } from '@ciphera-net/ui' import { getAuthErrorMessage } from '@/lib/utils/authErrors' import { LoadingOverlay, UserIcon } from '@ciphera-net/ui' +import { motion, AnimatePresence } from 'framer-motion' function formatTimeAgo(dateString: string) { const date = new Date(dateString) @@ -135,14 +136,19 @@ export default function RealtimePage() {
) : (
- {visitors.map((visitor) => ( - - ))} + + ))} +
)}
diff --git a/components/PricingSection.tsx b/components/PricingSection.tsx index 62570e7..f1001f1 100644 --- a/components/PricingSection.tsx +++ b/components/PricingSection.tsx @@ -2,6 +2,7 @@ import { useState, useEffect } from 'react' import { useSearchParams } from 'next/navigation' +import { motion } from 'framer-motion' import { Button, CheckCircleIcon } from '@ciphera-net/ui' import { useAuth } from '@/lib/auth/context' import { initiateOAuthFlow } from '@/lib/api/oauth' @@ -212,17 +213,27 @@ export default function PricingSection() { return (
-
+

Transparent Pricing

Scale with your traffic. No hidden fees.

-
+ {/* Unified Container */} -
+ {/* Top Toolbar */}
@@ -380,7 +391,7 @@ export default function PricingSection() {
-
+ ) } diff --git a/components/dashboard/Campaigns.tsx b/components/dashboard/Campaigns.tsx index b404795..b67765c 100644 --- a/components/dashboard/Campaigns.tsx +++ b/components/dashboard/Campaigns.tsx @@ -92,8 +92,9 @@ export default function Campaigns({ siteId, dateRange }: CampaignsProps) { {isLoading ? ( -
-

Loading...

+
+
+

Loading...

) : hasData ? (
@@ -152,7 +153,10 @@ export default function Campaigns({ siteId, dateRange }: CampaignsProps) { >
{isLoadingFull ? ( -
Loading...
+
+
+

Loading...

+
) : ( <>
diff --git a/components/dashboard/ContentStats.tsx b/components/dashboard/ContentStats.tsx index d21e3fe..c19277d 100644 --- a/components/dashboard/ContentStats.tsx +++ b/components/dashboard/ContentStats.tsx @@ -171,7 +171,10 @@ export default function ContentStats({ topPages, entryPages, exitPages, domain, >
{isLoadingFull ? ( -
Loading...
+
+
+

Loading...

+
) : ( (fullData.length > 0 ? fullData : data).map((page, index) => (
diff --git a/components/dashboard/Locations.tsx b/components/dashboard/Locations.tsx index eb77305..98519f1 100644 --- a/components/dashboard/Locations.tsx +++ b/components/dashboard/Locations.tsx @@ -286,7 +286,10 @@ export default function Locations({ countries, cities, regions, geoDataLevel = ' >
{isLoadingFull ? ( -
Loading...
+
+
+

Loading...

+
) : ( (fullData.length > 0 ? fullData : data as any[]).map((item, index) => (
diff --git a/components/dashboard/TechSpecs.tsx b/components/dashboard/TechSpecs.tsx index e5682a9..493c9e0 100644 --- a/components/dashboard/TechSpecs.tsx +++ b/components/dashboard/TechSpecs.tsx @@ -187,7 +187,10 @@ export default function TechSpecs({ browsers, os, devices, screenResolutions, co >
{isLoadingFull ? ( -
Loading...
+
+
+

Loading...

+
) : ( (fullData.length > 0 ? fullData : data).map((item, index) => (
diff --git a/components/dashboard/TopReferrers.tsx b/components/dashboard/TopReferrers.tsx index d398f82..20a3631 100644 --- a/components/dashboard/TopReferrers.tsx +++ b/components/dashboard/TopReferrers.tsx @@ -115,7 +115,10 @@ export default function TopReferrers({ referrers, collectReferrers = true, siteI >
{isLoadingFull ? ( -
Loading...
+
+
+

Loading...

+
) : ( (fullData.length > 0 ? fullData : filteredReferrers).map((ref, index) => (