-
+
{useCase.title}
-
+
{useCase.description}
diff --git a/surfsense_web/components/homepage/logo-cloud.tsx b/surfsense_web/components/homepage/logo-cloud.tsx
new file mode 100644
index 000000000..607deef0a
--- /dev/null
+++ b/surfsense_web/components/homepage/logo-cloud.tsx
@@ -0,0 +1,111 @@
+"use client";
+
+import { AnimatePresence, motion } from "motion/react";
+import { useEffect, useState } from "react";
+import { Reveal } from "@/components/connectors-marketing/reveal";
+import { MarketingSection } from "@/components/marketing/section";
+
+/**
+ * Real signups pulled from prod (Google-auth), curated to the most recognizable
+ * names. These are self-serve users, not signed enterprise accounts, so the
+ * heading stays honest ("Used by people at") rather than implying contracts.
+ *
+ * Logos live in `public/logos/` — official marks from Wikimedia Commons /
+ * Wikipedia (universities use their seals). Bosta, Devoteam, and Leverage Edu
+ * have no clean Wikimedia logo, so they fall back to a brand favicon. Each item
+ * also falls back to a text wordmark on image error.
+ */
+const COMPANIES: { title: string; file: string }[] = [
+ { title: "UC Berkeley", file: "berkeley.svg" },
+ { title: "USC", file: "usc.svg" },
+ { title: "Texas A&M", file: "tamu.svg" },
+ { title: "UW–Madison", file: "wisc.svg" },
+ { title: "Pitt", file: "pitt.svg" },
+ { title: "Korean Air", file: "koreanair.svg" },
+ { title: "Iron Mountain", file: "ironmountain.svg" },
+ { title: "Globant", file: "globant.svg" },
+ { title: "Devoteam", file: "devoteam.png" },
+ { title: "VNG", file: "vng.svg" },
+ { title: "TPBank", file: "tpbank.svg" },
+ { title: "OpenGov", file: "opengov.png" },
+ { title: "WeLab", file: "welab.png" },
+ { title: "Leverage Edu", file: "leverageedu.png" },
+ { title: "Zopper", file: "zopper.png" },
+ { title: "Tec de Monterrey", file: "tec.svg" },
+ { title: "Chulalongkorn", file: "chula.svg" },
+ { title: "Univ. of Bristol", file: "bristol.svg" },
+ { title: "Nutresa", file: "nutresa.svg" },
+ { title: "Bosta", file: "bosta.png" },
+];
+
+const LOGOS_PER_SET = 10;
+const TOTAL_SETS = Math.ceil(COMPANIES.length / LOGOS_PER_SET);
+
+function LogoItem({ title, file }: { title: string; file: string }) {
+ const [failed, setFailed] = useState(false);
+
+ if (failed) {
+ return (
+
{title}
+ );
+ }
+
+ return (
+ // biome-ignore lint/performance/noImgElement: swapped in/out by the cycling animation, next/image adds no value here
+

setFailed(true)}
+ // dark mode: dark-on-transparent marks would vanish, so render every logo as a
+ // uniform light silhouette (brightness-0 + invert) instead of relying on its own color
+ className="h-10 w-auto max-w-[130px] object-contain opacity-60 grayscale transition duration-300 hover:opacity-100 hover:grayscale-0 dark:opacity-70 dark:brightness-0 dark:invert dark:hover:opacity-100"
+ />
+ );
+}
+
+export function LogoCloud() {
+ const [currentSet, setCurrentSet] = useState(0);
+
+ useEffect(() => {
+ const interval = setInterval(() => {
+ setCurrentSet((prev) => (prev + 1) % TOTAL_SETS);
+ }, 3000);
+ return () => clearInterval(interval);
+ }, []);
+
+ const startIndex = currentSet * LOGOS_PER_SET;
+ const currentLogos = Array.from(
+ { length: LOGOS_PER_SET },
+ (_, i) => COMPANIES[(startIndex + i) % COMPANIES.length]
+ );
+
+ return (
+
+
+
+ Used by people at
+
+
+
+
+ {currentLogos.map((logo, index) => (
+
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/surfsense_web/components/homepage/navbar.tsx b/surfsense_web/components/homepage/navbar.tsx
index 4cce7ff82..da71f8be0 100644
--- a/surfsense_web/components/homepage/navbar.tsx
+++ b/surfsense_web/components/homepage/navbar.tsx
@@ -250,17 +250,22 @@ const DesktopNav = ({ navItems, isScrolled, scrolledBgClassName }: DesktopNavPro
href="https://discord.gg/ejRNvftDp9"
target="_blank"
rel="noopener noreferrer"
+ aria-label="SurfSense on Discord"
className="hidden rounded-full p-2 hover:bg-gray-100 dark:hover:bg-neutral-800 transition-colors md:flex items-center justify-center"
>
-
+
-
+
@@ -362,17 +367,25 @@ const MobileNav = ({ navItems, isScrolled, scrolledBgClassName }: MobileNavProps
href="https://discord.gg/ejRNvftDp9"
target="_blank"
rel="noopener noreferrer"
+ aria-label="SurfSense on Discord"
className="flex items-center justify-center rounded-lg p-2 hover:bg-gray-100 dark:hover:bg-neutral-800 transition-colors touch-manipulation"
>
-
+
-
+
diff --git a/surfsense_web/components/homepage/social-proof.tsx b/surfsense_web/components/homepage/social-proof.tsx
new file mode 100644
index 000000000..35c464e3c
--- /dev/null
+++ b/surfsense_web/components/homepage/social-proof.tsx
@@ -0,0 +1,298 @@
+"use client";
+
+import {
+ IconBrandLinkedin,
+ IconBrandTiktok,
+ IconBrandX,
+ IconBrandYoutube,
+} from "@tabler/icons-react";
+import { Component, type ReactNode, useEffect, useRef, useState } from "react";
+import { LinkedInEmbed, TikTokEmbed, XEmbed, YouTubeEmbed } from "react-social-media-embed";
+import { Reveal } from "@/components/connectors-marketing/reveal";
+
+type Post =
+ | { kind: "youtube"; url: string; title: string; channel: string }
+ | { kind: "x"; url: string }
+ | { kind: "linkedin"; url: string; postUrl: string }
+ | { kind: "tiktok"; url: string };
+
+/**
+ * Organic SurfSense coverage — real posts embedded live with react-social-media-embed,
+ * grouped into three platform-uniform marquee rows (heights match within a row).
+ *
+ * Note: LinkedIn only renders when the author enabled embedding on the post; if
+ * disabled, the EmbedBoundary swaps in a link card to the original.
+ *
+ * ponytail: three rows, each list duplicated once for a seamless CSS loop. Ceiling:
+ * heavy third-party embeds. Mitigated by lazy-mounting the whole section on scroll
+ * (IntersectionObserver). Upgrade path: per-card virtualization, or swap YouTube
+ * players for thumbnail links.
+ */
+const YOUTUBE: Post[] = [
+ {
+ kind: "youtube",
+ url: "https://www.youtube.com/watch?v=i9AJ7PHGSGg",
+ title: "SurfSense vs NotebookLM",
+ channel: "rezasaad plus",
+ },
+ {
+ kind: "youtube",
+ url: "https://www.youtube.com/watch?v=VBOwuD6xVK0",
+ title: "NotebookLM Is Great… Until You See SurfSense",
+ channel: "Thomas AI",
+ },
+ {
+ kind: "youtube",
+ url: "https://www.youtube.com/watch?v=UaekqjhUiJM",
+ title: "NotebookLM vs SurfSense en 6 pruebas reales (sorprendente)",
+ channel: "NextGen IA Hub",
+ },
+ {
+ kind: "youtube",
+ url: "https://www.youtube.com/watch?v=QGjKpZJJ9aw",
+ title: "Gana DINERO configurando “Cerebros de IA” privados con SurfSense",
+ channel: "Creando Con La IA",
+ },
+ {
+ kind: "youtube",
+ url: "https://www.youtube.com/watch?v=cfNAIQtNbKY",
+ title: "¿Adiós NotebookLM? Probé SurfSense y es BRUTAL (IA Gratis)",
+ channel: "NextGen IA Hub",
+ },
+ {
+ kind: "youtube",
+ url: "https://www.youtube.com/watch?v=pIWOKSHhf38",
+ title: "¿Superaron a NotebookLM? SurfSense es Open Source, privada y GRATIS",
+ channel: "academIArtificial",
+ },
+ {
+ kind: "youtube",
+ url: "https://www.youtube.com/watch?v=K5xx-J_mQZ8",
+ title: "¿Mejor que NotebookLM? IA GRATIS con modo local",
+ channel: "Migue Baena IA",
+ },
+ {
+ kind: "youtube",
+ url: "https://www.youtube.com/watch?v=AKxM3RUBFsc",
+ title: "¿Nueva IA GRATIS destroza a NotebookLM de Google? (OPEN SOURCE)",
+ channel: "Inteligencia Artificial Top",
+ },
+ {
+ kind: "youtube",
+ url: "https://www.youtube.com/watch?v=jCAgeaVgPDA",
+ title: "¿Nueva Herramienta IA GRATIS Destroza a NotebookLM? (OPEN SOURCE)",
+ channel: "Joaquín Barberá",
+ },
+];
+
+const TWEETS: Post[] = [
+ { kind: "x", url: "https://x.com/LangChain/status/1853133037019562434" },
+ { kind: "x", url: "https://x.com/MoureDev/status/1976279289780740448" },
+ { kind: "x", url: "https://x.com/GithubProjects/status/2004892541590929490" },
+ { kind: "x", url: "https://x.com/GitHub_Daily/status/1920418408736436438" },
+ { kind: "x", url: "https://x.com/tom_doerr/status/2066062170173977088" },
+ { kind: "x", url: "https://x.com/itsharmanjot/status/2066118517905354816" },
+ { kind: "x", url: "https://x.com/JulianGoldieSEO/status/2011085275133604095" },
+ { kind: "x", url: "https://x.com/L_go_mrk/status/2066482853232115847" },
+ { kind: "x", url: "https://x.com/semihdev/status/2006275500952736028" },
+ { kind: "x", url: "https://x.com/shao__meng/status/1919912860957999494" },
+ { kind: "x", url: "https://x.com/LangChain/status/1840406184316342561" },
+];
+
+const SOCIAL: Post[] = [
+ {
+ kind: "linkedin",
+ url: "https://www.linkedin.com/embed/feed/update/urn:li:ugcPost:7448203908834938881",
+ postUrl:
+ "https://www.linkedin.com/posts/vikas-singh-546643206_most-ai-tools-live-in-your-browser-and-ugcPost-7448203908834938881-gR6y",
+ },
+ {
+ kind: "linkedin",
+ url: "https://www.linkedin.com/embed/feed/update/urn:li:share:7448351685409701889",
+ postUrl:
+ "https://www.linkedin.com/posts/neha-jain-279b80118_ive-been-using-a-lot-of-ai-tools-daily-share-7448351685409701889-JvFP",
+ },
+ {
+ kind: "tiktok",
+ url: "https://www.tiktok.com/@alejavirivera/video/7603064928114625814",
+ },
+];
+
+const CARD = "mr-4 shrink-0 overflow-hidden rounded-xl border bg-card";
+
+const SIZE: Record
= {
+ youtube: "h-[262px] w-[340px]",
+ x: "h-[440px] w-[340px]",
+ linkedin: "h-[540px] w-[340px]",
+ tiktok: "h-[540px] w-[340px]",
+};
+
+const META: Record = {
+ youtube: { Icon: IconBrandYoutube, label: "YouTube" },
+ x: { Icon: IconBrandX, label: "X" },
+ linkedin: { Icon: IconBrandLinkedin, label: "LinkedIn" },
+ tiktok: { Icon: IconBrandTiktok, label: "TikTok" },
+};
+
+/**
+ * Some embeds (notably Facebook, and LinkedIn when the author disabled embedding)
+ * throw at render/mount instead of degrading gracefully. This boundary stops one
+ * bad embed from taking down the whole marquee — it swaps in a link card instead.
+ */
+class EmbedBoundary extends Component<
+ { fallback: ReactNode; children: ReactNode },
+ { failed: boolean }
+> {
+ state = { failed: false };
+ static getDerivedStateFromError() {
+ return { failed: true };
+ }
+ render() {
+ return this.state.failed ? this.props.fallback : this.props.children;
+ }
+}
+
+function FallbackCard({ post }: { post: Post }) {
+ const { Icon, label } = META[post.kind];
+ const href = post.kind === "linkedin" ? post.postUrl : post.url;
+ return (
+
+ );
+}
+
+function Card({ post }: { post: Post }) {
+ switch (post.kind) {
+ case "youtube":
+ return (
+
+ );
+ case "x":
+ return (
+
+
+
+ );
+ case "linkedin":
+ return (
+
+
+
+ );
+ case "tiktok":
+ return (
+
+
+
+ );
+ }
+}
+
+function Row({
+ posts,
+ animation,
+ duration,
+}: {
+ posts: Post[];
+ animation: "ss-marquee-l" | "ss-marquee-r";
+ duration: number;
+}) {
+ return (
+
+ {/* Track holds the list twice; the -50% shift wraps seamlessly (margins, not gap). */}
+
+ {[...posts, ...posts].map((post, i) => (
+ }
+ >
+
+
+ ))}
+
+
+ );
+}
+
+export function SocialProof() {
+ // Third-party embeds are heavy; only mount them once the section scrolls near view.
+ const ref = useRef(null);
+ const [visible, setVisible] = useState(false);
+ useEffect(() => {
+ const el = ref.current;
+ if (!el) return;
+ const io = new IntersectionObserver(
+ (entries) => {
+ if (entries[0]?.isIntersecting) {
+ setVisible(true);
+ io.disconnect();
+ }
+ },
+ { rootMargin: "300px" }
+ );
+ io.observe(el);
+ return () => io.disconnect();
+ }, []);
+
+ return (
+
+
+
+
+ Loved across the internet
+
+
+
+
+ {visible ? (
+ <>
+
+
+ {/* Only 3 social cards — pre-double so one set spans wide viewports (no loop gap). */}
+
+ >
+ ) : null}
+
+
+
+ );
+}
diff --git a/surfsense_web/package.json b/surfsense_web/package.json
index 82e4144f0..4de9077bb 100644
--- a/surfsense_web/package.json
+++ b/surfsense_web/package.json
@@ -138,6 +138,7 @@
"react-dom": "^19.2.3",
"react-dropzone": "^14.3.8",
"react-hook-form": "^7.61.1",
+ "react-social-media-embed": "^2.5.18",
"react-syntax-highlighter": "^15.6.1",
"react-wrap-balancer": "^1.1.1",
"rehype-katex": "^7.0.1",
diff --git a/surfsense_web/pnpm-lock.yaml b/surfsense_web/pnpm-lock.yaml
index d93ad580d..29719c759 100644
--- a/surfsense_web/pnpm-lock.yaml
+++ b/surfsense_web/pnpm-lock.yaml
@@ -335,6 +335,9 @@ importers:
react-hook-form:
specifier: ^7.61.1
version: 7.71.2(react@19.2.4)
+ react-social-media-embed:
+ specifier: ^2.5.18
+ version: 2.5.18(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
react-syntax-highlighter:
specifier: ^15.6.1
version: 15.6.6(react@19.2.4)
@@ -1155,28 +1158,24 @@ packages:
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@biomejs/cli-linux-arm64@2.4.6':
resolution: {integrity: sha512-kMLaI7OF5GN1Q8Doymjro1P8rVEoy7BKQALNz6fiR8IC1WKduoNyteBtJlHT7ASIL0Cx2jR6VUOBIbcB1B8pew==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@biomejs/cli-linux-x64-musl@2.4.6':
resolution: {integrity: sha512-C9s98IPDu7DYarjlZNuzJKTjVHN03RUnmHV5htvqsx6vEUXCDSJ59DNwjKVD5XYoSS4N+BYhq3RTBAL8X6svEg==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
- libc: [musl]
'@biomejs/cli-linux-x64@2.4.6':
resolution: {integrity: sha512-oHXmUFEoH8Lql1xfc3QkFLiC1hGR7qedv5eKNlC185or+o4/4HiaU7vYODAH3peRCfsuLr1g6v2fK9dFFOYdyw==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@biomejs/cli-win32-arm64@2.4.6':
resolution: {integrity: sha512-xzThn87Pf3YrOGTEODFGONmqXpTwUNxovQb72iaUOdcw8sBSY3+3WD8Hm9IhMYLnPi0n32s3L3NWU6+eSjfqFg==}
@@ -1864,105 +1863,89 @@ packages:
resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-arm@1.2.4':
resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
cpu: [arm]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-ppc64@1.2.4':
resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==}
cpu: [ppc64]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-riscv64@1.2.4':
resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-s390x@1.2.4':
resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-x64@1.2.4':
resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linuxmusl-arm64@1.2.4':
resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@img/sharp-libvips-linuxmusl-x64@1.2.4':
resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
cpu: [x64]
os: [linux]
- libc: [musl]
'@img/sharp-linux-arm64@0.34.5':
resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-arm@0.34.5':
resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-ppc64@0.34.5':
resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [ppc64]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-riscv64@0.34.5':
resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-s390x@0.34.5':
resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-x64@0.34.5':
resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@img/sharp-linuxmusl-arm64@0.34.5':
resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@img/sharp-linuxmusl-x64@0.34.5':
resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
- libc: [musl]
'@img/sharp-wasm32@0.34.5':
resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==}
@@ -2082,35 +2065,30 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@napi-rs/canvas-linux-arm64-musl@0.1.97':
resolution: {integrity: sha512-kKmSkQVnWeqg7qdsiXvYxKhAFuHz3tkBjW/zyQv5YKUPhotpaVhpBGv5LqCngzyuRV85SXoe+OFj+Tv0a0QXkQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@napi-rs/canvas-linux-riscv64-gnu@0.1.97':
resolution: {integrity: sha512-Jc7I3A51jnEOIAXeLsN/M/+Z28LUeakcsXs07FLq9prXc0eYOtVwsDEv913Gr+06IRo34gJJVgT0TXvmz+N2VA==}
engines: {node: '>= 10'}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
'@napi-rs/canvas-linux-x64-gnu@0.1.97':
resolution: {integrity: sha512-iDUBe7AilfuBSRbSa8/IGX38Mf+iCSBqoVKLSQ5XaY2JLOaqz1TVyPFEyIck7wT6mRQhQt5sN6ogfjIDfi74tg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@napi-rs/canvas-linux-x64-musl@0.1.97':
resolution: {integrity: sha512-AKLFd/v0Z5fvgqBDqhvqtAdx+fHMJ5t9JcUNKq4FIZ5WH+iegGm8HPdj00NFlCSnm83Fp3Ln8I2f7uq1aIiWaA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- libc: [musl]
'@napi-rs/canvas-win32-arm64-msvc@0.1.97':
resolution: {integrity: sha512-u883Yr6A6fO7Vpsy9YE4FVCIxzzo5sO+7pIUjjoDLjS3vQaNMkVzx5bdIpEL+ob+gU88WDK4VcxYMZ6nmnoX9A==}
@@ -2154,28 +2132,24 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@next/swc-linux-arm64-musl@16.1.6':
resolution: {integrity: sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@next/swc-linux-x64-gnu@16.1.6':
resolution: {integrity: sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@next/swc-linux-x64-musl@16.1.6':
resolution: {integrity: sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- libc: [musl]
'@next/swc-win32-arm64-msvc@16.1.6':
resolution: {integrity: sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==}
@@ -2827,56 +2801,48 @@ packages:
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@oxfmt/binding-linux-arm64-musl@0.45.0':
resolution: {integrity: sha512-XQKXZIKYJC3GQJ8FnD3iMntpw69Wd9kDDK/Xt79p6xnFYlGGxSNv2vIBvRTDg5CKByWFWWZLCRDOXoP/m6YN4g==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@oxfmt/binding-linux-ppc64-gnu@0.45.0':
resolution: {integrity: sha512-+g5RiG+xOkdrCWkKodv407nTvMq4vYM18Uox2MhZBm/YoqFxxJpWKsloskFFG5NU13HGPw1wzYjjOVcyd9moCA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ppc64]
os: [linux]
- libc: [glibc]
'@oxfmt/binding-linux-riscv64-gnu@0.45.0':
resolution: {integrity: sha512-V7dXKoSyEbWAkkSF4JJNtF+NJZDmJoSarSoP30WCsB3X636Rehd3CvxBj49FIJxEBFWhvcUjGSHVeU8Erck1bQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
'@oxfmt/binding-linux-riscv64-musl@0.45.0':
resolution: {integrity: sha512-Vdelft1sAEYojVGgcODEFXSWYQYlIvoyIGWebKCuUibd1tvS1TjTx413xG2ZLuHpYj45CkN/ztMLMX6jrgqpgg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64]
os: [linux]
- libc: [musl]
'@oxfmt/binding-linux-s390x-gnu@0.45.0':
resolution: {integrity: sha512-RR7xKgNpqwENnK0aYCGYg0JycY2n93J0reNjHyes+I9Gq52dH95x+CBlnlAQHCPfz6FGnKA9HirgUl14WO6o7w==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@oxfmt/binding-linux-x64-gnu@0.45.0':
resolution: {integrity: sha512-U/QQ0+BQNSHxjuXR/utvXnQ50Vu5kUuqEomZvQ1/3mhgbBiMc2WU9q5kZ5WwLp3gnFIx9ibkveoRSe2EZubkqg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@oxfmt/binding-linux-x64-musl@0.45.0':
resolution: {integrity: sha512-o5TLOUCF0RWQjsIS06yVC+kFgp092/yLe6qBGSUvtnmTVw9gxjpdQSXc3VN5Cnive4K11HNstEZF8ROKHfDFSw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
- libc: [musl]
'@oxfmt/binding-openharmony-arm64@0.45.0':
resolution: {integrity: sha512-RnGcV3HgPuOjsGx/k9oyRNKmOp+NBLGzZTdPDYbc19r7NGeYPplnUU/BfU35bX2Y/O4ejvHxcfkvW2WoYL/gsg==}
@@ -2931,42 +2897,36 @@ packages:
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
- libc: [glibc]
'@parcel/watcher-linux-arm-musl@2.5.6':
resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==}
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
- libc: [musl]
'@parcel/watcher-linux-arm64-glibc@2.5.6':
resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@parcel/watcher-linux-arm64-musl@2.5.6':
resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@parcel/watcher-linux-x64-glibc@2.5.6':
resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@parcel/watcher-linux-x64-musl@2.5.6':
resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
- libc: [musl]
'@parcel/watcher-win32-arm64@2.5.6':
resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==}
@@ -4287,79 +4247,66 @@ packages:
resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==}
cpu: [arm]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-arm-musleabihf@4.59.0':
resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==}
cpu: [arm]
os: [linux]
- libc: [musl]
'@rollup/rollup-linux-arm64-gnu@4.59.0':
resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-arm64-musl@4.59.0':
resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@rollup/rollup-linux-loong64-gnu@4.59.0':
resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==}
cpu: [loong64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-loong64-musl@4.59.0':
resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==}
cpu: [loong64]
os: [linux]
- libc: [musl]
'@rollup/rollup-linux-ppc64-gnu@4.59.0':
resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==}
cpu: [ppc64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-ppc64-musl@4.59.0':
resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==}
cpu: [ppc64]
os: [linux]
- libc: [musl]
'@rollup/rollup-linux-riscv64-gnu@4.59.0':
resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-riscv64-musl@4.59.0':
resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==}
cpu: [riscv64]
os: [linux]
- libc: [musl]
'@rollup/rollup-linux-s390x-gnu@4.59.0':
resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.59.0':
resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-x64-musl@4.59.0':
resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==}
cpu: [x64]
os: [linux]
- libc: [musl]
'@rollup/rollup-openbsd-x64@4.59.0':
resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==}
@@ -4550,28 +4497,24 @@ packages:
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@swc/core-linux-arm64-musl@1.15.13':
resolution: {integrity: sha512-SmZ9m+XqCB35NddHCctvHFLqPZDAs5j8IgD36GoutufDJmeq2VNfgk5rQoqNqKmAK3Y7iFdEmI76QoHIWiCLyw==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@swc/core-linux-x64-gnu@1.15.13':
resolution: {integrity: sha512-5rij+vB9a29aNkHq72EXI2ihDZPszJb4zlApJY4aCC/q6utgqFA6CkrfTfIb+O8hxtG3zP5KERETz8mfFK6A0A==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@swc/core-linux-x64-musl@1.15.13':
resolution: {integrity: sha512-OlSlaOK9JplQ5qn07WiBLibkOw7iml2++ojEXhhR3rbWrNEKCD7sd8+6wSavsInyFdw4PhLA+Hy6YyDBIE23Yw==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
- libc: [musl]
'@swc/core-win32-arm64-msvc@1.15.13':
resolution: {integrity: sha512-zwQii5YVdsfG8Ti9gIKgBKZg8qMkRZxl+OlYWUT5D93Jl4NuNBRausP20tfEkQdAPSRrMCSUZBM6FhW7izAZRg==}
@@ -4655,28 +4598,24 @@ packages:
engines: {node: '>= 20'}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@tailwindcss/oxide-linux-arm64-musl@4.2.1':
resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==}
engines: {node: '>= 20'}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@tailwindcss/oxide-linux-x64-gnu@4.2.1':
resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==}
engines: {node: '>= 20'}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@tailwindcss/oxide-linux-x64-musl@4.2.1':
resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==}
engines: {node: '>= 20'}
cpu: [x64]
os: [linux]
- libc: [musl]
'@tailwindcss/oxide-wasm32-wasi@4.2.1':
resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==}
@@ -4976,6 +4915,9 @@ packages:
'@types/ws@8.18.1':
resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==}
+ '@types/youtube-player@5.5.11':
+ resolution: {integrity: sha512-pM41CDBqJqBmTeJWnF7NOGz82IQoYOhqzMYXv5vKCXBqGiYSLldxMtpCk6KAEtADTy49S45AriYaCaZyeUX38Q==}
+
'@typescript-eslint/eslint-plugin@8.56.0':
resolution: {integrity: sha512-lRyPDLzNCuae71A3t9NEINBiTn7swyOhvUj3MyUOxb8x6g6vPEFoOU+ZRmGMusNC3X3YMhqMIX7i8ShqhT74Pw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -5100,49 +5042,41 @@ packages:
resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@unrs/resolver-binding-linux-arm64-musl@1.11.1':
resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==}
cpu: [ppc64]
os: [linux]
- libc: [glibc]
'@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
'@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==}
cpu: [riscv64]
os: [linux]
- libc: [musl]
'@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@unrs/resolver-binding-linux-x64-gnu@1.11.1':
resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@unrs/resolver-binding-linux-x64-musl@1.11.1':
resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==}
cpu: [x64]
os: [linux]
- libc: [musl]
'@unrs/resolver-binding-wasm32-wasi@1.11.1':
resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==}
@@ -5830,6 +5764,14 @@ packages:
dayjs@1.11.21:
resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==}
+ debug@2.6.9:
+ resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
debug@3.2.7:
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
peerDependencies:
@@ -7255,28 +7197,24 @@ packages:
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
- libc: [glibc]
lightningcss-linux-arm64-musl@1.31.1:
resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
- libc: [musl]
lightningcss-linux-x64-gnu@1.31.1:
resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
- libc: [glibc]
lightningcss-linux-x64-musl@1.31.1:
resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
- libc: [musl]
lightningcss-win32-arm64-msvc@1.31.1:
resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==}
@@ -7297,6 +7235,9 @@ packages:
lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+ load-script@1.0.0:
+ resolution: {integrity: sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA==}
+
locate-path@6.0.0:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
@@ -7617,6 +7558,9 @@ packages:
react-dom:
optional: true
+ ms@2.0.0:
+ resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
+
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@@ -8169,6 +8113,12 @@ packages:
peerDependencies:
react: ^16.8.0 || ^17 || ^18 || ^19
+ react-html-props@2.1.1:
+ resolution: {integrity: sha512-tM+YCYlr90m3JontKUAa+gNVU2zkyprlCS7OQ9aa3z2MfyJjAioJzrSmi1Vef/+UCTE6CQlPqLX4ebdLIJDKxw==}
+ peerDependencies:
+ react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0
+ react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0
+
react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
@@ -8227,6 +8177,12 @@ packages:
'@types/react':
optional: true
+ react-social-media-embed@2.5.18:
+ resolution: {integrity: sha512-+PkzLRGAwnySkxKajaiK5VD+EjOhlFsh/vjNxgHsDfKBTseDpFxPrMXXQWkk6BRCwFBNVWX+V1HZ9AU0y54Wgw==}
+ peerDependencies:
+ react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0
+ react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0
+
react-style-singleton@2.2.3:
resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==}
engines: {node: '>=10'}
@@ -8237,6 +8193,12 @@ packages:
'@types/react':
optional: true
+ react-sub-unsub@2.2.8:
+ resolution: {integrity: sha512-o3tmiOOZPdQUCmRhkdCHXRFLOHnCwdz/N3QZ1JQ14fQGA2HysKMF0kWu56ERnQUCK7wYVCQzI8pFbnivAYNQ+A==}
+ peerDependencies:
+ react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0
+ react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0
+
react-syntax-highlighter@15.6.6:
resolution: {integrity: sha512-DgXrc+AZF47+HvAPEmn7Ua/1p10jNoVZVI/LoPiYdtY+OM+/nG5yefLHKJwdKqY1adMuHFbeyBaG9j64ML7vTw==}
peerDependencies:
@@ -8261,11 +8223,24 @@ packages:
react-native:
optional: true
+ react-twitter-embed@4.0.4:
+ resolution: {integrity: sha512-2JIL7qF+U62zRzpsh6SZDXNI3hRNVYf5vOZ1WRcMvwKouw+xC00PuFaD0aEp2wlyGaZ+f4x2VvX+uDadFQ3HVA==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ react: ^16.0.0 || ^17.0.0 || ^18.0.0
+ react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0
+
react-wrap-balancer@1.1.1:
resolution: {integrity: sha512-AB+l7FPRWl6uZ28VcJ8skkwLn2+UC62bjiw8tQUrZPlEWDVnR9MG0lghyn7EyxuJSsFEpht4G+yh2WikEqQ/5Q==}
peerDependencies:
react: '>=16.8.0 || ^17.0.0 || ^18'
+ react-youtube@10.1.0:
+ resolution: {integrity: sha512-ZfGtcVpk0SSZtWCSTYOQKhfx5/1cfyEW1JN/mugGNfAxT3rmVJeMbGpA9+e78yG21ls5nc/5uZJETE3cm3knBg==}
+ engines: {node: '>= 14.x'}
+ peerDependencies:
+ react: '>=0.14.1'
+
react@19.2.4:
resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==}
engines: {node: '>=0.10.0'}
@@ -8489,6 +8464,9 @@ packages:
scheduler@0.27.0:
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
+ scriptjs@2.5.9:
+ resolution: {integrity: sha512-qGVDoreyYiP1pkQnbnFAUIS5AjenNwwQBdl7zeos9etl+hYKWahjRTfzAZZYBv5xNHx7vNKCmaLDQZ6Fr2AEXg==}
+
scroll-into-view-if-needed@3.1.0:
resolution: {integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==}
@@ -8574,6 +8552,9 @@ packages:
simple-swizzle@0.2.4:
resolution: {integrity: sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==}
+ sister@3.0.2:
+ resolution: {integrity: sha512-p19rtTs+NksBRKW9qn0UhZ8/TUI9BPw9lmtHny+Y3TinWlOa9jWh9xB0AtPSdmOy49NJJJSSe0Ey4C7h0TrcYA==}
+
slate-dom@0.119.0:
resolution: {integrity: sha512-foc8a2NkE+1SldDIYaoqjhVKupt8RSuvHI868rfYOcypD4we5TT7qunjRKJ852EIRh/Ql8sSTepXgXKOUJnt1w==}
peerDependencies:
@@ -9240,6 +9221,9 @@ packages:
resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==}
engines: {node: '>=18'}
+ youtube-player@5.5.2:
+ resolution: {integrity: sha512-ZGtsemSpXnDky2AUYWgxjaopgB+shFHgXVpiJFeNB5nWEugpW1KWYDaHKuLqh2b67r24GtP6HoSW5swvf0fFIQ==}
+
zod-to-json-schema@3.25.1:
resolution: {integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==}
peerDependencies:
@@ -13989,6 +13973,8 @@ snapshots:
dependencies:
'@types/node': 20.19.33
+ '@types/youtube-player@5.5.11': {}
+
'@typescript-eslint/eslint-plugin@8.56.0(@typescript-eslint/parser@8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@eslint-community/regexpp': 4.12.2
@@ -14881,6 +14867,10 @@ snapshots:
dayjs@1.11.21: {}
+ debug@2.6.9:
+ dependencies:
+ ms: 2.0.0
+
debug@3.2.7:
dependencies:
ms: 2.1.3
@@ -16535,6 +16525,8 @@ snapshots:
lines-and-columns@1.2.4: {}
+ load-script@1.0.0: {}
+
locate-path@6.0.0:
dependencies:
p-locate: 5.0.0
@@ -17136,6 +17128,8 @@ snapshots:
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
+ ms@2.0.0: {}
+
ms@2.1.3: {}
mutative@1.1.0: {}
@@ -17802,6 +17796,11 @@ snapshots:
dependencies:
react: 19.2.4
+ react-html-props@2.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
+ dependencies:
+ react: 19.2.4
+ react-dom: 19.2.4(react@19.2.4)
+
react-is@16.13.1: {}
react-lifecycles-compat@3.0.4: {}
@@ -17870,6 +17869,19 @@ snapshots:
optionalDependencies:
'@types/react': 19.2.14
+ react-social-media-embed@2.5.18(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
+ dependencies:
+ '@types/youtube-player': 5.5.11
+ classnames: 2.5.1
+ react: 19.2.4
+ react-dom: 19.2.4(react@19.2.4)
+ react-html-props: 2.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ react-sub-unsub: 2.2.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ react-twitter-embed: 4.0.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ react-youtube: 10.1.0(react@19.2.4)
+ transitivePeerDependencies:
+ - supports-color
+
react-style-singleton@2.2.3(@types/react@19.2.14)(react@19.2.4):
dependencies:
get-nonce: 1.0.1
@@ -17878,6 +17890,11 @@ snapshots:
optionalDependencies:
'@types/react': 19.2.14
+ react-sub-unsub@2.2.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
+ dependencies:
+ react: 19.2.4
+ react-dom: 19.2.4(react@19.2.4)
+
react-syntax-highlighter@15.6.6(react@19.2.4):
dependencies:
'@babel/runtime': 7.29.2
@@ -17906,10 +17923,25 @@ snapshots:
optionalDependencies:
react-dom: 19.2.4(react@19.2.4)
+ react-twitter-embed@4.0.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
+ dependencies:
+ react: 19.2.4
+ react-dom: 19.2.4(react@19.2.4)
+ scriptjs: 2.5.9
+
react-wrap-balancer@1.1.1(react@19.2.4):
dependencies:
react: 19.2.4
+ react-youtube@10.1.0(react@19.2.4):
+ dependencies:
+ fast-deep-equal: 3.1.3
+ prop-types: 15.8.1
+ react: 19.2.4
+ youtube-player: 5.5.2
+ transitivePeerDependencies:
+ - supports-color
+
react@19.2.4: {}
readable-stream@2.3.8:
@@ -18250,6 +18282,8 @@ snapshots:
scheduler@0.27.0: {}
+ scriptjs@2.5.9: {}
+
scroll-into-view-if-needed@3.1.0:
dependencies:
compute-scroll-into-view: 3.1.1
@@ -18383,6 +18417,8 @@ snapshots:
dependencies:
is-arrayish: 0.3.4
+ sister@3.0.2: {}
+
slate-dom@0.119.0(slate@0.120.0):
dependencies:
'@juggle/resize-observer': 3.4.0
@@ -19095,6 +19131,14 @@ snapshots:
yoctocolors@2.1.2: {}
+ youtube-player@5.5.2:
+ dependencies:
+ debug: 2.6.9
+ load-script: 1.0.0
+ sister: 3.0.2
+ transitivePeerDependencies:
+ - supports-color
+
zod-to-json-schema@3.25.1(zod@4.3.6):
dependencies:
zod: 4.3.6
diff --git a/surfsense_web/public/logos/berkeley.svg b/surfsense_web/public/logos/berkeley.svg
new file mode 100644
index 000000000..97700a05e
--- /dev/null
+++ b/surfsense_web/public/logos/berkeley.svg
@@ -0,0 +1,874 @@
+
+
+
+
\ No newline at end of file
diff --git a/surfsense_web/public/logos/bosta.png b/surfsense_web/public/logos/bosta.png
new file mode 100644
index 000000000..12b579129
Binary files /dev/null and b/surfsense_web/public/logos/bosta.png differ
diff --git a/surfsense_web/public/logos/bristol.svg b/surfsense_web/public/logos/bristol.svg
new file mode 100644
index 000000000..dc0e18921
--- /dev/null
+++ b/surfsense_web/public/logos/bristol.svg
@@ -0,0 +1,295 @@
+
diff --git a/surfsense_web/public/logos/chula.svg b/surfsense_web/public/logos/chula.svg
new file mode 100644
index 000000000..01ec9298a
--- /dev/null
+++ b/surfsense_web/public/logos/chula.svg
@@ -0,0 +1,578 @@
+
+
\ No newline at end of file
diff --git a/surfsense_web/public/logos/devoteam.png b/surfsense_web/public/logos/devoteam.png
new file mode 100644
index 000000000..71b1f29d2
Binary files /dev/null and b/surfsense_web/public/logos/devoteam.png differ
diff --git a/surfsense_web/public/logos/globant.svg b/surfsense_web/public/logos/globant.svg
new file mode 100644
index 000000000..cd3e6b96d
--- /dev/null
+++ b/surfsense_web/public/logos/globant.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/surfsense_web/public/logos/ironmountain.svg b/surfsense_web/public/logos/ironmountain.svg
new file mode 100644
index 000000000..bbfa907de
--- /dev/null
+++ b/surfsense_web/public/logos/ironmountain.svg
@@ -0,0 +1,44 @@
+
+
+
diff --git a/surfsense_web/public/logos/koreanair.svg b/surfsense_web/public/logos/koreanair.svg
new file mode 100644
index 000000000..9bb9df295
--- /dev/null
+++ b/surfsense_web/public/logos/koreanair.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/surfsense_web/public/logos/leverageedu.png b/surfsense_web/public/logos/leverageedu.png
new file mode 100644
index 000000000..ff9ecad31
Binary files /dev/null and b/surfsense_web/public/logos/leverageedu.png differ
diff --git a/surfsense_web/public/logos/nutresa.svg b/surfsense_web/public/logos/nutresa.svg
new file mode 100644
index 000000000..0b8a1db80
--- /dev/null
+++ b/surfsense_web/public/logos/nutresa.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/surfsense_web/public/logos/opengov.png b/surfsense_web/public/logos/opengov.png
new file mode 100644
index 000000000..042a50b29
Binary files /dev/null and b/surfsense_web/public/logos/opengov.png differ
diff --git a/surfsense_web/public/logos/pitt.svg b/surfsense_web/public/logos/pitt.svg
new file mode 100644
index 000000000..101f7e7b5
--- /dev/null
+++ b/surfsense_web/public/logos/pitt.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/surfsense_web/public/logos/tamu.svg b/surfsense_web/public/logos/tamu.svg
new file mode 100644
index 000000000..9bb086c67
--- /dev/null
+++ b/surfsense_web/public/logos/tamu.svg
@@ -0,0 +1,810 @@
+
+
+
diff --git a/surfsense_web/public/logos/tec.svg b/surfsense_web/public/logos/tec.svg
new file mode 100644
index 000000000..3e68ed5ca
--- /dev/null
+++ b/surfsense_web/public/logos/tec.svg
@@ -0,0 +1,569 @@
+
+
+
diff --git a/surfsense_web/public/logos/tpbank.svg b/surfsense_web/public/logos/tpbank.svg
new file mode 100644
index 000000000..4874bb42c
--- /dev/null
+++ b/surfsense_web/public/logos/tpbank.svg
@@ -0,0 +1,166 @@
+
+
diff --git a/surfsense_web/public/logos/usc.svg b/surfsense_web/public/logos/usc.svg
new file mode 100644
index 000000000..6176e5d61
--- /dev/null
+++ b/surfsense_web/public/logos/usc.svg
@@ -0,0 +1,1335 @@
+
+
+
+
\ No newline at end of file
diff --git a/surfsense_web/public/logos/vng.svg b/surfsense_web/public/logos/vng.svg
new file mode 100644
index 000000000..33c9392e6
--- /dev/null
+++ b/surfsense_web/public/logos/vng.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/surfsense_web/public/logos/welab.png b/surfsense_web/public/logos/welab.png
new file mode 100644
index 000000000..d8c283428
Binary files /dev/null and b/surfsense_web/public/logos/welab.png differ
diff --git a/surfsense_web/public/logos/wisc.svg b/surfsense_web/public/logos/wisc.svg
new file mode 100644
index 000000000..59f4a1290
--- /dev/null
+++ b/surfsense_web/public/logos/wisc.svg
@@ -0,0 +1,7 @@
+
+
diff --git a/surfsense_web/public/logos/zopper.png b/surfsense_web/public/logos/zopper.png
new file mode 100644
index 000000000..7d01bc672
Binary files /dev/null and b/surfsense_web/public/logos/zopper.png differ