From 623ca1a26a427c7bc2cb338a4588a2488a5882ae Mon Sep 17 00:00:00 2001 From: Krrish Dholakia Date: Thu, 15 Jan 2026 16:27:12 +0530 Subject: [PATCH 1/3] feat(main.svelte): add new cookbook tab new tab for publishing guides to ai coding tools with litellm --- public/_redirects | 2 ++ src/Main.svelte | 91 ++++++++++++++++++++++++++++++++++++++++++++--- vercel.json | 9 +++++ vite.config.ts | 4 +++ 4 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 public/_redirects create mode 100644 vercel.json diff --git a/public/_redirects b/public/_redirects new file mode 100644 index 0000000..4e31746 --- /dev/null +++ b/public/_redirects @@ -0,0 +1,2 @@ +/* /index.html 200 + diff --git a/src/Main.svelte b/src/Main.svelte index c9b4b78..17890ff 100644 --- a/src/Main.svelte +++ b/src/Main.svelte @@ -5,13 +5,30 @@ import RequestForm from "./RequestForm.svelte"; import { initAnalytics, trackPageView, trackTabChange } from "./analytics"; - let activeTab: "models" | "providers" = "models"; + let activeTab: "models" | "providers" | "cookbook" = "models"; let mobileMenuOpen = false; let requestForm: RequestForm; const GITHUB_URL = "https://github.com/BerriAI/litellm"; const DOCS_URL = "https://docs.litellm.ai"; + // Map URL paths to tab names + function getTabFromPath(path: string): "models" | "providers" | "cookbook" { + if (path === "/providers" || path === "/providers/") { + return "providers"; + } else if (path === "/cookbook" || path === "/cookbook/") { + return "cookbook"; + } + return "models"; + } + + // Get path from tab name + function getPathFromTab(tab: "models" | "providers" | "cookbook"): string { + if (tab === "providers") return "/providers"; + if (tab === "cookbook") return "/cookbook"; + return "/"; + } + function toggleMobileMenu() { mobileMenuOpen = !mobileMenuOpen; } @@ -20,10 +37,22 @@ mobileMenuOpen = false; } - function selectTab(tab: "models" | "providers") { + function selectTab(tab: "models" | "providers" | "cookbook", updateUrl = true) { activeTab = tab; closeMobileMenu(); trackTabChange(tab); + + // Update URL without page reload + if (updateUrl) { + const path = getPathFromTab(tab); + window.history.pushState({ tab }, "", path); + } + } + + // Handle browser back/forward buttons + function handlePopState(event: PopStateEvent) { + const tab = event.state?.tab || getTabFromPath(window.location.pathname); + selectTab(tab, false); } const PROVIDERS_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/provider_endpoints_support.json"; const MODELS_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json"; @@ -39,6 +68,16 @@ initAnalytics(); trackPageView('Home'); + // Set initial tab based on URL + const initialTab = getTabFromPath(window.location.pathname); + activeTab = initialTab; + + // Set initial history state + window.history.replaceState({ tab: initialTab }, "", window.location.pathname); + + // Listen for browser back/forward navigation + window.addEventListener("popstate", handlePopState); + // Check if URL has ?request=true to auto-open the form const urlParams = new URLSearchParams(window.location.search); if (urlParams.get('request') === 'true') { @@ -82,6 +121,11 @@ console.error("Failed to load statistics:", error); statsLoading = false; } + + // Cleanup event listener on component destroy + return () => { + window.removeEventListener("popstate", handlePopState); + }; }); @@ -109,7 +153,14 @@ class:active={activeTab === "providers"} on:click={() => selectTab("providers")} > - AI Gateway - Endpoints & Providers + Endpoints & Providers + +