- {/* Right Image - Only show if current slide has an image */}
+ {/* Image - Show below on mobile, right side on desktop */}
{carouselData[currentSlide].image && (
-
+
![{carouselData[currentSlide].category}]({carouselData[currentSlide].image})
+
+ )}
+
+ {/* Right Image - Desktop only */}
+ {carouselData[currentSlide].image && (
+
+
)}
diff --git a/www/src/components/IntroSection.tsx b/www/src/components/IntroSection.tsx
index 1cf1ed31..a0dcf3a5 100644
--- a/www/src/components/IntroSection.tsx
+++ b/www/src/components/IntroSection.tsx
@@ -23,8 +23,10 @@ export function IntroSection() {
Plano is a framework-friendly proxy server and dataplane for agents,
deployed as a sidecar. Plano handles the critical plumbing work in AI
like agent routing and orchestration, comprehensive traces for agentic
- interactions, guardrail hooks, unified APIs for LLMs — so
developers
- can focus more on modeling workflows,
product teams can accelerate
+ interactions, guardrail hooks, unified APIs for LLMs —
+
+
+ Developers can focus more on modeling workflows, product teams can accelerate
feedback loops for reinforcement learning and engineering teams can
standardize policies and access controls across every agent and LLM for
safer, more reliable scaling.
diff --git a/www/src/components/LogoCloud.tsx b/www/src/components/LogoCloud.tsx
index 049acd45..5d05e56b 100644
--- a/www/src/components/LogoCloud.tsx
+++ b/www/src/components/LogoCloud.tsx
@@ -26,23 +26,28 @@ const customerLogos = [
export function LogoCloud() {
return (
-
+
-
- {customerLogos.map((logo) => (
-
-
-
- ))}
+
+ {customerLogos.map((logo, index) => {
+ const isLast = index === customerLogos.length - 1;
+ return (
+
+
+
+ );
+ })}
diff --git a/www/src/components/Navbar.tsx b/www/src/components/Navbar.tsx
index 14adfa4c..426454f3 100644
--- a/www/src/components/Navbar.tsx
+++ b/www/src/components/Navbar.tsx
@@ -1,10 +1,12 @@
"use client";
-import React from "react";
+import React, { useState, useEffect } from "react";
import Link from "next/link";
import { Logo } from "./Logo";
import { Button } from "./ui/button";
import { cn } from "@/lib/utils";
+import { motion, AnimatePresence } from "framer-motion";
+import { X, Menu } from "lucide-react";
const navItems = [
{ href: "/start", label: "start locally" },
@@ -15,6 +17,147 @@ const navItems = [
];
export function Navbar() {
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
+ const [isDarkBackground, setIsDarkBackground] = useState(false);
+
+ // Detect background color behind dropdown menu
+ useEffect(() => {
+ if (!isMenuOpen) {
+ setIsDarkBackground(false);
+ return;
+ }
+
+ const detectBackground = () => {
+ // Small delay to ensure DOM is ready
+ setTimeout(() => {
+ const nav = document.querySelector("nav");
+ if (!nav) return;
+
+ const navRect = nav.getBoundingClientRect();
+ const dropdownBottom = navRect.bottom;
+ const checkY = dropdownBottom + 20; // Just below the dropdown
+
+ // First, try to find section elements directly
+ const main = document.querySelector("main");
+ if (main) {
+ const sections = main.querySelectorAll("section");
+ let foundDarkSection = false;
+
+ sections.forEach((section) => {
+ const rect = section.getBoundingClientRect();
+ // Check if this section is visible below the navbar
+ if (rect.top <= checkY && rect.bottom > checkY) {
+ // Check for dark background classes
+ const classList = Array.from(section.classList);
+ const hasDarkBg = classList.some(cls =>
+ cls.includes('bg-[#1a1a1a]') ||
+ cls.includes('bg-black') ||
+ cls.includes('bg-gray-900') ||
+ cls.includes('bg-neutral-900') ||
+ cls.includes('dark')
+ );
+
+ if (hasDarkBg) {
+ foundDarkSection = true;
+ setIsDarkBackground(true);
+ return;
+ }
+
+ // Also check computed background
+ const computed = window.getComputedStyle(section);
+ const bg = computed.backgroundColor;
+ if (bg && bg !== "rgba(0, 0, 0, 0)" && bg !== "transparent") {
+ const rgbMatch = bg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
+ if (rgbMatch) {
+ const r = parseInt(rgbMatch[1]);
+ const g = parseInt(rgbMatch[2]);
+ const b = parseInt(rgbMatch[3]);
+ const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
+ setIsDarkBackground(luminance < 0.5);
+ foundDarkSection = true;
+ return;
+ }
+ }
+ }
+ });
+
+ if (foundDarkSection) return;
+ }
+
+ // Fallback: Check element at point
+ const centerX = window.innerWidth / 2;
+ const elementBelow = document.elementFromPoint(centerX, checkY);
+
+ if (elementBelow) {
+ let current: HTMLElement | null = elementBelow as HTMLElement;
+ let backgroundColor = "";
+
+ // Walk up the DOM tree
+ let levels = 0;
+ while (current && !backgroundColor && current !== document.body && levels < 15) {
+ const computed = window.getComputedStyle(current);
+ const bg = computed.backgroundColor;
+
+ if (bg && bg !== "rgba(0, 0, 0, 0)" && bg !== "transparent") {
+ const rgbaMatch = bg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
+ if (rgbaMatch) {
+ const alpha = rgbaMatch[4] ? parseFloat(rgbaMatch[4]) : 1;
+ if (alpha > 0.1) {
+ backgroundColor = bg;
+ break;
+ }
+ } else {
+ backgroundColor = bg;
+ break;
+ }
+ }
+
+ current = current.parentElement;
+ levels++;
+ }
+
+ if (!backgroundColor) {
+ const bodyBg = window.getComputedStyle(document.body).backgroundColor;
+ backgroundColor = bodyBg;
+ }
+
+ if (backgroundColor) {
+ const rgbMatch = backgroundColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
+ if (rgbMatch) {
+ const r = parseInt(rgbMatch[1]);
+ const g = parseInt(rgbMatch[2]);
+ const b = parseInt(rgbMatch[3]);
+ const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
+ setIsDarkBackground(luminance < 0.5);
+ } else {
+ const darkColors = ['black', '#000', '#000000', 'rgb(0,0,0)', 'rgba(0,0,0', '#1a1a1a'];
+ const isDark = darkColors.some(color => backgroundColor.toLowerCase().includes(color.toLowerCase()));
+ setIsDarkBackground(isDark);
+ }
+ }
+ }
+ }, 100);
+ };
+
+ // Detect on open and on scroll
+ detectBackground();
+ const scrollHandler = () => detectBackground();
+ const resizeHandler = () => detectBackground();
+
+ window.addEventListener("scroll", scrollHandler, { passive: true });
+ window.addEventListener("resize", resizeHandler);
+
+ return () => {
+ window.removeEventListener("scroll", scrollHandler);
+ window.removeEventListener("resize", resizeHandler);
+ };
+ }, [isMenuOpen]);
+
+ // Close menu when route changes
+ const handleLinkClick = () => {
+ setIsMenuOpen(false);
+ };
+
return (
+
+ {/* Mobile Dropdown Menu - Outside constrained container for full width */}
+
+ {isMenuOpen && (
+
+
+
+ {navItems.map((item, index) => (
+
+
+ {item.label}
+
+
+ ))}
+
+
+
+ )}
+
);
}
diff --git a/www/src/components/UseCasesSection.tsx b/www/src/components/UseCasesSection.tsx
index 07a408a3..98381d8d 100644
--- a/www/src/components/UseCasesSection.tsx
+++ b/www/src/components/UseCasesSection.tsx
@@ -1,9 +1,9 @@
"use client";
import React, { useState } from "react";
-import { ArrowRightIcon } from "lucide-react";
+import { ArrowRightIcon, Network, Filter, TrendingUp, Shield, Server, XIcon } from "lucide-react";
import { Button } from "./ui/button";
-import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "./ui/dialog";
+import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogClose } from "./ui/dialog";
import { motion, AnimatePresence } from "framer-motion";
interface UseCase {
@@ -12,6 +12,8 @@ interface UseCase {
title: string;
summary: string;
fullContent: string;
+ icon: React.ComponentType<{ className?: string }>;
+ gradient: string;
}
const useCasesData: UseCase[] = [
@@ -20,35 +22,45 @@ const useCasesData: UseCase[] = [
category: "AGENT ORCHESTRATION",
title: "Multi-agent systems without framework lock-in",
summary: "Seamless routing and orchestration for complex agent interactions",
- fullContent: "Plano manages agent routing and orchestration without framework dependencies, allowing seamless multi-agent interactions. This is ideal for building complex systems like automated customer support or data processing pipelines, where agents hand off tasks efficiently to deliver end-to-end solutions faster."
+ fullContent: "Plano manages agent routing and orchestration without framework dependencies, allowing seamless multi-agent interactions. This is ideal for building complex systems like automated customer support or data processing pipelines, where agents hand off tasks efficiently to deliver end-to-end solutions faster.",
+ icon: Network,
+ gradient: "from-[rgba(119,128,217,0.15)] via-[rgba(119,128,217,0.08)] to-[rgba(17,28,132,0.05)]"
},
{
id: 2,
category: "CONTEXT ENGINEERING",
title: "Reusable filters for smarter agents",
summary: "Inject data, reformulate queries, and enforce policies efficiently",
- fullContent: "Plano's filter chain encourages reuse and decoupling for context engineering tasks like injecting data, reformulating queries, and enforcing policy before calls reach an agent or LLM. This means faster debugging, cleaner architecture, and more accurate, on-policy agents —without bespoke glue code."
+ fullContent: "Plano's filter chain encourages reuse and decoupling for context engineering tasks like injecting data, reformulating queries, and enforcing policy before calls reach an agent or LLM. This means faster debugging, cleaner architecture, and more accurate, on-policy agents —without bespoke glue code.",
+ icon: Filter,
+ gradient: "from-[rgba(177,184,255,0.15)] via-[rgba(177,184,255,0.08)] to-[rgba(17,28,132,0.05)]"
},
{
id: 3,
category: "REINFORCEMENT LEARNING",
title: "Production signals for continuous improvement",
summary: "Capture rich traces to accelerate training and refinement",
- fullContent: "Plano captures hyper-rich tracing and log samples from production traffic, feeding into reinforcement learning and fine-tuning cycles. This accelerates iteration in areas like recommendation engines, helping teams quickly identify failures, refine prompts, and boost agent effectiveness based on real-user signals."
+ fullContent: "Plano captures hyper-rich tracing and log samples from production traffic, feeding into reinforcement learning and fine-tuning cycles. This accelerates iteration in areas like recommendation engines, helping teams quickly identify failures, refine prompts, and boost agent effectiveness based on real-user signals.",
+ icon: TrendingUp,
+ gradient: "from-[rgba(185,191,255,0.15)] via-[rgba(185,191,255,0.08)] to-[rgba(17,28,132,0.05)]"
},
{
id: 4,
category: "SECURITY",
title: "Built-in guardrails and centralized policies",
summary: "Safe scaling with jailbreak detection and access controls",
- fullContent: "With built-in guardrails, centralized policies, and access controls, Plano ensures safe scaling across LLMs, detecting issues like jailbreak attempts. This is critical for deployments in regulated fields like finance or healthcare, and minimizing risks while standardizing reliability and security of agents."
+ fullContent: "With built-in guardrails, centralized policies, and access controls, Plano ensures safe scaling across LLMs, detecting issues like jailbreak attempts. This is critical for deployments in regulated fields like finance or healthcare, and minimizing risks while standardizing reliability and security of agents.",
+ icon: Shield,
+ gradient: "from-[rgba(119,128,217,0.15)] via-[rgba(119,128,217,0.08)] to-[rgba(17,28,132,0.05)]"
},
{
id: 5,
category: "ON-PREMISES",
title: "Full data control in regulated environments",
summary: "Deploy on private infrastructure without compromising features",
- fullContent: "Plano's lightweight sidecar model deploys effortlessly on your private infrastructure, empowering teams in regulated sectors to maintain full data control while benefiting from unified LLM access, custom filter chains, and production-grade tracing—without compromising on security or scalability."
+ fullContent: "Plano's lightweight sidecar model deploys effortlessly on your private infrastructure, empowering teams in regulated sectors to maintain full data control while benefiting from unified LLM access, custom filter chains, and production-grade tracing—without compromising on security or scalability.",
+ icon: Server,
+ gradient: "from-[rgba(177,184,255,0.15)] via-[rgba(177,184,255,0.08)] to-[rgba(17,28,132,0.05)]"
}
];
@@ -56,23 +68,23 @@ export function UseCasesSection() {
const [selectedUseCase, setSelectedUseCase] = useState(null);
return (
-
+
{/* Section Header */}
-
+
{/* USE CASES Badge */}
-
-
-
USE CASES
+
{/* Main Heading and CTA Button */}
-
-
+
+
What's possible with Plano
-
@@ -85,65 +97,143 @@ export function UseCasesSection() {
key={useCase.id}
whileHover={{ y: -4 }}
transition={{ duration: 0.2 }}
- className="bg-gradient-to-b from-[rgba(177,184,255,0.16)] to-[rgba(17,28,132,0.035)] border-2 border-[rgba(171,178,250,0.27)] rounded-md p-8 h-90 flex flex-col justify-between cursor-pointer"
+ className="bg-gradient-to-b from-[rgba(177,184,255,0.16)] to-[rgba(17,28,132,0.035)] border-2 border-[rgba(171,178,250,0.27)] rounded-md p-4 sm:p-6 lg:p-8 h-auto sm:h-64 md:h-72 lg:h-90 flex flex-col justify-between cursor-pointer"
onClick={() => setSelectedUseCase(useCase)}
>
{/* Category */}
-
-
+
+
{useCase.category}
{/* Title */}
-
+
{useCase.title}
{/* Learn More Link */}
))}
+
+ {/* Start building button - Mobile only, appears last */}
+
+
+ Start building
+
+
{/* Modal */}