Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
95dea25
refactor(web): restructure landing around an "agent is a directory" n…
claude Jun 26, 2026
f663ef4
refactor(web): re-architect the landing IA around eve's full page str…
claude Jun 26, 2026
43584a8
refactor(web): ground the landing in real product facts + add binding…
claude Jun 26, 2026
fe9d3e2
refactor(web): adopt eve's hero toggle + alternating code walkthrough
claude Jun 26, 2026
f71f4ff
refactor(web): eve-style stacked production cards + two-column primit…
claude Jun 26, 2026
4a4e261
fix(web): replace the sparse alternating walkthrough with a compact f…
claude Jun 26, 2026
5518ee8
feat(web): premium code windows + typed hero terminal
claude Jun 26, 2026
3fa3c5d
refactor(web): rebuild hero + walkthrough to match the real eve layout
claude Jun 26, 2026
7750309
refactor(web): eve-style 3-column production + shorten the page
claude Jun 26, 2026
0180014
refactor(web): give the directory walkthrough panel equal weight
claude Jun 26, 2026
e6f19e8
refactor(web): match eve's sticky-swap walkthrough animation
claude Jun 26, 2026
4de88a3
style(web): more breathing room between walkthrough steps
claude Jun 26, 2026
c1b01a9
content(web): richer markdown bodies in the directory walkthrough
claude Jun 26, 2026
09e40ba
refactor(web): eve-style "built on primitives" with product cards + C…
claude Jun 26, 2026
d773fd4
feat(web): make the hero command copyable + stop the toggle layout bump
claude Jun 26, 2026
1c663ae
refactor(web): fill the hero agent card + align the production columns
claude Jun 26, 2026
d29de54
copy(web): final CTA headline → "Give it a sandbox. Watch it work."
claude Jun 26, 2026
e150694
refactor(marketing): tighten landing density and unify production mocks
claude Jun 26, 2026
9e3be64
fix(marketing): ground landing copy in real codebase facts
claude Jun 26, 2026
d67a562
refactor(marketing): de-dupe landing narrative, unify on outname's terms
claude Jun 26, 2026
8ec0079
feat(marketing): add brand logos to integrations and inference providers
claude Jun 26, 2026
c8fe80e
feat(marketing): real brand marks for Neon and the custom-logo integr…
claude Jun 26, 2026
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
5 changes: 4 additions & 1 deletion packages/shared/doctor.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
"ignore": {
"overrides": [
{
"files": ["marketing/components/landing/composable-workbench/**"],
"files": [
"marketing/components/landing/agent-anatomy/**",
"marketing/components/landing/landing-primitives.tsx"
],
"rules": [
"react-doctor/design-no-em-dash-in-jsx-text",
"react-doctor/design-no-redundant-padding-axes",
Expand Down
28 changes: 22 additions & 6 deletions packages/shared/marketing/components/landing-home-page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
'use client'

import { LandingComposableWorkbench } from '@outname/shared/marketing/components/landing/composable-workbench/landing-composable-workbench'
import { LandingChatShowcase } from '@outname/shared/marketing/components/landing/landing-chat-showcase'
import { LandingAgentAnatomy } from '@outname/shared/marketing/components/landing/agent-anatomy/landing-agent-anatomy'
import { LandingBindings } from '@outname/shared/marketing/components/landing/landing-bindings'
import { LandingFinalCta } from '@outname/shared/marketing/components/landing/landing-final-cta'
import { LandingFooter } from '@outname/shared/marketing/components/landing/landing-footer'
import { LandingHeartbeatCloser } from '@outname/shared/marketing/components/landing/landing-heartbeat-closer'
import { LandingHeroDemo } from '@outname/shared/marketing/components/landing/landing-hero-demo'
import { LandingNav } from '@outname/shared/marketing/components/landing/landing-nav'
import { LandingPrimitives } from '@outname/shared/marketing/components/landing/landing-primitives'
import { LandingProduction } from '@outname/shared/marketing/components/landing/landing-production'
import { useReducedMotion } from 'motion/react'

export function LandingHomePage() {
Expand All @@ -16,10 +18,24 @@ export function LandingHomePage() {
<main className="relative isolate overflow-x-clip bg-background text-foreground">
<LandingNav />

{/* 1 — Positioning, command, and the directory artifact */}
<LandingHeroDemo shouldReduceMotion={reduceMotionFlag} />
<LandingChatShowcase shouldReduceMotion={reduceMotionFlag} />
<LandingComposableWorkbench shouldReduceMotion={reduceMotionFlag} />
<LandingHeartbeatCloser shouldReduceMotion={reduceMotionFlag} />

{/* 2 — An agent is a directory: overview + alternating file walkthrough */}
<LandingAgentAnatomy shouldReduceMotion={reduceMotionFlag} />

{/* 3 — What you bind around the folder */}
<LandingBindings shouldReduceMotion={reduceMotionFlag} />

{/* 4 — What it's built on */}
<LandingPrimitives shouldReduceMotion={reduceMotionFlag} />

{/* 5 — Production, proven live in stacked cards */}
<LandingProduction shouldReduceMotion={reduceMotionFlag} />

{/* 6 — Final call to action */}
<LandingFinalCta shouldReduceMotion={reduceMotionFlag} />

<LandingFooter />
</main>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
'use client'

import {
type AgentTreeNode,
type AnatomyStepId,
agentSlug,
agentTree,
type FileOwner,
} from '@outname/shared/marketing/data/agent-anatomy'
import { cn } from '@outname/ui/lib/utils'
import { FileTextIcon, FolderIcon } from 'lucide-react'

const DEPTH_INDENT_REM = 0.75

const ownerDot: Record<FileOwner, string> = {
agent: 'border border-current opacity-50',
shared: 'bg-current opacity-50',
user: 'bg-brand',
}

function rowClasses(active: boolean, interactive: boolean) {
return cn(
'ease flex w-full items-center gap-2 border-l-2 py-1.5 pr-3 text-left font-mono text-xs tracking-normal transition-colors duration-150',
active
? 'border-brand bg-foreground text-background'
: 'border-transparent text-muted-foreground',
interactive && !active && 'hover:bg-muted hover:text-foreground'
)
}

function TreeRow({
active,
node,
onSelectStep,
}: {
active: boolean
node: AgentTreeNode
onSelectStep?: (id: AnatomyStepId) => void
}) {
const Icon = node.kind === 'dir' ? FolderIcon : FileTextIcon
const isStepNode = Boolean(node.stepId)
const paddingLeft = `${node.depth * DEPTH_INDENT_REM + 0.5}rem`

const inner = (
<>
<Icon
className={cn(
'size-3.5 shrink-0',
active ? 'text-background' : 'text-muted-foreground'
)}
/>
<span
className={cn(
'truncate',
active && 'font-semibold',
!(active || isStepNode) && 'opacity-70'
)}
>
{node.label}
</span>
{node.owner ? (
<span
aria-hidden
className={cn('ml-auto size-2 shrink-0', ownerDot[node.owner])}
/>
) : null}
</>
)

return (
<li>
{node.stepId && onSelectStep ? (
<button
className={rowClasses(active, true)}
onClick={() => onSelectStep(node.stepId as AnatomyStepId)}
style={{ paddingLeft }}
type="button"
>
{inner}
</button>
Comment on lines +72 to +80

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Expose the selected row to assistive tech.

These buttons drive the active detail pane, but the current selection is only styled visually. Add a selected/current-state attribute here (for example aria-current on the active row, or full tab/listbox semantics) so screen-reader users can tell which file is open.

As per coding guidelines, **/*.{jsx,tsx}: "Use semantic HTML and ARIA attributes for accessibility".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/shared/marketing/components/landing/agent-anatomy/agent-file-tree.tsx`
around lines 72 - 80, The clickable row in agent-file-tree.tsx only indicates
the active file visually, so the current selection is not exposed to assistive
tech. Update the button rendered in the node.stepId && onSelectStep branch to
include a selected/current-state accessibility attribute for the active row,
such as aria-current when active, or apply appropriate listbox/tab semantics if
that better matches the component behavior. Use the existing active flag and
rowClasses logic in AgentFileTree to keep the visual and accessible state in
sync.

Source: Coding guidelines

) : (
<span className={rowClasses(active, false)} style={{ paddingLeft }}>
{inner}
</span>
)}
</li>
)
}

export function AgentFileTree({
activeStepId,
className,
onSelectStep,
}: {
activeStepId?: AnatomyStepId
className?: string
onSelectStep?: (id: AnatomyStepId) => void
}) {
return (
<div className={cn('border border-border bg-background', className)}>
<div className="flex items-center gap-2 border-border border-b px-4 py-3">
<span aria-hidden className="size-2.5 shrink-0 bg-brand" />
<span className="truncate font-mono text-xs tracking-normal">
{agentSlug}/
</span>
<span className="swiss-label ml-auto text-muted-foreground">
sandbox
</span>
</div>
<ul className="py-2">
{agentTree.map((node) => (
<TreeRow
active={Boolean(node.stepId && node.stepId === activeStepId)}
key={node.id}
node={node}
onSelectStep={onSelectStep}
/>
))}
</ul>
<div className="flex items-center gap-4 border-border border-t px-4 py-2.5 font-mono text-[10px] text-muted-foreground tracking-normal">
<span className="flex items-center gap-1.5">
<span aria-hidden className="size-2 bg-brand" /> you author
</span>
<span className="flex items-center gap-1.5">
<span
aria-hidden
className="size-2 border border-muted-foreground opacity-50"
/>{' '}
agent writes
</span>
</div>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { AnatomyStepId } from '@outname/shared/marketing/data/agent-anatomy'
import {
BrainIcon,
CalendarIcon,
ContactIcon,
ListChecksIcon,
type LucideIcon,
MoonIcon,
ScrollTextIcon,
SparklesIcon,
TargetIcon,
UserIcon,
} from 'lucide-react'

export const stepIcons: Record<AnatomyStepId, LucideIcon> = {
calendar: CalendarIcon,
dreams: MoonIcon,
goals: TargetIcon,
identity: ContactIcon,
instructions: ScrollTextIcon,
memory: BrainIcon,
soul: SparklesIcon,
tasks: ListChecksIcon,
user: UserIcon,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
'use client'

import { CodeWindow } from '@outname/shared/marketing/components/landing/code-window'
import {
revealVariants,
staggerVariants,
} from '@outname/shared/marketing/components/landing/landing-motion'
import {
type AnatomyStepId,
agentTree,
anatomySteps,
ownerLabel,
} from '@outname/shared/marketing/data/agent-anatomy'
import { Badge } from '@outname/ui/components/ui/badge'
import { cn } from '@outname/ui/lib/utils'
import {
AnimatePresence,
domAnimation,
LazyMotion,
m as motion,
} from 'motion/react'
import { useEffect, useRef, useState } from 'react'
import { AgentFileTree } from './agent-file-tree'
import { stepIcons } from './constants'

const CYCLE_MS = 2800
const fileNameByNode = new Map(agentTree.map((node) => [node.id, node.label]))

function FileViewer({ activeId }: { activeId: AnatomyStepId }) {
const step =
anatomySteps.find((entry) => entry.id === activeId) ?? anatomySteps[0]
const Icon = stepIcons[step.id]
const fileName = fileNameByNode.get(step.node) ?? step.node
const total = String(anatomySteps.length).padStart(2, '0')

return (
<div className="min-h-[26rem] lg:min-h-[30rem]">
<AnimatePresence initial={false} mode="wait">
<motion.div
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -6 }}
initial={{ opacity: 0, y: 6 }}
key={step.id}
transition={{ duration: 0.26, ease: [0.16, 1, 0.3, 1] }}
>
<CodeWindow
code={step.code}
filename={fileName}
label={`${step.index} / ${total}`}
/>
<div className="mt-6 flex items-start gap-4">
<span className="grid size-9 shrink-0 place-items-center border border-border bg-brand text-brand-foreground">
<Icon className="size-4" />
</span>
<div className="min-w-0">
<h3 className="font-semibold text-xl tracking-tight md:text-2xl">
{step.title}
</h3>
<p className="mt-2 max-w-md text-muted-foreground text-sm leading-relaxed">
{step.caption}
</p>
<div className="mt-4 flex flex-wrap items-center gap-2">
<Badge
className={cn(
step.owner === 'user' &&
'border-transparent bg-brand text-brand-foreground'
)}
variant={step.owner === 'user' ? 'default' : 'outline'}
>
{ownerLabel[step.owner]}
</Badge>
<span className="swiss-label text-muted-foreground">
{step.note}
</span>
</div>
</div>
</div>
</motion.div>
</AnimatePresence>
</div>
)
}

export function LandingAgentAnatomy({
shouldReduceMotion,
}: {
shouldReduceMotion: boolean
}) {
const [activeId, setActiveId] = useState<AnatomyStepId>(anatomySteps[0].id)
const timerRef = useRef<ReturnType<typeof setInterval> | null>(null)

useEffect(() => {
if (shouldReduceMotion) {
return
}
timerRef.current = setInterval(() => {
setActiveId((current) => {
const index = anatomySteps.findIndex((entry) => entry.id === current)
return anatomySteps[(index + 1) % anatomySteps.length].id
})
}, CYCLE_MS)
return () => {
if (timerRef.current) {
clearInterval(timerRef.current)
}
}
}, [shouldReduceMotion])

const handleSelect = (id: AnatomyStepId) => {
if (timerRef.current) {
clearInterval(timerRef.current)
timerRef.current = null
}
setActiveId(id)
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

return (
<section
className="px-4 py-20 sm:px-6 md:px-10 md:py-28 lg:px-12"
id="anatomy"
>
<LazyMotion features={domAnimation}>
<motion.div
className="mx-auto max-w-7xl"
initial={shouldReduceMotion ? false : 'hidden'}
variants={staggerVariants}
viewport={{ margin: '-80px', once: true }}
whileInView="visible"
>
<motion.div
className="grid gap-5 border-border border-t pt-5 md:grid-cols-[minmax(0,0.82fr)_minmax(0,1fr)] md:items-end"
variants={revealVariants}
>
<div>
<p className="swiss-label text-muted-foreground">
The mental model
</p>
<h2 className="mt-4 text-balance font-semibold text-3xl leading-tight tracking-tight md:text-4xl">
An agent is a directory.
</h2>
</div>
<p className="max-w-2xl text-muted-foreground leading-relaxed">
Nine canonical markdown files in a sandbox, each with a job. Some
you author; the rest it keeps current itself. Open one.
</p>
</motion.div>

<motion.div
className="mt-10 grid gap-5 lg:grid-cols-[minmax(0,20rem)_minmax(0,1fr)] lg:items-start"
variants={revealVariants}
>
<AgentFileTree
activeStepId={activeId}
onSelectStep={handleSelect}
/>
<FileViewer activeId={activeId} />
</motion.div>
</motion.div>
</LazyMotion>
</section>
)
}
Loading