Align visual style with Pages, Referrers, and Locations panels — flat
rows with hover state, rank numbers, muted count colors, and a
slide-in percentage on hover. Add empty slots for consistent height.
Add LRU cache provider (200 entries) to prevent unbounded SWR memory
growth. Clean up stale PKCE localStorage keys on app init. Cap chart
annotations to 20 visible reference lines with overflow indicator.
Globe and DottedMap now only render when the Locations section enters
the viewport via IntersectionObserver. Added changelog entries for
rate limit fallback, buffer improvements, and lazy loading.
Replace 5-second setInterval polling with EventSource connection to the
new /realtime/stream SSE endpoint. The server pushes visitor updates
instead of each client independently polling. Auto-reconnects on
connection drops.
Replace useDashboardOverview, useDashboardPages, useDashboardLocations,
useDashboardDevices, useDashboardReferrers, useDashboardPerformance, and
useDashboardGoals with a single useDashboard hook that calls the existing
/dashboard batch endpoint. This endpoint runs all queries in parallel on
the backend and caches the result in Redis (30s TTL).
Reduces dashboard requests from 12 to 6 per refresh cycle (50% reduction).
At 1,000 concurrent users: ~6,000 req/min instead of 12,000.
- Remove redundant prefixes from modal titles
- Remove -mx-2 from modal rows so hover rounds evenly on both sides
- Fix page filter using wrong dimension name (path -> page)
- Bump @ciphera-net/ui to 0.1.3 (fixes search input losing focus)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Widen modals from max-w-lg to max-w-2xl
- Increase max height from 60vh to 80vh
- Add hover percentage on each row (matching card behavior)
- Click any row to filter dashboard and close modal
The setInterval that drives the "Live · Xs ago" display was at the page level,
forcing all 10+ dashboard components to re-render every second. Now it lives
inside Chart — the only consumer — so the rest of the dashboard is unaffected.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reposition FrameCornersIcon from next to the title to the far right
of each card header (after tabs). Increase size from w-3.5 to w-4
and add hover background for better visibility and discoverability.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When navigating to dashboard with cached SWR data, setLastUpdatedAt
triggered a second full render of the entire dashboard immediately
after the first. Using a ref instead avoids this — the value still
updates and Chart reads it on the next 1-second tick re-render.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add ArrowsOutSimpleIcon next to each panel title (Pages, Referrers,
Locations, Technology, Campaigns) that opens the full-data modal.
Remove the old text-based 'View all' button from the bottom of lists.
Update changelog with performance and UI improvements.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DottedMap: move createMap, stagger helpers, and base dots path to module
scope so they compute once on module load and survive unmount/remount
cycles — eliminates all recomputation when switching tabs.
Dashboard: restore static imports for the 5 above-fold components
(Chart, ContentStats, TopReferrers, Locations, TechSpecs) now that
their heavy computations are memoized. Keeps below-fold components
(PerformanceStats, GoalStats, ScrollDepth, Campaigns, etc.) dynamic.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of rendering 8000 individual <circle> elements (each a React
node to reconcile), batch all map dots into a single <path d="...">
string. Reduces DOM nodes from ~8000 to 1 for the base map layer.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Chart: wrap chartData (Date formatting on every data point) and
metricsWithTrends in useMemo — these ran on every render.
Globe: memoize marker computation (Math.max + filter + map on every render).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Memoize createMap() in DottedMap (was regenerating 8000 SVG dots every
render) and convert 11 heavy dashboard components to next/dynamic imports
so the page shell renders instantly instead of blocking on one massive
render pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SiteNav now lives in the [id] layout instead of each page, so it stays
mounted during route transitions. Switching between Dashboard, Uptime,
Funnels, and Settings no longer flashes a full-page skeleton.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Drops in the exact 21st.dev FunnelChart component with motion/react,
curved bezier segments, layered rings, and spring hover animations.
Removes the previous custom SVG implementation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Swap the main site dashboard chart from a bar chart to a line chart
using 21st.dev's line-charts-6 component with dot grid background,
glow shadow, and animated active dots. Add Badge trend indicators
on metric cards using Phosphor icons. All existing features preserved
(annotations, comparison, export, live indicator, interval controls).
New UI primitives: line-charts-6, badge-2, card, button-1, avatar.
Added shadcn-compatible CSS variables and Tailwind color mappings.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces crude clip-path divs with SVG bezier paths matching the 21st.dev
reference: smooth curved sides, background glow, divider lines, centered
percentage pills, and labels on both sides.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the recharts BarChart with a custom funnel component using clip-path
trapezoid segments, framer-motion animations, and hover interactions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>