+
+
+ 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 */}
-
-
- {/* 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}
+
-
+
+
+
+
+
-
+
+
+
+
+
+
+
+
-
+
diff --git a/frontend/packages/website/src/pages/index.astro b/frontend/packages/website/src/pages/index.astro
index da607db..854c82f 100644
--- a/frontend/packages/website/src/pages/index.astro
+++ b/frontend/packages/website/src/pages/index.astro
@@ -11,8 +11,7 @@ import { Footer } from '../components/Footer';
---
-
-
+
@@ -21,6 +20,5 @@ import { Footer } from '../components/Footer';
-
-
+
diff --git a/frontend/packages/website/src/styles/global.css b/frontend/packages/website/src/styles/global.css
index 8dbb6f8..6f4187e 100644
--- a/frontend/packages/website/src/styles/global.css
+++ b/frontend/packages/website/src/styles/global.css
@@ -3,13 +3,61 @@
@tailwind utilities;
@layer base {
+ :root {
+ --header-height: 3.5rem;
+
+ /* Theme colors (HSL for flexibility) */
+ --background: 20 14.3% 4.1%;
+ --foreground: 60 9.1% 97.8%;
+ --primary: 18.5 100% 50%;
+ --primary-foreground: 60 9.1% 97.8%;
+ --muted: 34 10% 10%;
+ --muted-foreground: 24 5.4% 63.9%;
+ --border: 12 6.5% 15.1%;
+ --card: 0 9.09% 6.47%;
+
+ /* Shiki syntax highlighting */
+ --shiki-color-text: theme('colors.white');
+ --shiki-foreground: hsl(var(--foreground));
+ --shiki-token-constant: theme('colors.violet.300');
+ --shiki-token-string: theme('colors.violet.300');
+ --shiki-token-comment: theme('colors.zinc.500');
+ --shiki-token-keyword: theme('colors.sky.300');
+ --shiki-token-parameter: theme('colors.pink.300');
+ --shiki-token-function: theme('colors.violet.300');
+ --shiki-token-string-expression: theme('colors.violet.300');
+ --shiki-token-punctuation: theme('colors.zinc.200');
+ }
+
+ * {
+ @apply border-white/10;
+ }
+
body {
@apply bg-black text-white antialiased;
font-family: 'Open Sans', system-ui, sans-serif;
}
+ /* Text selection - matches rivet.dev */
::selection {
- @apply bg-accent/30 text-white;
+ background-color: rgba(255, 79, 0, 0.3);
+ color: #fed7aa;
+ }
+
+ ::-moz-selection {
+ background-color: rgba(255, 79, 0, 0.3);
+ color: #fed7aa;
+ }
+
+ /* Selection style for white/light backgrounds */
+ .selection-dark::selection {
+ background-color: #18181b;
+ color: white;
+ }
+
+ .selection-dark::-moz-selection {
+ background-color: #18181b;
+ color: white;
}
/* Firefox scrollbar */
@@ -65,6 +113,7 @@
}
@layer components {
+ /* Glass morphism effects */
.glass {
@apply bg-white/[0.02] backdrop-blur-md border border-white/10;
}
@@ -72,4 +121,123 @@
.glass-hover {
@apply hover:bg-white/[0.04] hover:border-white/20 transition-all;
}
+
+ .glass-strong {
+ @apply bg-black/95 backdrop-blur-lg border border-white/10;
+ }
+
+ /* Bento box card effects */
+ .bento-box {
+ transition: border-color 0.3s ease;
+ }
+
+ .bento-box:hover {
+ border-color: rgba(255, 255, 255, 0.2);
+ }
+
+ /* Scroll-triggered animations */
+ .animate-on-scroll {
+ opacity: 0;
+ transition: opacity 0.8s ease-out, transform 0.8s cubic-bezier(0.19, 1, 0.22, 1);
+ transition-delay: var(--scroll-delay, 0s);
+ will-change: opacity, transform;
+ }
+
+ .animate-fade-up {
+ transform: translateY(30px);
+ }
+
+ .animate-on-scroll.is-visible {
+ opacity: 1;
+ transform: translateY(0);
+ }
+
+ /* Delay utilities for staggered animations */
+ .delay-100 { --scroll-delay: 100ms; }
+ .delay-200 { --scroll-delay: 200ms; }
+ .delay-300 { --scroll-delay: 300ms; }
+ .delay-400 { --scroll-delay: 400ms; }
+ .delay-500 { --scroll-delay: 500ms; }
+ .delay-600 { --scroll-delay: 600ms; }
+
+ /* Top shine highlight for cards */
+ .shine-top {
+ position: relative;
+ }
+
+ .shine-top::after {
+ content: "";
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ height: 1px;
+ background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.2), transparent);
+ pointer-events: none;
+ }
+
+ /* Glow effect for buttons and interactive elements */
+ .glow-accent {
+ box-shadow: 0 0 20px rgba(255, 69, 0, 0.3);
+ }
+
+ .glow-accent-hover:hover {
+ box-shadow: 0 0 30px rgba(255, 69, 0, 0.5);
+ }
+
+ /* Code highlight styling */
+ .code-highlight-ref {
+ position: relative;
+ transition: background-color 0.3s ease-out;
+ display: block;
+ margin: 0 -1.5rem;
+ padding: 0 1.5rem;
+ }
+
+ .code-highlight-ref.is-active {
+ background-color: rgba(255, 69, 0, 0.1);
+ }
+
+ .code-highlight-ref.is-active::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: 0;
+ width: 2px;
+ background-color: #ff4500;
+ }
+
+ /* Hide scrollbar */
+ .scrollbar-hide::-webkit-scrollbar {
+ display: none;
+ }
+
+ .scrollbar-hide {
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+ }
+}
+
+@layer utilities {
+ /* Gradient text */
+ .text-gradient-accent {
+ @apply bg-gradient-to-r from-orange-400 to-orange-600 bg-clip-text text-transparent;
+ }
+
+ /* Backdrop with blur */
+ .backdrop-glow {
+ @apply backdrop-blur-lg bg-black/80;
+ }
+
+ /* Better focus ring */
+ .focus-ring {
+ @apply focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-black;
+ }
+}
+
+/* View transition disable (for smooth prefetching) */
+::view-transition-old(root),
+::view-transition-new(root) {
+ animation: none;
}
diff --git a/frontend/packages/website/tailwind.config.mjs b/frontend/packages/website/tailwind.config.mjs
index 142adbc..168c2ff 100644
--- a/frontend/packages/website/tailwind.config.mjs
+++ b/frontend/packages/website/tailwind.config.mjs
@@ -4,21 +4,59 @@ export default {
theme: {
extend: {
colors: {
+ // Primary accent (OrangeRed)
accent: '#FF4500',
+ // Extended color palette
+ background: '#000000',
+ 'text-primary': '#FAFAFA',
+ 'text-secondary': '#A0A0A0',
+ border: '#252525',
+ // Code syntax highlighting
+ 'code-keyword': '#c084fc',
+ 'code-function': '#60a5fa',
+ 'code-string': '#4ade80',
+ 'code-comment': '#737373',
},
fontFamily: {
sans: ['Open Sans', 'system-ui', 'sans-serif'],
+ heading: ['Satoshi', 'Open Sans', 'system-ui', 'sans-serif'],
mono: ['JetBrains Mono', 'monospace'],
},
animation: {
- 'fade-in-up': 'fade-in-up 0.6s ease-out forwards',
- 'pulse-slow': 'pulse 3s ease-in-out infinite',
+ 'fade-in-up': 'fade-in-up 0.8s ease-out forwards',
+ 'hero-line': 'hero-line 1s cubic-bezier(0.19, 1, 0.22, 1) forwards',
+ 'hero-p': 'hero-p 0.8s ease-out 0.6s forwards',
+ 'hero-cta': 'hero-p 0.8s ease-out 0.8s forwards',
+ 'hero-visual': 'hero-p 0.8s ease-out 1s forwards',
+ 'infinite-scroll': 'infinite-scroll 25s linear infinite',
+ 'pulse-slow': 'pulse-slow 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
},
keyframes: {
'fade-in-up': {
- '0%': { opacity: '0', transform: 'translateY(20px)' },
- '100%': { opacity: '1', transform: 'translateY(0)' },
+ from: { opacity: '0', transform: 'translateY(24px)' },
+ to: { opacity: '1', transform: 'translateY(0)' },
},
+ 'hero-line': {
+ '0%': { opacity: '0', transform: 'translateY(100%) skewY(6deg)' },
+ '100%': { opacity: '1', transform: 'translateY(0) skewY(0deg)' },
+ },
+ 'hero-p': {
+ from: { opacity: '0', transform: 'translateY(20px)' },
+ to: { opacity: '1', transform: 'translateY(0)' },
+ },
+ 'infinite-scroll': {
+ from: { transform: 'translateX(0)' },
+ to: { transform: 'translateX(-50%)' },
+ },
+ 'pulse-slow': {
+ '50%': { opacity: '.5' },
+ },
+ },
+ spacing: {
+ header: 'var(--header-height, 3.5rem)',
+ },
+ borderRadius: {
+ '4xl': '2rem',
},
},
},