diff --git a/components/SelfGuidedTours-backup.tsx b/components/SelfGuidedTours-backup.tsx
new file mode 100644
index 0000000000..36e6a076b9
--- /dev/null
+++ b/components/SelfGuidedTours-backup.tsx
@@ -0,0 +1,309 @@
+'use client';
+import React from 'react';
+import Image from 'next/image';
+import Script from 'next/script';
+
+/**
+ * Card data shape passed from MDX.
+ * - navatticOpen: the Navattic demo id (e.g., "cmfkxwfa5000004lc8408f5wi")
+ * - navatticTitle: optional; title for the Navattic popup chrome
+ * - img: optional; if omitted, a dark placeholder fills the media area
+ */
+type Card = {
+ badge: string;
+ title: string;
+ blurb?: string;
+ img?: string;
+ href?: string;
+ navatticOpen?: string;
+ navatticTitle?: string;
+};
+
+interface Props {
+ cards: Card[];
+}
+
+/* ---- Constants / design tokens (keep in sync with MDX usage) ---- */
+const MP_PURPLE = 'rgb(139 92 246)';
+const BORDER_RADIUS = 14;
+const CARD_W = 296;
+const CARD_H = 319;
+/** Image height is fixed for consistent badge anchoring */
+const IMAGE_H = 140;
+/** Image width is indented left and bleeds to the right edge */
+const IMAGE_W = 276;
+
+/* ---- Inline “CSS-in-TS” styles (layout is pixel-exact to your spec) ---- */
+const styles = {
+ grid: {
+ display: 'grid',
+ gap: 20,
+ gridTemplateColumns: 'repeat(auto-fit, minmax(296px, 1fr))',
+ justifyContent: 'center',
+ marginTop: 32,
+ } as React.CSSProperties,
+
+ card: {
+ position: 'relative',
+ width: CARD_W,
+ height: CARD_H,
+ borderRadius: BORDER_RADIUS,
+ overflow: 'hidden',
+ border: `2px solid ${MP_PURPLE}`,
+ boxShadow: '0 10px 30px rgba(0,0,0,.25)',
+ transition: 'transform .25s ease, box-shadow .25s ease, background .3s ease, color .3s ease',
+ } as React.CSSProperties,
+
+ dogEar: {
+ position: 'absolute',
+ right: 10,
+ top: 10,
+ width: 22,
+ height: 22,
+ background: 'var(--sgt-dogear)',
+ clipPath: 'polygon(0 0, 100% 0, 100% 100%)',
+ boxShadow: '0 0 0 2px rgba(0,0,0,.15) inset',
+ zIndex: 5,
+ pointerEvents: 'none',
+ } as React.CSSProperties,
+
+ mediaWrap: {
+ position: 'absolute',
+ top: 18, // aligns the image to the badge’s left indent
+ height: IMAGE_H,
+ width: IMAGE_W,
+ marginLeft: 16, // left indent (aligns with badge)
+ marginRight: -16, // bleed to right edge (no right indent)
+ borderTopLeftRadius: 8,
+ borderBottomLeftRadius: 8,
+ overflow: 'hidden',
+ background: 'var(--sgt-media-bg)', // placeholder color behind images
+ zIndex: 1,
+ } as React.CSSProperties,
+
+ mediaImg: {
+ width: '100%',
+ height: '100%',
+ objectFit: 'cover',
+ objectPosition: 'left top',
+ display: 'block',
+ } as React.CSSProperties,
+
+ placeholder: {
+ width: '100%',
+ height: '100%',
+ background: 'var(--sgt-media-bg)',
+ } as React.CSSProperties,
+
+ /**
+ * Anchored text block:
+ * - Badge top is locked to IMAGE_H + offset so all cards align visually
+ * - Title and blurb naturally flow below the badge
+ */
+ bottom: {
+ position: 'absolute' as const,
+ top: IMAGE_H + 22,
+ left: 0,
+ right: 0,
+ bottom: 0,
+ padding: '16px 18px 22px',
+ zIndex: 3,
+ },
+
+ /* Badge = stronger weight + tighter tracking for a pill look */
+ badge: {
+ display: 'inline-block',
+ background: 'var(--sgt-badge-bg)',
+ color: 'var(--sgt-badge-fg)',
+ fontWeight: 800,
+ letterSpacing: '.04em',
+ fontSize: '11.5px',
+ lineHeight: 1,
+ borderRadius: 8,
+ padding: '8px 10px',
+ marginBottom: 10,
+ } as React.CSSProperties,
+
+ title: {
+ fontSize: 23,
+ fontWeight: 700,
+ lineHeight: 1.2,
+ margin: 0,
+ color: 'var(--sgt-title)',
+ } as React.CSSProperties,
+
+ blurb: {
+ marginTop: 8,
+ fontSize: 15,
+ color: 'var(--sgt-blurb)',
+ opacity: 0.75,
+ } as React.CSSProperties,
+
+ clickable: {
+ display: 'block',
+ width: '100%',
+ height: '100%',
+ background: 'transparent',
+ border: 0,
+ padding: 0,
+ cursor: 'pointer',
+ textAlign: 'inherit',
+ } as React.CSSProperties,
+};
+
+/* ---- One card view (supports Navattic popup or plain link) ---- */
+function CardView({ c }: { c: Card }) {
+ const inside = (
+ <>
+
+
+ {c.img ? (
+
+ ) : (
+
+ )}
+
+
+
+
{c.badge}
+
{c.title}
+ {c.blurb ?
{c.blurb}
: null}
+
+ >
+ );
+
+ // Use Navattic popup if navatticOpen is provided
+ if (c.navatticOpen) {
+ const navatticUrl = c.navatticOpen.startsWith('http')
+ ? c.navatticOpen
+ : `https://capture.navattic.com/${c.navatticOpen}`;
+
+ return (
+
+
+ {inside}
+
+
+ );
+ }
+
+ // Fallback to href links if needed
+ if (c.href) {
+ return (
+
+ );
+ }
+
+ // Static (non-clickable) card
+ return (
+
+ {inside}
+
+ );
+}
+
+/**
+ * SelfGuidedTours
+ * - Renders a responsive grid of product-tour cards
+ * - Loads Navattic's embed script once (popup mode)
+ * - Exposes a simple props API so MDX controls the content
+ */
+export default function SelfGuidedTours({ cards }: Props) {
+ return (
+ <>
+ {/* Navattic embed loader (newer API) */}
+
+
+ {/* Grid */}
+
+ {cards.map((c, i) => (
+
+ ))}
+
+
+ {/* Theme variables + interactions */}
+
+ >
+ );
+}
diff --git a/components/SelfGuidedTours.tsx b/components/SelfGuidedTours.tsx
new file mode 100644
index 0000000000..36e6a076b9
--- /dev/null
+++ b/components/SelfGuidedTours.tsx
@@ -0,0 +1,309 @@
+'use client';
+import React from 'react';
+import Image from 'next/image';
+import Script from 'next/script';
+
+/**
+ * Card data shape passed from MDX.
+ * - navatticOpen: the Navattic demo id (e.g., "cmfkxwfa5000004lc8408f5wi")
+ * - navatticTitle: optional; title for the Navattic popup chrome
+ * - img: optional; if omitted, a dark placeholder fills the media area
+ */
+type Card = {
+ badge: string;
+ title: string;
+ blurb?: string;
+ img?: string;
+ href?: string;
+ navatticOpen?: string;
+ navatticTitle?: string;
+};
+
+interface Props {
+ cards: Card[];
+}
+
+/* ---- Constants / design tokens (keep in sync with MDX usage) ---- */
+const MP_PURPLE = 'rgb(139 92 246)';
+const BORDER_RADIUS = 14;
+const CARD_W = 296;
+const CARD_H = 319;
+/** Image height is fixed for consistent badge anchoring */
+const IMAGE_H = 140;
+/** Image width is indented left and bleeds to the right edge */
+const IMAGE_W = 276;
+
+/* ---- Inline “CSS-in-TS” styles (layout is pixel-exact to your spec) ---- */
+const styles = {
+ grid: {
+ display: 'grid',
+ gap: 20,
+ gridTemplateColumns: 'repeat(auto-fit, minmax(296px, 1fr))',
+ justifyContent: 'center',
+ marginTop: 32,
+ } as React.CSSProperties,
+
+ card: {
+ position: 'relative',
+ width: CARD_W,
+ height: CARD_H,
+ borderRadius: BORDER_RADIUS,
+ overflow: 'hidden',
+ border: `2px solid ${MP_PURPLE}`,
+ boxShadow: '0 10px 30px rgba(0,0,0,.25)',
+ transition: 'transform .25s ease, box-shadow .25s ease, background .3s ease, color .3s ease',
+ } as React.CSSProperties,
+
+ dogEar: {
+ position: 'absolute',
+ right: 10,
+ top: 10,
+ width: 22,
+ height: 22,
+ background: 'var(--sgt-dogear)',
+ clipPath: 'polygon(0 0, 100% 0, 100% 100%)',
+ boxShadow: '0 0 0 2px rgba(0,0,0,.15) inset',
+ zIndex: 5,
+ pointerEvents: 'none',
+ } as React.CSSProperties,
+
+ mediaWrap: {
+ position: 'absolute',
+ top: 18, // aligns the image to the badge’s left indent
+ height: IMAGE_H,
+ width: IMAGE_W,
+ marginLeft: 16, // left indent (aligns with badge)
+ marginRight: -16, // bleed to right edge (no right indent)
+ borderTopLeftRadius: 8,
+ borderBottomLeftRadius: 8,
+ overflow: 'hidden',
+ background: 'var(--sgt-media-bg)', // placeholder color behind images
+ zIndex: 1,
+ } as React.CSSProperties,
+
+ mediaImg: {
+ width: '100%',
+ height: '100%',
+ objectFit: 'cover',
+ objectPosition: 'left top',
+ display: 'block',
+ } as React.CSSProperties,
+
+ placeholder: {
+ width: '100%',
+ height: '100%',
+ background: 'var(--sgt-media-bg)',
+ } as React.CSSProperties,
+
+ /**
+ * Anchored text block:
+ * - Badge top is locked to IMAGE_H + offset so all cards align visually
+ * - Title and blurb naturally flow below the badge
+ */
+ bottom: {
+ position: 'absolute' as const,
+ top: IMAGE_H + 22,
+ left: 0,
+ right: 0,
+ bottom: 0,
+ padding: '16px 18px 22px',
+ zIndex: 3,
+ },
+
+ /* Badge = stronger weight + tighter tracking for a pill look */
+ badge: {
+ display: 'inline-block',
+ background: 'var(--sgt-badge-bg)',
+ color: 'var(--sgt-badge-fg)',
+ fontWeight: 800,
+ letterSpacing: '.04em',
+ fontSize: '11.5px',
+ lineHeight: 1,
+ borderRadius: 8,
+ padding: '8px 10px',
+ marginBottom: 10,
+ } as React.CSSProperties,
+
+ title: {
+ fontSize: 23,
+ fontWeight: 700,
+ lineHeight: 1.2,
+ margin: 0,
+ color: 'var(--sgt-title)',
+ } as React.CSSProperties,
+
+ blurb: {
+ marginTop: 8,
+ fontSize: 15,
+ color: 'var(--sgt-blurb)',
+ opacity: 0.75,
+ } as React.CSSProperties,
+
+ clickable: {
+ display: 'block',
+ width: '100%',
+ height: '100%',
+ background: 'transparent',
+ border: 0,
+ padding: 0,
+ cursor: 'pointer',
+ textAlign: 'inherit',
+ } as React.CSSProperties,
+};
+
+/* ---- One card view (supports Navattic popup or plain link) ---- */
+function CardView({ c }: { c: Card }) {
+ const inside = (
+ <>
+
+
+ {c.img ? (
+
+ ) : (
+
+ )}
+
+
+
+
{c.badge}
+
{c.title}
+ {c.blurb ?
{c.blurb}
: null}
+
+ >
+ );
+
+ // Use Navattic popup if navatticOpen is provided
+ if (c.navatticOpen) {
+ const navatticUrl = c.navatticOpen.startsWith('http')
+ ? c.navatticOpen
+ : `https://capture.navattic.com/${c.navatticOpen}`;
+
+ return (
+
+
+ {inside}
+
+
+ );
+ }
+
+ // Fallback to href links if needed
+ if (c.href) {
+ return (
+
+ );
+ }
+
+ // Static (non-clickable) card
+ return (
+
+ {inside}
+
+ );
+}
+
+/**
+ * SelfGuidedTours
+ * - Renders a responsive grid of product-tour cards
+ * - Loads Navattic's embed script once (popup mode)
+ * - Exposes a simple props API so MDX controls the content
+ */
+export default function SelfGuidedTours({ cards }: Props) {
+ return (
+ <>
+ {/* Navattic embed loader (newer API) */}
+
+
+ {/* Grid */}
+
+ {cards.map((c, i) => (
+
+ ))}
+
+
+ {/* Theme variables + interactions */}
+
+ >
+ );
+}
diff --git a/components/WhatsNewVertical.tsx b/components/WhatsNewVertical.tsx
new file mode 100644
index 0000000000..1161565906
--- /dev/null
+++ b/components/WhatsNewVertical.tsx
@@ -0,0 +1,469 @@
+'use client';
+
+import React, { useMemo, useState } from 'react';
+import { getPagesUnderRoute } from 'nextra/context';
+
+type Item = {
+ url: string;
+ title: string;
+ date: string;
+ thumbnail: string;
+ videoEmbed?: string; // derived embed URL if a supported video is present
+};
+
+const changelogPages = getPagesUnderRoute('/changelogs');
+
+/* ---------- helpers ---------- */
+const parseDate = (s = '') => {
+ const m = s.match(/(\d{4}-\d{2}-\d{2})/);
+ return m ? m[1] : '';
+};
+const humanize = (s = '') =>
+ s.replace(/^\d{4}-\d{2}-\d{2}-/, '').replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
+
+const fmtDay = (dateStr: string) => {
+ const d = new Date(dateStr);
+ if (isNaN(d as any)) return dateStr || '';
+ return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' });
+};
+
+const firstNonEmpty = (...vals: any[]) =>
+ vals.find((v) => {
+ if (!v) return false;
+ if (Array.isArray(v)) return v.length > 0 && typeof v[0] === 'string';
+ return typeof v === 'string';
+ });
+
+const clampStyle = (lines: number): React.CSSProperties => ({
+ display: '-webkit-box',
+ WebkitLineClamp: lines,
+ WebkitBoxOrient: 'vertical',
+ overflow: 'hidden'
+});
+
+/** Build an embeddable URL for common hosts */
+function getVideoEmbedURL(videoURL?: string): string | undefined {
+ if (!videoURL) return undefined;
+ try {
+ const url = new URL(videoURL);
+ const host = url.host.replace(/^www\./, '');
+
+ // YouTube
+ if (host === 'youtube.com') {
+ const id = url.searchParams.get('v') || url.pathname.split('/').pop();
+ return id ? `https://www.youtube.com/embed/${id}` : undefined;
+ }
+ if (host === 'youtu.be') {
+ const id = url.pathname.split('/').pop();
+ return id ? `https://www.youtube.com/embed/${id}` : undefined;
+ }
+
+ // Loom
+ if (host === 'loom.com') {
+ const id = url.pathname.split('/').pop();
+ return id ? `https://www.loom.com/embed/${id}?hideEmbedTopBar=true` : undefined;
+ }
+
+ // Vimeo
+ if (host === 'vimeo.com') {
+ const id = url.pathname.split('/').pop();
+ return id ? `https://player.vimeo.com/video/${id}` : undefined;
+ }
+ } catch {
+ // ignore invalid URL
+ }
+ return undefined;
+}
+
+/* ---------- build items (NEWEST → OLDEST) ---------- */
+function buildItems(): Item[] {
+ return (changelogPages || [])
+ .map((p: any) => {
+ const fm = p.frontMatter || p.meta || {};
+ const route = p.route || '';
+ if (!/\/changelogs\/.+/.test(route)) return null;
+
+ const name = p.name || route.split('/').pop() || '';
+ const date = fm.date || parseDate(name) || parseDate(route);
+
+ const thumb = firstNonEmpty(
+ fm.thumbnail,
+ fm.image,
+ fm.cover,
+ fm.ogImage,
+ fm.hero,
+ fm.screenshot,
+ Array.isArray(fm.images) ? fm.images[0] : undefined
+ ) as string | undefined;
+
+ const videoEmbed = getVideoEmbedURL(fm.video);
+
+ return {
+ url: route,
+ title: fm.title || p.title || humanize(name),
+ date,
+ thumbnail: thumb || '',
+ videoEmbed
+ } as Item;
+ })
+ .filter(Boolean)
+ .sort((a: Item, b: Item) => new Date(b.date).getTime() - new Date(a.date).getTime());
+}
+
+/* ---------- shared inline styles (theme-safe) ---------- */
+const TL_X = 12; // timeline line X (relative to UL left)
+const TL_PAD = TL_X + 16; // left padding so content clears the gutter
+
+const s = {
+ page: { maxWidth: 880, margin: '0 auto' },
+ h1: {
+ marginTop: 16,
+ marginBottom: 0,
+ fontSize: '44px',
+ lineHeight: 1.1,
+ fontWeight: 600 as const,
+ letterSpacing: '-0.02em' as const,
+ },
+ heroP: {
+ marginTop: 12,
+ fontSize: 15,
+ lineHeight: 1.6,
+ // color inherits for light/dark
+ },
+ heroLink: {
+ marginTop: 12,
+ fontSize: 14,
+ textDecoration: 'underline',
+ textUnderlineOffset: '4px',
+ display: 'inline-block',
+ },
+ rowBar: {
+ marginTop: 24,
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ gap: 12,
+ },
+ showing: {
+ fontSize: 12,
+ opacity: 0.7,
+ },
+ controlsWrap: { whiteSpace: 'nowrap' as const, minWidth: 0 },
+ btn: {
+ fontSize: 12,
+ padding: '6px 8px',
+ borderRadius: 6,
+ border: '1px solid currentColor',
+ background: 'transparent',
+ color: 'inherit',
+ cursor: 'pointer',
+ },
+ select: {
+ fontSize: 12,
+ padding: '6px 8px',
+ borderRadius: 6,
+ border: '1px solid currentColor',
+ background: 'transparent',
+ color: 'inherit',
+ },
+ /* list + timeline */
+ list: {
+ marginTop: 12,
+ listStyle: 'none',
+ padding: 0,
+ position: 'relative' as const,
+ paddingLeft: TL_PAD,
+ },
+ timelineLine: {
+ position: 'absolute' as const,
+ left: TL_X,
+ top: 0,
+ bottom: 0,
+ width: 2,
+ background: 'currentColor',
+ opacity: 0.12,
+ },
+ /* card */
+ cardLi: { padding: '12px 0', position: 'relative' as const },
+ cardA: { display: 'block', borderRadius: 12, padding: 12, textDecoration: 'none', color: 'inherit' },
+ cardHeader: {
+ display: 'grid',
+ gridTemplateColumns: '1fr auto',
+ alignItems: 'center',
+ gap: 12,
+ marginBottom: 8,
+ },
+ cardTitle: {
+ fontSize: 20,
+ fontWeight: 600 as const,
+ lineHeight: 1.2,
+ textDecorationThickness: '1px',
+ textUnderlineOffset: '4px',
+ },
+ cardDate: {
+ fontSize: 12,
+ opacity: 0.6,
+ },
+ imgWrap: {
+ width: '100%',
+ borderRadius: 12,
+ overflow: 'hidden',
+ aspectRatio: '16 / 9',
+ background:
+ 'radial-gradient(120% 120% at 0% 100%, rgba(168,85,247,0.18), transparent 60%), radial-gradient(120% 120% at 100% 0%, rgba(59,130,246,0.18), transparent 60%)',
+ },
+ readLink: {
+ marginTop: 6,
+ fontSize: 13,
+ textDecoration: 'underline',
+ textUnderlineOffset: '4px',
+ display: 'inline-block',
+ },
+ footerLink: {
+ fontSize: 14,
+ color: 'rgb(167 139 250)',
+ textDecoration: 'underline',
+ textUnderlineOffset: '4px',
+ },
+ /* timeline dot */
+ dot: {
+ position: 'absolute' as const,
+ left: -(TL_PAD - TL_X),
+ top: 12,
+ width: 8,
+ height: 8,
+ borderRadius: 999,
+ background: 'rgb(167 139 250)',
+ boxShadow: '0 0 0 2px rgba(20,20,30,0.9)',
+ },
+ /* NEW badge */
+ newBadge: {
+ marginLeft: 8,
+ fontSize: 11,
+ fontWeight: 700 as const,
+ letterSpacing: '0.02em',
+ color: 'rgb(26, 26, 31)',
+ background: 'linear-gradient(90deg, rgba(167,139,250,0.95), rgba(99,102,241,0.95))',
+ borderRadius: 999,
+ padding: '2px 6px',
+ lineHeight: 1.1,
+ verticalAlign: 'middle',
+ },
+
+ /* text-only mode */
+ textOnly: {
+ marginTop: 4,
+ },
+ divider: {
+ height: 1,
+ background: 'currentColor',
+ opacity: 0.1,
+ margin: '6px 0 2px',
+ },
+ readLinkSmall: {
+ fontSize: 13,
+ textDecoration: 'underline',
+ textUnderlineOffset: '4px',
+ },
+};
+
+/* ---------- control components ---------- */
+function ControlsTop({
+ pageSize,
+ canPrev,
+ canNext,
+ changeSize,
+ prev,
+ next,
+}: {
+ pageSize: number;
+ canPrev: boolean;
+ canNext: boolean;
+ changeSize: (n: number) => void;
+ prev: () => void;
+ next: () => void;
+}) {
+ return (
+
+ Show
+ changeSize(Number(e.target.value))}>
+ {[5, 10, 15, 20].map((n) => (
+
+ Latest {n}
+
+ ))}
+
+
+ ← Prev
+
+
+ Next →
+
+
+ );
+}
+
+function ControlsBottom({
+ canPrev,
+ canNext,
+ prev,
+ next,
+}: {
+ canPrev: boolean;
+ canNext: boolean;
+ prev: () => void;
+ next: () => void;
+}) {
+ return (
+
+
+ ← Prev
+
+
+ Next →
+
+
+ );
+}
+
+/* ---------- card ---------- */
+function Row({ item }: { item: Item }) {
+ // NEW badge if within last 14 days
+ const isNew = (() => {
+ const d = new Date(item.date);
+ if (isNaN(d as any)) return false;
+ const days = (Date.now() - d.getTime()) / (1000 * 60 * 60 * 24);
+ return days <= 14;
+ })();
+
+ const hasThumb = !!item.thumbnail;
+ const hasVideo = !!item.videoEmbed;
+ const hasMedia = hasThumb || hasVideo;
+
+ return (
+
+ {/* timeline dot */}
+
+
+
+
+
+ {item.title}
+ {isNew && NEW }
+
+
{fmtDay(item.date)}
+
+
+ {hasMedia ? (
+
+ {hasVideo ? (
+
+ ) : (
+ // eslint-disable-next-line @next/next/no-img-element
+
+ )}
+
+ ) : (
+ // Text-only compact mode (no blank gradient box)
+
+ )}
+
+
+ );
+}
+
+/* ---------- main ---------- */
+export default function WhatsNewVertical() {
+ const items = useMemo(buildItems, []);
+
+ // paging (Latest X)
+ const [pageSize, setPageSize] = useState(5);
+ const [offset, setOffset] = useState(0);
+
+ const total = items.length;
+ const start = offset;
+ const end = Math.min(offset + pageSize, total);
+ const page = items.slice(start, end);
+
+ const canPrev = start > 0;
+ const canNext = end < total;
+
+ const changeSize = (n: number) => {
+ setPageSize(n);
+ setOffset(0);
+ };
+ const prev = () => setOffset(Math.max(0, offset - pageSize));
+ const next = () => setOffset(Math.min(total, offset + pageSize));
+
+ return (
+
+ {/* HERO */}
+
+
What's New
+
+
+ Track Mixpanel product releases and improvements in one place. See what’s
+ new, what got faster, and what opens up entirely new ways to answer questions about your
+ product. These changes are built from customer feedback and real workflows—less setup,
+ fewer manual steps, clearer answers.
+
+
+ From performance boosts to streamlined analysis and collaboration, each release is here to
+ shorten the path from “what happened?” to “what should we do?”. Browse the highlights below
+ and put the most impactful updates to work on your team today.
+
+
+
+ Browse Changelog
+
+
+
+ {/* TOP BAR — single line */}
+
+
+ Showing {total === 0 ? 0 : start + 1}–{end} of {total}
+
+
+
+
+ {/* LIST + TIMELINE */}
+
+
+ {page.map((item) => (
+
+ ))}
+
+
+ {/* BOTTOM BAR — single line */}
+
+
+ );
+}
diff --git a/cspell.json b/cspell.json
index 725970207c..e9c3b25fb1 100644
--- a/cspell.json
+++ b/cspell.json
@@ -75,6 +75,7 @@
"cloudfunctions",
"cloudimport",
"clsx",
+ "cmfkxwfa",
"cnlhbjpye",
"Cocoapods",
"cohorting",
@@ -142,6 +143,7 @@
"Iframely",
"intervalize",
"Intervalized",
+ "inited",
"irlandese",
"Isha",
"ivandiblasi",
@@ -173,6 +175,7 @@
"mxpnl",
"MYAPP",
"mytoken",
+ "navattic",
"nessie",
"Next.js",
"nextjs",
diff --git a/middleware.ts b/middleware.ts
index 9b5df4907d..f5bd331d10 100644
--- a/middleware.ts
+++ b/middleware.ts
@@ -6,7 +6,7 @@ export function middleware() {
// Set custom header
response.headers.set(`X-Frame-Options`, `deny`);
response.headers.set(`X-Content-Type-Options`, `nosniff`);
- response.headers.set(`Content-Security-Policy`, `default-src 'self' https://*.mixpanel.com https://cdn.mxpnl.com https://cdn-dev.mxpnl.com https://ekr.zendesk.com wss://mixpanelsupport.zendesk.com https://mixpanel.com https://*.mixpanel.com; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://*.kapa.ai https://*.hotjar.com https://cdn.mxpnl.com https://cdn-dev.mxpnl.com https://cdn.rollbar.com https://*.zopim.com https://assets.zendesk.com https://www.youtube.com/embed/ https://connect.facebook.net https://apis.google.com https://accounts.google.com 'unsafe-eval' https://*.6sc.co https://*.bing.com https://*.clarity.ms https://cdnjs.cloudflare.com d2wy8f7a9ursnm.cloudfront.net https://*.doubleclick.net https://*.google.com https://*.google-analytics.com https://*.googlesyndication.com https://www.googletagmanager.com https://*.gstatic.cn https://*.gstatic.com https://*.g2crowd.com https://snap.licdn.com https://*.marketo.com https://*.marketo.net https://mixpanel.com https://*.mixpanel.com https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ https://recaptcha.net https://*.recaptcha.net https://www.redditstatic.com/ads/ https://*.singular.net https://*.ads-twitter.com https://mxpnlcms.wpengine.com https://*.youtube.com https://*.zoominfo.com https://cdn.sprig.com; connect-src 'self' blob: data: https://kapa-widget-proxy-la7dkmplpq-uc.a.run.app https://*.hotjar.com wss://*.hotjar.com https://*.hotjar.io https://*.mixpanel.com https://cdn.mxpnl.com https://cdn-dev.mxpnl.com https://api.rollbar.com https://api.sprig.com https://cdn.sprig.com https://*.zdassets.com https://mixpanelsupport.zendesk.com https://*.zopim.com wss://*.zopim.com https://storage.googleapis.com https://*.facebook.com https://*.6sc.co https://*.adnxs.com https://*.bing.com https://*.bugsnag.com https://*.clarity.ms https://*.doubleclick.net https://*.google.com https://*.google-analytics.com https://*.googlesyndication.com https://*.g2crowd.com https://*.linkedin.com https://mixpanel.com https://*.mixpanel.com https://*.mktoresp.com https://cdn.linkedin.oribi.io https://*.reddit.com https://www.redditstatic.com/ads/ https://*.singular.net https://mxpnlcms.wpengine.com https://*.zoominfo.com; media-src 'self' https://user-images.githubusercontent.com; img-src 'self' blob: data: https://www.google.com https://*.gstatic.com https://t2.gstatic.com https://github-production-user-asset-6210df.s3.amazonaws.com https://github.com https://user-images.githubusercontent.com https://avatars.githubusercontent.com/ https://*.chmln-cdn.com https://cdn.mxpnl.com https://cdn-dev.mxpnl.com https://*.zdassets.com https://*.zopim.com https://v2uploads.zopim.io https://*.facebook.com https://*.gravatar.com https://*.wp.com https://*.6sc.co https://*.adnxs.com https://*.adroll.com https://*.bidswitch.net https://*.bing.com https://cdn.bizible.com https://cdn.bizibly.com https://*.bugsnag.com https://*.casalemedia.com https://*.clarity.ms https://*.crwdcntrl.net https://*.doubleclick.net https://*.exelator.com https://*.google-analytics.com https://*.googlesyndication.com https://www.googletagmanager.com https://*.googleusercontent.com https://*.imrworldwide.com https://*.linkedin.com https://mixpanel.com https://*.mixpanel.com https://*.reddit.com https://t.co/ https://analytics.twitter.com https://*.wpengine.com https://mxpnlcms.wpengine.com https://mxpnlcms.wpenginepowered.com https://*.analytics.yahoo.com https://*.google.com https://*.google.ad https://*.google.ae https://*.google.com.af https://*.google.com.ag https://*.google.al https://*.google.am https://*.google.co.ao https://*.google.com.ar https://*.google.as https://*.google.at https://*.google.com.au https://*.google.az https://*.google.ba https://*.google.com.bd https://*.google.be https://*.google.bf https://*.google.bg https://*.google.com.bh https://*.google.bi https://*.google.bj https://*.google.com.bn https://*.google.com.bo https://*.google.com.br https://*.google.bs https://*.google.bt https://*.google.co.bw https://*.google.by https://*.google.com.bz https://*.google.ca https://*.google.cd https://*.google.cf https://*.google.cg https://*.google.ch https://*.google.ci https://*.google.co.ck https://*.google.cl https://*.google.cm https://*.google.cn https://*.google.com.co https://*.google.co.cr https://*.google.com.cu https://*.google.cv https://*.google.com.cy https://*.google.cz https://*.google.de https://*.google.dj https://*.google.dk https://*.google.dm https://*.google.com.do https://*.google.dz https://*.google.com.ec https://*.google.ee https://*.google.com.eg https://*.google.es https://*.google.com.et https://*.google.fi https://*.google.com.fj https://*.google.fm https://*.google.fr https://*.google.ga https://*.google.ge https://*.google.gg https://*.google.com.gh https://*.google.com.gi https://*.google.gl https://*.google.gm https://*.google.gr https://*.google.com.gt https://*.google.gy https://*.google.com.hk https://*.google.hn https://*.google.hr https://*.google.ht https://*.google.hu https://*.google.co.id https://*.google.ie https://*.google.co.il https://*.google.im https://*.google.co.in https://*.google.iq https://*.google.is https://*.google.it https://*.google.je https://*.google.com.jm https://*.google.jo https://*.google.co.jp https://*.google.co.ke https://*.google.com.kh https://*.google.ki https://*.google.kg https://*.google.co.kr https://*.google.com.kw https://*.google.kz https://*.google.la https://*.google.com.lb https://*.google.li https://*.google.lk https://*.google.co.ls https://*.google.lt https://*.google.lu https://*.google.lv https://*.google.com.ly https://*.google.co.ma https://*.google.md https://*.google.me https://*.google.mg https://*.google.mk https://*.google.ml https://*.google.com.mm https://*.google.mn https://*.google.com.mt https://*.google.mu https://*.google.mv https://*.google.mw https://*.google.com.mx https://*.google.com.my https://*.google.co.mz https://*.google.com.na https://*.google.com.ng https://*.google.com.ni https://*.google.ne https://*.google.nl https://*.google.no https://*.google.com.np https://*.google.nr https://*.google.nu https://*.google.co.nz https://*.google.com.om https://*.google.com.pa https://*.google.com.pe https://*.google.com.pg https://*.google.com.ph https://*.google.com.pk https://*.google.pl https://*.google.pn https://*.google.com.pr https://*.google.ps https://*.google.pt https://*.google.com.py https://*.google.com.qa https://*.google.ro https://*.google.ru https://*.google.rw https://*.google.com.sa https://*.google.com.sb https://*.google.sc https://*.google.se https://*.google.com.sg https://*.google.sh https://*.google.si https://*.google.sk https://*.google.com.sl https://*.google.sn https://*.google.so https://*.google.sm https://*.google.sr https://*.google.st https://*.google.com.sv https://*.google.td https://*.google.tg https://*.google.co.th https://*.google.com.tj https://*.google.tl https://*.google.tm https://*.google.tn https://*.google.to https://*.google.com.tr https://*.google.tt https://*.google.com.tw https://*.google.co.tz https://*.google.com.ua https://*.google.co.ug https://*.google.co.uk https://*.google.com.uy https://*.google.co.uz https://*.google.com.vc https://*.google.co.ve https://*.google.co.vi https://*.google.com.vn https://*.google.vu https://*.google.ws https://*.google.rs https://*.google.co.za https://*.google.co.zm https://*.google.co.zw https://*.google.cat; style-src 'self' 'unsafe-inline' https://cdn.mxpnl.com https://cdn-dev.mxpnl.com https://*.google.com https://*.marketo.com https://mixpanel.com https://*.mixpanel.com https://hello.myfonts.net; font-src 'self' data: https://cdn.mxpnl.com https://cdn-dev.mxpnl.com https://mixpanel.com https://*.mixpanel.com; frame-src 'self' https://www.googletagmanager.com https://js.stripe.com https://www.loom.com/embed/ https://player.vimeo.com/video/ https://www.youtube.com/embed/ https://*.facebook.com https://accounts.google.com https://static.addtoany.com https://*.bing.com https://*.doubleclick.net https://*.google.com https://*.marketo.com https://mixpanel.com https://*.mixpanel.com https://www.google.com/recaptcha/ https://recaptcha.google.com/recaptcha/ https://recaptcha.net https://*.recaptcha.net; worker-src 'self' blob:;`);
+ response.headers.set(`Content-Security-Policy`, `default-src 'self' https://*.mixpanel.com https://cdn.mxpnl.com https://cdn-dev.mxpnl.com https://ekr.zendesk.com wss://mixpanelsupport.zendesk.com https://mixpanel.com https://*.mixpanel.com; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://*.kapa.ai https://*.hotjar.com https://cdn.mxpnl.com https://cdn-dev.mxpnl.com https://cdn.rollbar.com https://*.zopim.com https://assets.zendesk.com https://www.youtube.com/embed/ https://connect.facebook.net https://apis.google.com https://accounts.google.com 'unsafe-eval' https://*.6sc.co https://*.bing.com https://*.clarity.ms https://cdnjs.cloudflare.com d2wy8f7a9ursnm.cloudfront.net https://*.doubleclick.net https://*.google.com https://*.google-analytics.com https://*.googlesyndication.com https://www.googletagmanager.com https://*.gstatic.cn https://*.gstatic.com https://*.g2crowd.com https://snap.licdn.com https://*.marketo.com https://*.marketo.net https://mixpanel.com https://*.mixpanel.com https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ https://recaptcha.net https://*.recaptcha.net https://www.redditstatic.com/ads/ https://*.singular.net https://*.ads-twitter.com https://mxpnlcms.wpengine.com https://*.youtube.com https://*.zoominfo.com https://cdn.sprig.com https://js.navattic.com; connect-src 'self' blob: data: https://kapa-widget-proxy-la7dkmplpq-uc.a.run.app https://*.hotjar.com wss://*.hotjar.com https://*.hotjar.io https://*.mixpanel.com https://cdn.mxpnl.com https://cdn-dev.mxpnl.com https://api.rollbar.com https://api.sprig.com https://cdn.sprig.com https://*.zdassets.com https://mixpanelsupport.zendesk.com https://*.zopim.com wss://*.zopim.com https://storage.googleapis.com https://*.facebook.com https://*.6sc.co https://*.adnxs.com https://*.bing.com https://*.bugsnag.com https://*.clarity.ms https://*.doubleclick.net https://*.google.com https://*.google-analytics.com https://*.googlesyndication.com https://*.g2crowd.com https://*.linkedin.com https://mixpanel.com https://*.mixpanel.com https://*.mktoresp.com https://cdn.linkedin.oribi.io https://*.reddit.com https://www.redditstatic.com/ads/ https://*.singular.net https://mxpnlcms.wpengine.com https://*.zoominfo.com; media-src 'self' https://user-images.githubusercontent.com; img-src 'self' blob: data: https://www.google.com https://*.gstatic.com https://t2.gstatic.com https://github-production-user-asset-6210df.s3.amazonaws.com https://github.com https://user-images.githubusercontent.com https://avatars.githubusercontent.com/ https://*.chmln-cdn.com https://cdn.mxpnl.com https://cdn-dev.mxpnl.com https://*.zdassets.com https://*.zopim.com https://v2uploads.zopim.io https://*.facebook.com https://*.gravatar.com https://*.wp.com https://*.6sc.co https://*.adnxs.com https://*.adroll.com https://*.bidswitch.net https://*.bing.com https://cdn.bizible.com https://cdn.bizibly.com https://*.bugsnag.com https://*.casalemedia.com https://*.clarity.ms https://*.crwdcntrl.net https://*.doubleclick.net https://*.exelator.com https://*.google-analytics.com https://*.googlesyndication.com https://www.googletagmanager.com https://*.googleusercontent.com https://*.imrworldwide.com https://*.linkedin.com https://mixpanel.com https://*.mixpanel.com https://*.reddit.com https://t.co/ https://analytics.twitter.com https://*.wpengine.com https://mxpnlcms.wpengine.com https://mxpnlcms.wpenginepowered.com https://*.analytics.yahoo.com https://*.google.com https://*.google.ad https://*.google.ae https://*.google.com.af https://*.google.com.ag https://*.google.al https://*.google.am https://*.google.co.ao https://*.google.com.ar https://*.google.as https://*.google.at https://*.google.com.au https://*.google.az https://*.google.ba https://*.google.com.bd https://*.google.be https://*.google.bf https://*.google.bg https://*.google.com.bh https://*.google.bi https://*.google.bj https://*.google.com.bn https://*.google.com.bo https://*.google.com.br https://*.google.bs https://*.google.bt https://*.google.co.bw https://*.google.by https://*.google.com.bz https://*.google.ca https://*.google.cd https://*.google.cf https://*.google.cg https://*.google.ch https://*.google.ci https://*.google.co.ck https://*.google.cl https://*.google.cm https://*.google.cn https://*.google.com.co https://*.google.co.cr https://*.google.com.cu https://*.google.cv https://*.google.com.cy https://*.google.cz https://*.google.de https://*.google.dj https://*.google.dk https://*.google.dm https://*.google.com.do https://*.google.dz https://*.google.com.ec https://*.google.ee https://*.google.com.eg https://*.google.es https://*.google.com.et https://*.google.fi https://*.google.com.fj https://*.google.fm https://*.google.fr https://*.google.ga https://*.google.ge https://*.google.gg https://*.google.com.gh https://*.google.com.gi https://*.google.gl https://*.google.gm https://*.google.gr https://*.google.com.gt https://*.google.gy https://*.google.com.hk https://*.google.hn https://*.google.hr https://*.google.ht https://*.google.hu https://*.google.co.id https://*.google.ie https://*.google.co.il https://*.google.im https://*.google.co.in https://*.google.iq https://*.google.is https://*.google.it https://*.google.je https://*.google.com.jm https://*.google.jo https://*.google.co.jp https://*.google.co.ke https://*.google.com.kh https://*.google.ki https://*.google.kg https://*.google.co.kr https://*.google.com.kw https://*.google.kz https://*.google.la https://*.google.com.lb https://*.google.li https://*.google.lk https://*.google.co.ls https://*.google.lt https://*.google.lu https://*.google.lv https://*.google.com.ly https://*.google.co.ma https://*.google.md https://*.google.me https://*.google.mg https://*.google.mk https://*.google.ml https://*.google.com.mm https://*.google.mn https://*.google.com.mt https://*.google.mu https://*.google.mv https://*.google.mw https://*.google.com.mx https://*.google.com.my https://*.google.co.mz https://*.google.com.na https://*.google.com.ng https://*.google.com.ni https://*.google.ne https://*.google.nl https://*.google.no https://*.google.com.np https://*.google.nr https://*.google.nu https://*.google.co.nz https://*.google.com.om https://*.google.com.pa https://*.google.com.pe https://*.google.com.pg https://*.google.com.ph https://*.google.com.pk https://*.google.pl https://*.google.pn https://*.google.com.pr https://*.google.ps https://*.google.pt https://*.google.com.py https://*.google.com.qa https://*.google.ro https://*.google.ru https://*.google.rw https://*.google.com.sa https://*.google.com.sb https://*.google.sc https://*.google.se https://*.google.com.sg https://*.google.sh https://*.google.si https://*.google.sk https://*.google.com.sl https://*.google.sn https://*.google.so https://*.google.sm https://*.google.sr https://*.google.st https://*.google.com.sv https://*.google.td https://*.google.tg https://*.google.co.th https://*.google.com.tj https://*.google.tl https://*.google.tm https://*.google.tn https://*.google.to https://*.google.com.tr https://*.google.tt https://*.google.com.tw https://*.google.co.tz https://*.google.com.ua https://*.google.co.ug https://*.google.co.uk https://*.google.com.uy https://*.google.co.uz https://*.google.com.vc https://*.google.co.ve https://*.google.co.vi https://*.google.com.vn https://*.google.vu https://*.google.ws https://*.google.rs https://*.google.co.za https://*.google.co.zm https://*.google.co.zw https://*.google.cat; style-src 'self' 'unsafe-inline' https://cdn.mxpnl.com https://cdn-dev.mxpnl.com https://*.google.com https://*.marketo.com https://mixpanel.com https://*.mixpanel.com https://hello.myfonts.net; font-src 'self' data: https://cdn.mxpnl.com https://cdn-dev.mxpnl.com https://mixpanel.com https://*.mixpanel.com; frame-src 'self' https://www.googletagmanager.com https://js.stripe.com https://www.loom.com/embed/ https://player.vimeo.com/video/ https://www.youtube.com/embed/ https://*.facebook.com https://accounts.google.com https://static.addtoany.com https://*.bing.com https://*.doubleclick.net https://*.google.com https://*.marketo.com https://mixpanel.com https://*.mixpanel.com https://www.google.com/recaptcha/ https://recaptcha.google.com/recaptcha/ https://recaptcha.net https://*.recaptcha.net https://capture.navattic.com; worker-src 'self' blob:;`);
response.headers.set(`X-Permitted-Cross-Domain-Policies`, `none`);
response.headers.set(`Referrer-Policy`, `strict-origin`);
response.headers.set(`Permissions-Policy`, `accelerometer=(), camera=(), encrypted-media=(self "https://www.youtube.com" "https://www.loom.com"), fullscreen=(self "https://www.youtube.com" "https://www.loom.com"), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), usb=()`);
diff --git a/pages/guides/_meta.ts b/pages/guides/_meta.ts
index 4a816478f9..32643e29b5 100644
--- a/pages/guides/_meta.ts
+++ b/pages/guides/_meta.ts
@@ -4,11 +4,8 @@ export default {
"title": "DISCOVER MIXPANEL"
},
"what-is-mixpanel": "What is Mixpanel?",
- "changelog": {
- title: "What's New? ↗",
- href: "/changelogs",
- newWindow: true
- },
+ "whats-new": "What's New?",
+ "self-guided-tours": "Self Guided Tours",
"solutions-and-workflows": {
"type": "separator",
"title": "SOLUTIONS & WORKFLOWS"
diff --git a/pages/guides/self-guided-tours.mdx b/pages/guides/self-guided-tours.mdx
new file mode 100644
index 0000000000..bbedb5fab6
--- /dev/null
+++ b/pages/guides/self-guided-tours.mdx
@@ -0,0 +1,110 @@
+import SelfGuidedTours from '../../components/SelfGuidedTours'
+
+# Self-Guided Product Tours
+
+Discover Mixpanel’s core features through quick, self-guided tours.
+Select any card below to explore interactive walkthroughs of key workflows.
+
+{/*
+ Cards API (examples):
+
+ {
+ badge: 'PRODUCT OVERVIEWS', // Pill label shown above the title
+ title: 'Mixpanel Experiments', // Main title
+ blurb: 'Setup a Mixpanel Experiment', // Short supporting text (optional)
+ img: '/navattic/launch-an-experiment.png', //Image src (public/… 314x139 pixels)
+ navatticOpen: 'cmfkxwfa5000004lc8408f5wi', // Navattic demo id (popup)
+ navatticTitle: 'Launch an Experiment', // Optional: popup title
+ // href: 'https://example.com' // (Alternative) card links out if provided
+ }
+
+ Notes:
+ - If `navatticOpen` is present, the card triggers a Navattic popup.
+ - If `img` is omitted, a dark placeholder fills the image area.
+ - If `href` is provided (and `navatticOpen` is not), the card becomes a link.
+ - Images should live under /public/navattic/ for easy referencing.
+*/}
+
+
+
+{/* Section CTA — content lives in MDX so it’s easy to change or A/B test */}
+
+
+
diff --git a/pages/guides/whats-new.mdx b/pages/guides/whats-new.mdx
new file mode 100644
index 0000000000..9c6dce03cf
--- /dev/null
+++ b/pages/guides/whats-new.mdx
@@ -0,0 +1,11 @@
+---
+title: "What's New"
+description: "Vertical compact board showing the latest updates"
+---
+
+import WhatsNewVertical from '../../components/WhatsNewVertical'
+
+{/* Keep this page minimal: no stray text above/below the component */}
+
+
+
diff --git a/public/navattic/launch-an-experiment.png b/public/navattic/launch-an-experiment.png
new file mode 100644
index 0000000000..dab6798654
Binary files /dev/null and b/public/navattic/launch-an-experiment.png differ