diff --git a/frontend/packages/website/astro.config.mjs b/frontend/packages/website/astro.config.mjs index 41e24e0..f11c53c 100644 --- a/frontend/packages/website/astro.config.mjs +++ b/frontend/packages/website/astro.config.mjs @@ -1,11 +1,14 @@ import { defineConfig } from 'astro/config'; import react from '@astrojs/react'; import tailwind from '@astrojs/tailwind'; +import sitemap from '@astrojs/sitemap'; export default defineConfig({ + site: 'https://sandbox-agent.dev', output: 'static', integrations: [ react(), - tailwind() + tailwind(), + sitemap() ] }); diff --git a/frontend/packages/website/package.json b/frontend/packages/website/package.json index aef9c0b..ced76f7 100644 --- a/frontend/packages/website/package.json +++ b/frontend/packages/website/package.json @@ -13,6 +13,7 @@ }, "dependencies": { "@astrojs/react": "^4.2.0", + "@astrojs/sitemap": "^3.2.0", "@astrojs/tailwind": "^6.0.0", "astro": "^5.1.0", "framer-motion": "^12.0.0", diff --git a/frontend/packages/website/public/robots.txt b/frontend/packages/website/public/robots.txt new file mode 100644 index 0000000..d2c5dd2 --- /dev/null +++ b/frontend/packages/website/public/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +Sitemap: https://sandbox-agent.dev/sitemap-index.xml diff --git a/frontend/packages/website/src/components/CTASection.tsx b/frontend/packages/website/src/components/CTASection.tsx deleted file mode 100644 index f47f14e..0000000 --- a/frontend/packages/website/src/components/CTASection.tsx +++ /dev/null @@ -1,112 +0,0 @@ -'use client'; - -import { useState, useEffect } from 'react'; -import { motion, AnimatePresence } from 'framer-motion'; -import { ArrowRight, Terminal, Check } from 'lucide-react'; - -const CTA_TITLES = [ - 'Run coding agents in sandboxes. Control them over HTTP.', - 'A server inside your sandbox. An API for your app.', - 'Claude Code, Codex, OpenCode, Amp, Pi — one HTTP API.', - 'Your app connects remotely. The coding agent runs isolated.', - 'Streaming events. Handling permissions. Managing sessions.', - 'Install with curl. Connect over HTTP. Control any coding agent.', - 'The bridge between your app and sandboxed coding agents.', -]; - -function AnimatedCTATitle() { - const [currentIndex, setCurrentIndex] = useState(0); - - useEffect(() => { - const interval = setInterval(() => { - setCurrentIndex(prev => (prev + 1) % CTA_TITLES.length); - }, 3000); - - return () => clearInterval(interval); - }, []); - - return ( -

- - - {CTA_TITLES[currentIndex]} - - -

- ); -} - -const CopyInstallButton = () => { - const [copied, setCopied] = useState(false); - const installCommand = 'curl -sSL https://sandboxagent.dev/install | sh'; - - const handleCopy = async () => { - try { - await navigator.clipboard.writeText(installCommand); - setCopied(true); - setTimeout(() => setCopied(false), 2000); - } catch (err) { - console.error('Failed to copy:', err); - } - }; - - return ( - - ); -}; - -export function CTASection() { - return ( -
- -
-
- -
- - A server that runs inside isolated environments.
- Your app connects remotely to control any coding agent. -
- - - Read the Docs - - - - -
-
- ); -} diff --git a/frontend/packages/website/src/components/FAQ.tsx b/frontend/packages/website/src/components/FAQ.tsx index 4000c22..fc80332 100644 --- a/frontend/packages/website/src/components/FAQ.tsx +++ b/frontend/packages/website/src/components/FAQ.tsx @@ -61,14 +61,14 @@ function FAQItem({ question, answer }: { question: string; answer: string }) { const [isOpen, setIsOpen] = useState(false); return ( -
+
+
+ +
+ Give this to your coding agent +
+
); }; export function Hero() { + const [scrollOpacity, setScrollOpacity] = useState(1); + + useEffect(() => { + const handleScroll = () => { + const scrollY = window.scrollY; + const windowHeight = window.innerHeight; + const isMobile = window.innerWidth < 1024; + + const fadeStart = windowHeight * (isMobile ? 0.3 : 0.15); + const fadeEnd = windowHeight * (isMobile ? 0.7 : 0.5); + const opacity = 1 - Math.min(1, Math.max(0, (scrollY - fadeStart) / (fadeEnd - fadeStart))); + setScrollOpacity(opacity); + }; + + window.addEventListener('scroll', handleScroll); + return () => window.removeEventListener('scroll', handleScroll); + }, []); + return ( -
-
-
-
-

- Run Coding Agents in Sandboxes.
- Control Them Over HTTP. -

-

- The Sandbox Agent SDK is a server that runs inside your sandbox. Your app connects remotely to control Claude Code, Codex, OpenCode, Amp, or Pi — streaming events, handling permissions, managing sessions. -

+
+ {/* Background gradient */} +
-
- +
+ + Run Coding Agents in Sandboxes. +
+ Control Them Over HTTP. + -
- + + The Sandbox Agent SDK is a server that runs inside your sandbox. Your app connects remotely to control Claude Code, Codex, OpenCode, Amp, or Pi — streaming events, handling permissions, managing sessions. + + + + + Read the Docs + + + + +
+ + {/* Right side - Diagram */} + + +
+
); } diff --git a/frontend/packages/website/src/components/Inspector.tsx b/frontend/packages/website/src/components/Inspector.tsx index 7e29185..26cdf09 100644 --- a/frontend/packages/website/src/components/Inspector.tsx +++ b/frontend/packages/website/src/components/Inspector.tsx @@ -1,23 +1,45 @@ 'use client'; +import { motion } from 'framer-motion'; + export function Inspector() { return ( -
-
-

- Built-in Debugger -

-

- Inspect sessions, view event payloads, and troubleshoot without writing code. -

+
+
+
+ + Built-in Debugger + + + Inspect sessions, view event payloads, and troubleshoot without writing code. + +
-
+ Sandbox Agent Inspector -
+
); diff --git a/frontend/packages/website/src/components/Navigation.tsx b/frontend/packages/website/src/components/Navigation.tsx index cc970a4..52c546f 100644 --- a/frontend/packages/website/src/components/Navigation.tsx +++ b/frontend/packages/website/src/components/Navigation.tsx @@ -6,11 +6,12 @@ import { GitHubStars } from './GitHubStars'; function NavItem({ href, children }: { href: string; children: React.ReactNode }) { return ( - + + {children} + ); } @@ -34,15 +35,17 @@ export function Navigation() { isScrolled ? "before:border-white/10" : "before:border-transparent" }`} > + {/* Background with blur */} {/* Desktop Nav */} -
+
Docs Changelog
{/* Right side */} -
+
setMobileMenuOpen(!mobileMenuOpen)} > {mobileMenuOpen ? : } @@ -101,26 +104,26 @@ export function Navigation() { {/* Mobile menu */} {mobileMenuOpen && ( -
-
+
+
setMobileMenuOpen(false)} > Docs setMobileMenuOpen(false)} > Changelog -
+ diff --git a/frontend/packages/website/src/components/PainPoints.tsx b/frontend/packages/website/src/components/PainPoints.tsx index 654286b..e206895 100644 --- a/frontend/packages/website/src/components/PainPoints.tsx +++ b/frontend/packages/website/src/components/PainPoints.tsx @@ -1,133 +1,91 @@ 'use client'; import { motion } from 'framer-motion'; -import { X, Check } from 'lucide-react'; +import { Shield, Layers, Database, X, Check } from 'lucide-react'; const frictions = [ { - number: '01', + icon: Shield, title: 'Coding Agents Need Sandboxes', problem: "You can't let AI execute arbitrary code on your production servers. Coding agents need isolated environments, but existing SDKs assume local execution.", solution: 'A server that runs inside the sandbox and exposes HTTP/SSE.', - accentColor: 'orange', }, { - number: '02', + icon: Layers, title: 'Every Coding Agent is Different', problem: 'Claude Code, Codex, OpenCode, Amp, and Pi each have proprietary APIs, event formats, and behaviors. Swapping coding agents means rewriting your entire integration.', solution: 'One HTTP API. Write your code once, swap coding agents with a config change.', - accentColor: 'purple', }, { - number: '03', + icon: Database, title: 'Sessions Are Ephemeral', problem: 'Coding agent transcripts live in the sandbox. When the process ends, you lose everything. Debugging and replay become impossible.', solution: 'Universal event schema streams to your storage. Persist to Postgres or Rivet, replay later, audit everything.', - accentColor: 'blue', }, ]; -const accentStyles = { - orange: { - gradient: 'from-orange-500/20', - border: 'border-orange-500/30', - glow: 'rgba(255,79,0,0.15)', - number: 'text-orange-500', - }, - purple: { - gradient: 'from-purple-500/20', - border: 'border-purple-500/30', - glow: 'rgba(168,85,247,0.15)', - number: 'text-purple-500', - }, - blue: { - gradient: 'from-blue-500/20', - border: 'border-blue-500/30', - glow: 'rgba(59,130,246,0.15)', - number: 'text-blue-500', - }, -}; - export function PainPoints() { return ( -
+
+
+ + Running coding agents remotely is hard. + + + The Sandbox Agent SDK is a server that runs inside your sandbox. Your app connects remotely to control Claude Code, Codex, OpenCode, Amp, or Pi — streaming events, handling permissions, managing sessions. + +
+ -

- Running coding agents remotely is hard. -

-

- Coding agents need sandboxes, but existing SDKs assume local execution. SSH breaks, CLI wrappers are fragile, and building from scratch means reimplementing everything for each coding agent. -

-
- -
- {frictions.map((friction, index) => { - const styles = accentStyles[friction.accentColor as keyof typeof accentStyles]; - return ( - - {/* Top shine */} -
- - {/* Hover glow */} -
- - {/* Corner highlight */} -
- -
- {/* Title */} -

{friction.title}

- - {/* Problem */} -
-
-
- -
- Problem -
-

{friction.problem}

-
- - {/* Solution */} -
-
-
- -
- Solution -
-

{friction.solution}

-
+ {frictions.map((friction) => ( +
+
+ +
+

{friction.title}

+
+
+ + Problem
- - ); - })} -
+

+ {friction.problem} +

+
+
+
+ + Solution +
+

+ {friction.solution} +

+
+
+ ))} +
); diff --git a/frontend/packages/website/src/layouts/Layout.astro b/frontend/packages/website/src/layouts/Layout.astro index 8e7f8e6..25683cd 100644 --- a/frontend/packages/website/src/layouts/Layout.astro +++ b/frontend/packages/website/src/layouts/Layout.astro @@ -4,32 +4,81 @@ interface Props { description?: string; } -const { title, description = "Universal SDK for coding agents. Control Claude Code, Codex, OpenCode, and Amp with unified events and sessions." } = Astro.props; +const { title, description = "Universal SDK for coding agents. Control Claude Code, Codex, OpenCode, Amp, and Pi with unified events and sessions." } = Astro.props; +const canonicalURL = new URL(Astro.url.pathname, 'https://sandbox-agent.dev'); +const ogImageURL = new URL('/og.png', 'https://sandbox-agent.dev'); + +const structuredData = { + "@context": "https://schema.org", + "@type": "SoftwareApplication", + "name": "Sandbox Agent SDK", + "applicationCategory": "DeveloperApplication", + "operatingSystem": "Linux, macOS, Windows", + "description": description, + "url": "https://sandbox-agent.dev", + "author": { + "@type": "Organization", + "name": "Rivet", + "url": "https://rivet.dev" + }, + "offers": { + "@type": "Offer", + "price": "0", + "priceCurrency": "USD" + }, + "keywords": "coding agents, AI SDK, Claude Code, Codex, OpenCode, Amp, sandbox, remote code execution, developer tools" +}; --- - + + + + + + + + + + + + + + + {title} + - + + + + + - + + + + + + + +