Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.577.0",
"motion": "^12.38.0",
"next": "16.2.6",
"next-themes": "^0.4.6",
"react": "19.2.3",
Expand Down
1 change: 1 addition & 0 deletions packages/dashboard/public/agents.md
111 changes: 63 additions & 48 deletions packages/dashboard/src/app/_api-endpoints.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { ArrowRightIcon } from "lucide-react";
import Link from "next/link";
import {
landingCard,
landingContainer,
landingHover,
MotionDiv,
MotionSection,
} from "@/components/landing/motion";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
Expand Down Expand Up @@ -31,54 +38,62 @@ const apiEndpoints = [

export function ApiEndpoints() {
return (
<section className="max-w-5xl mx-auto px-6 pb-24">
<Card>
<CardHeader>
<CardTitle>API endpoints</CardTitle>
<CardDescription>
The public surface stays small enough for agents and humans to keep in context.
</CardDescription>
</CardHeader>
<CardContent>
<Table className="table-fixed">
<TableHeader>
<TableRow>
<TableHead className="w-24">Method</TableHead>
<TableHead>Path</TableHead>
<TableHead className="hidden w-56 sm:table-cell">Use</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{apiEndpoints.map(([method, path, desc]) => (
<TableRow key={path + method}>
<TableCell>
<Badge variant="outline">{method}</Badge>
</TableCell>
<TableCell className="truncate font-mono">{path}</TableCell>
<TableCell className="hidden text-muted-foreground sm:table-cell">
{desc}
</TableCell>
<MotionSection
className="max-w-5xl mx-auto px-6 pb-24"
animate="visible"
initial="hidden"
variants={landingContainer}
>
<MotionDiv variants={landingCard} whileHover={landingHover}>
<Card>
<CardHeader>
<CardTitle>API endpoints</CardTitle>
<CardDescription>
The public surface stays small enough for agents and humans to keep in context.
</CardDescription>
</CardHeader>
<CardContent>
<Table className="table-fixed">
<TableHeader>
<TableRow>
<TableHead className="w-24">Method</TableHead>
<TableHead>Path</TableHead>
<TableHead className="hidden w-56 sm:table-cell">Use</TableHead>
</TableRow>
))}
</TableBody>
</Table>
</CardContent>
<CardFooter className="flex flex-wrap gap-2">
<Button variant="outline" size="sm" nativeButton={false} render={<Link href="/docs" />}>
Full API reference
<ArrowRightIcon data-icon="inline-end" />
</Button>
<Button
variant="ghost"
size="sm"
nativeButton={false}
render={<Link href="/agents.md" />}
>
agents.md
<ArrowRightIcon data-icon="inline-end" />
</Button>
</CardFooter>
</Card>
</section>
</TableHeader>
<TableBody>
{apiEndpoints.map(([method, path, desc]) => (
<TableRow key={path + method}>
<TableCell>
<Badge variant="outline">{method}</Badge>
</TableCell>
<TableCell className="truncate font-mono">{path}</TableCell>
<TableCell className="hidden text-muted-foreground sm:table-cell">
{desc}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</CardContent>
<CardFooter className="flex flex-wrap gap-2">
<Button variant="outline" size="sm" nativeButton={false} render={<Link href="/docs" />}>
Full API reference
<ArrowRightIcon data-icon="inline-end" />
</Button>
<Button
variant="ghost"
size="sm"
nativeButton={false}
// biome-ignore lint/a11y/useAnchorContent: Base UI injects the Button children into this render anchor.
render={<a href="/agents.md" />}
>
agents.md
<ArrowRightIcon data-icon="inline-end" />
</Button>
</CardFooter>
</Card>
</MotionDiv>
</MotionSection>
);
}
55 changes: 35 additions & 20 deletions packages/dashboard/src/app/_code-examples.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
import {
landingCard,
landingContainer,
landingHover,
landingItem,
MotionDiv,
MotionSection,
} from "@/components/landing/motion";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";

Expand All @@ -23,34 +31,41 @@ API key: as_live_...`,

export function CodeExamples() {
return (
<section className="max-w-5xl mx-auto px-6 pb-20">
<MotionSection
className="max-w-5xl mx-auto px-6 pb-20"
animate="visible"
initial="hidden"
variants={landingContainer}
>
<div className="flex flex-col gap-6">
<div className="flex flex-col gap-2">
<MotionDiv className="flex flex-col gap-2" variants={landingItem}>
<h2 className="text-lg font-medium">Integration paths</h2>
<p className="max-w-2xl text-sm text-muted-foreground">
Start with agent-readable docs or a direct API call. Both paths hit the same storage
contract.
</p>
</div>
<div className="grid gap-4 sm:grid-cols-2">
</MotionDiv>
<MotionDiv className="grid gap-4 sm:grid-cols-2" variants={landingContainer}>
{examples.map((example) => (
<Card key={example.label} size="sm">
<CardHeader>
<CardTitle>{example.title}</CardTitle>
<CardDescription className="flex flex-col gap-2">
<Badge variant="outline">{example.label}</Badge>
<span>{example.description}</span>
</CardDescription>
</CardHeader>
<CardContent>
<pre className="whitespace-pre-wrap break-words rounded-md bg-muted p-3 font-mono text-sm leading-6 text-muted-foreground">
<code>{example.code}</code>
</pre>
</CardContent>
</Card>
<MotionDiv key={example.label} variants={landingCard} whileHover={landingHover}>
<Card size="sm">
<CardHeader>
<CardTitle>{example.title}</CardTitle>
<CardDescription className="flex flex-col gap-2">
<Badge variant="outline">{example.label}</Badge>
<span>{example.description}</span>
</CardDescription>
</CardHeader>
<CardContent>
<pre className="whitespace-pre-wrap break-words rounded-md bg-muted p-3 font-mono text-sm leading-6 text-muted-foreground">
<code>{example.code}</code>
</pre>
</CardContent>
</Card>
</MotionDiv>
))}
</div>
</MotionDiv>
</div>
</section>
</MotionSection>
);
}
59 changes: 37 additions & 22 deletions packages/dashboard/src/app/_features.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ import {
type LucideIcon,
ShieldCheckIcon,
} from "lucide-react";
import {
landingCard,
landingContainer,
landingHover,
landingItem,
MotionDiv,
MotionSection,
} from "@/components/landing/motion";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";

Expand Down Expand Up @@ -46,35 +54,42 @@ const features: readonly Feature[] = [

export function Features() {
return (
<section className="max-w-5xl mx-auto px-6 pb-20">
<MotionSection
className="max-w-5xl mx-auto px-6 pb-20"
animate="visible"
initial="hidden"
variants={landingContainer}
>
<div className="flex flex-col gap-6">
<div className="flex flex-col gap-2">
<MotionDiv className="flex flex-col gap-2" variants={landingItem}>
<h2 className="text-lg font-medium">Operations snapshot</h2>
<p className="max-w-2xl text-sm text-muted-foreground">
The primitives an agent product needs after the first conversation lands in production.
</p>
</div>
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
</MotionDiv>
<MotionDiv className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4" variants={landingContainer}>
{features.map(({ title, badge, icon: Icon, description }) => (
<Card key={title}>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<span className="flex size-8 items-center justify-center rounded-lg bg-muted text-muted-foreground">
<Icon aria-hidden="true" />
</span>
{title}
</CardTitle>
<CardDescription>
<Badge variant="secondary">{badge}</Badge>
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-muted-foreground leading-relaxed">{description}</p>
</CardContent>
</Card>
<MotionDiv key={title} variants={landingCard} whileHover={landingHover}>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<span className="flex size-8 items-center justify-center rounded-lg bg-muted text-muted-foreground">
<Icon aria-hidden="true" />
</span>
{title}
</CardTitle>
<CardDescription>
<Badge variant="secondary">{badge}</Badge>
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-muted-foreground leading-relaxed">{description}</p>
</CardContent>
</Card>
</MotionDiv>
))}
</div>
</MotionDiv>
</div>
</section>
</MotionSection>
);
}
10 changes: 8 additions & 2 deletions packages/dashboard/src/app/_header.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { ArrowRightIcon } from "lucide-react";
import Image from "next/image";
import Link from "next/link";
import { MotionHeader } from "@/components/landing/motion";
import { Button } from "@/components/ui/button";

export function Header() {
return (
<header className="sticky top-0 z-50 border-b border-border bg-card/80 px-6 py-3 backdrop-blur-sm">
<MotionHeader
animate={{ opacity: 1, y: 0 }}
className="sticky top-0 z-50 border-b border-border bg-card/80 px-6 py-3 backdrop-blur-sm"
initial={{ opacity: 0, y: -8 }}
transition={{ duration: 0.35 }}
>
<div className="max-w-5xl mx-auto flex items-center justify-between">
<div className="flex items-center gap-2">
<Image
Expand Down Expand Up @@ -39,6 +45,6 @@ export function Header() {
</Button>
</div>
</div>
</header>
</MotionHeader>
);
}
Loading
Loading