Blog
Login
diff --git a/packages/shared/marketing/components/landing/landing-primitives.tsx b/packages/shared/marketing/components/landing/landing-primitives.tsx
new file mode 100644
index 00000000..645ace09
--- /dev/null
+++ b/packages/shared/marketing/components/landing/landing-primitives.tsx
@@ -0,0 +1,142 @@
+'use client'
+
+import { BrandGlyph } from '@outname/shared/marketing/components/landing/brand-glyph'
+import {
+ revealVariants,
+ staggerVariants,
+} from '@outname/shared/marketing/components/landing/landing-motion'
+import {
+ channelsCard,
+ type PrimitiveProduct,
+ primitiveCards,
+} from '@outname/shared/marketing/data/primitives'
+import { domAnimation, LazyMotion, m as motion } from 'motion/react'
+
+function ProductRow({ product }: { product: PrimitiveProduct }) {
+ return (
+
+
+
+
{product.name}
+
+ {product.role}
+
+
+
+ )
+}
+
+export function LandingPrimitives({
+ shouldReduceMotion,
+}: {
+ shouldReduceMotion: boolean
+}) {
+ return (
+
+
+
+
+
+
+ Built on primitives
+
+
+ Nothing you can't host yourself.
+
+
+
+ Open source, sitting on building blocks you already trust. Bring
+ your own keys, swap the providers, run the whole thing on your own
+ infrastructure.
+
+
+
+
+ {primitiveCards.map((card) => (
+
+
{card.eyebrow}
+
+ {card.summary}
+
+
+ {card.products.map((product) => (
+
+ ))}
+
+
+ ))}
+
+
+
+
+ {channelsCard.eyebrow}
+
+
+ {channelsCard.summary}
+
+
+
+
+
+
+
Channels
+
+ {channelsCard.channels.map((channel) => (
+ -
+
+
+ {channel}
+
+
+ ))}
+
+
+
+
+ Connections
+
+
+ {channelsCard.connections.map((connection) => (
+ -
+
+
+ {connection}
+
+
+ ))}
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/packages/shared/marketing/components/landing/landing-production.tsx b/packages/shared/marketing/components/landing/landing-production.tsx
new file mode 100644
index 00000000..a9cc7b3a
--- /dev/null
+++ b/packages/shared/marketing/components/landing/landing-production.tsx
@@ -0,0 +1,243 @@
+'use client'
+
+import {
+ revealVariants,
+ staggerVariants,
+} from '@outname/shared/marketing/components/landing/landing-motion'
+import { cn } from '@outname/ui/lib/utils'
+import {
+ ActivityIcon,
+ GaugeIcon,
+ type LucideIcon,
+ RefreshCwIcon,
+} from 'lucide-react'
+import { domAnimation, LazyMotion, m as motion } from 'motion/react'
+import type { ReactNode } from 'react'
+
+// Durable execution: the phases a single run checkpoints through, so a crash
+// resumes mid-step instead of restarting.
+const runPhases = [
+ { fill: 1, label: 'load memory', state: 'completed' },
+ { fill: 1, label: 'scan channels', state: 'completed' },
+ { fill: 0.66, label: 'call sub-agent', state: 'running' },
+ { fill: 0.2, label: 'write memory', state: 'queued' },
+ { fill: 0, label: 'append log', state: 'queued' },
+] as const
+
+// Observability: the Events log — every run is an Event with a real type and
+// status from the runtime vocabulary.
+const eventLog = [
+ { id: 'heartbeat · 06:00', status: 'completed', meta: '4.2s' },
+ { id: 'dreaming · 14:01', status: 'completed', meta: '11s' },
+ { id: 'invocation · now', status: 'running', meta: 'live' },
+ { id: 'heartbeat · 18:00', status: 'queued', meta: '—' },
+] as const
+
+const statusTone: Record
= {
+ completed: 'bg-muted-foreground/40',
+ queued: 'bg-muted-foreground/25',
+ running: 'bg-brand',
+}
+
+// Governance: real budget periods (USD spend vs. ceiling) plus the per-run
+// step limit.
+const budgetRules = [
+ { ceiling: '$5.00', fill: 0.48, label: 'daily', spent: '$2.40' },
+ { ceiling: '$25.00', fill: 0.47, label: 'weekly', spent: '$11.80' },
+ { ceiling: '$100.00', fill: 0.36, label: 'monthly', spent: '$36.00' },
+] as const
+
+interface Pillar {
+ icon: LucideIcon
+ id: string
+ text: string
+ title: string
+}
+
+const pillars: readonly Pillar[] = [
+ {
+ icon: RefreshCwIcon,
+ id: 'durable',
+ text: 'A crash or redeploy resumes the run mid-step — no lost work, no double-sends. Every run is an event-driven Vercel Workflow.',
+ title: 'Durable execution',
+ },
+ {
+ icon: ActivityIcon,
+ id: 'events',
+ text: 'Heartbeats, dreaming passes, and sub-agent calls all land in one Events log — type, status, and duration on every run.',
+ title: 'Observable by default',
+ },
+ {
+ icon: GaugeIcon,
+ id: 'bounded',
+ text: 'Per-agent and account-wide budgets in USD, plus a step limit on every run. Estimated and actual cost is tracked per Event.',
+ title: 'Bounded spend',
+ },
+]
+
+function DurableMock() {
+ return (
+
+ )
+}
+
+function EventsMock() {
+ return (
+
+ )
+}
+
+function BudgetMock() {
+ return (
+
+
+
+ step limit
+ medium · 40 / run
+
+
+ )
+}
+
+const mocks: Record ReactNode> = {
+ bounded: BudgetMock,
+ durable: DurableMock,
+ events: EventsMock,
+}
+
+export function LandingProduction({
+ shouldReduceMotion,
+}: {
+ shouldReduceMotion: boolean
+}) {
+ return (
+
+
+
+
+
+
+ Production agents
+
+
+ Everything you need for production agents.
+
+
+
+ Durability, observability, and governance come standard. Focus on
+ what the agent does, not the plumbing that keeps it running.
+
+
+
+ {/* Shared visual panel: three mocks in equal-height cells. */}
+
+ {pillars.map((pillar) => {
+ const Mock = mocks[pillar.id]
+ return (
+
+ )
+ })}
+
+
+ {/* Aligned text row: one label + description per column. */}
+
+ {pillars.map((pillar) => {
+ const Icon = pillar.icon
+ return (
+
+ )
+ })}
+
+
+
+
+ )
+}
diff --git a/packages/shared/marketing/data/agent-anatomy.ts b/packages/shared/marketing/data/agent-anatomy.ts
new file mode 100644
index 00000000..57be09f7
--- /dev/null
+++ b/packages/shared/marketing/data/agent-anatomy.ts
@@ -0,0 +1,317 @@
+// The agent-anatomy section walks a real outname agent's sandbox. Every file
+// below is canonical in the runtime (see the AGENTS.md template and
+// sandbox-file-helpers/paths.ts). Snippets reflect the documented conventions
+// for each file — nothing here is invented product surface.
+
+export type AnatomyStepId =
+ | 'instructions'
+ | 'identity'
+ | 'soul'
+ | 'user'
+ | 'memory'
+ | 'tasks'
+ | 'calendar'
+ | 'goals'
+ | 'dreams'
+
+/** Who owns each file: the operator authors some, the agent maintains others. */
+export type FileOwner = 'user' | 'agent' | 'shared'
+
+export interface AgentTreeNode {
+ /** Indentation level inside the tree. Root children are depth 1. */
+ depth: number
+ /** Stable id; matches a step id when the node is the focus of a step. */
+ id: string
+ kind: 'dir' | 'file'
+ label: string
+ owner?: FileOwner
+ /** The step that highlights this node, when any. */
+ stepId?: AnatomyStepId
+}
+
+export interface AnatomyStep {
+ caption: string
+ /** Short markdown excerpt rendered as a mono block. */
+ code: string
+ id: AnatomyStepId
+ /** Two-digit ordinal, e.g. "01". */
+ index: string
+ /** Tree node this step focuses. */
+ node: string
+ /** A real convention from the runtime, shown as a tag. */
+ note: string
+ owner: FileOwner
+ title: string
+}
+
+export const agentSlug = 'inbox-sentinel'
+
+export const ownerLabel: Record = {
+ agent: 'Agent writes it',
+ shared: 'Shared',
+ user: 'You author it',
+}
+
+export const agentTree: readonly AgentTreeNode[] = [
+ {
+ depth: 1,
+ id: 'instructions',
+ kind: 'file',
+ label: 'AGENTS.md',
+ owner: 'user',
+ stepId: 'instructions',
+ },
+ {
+ depth: 1,
+ id: 'identity',
+ kind: 'file',
+ label: 'IDENTITY.md',
+ owner: 'user',
+ stepId: 'identity',
+ },
+ {
+ depth: 1,
+ id: 'soul',
+ kind: 'file',
+ label: 'SOUL.md',
+ owner: 'user',
+ stepId: 'soul',
+ },
+ {
+ depth: 1,
+ id: 'user',
+ kind: 'file',
+ label: 'USER.md',
+ owner: 'shared',
+ stepId: 'user',
+ },
+ {
+ depth: 1,
+ id: 'memory',
+ kind: 'file',
+ label: 'MEMORY.md',
+ owner: 'agent',
+ stepId: 'memory',
+ },
+ {
+ depth: 1,
+ id: 'tasks',
+ kind: 'file',
+ label: 'TASKS.md',
+ owner: 'agent',
+ stepId: 'tasks',
+ },
+ {
+ depth: 1,
+ id: 'calendar',
+ kind: 'file',
+ label: 'CALENDAR.md',
+ owner: 'agent',
+ stepId: 'calendar',
+ },
+ {
+ depth: 1,
+ id: 'goals',
+ kind: 'file',
+ label: 'GOALS.md',
+ owner: 'agent',
+ stepId: 'goals',
+ },
+ {
+ depth: 1,
+ id: 'dreams',
+ kind: 'file',
+ label: 'DREAMS.md',
+ owner: 'agent',
+ stepId: 'dreams',
+ },
+ { depth: 1, id: 'logs', kind: 'dir', label: 'logs/', owner: 'agent' },
+]
+
+export const anatomySteps: readonly AnatomyStep[] = [
+ {
+ caption:
+ 'Its operational manual. You write the custom instructions; the agent reads them at the start of every event.',
+ code: `# AGENTS.md
+Your operational manual. Read it at the
+start of every event.
+
+## Conventions
+- Dates are ISO-8601.
+- Append one bullet to today's log.
+- Terse output; bullets over prose.
+
+## User custom instructions
+- Triage the #ops Slack channel by 09:00.
+- Never send external email without a
+ confirm.
+- Keep replies short; prefer "Tomas".`,
+ id: 'instructions',
+ index: '01',
+ node: 'instructions',
+ note: 'Read every event',
+ owner: 'user',
+ title: 'How it should behave',
+ },
+ {
+ caption:
+ 'A compact identity card: name, role, vibe. Short by design, it is injected into every prompt the agent runs.',
+ code: `# Inbox Sentinel
+Role: personal chief of staff
+Vibe: terse, calm, proactive
+Emoji: 🛰️
+
+Read every turn — keep it short.
+First-impression cues only; the
+deeper self-model lives in SOUL.md.`,
+ id: 'identity',
+ index: '02',
+ node: 'identity',
+ note: 'Injected every turn',
+ owner: 'user',
+ title: 'Who it is, at a glance',
+ },
+ {
+ caption:
+ 'Its persona, voice, and self-model. Also injected every turn — if behavior drifts from it, the agent flags the contradiction.',
+ code: `# SOUL.md
+I default to action over explanation.
+Bullets over prose. I do one small
+useful thing well, then stop.
+
+I surface contradictions instead of
+working around them. If my behavior
+drifts from this file, I raise it.
+
+I protect the user's focus: batch the
+low-signal updates, interrupt only for
+what truly needs them.`,
+ id: 'soul',
+ index: '03',
+ node: 'soul',
+ note: 'Injected every turn',
+ owner: 'user',
+ title: 'Its voice and self-model',
+ },
+ {
+ caption:
+ 'The profile of the human it serves. You can seed it; the agent keeps it current as conversations reveal stable facts.',
+ code: `## Basic Info
+- Preferred name: Tomas
+- Timezone: Europe/Rome
+- Language: English
+
+## My World
+- Founder, shipping outname.
+- Mornings are deep-work; protect them.
+
+## Hard Boundaries
+- Ask before sending external email.
+- Never invent facts about people.`,
+ id: 'user',
+ index: '04',
+ node: 'user',
+ note: 'It maintains, you can edit',
+ owner: 'shared',
+ title: 'What it knows about you',
+ },
+ {
+ caption:
+ 'Broader durable facts, commitments, and evidence. Append-only by convention, with a citation back to where each fact came from.',
+ code: `## 2026-05-13
+- Skip auto-summary on Sundays.
+- Prefers "Tomas" in replies. (msg_8f12)
+- #ops blocker is owned by Dana. (msg_77a1)
+
+## 2026-05-11
+- Weekly digest ships Mondays 18:00.
+- Cal.com is the source of truth for
+ meetings, not email. (msg_5c0e)`,
+ id: 'memory',
+ index: '05',
+ node: 'memory',
+ note: 'Append-only',
+ owner: 'agent',
+ title: 'Durable facts it commits',
+ },
+ {
+ caption:
+ 'Active tactical items with status and dependencies, kept current without waiting for a reminder. Plain GitHub-flavored checkboxes.',
+ code: `## In progress
+- [ ] Confirm Tue 15:00 → Wed 10:00 move
+- [ ] Chase invoice #204 (due Fri)
+
+## Done
+- [x] Draft weekly digest
+- [x] Summarize #ops overnight threads
+- [x] Update USER.md timezone
+
+## Blocked
+- [ ] Onboarding rewrite — waiting on Dana`,
+ id: 'tasks',
+ index: '06',
+ node: 'tasks',
+ note: 'Checkbox conventions',
+ owner: 'agent',
+ title: 'The work it is tracking',
+ },
+ {
+ caption:
+ 'Known time-bound events and deadlines, ISO-8601 dated. The agent adds, updates, and removes entries as plans change.',
+ code: `# CALENDAR.md
+ISO-8601 dated. Add, update, and remove
+entries as plans change.
+
+- 2026-05-14T10:00Z Design review
+- 2026-05-14T15:00Z Tomas / 1:1 (moved)
+- 2026-05-16 Invoice #204 due
+- 2026-05-18T09:00Z Weekly planning`,
+ id: 'calendar',
+ index: '07',
+ node: 'calendar',
+ note: 'ISO-8601 dated',
+ owner: 'agent',
+ title: 'Its time-bound context',
+ },
+ {
+ caption:
+ 'Long-horizon objectives, updated rarely. The agent consults them before deciding what is worth surfacing in a heartbeat.',
+ code: `# GOALS.md
+Long-horizon. Updated rarely; consult
+before surfacing work in a heartbeat.
+
+- Keep the inbox under 10 open threads.
+- Protect Tomas's deep-work mornings.
+- Reduce onboarding to three steps.
+- Zero missed invoices this quarter.`,
+ id: 'goals',
+ index: '08',
+ node: 'goals',
+ note: 'Steers every heartbeat',
+ owner: 'agent',
+ title: 'The long horizon',
+ },
+ {
+ caption:
+ 'Notes from dreaming passes: pattern anticipation and self-evaluation, written only when there is real signal, with log citations.',
+ code: `# DREAMS.md
+Pattern notes from dreaming passes.
+Written only when there is real signal.
+
+## 2026-05-12
+- Replies spike on Mondays; pre-draft
+ the digest Sunday night.
+ (logs/2026-05-11.md:14)
+- "Tomas" preference is firm across 12
+ threads — promote it to USER.md.
+ (logs/2026-05-10.md:6)`,
+ id: 'dreams',
+ index: '09',
+ node: 'dreams',
+ note: 'Written while dreaming',
+ owner: 'agent',
+ title: 'What it learns in its sleep',
+ },
+]
+
+export const anatomyStepCount = anatomySteps.length
diff --git a/packages/shared/marketing/data/composability-demo.ts b/packages/shared/marketing/data/composability-demo.ts
deleted file mode 100644
index 77ca4fb5..00000000
--- a/packages/shared/marketing/data/composability-demo.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-export type StageId = 'tools' | 'subagents' | 'channels' | 'memory'
-export type Corner = 'ne' | 'nw' | 'se' | 'sw'
-
-export interface ComposabilityPart {
- id: string
- label: string
-}
-
-export interface ComposabilityStage {
- caption: string
- corner: Corner
- eyebrow: string
- id: StageId
- label: string
- parts: readonly ComposabilityPart[]
-}
-
-export const composabilityStages: readonly ComposabilityStage[] = [
- {
- caption:
- 'Typed contracts. Rate-limited. Scoped per agent. The agent only calls what you bound.',
- corner: 'ne',
- eyebrow: '01 / 04',
- id: 'tools',
- label: 'Tools',
- parts: [
- { id: 'tool-slack', label: 'slack.search_threads' },
- { id: 'tool-gmail', label: 'gmail.draft' },
- { id: 'tool-cal', label: 'cal.create_event' },
- ],
- },
- {
- caption:
- 'Delegate work. Each call is a traced run on its own. The parent waits or fires-and-forgets.',
- corner: 'nw',
- eyebrow: '02 / 04',
- id: 'subagents',
- label: 'Sub-agents',
- parts: [
- { id: 'sub-research', label: 'research-synthesizer' },
- { id: 'sub-digester', label: 'weekly-digester' },
- ],
- },
- {
- caption:
- 'Where the agent listens and speaks. Slack DMs, email threads, webhook intake — bound, not guessed.',
- corner: 'se',
- eyebrow: '03 / 04',
- id: 'channels',
- label: 'Channels',
- parts: [
- { id: 'channel-slack', label: 'slack:@you' },
- { id: 'channel-email', label: 'email:inbound' },
- ],
- },
- {
- caption:
- 'One markdown file per agent. The agent appends its own notes. You read them anytime.',
- corner: 'sw',
- eyebrow: '04 / 04',
- id: 'memory',
- label: 'Memory',
- parts: [{ id: 'memory-dreams', label: 'DREAMS.md · 47 entries' }],
- },
-]
diff --git a/packages/shared/marketing/data/heartbeat-demo.ts b/packages/shared/marketing/data/heartbeat-demo.ts
deleted file mode 100644
index c5926cb4..00000000
--- a/packages/shared/marketing/data/heartbeat-demo.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-export type HeartbeatKind =
- | 'cron'
- | 'slack'
- | 'memory'
- | 'heartbeat'
- | 'cal'
- | 'subagent'
- | 'gmail'
-
-export interface HeartbeatEvent {
- detail: string
- emphasis?: 'memory' | 'highlight'
- event: string
- kind: HeartbeatKind
- time: string
-}
-
-export const heartbeatStats = [
- { label: 'Unprompted runs', value: '21' },
- { label: 'Memory entries written', value: '+8' },
- { label: 'Questions asked', value: '0' },
-] as const
-
-export const heartbeatEvents: readonly HeartbeatEvent[] = [
- {
- detail: 'daily.triage queued',
- event: 'cron.fire',
- kind: 'cron',
- time: '06:00',
- },
- {
- detail: '14 threads scanned · 2 flagged',
- event: 'slack.read',
- kind: 'slack',
- time: '06:00',
- },
- {
- detail: '+ skip auto-summary on Sundays',
- emphasis: 'memory',
- event: 'memory.write',
- kind: 'memory',
- time: '06:01',
- },
- {
- detail: 'calendar conflict spotted · draft sent',
- event: 'heartbeat',
- kind: 'heartbeat',
- time: '09:14',
- },
- {
- detail: 'tue 15:00 → wed 10:00 proposed',
- event: 'cal.draft',
- kind: 'cal',
- time: '09:14',
- },
- {
- detail: 'research-synthesizer · 4.2s',
- event: 'subagent.call',
- kind: 'subagent',
- time: '11:02',
- },
- {
- detail: '+ user prefers "Tomas" in replies',
- emphasis: 'memory',
- event: 'memory.write',
- kind: 'memory',
- time: '11:02',
- },
- {
- detail: 'weekly.digest queued',
- event: 'cron.fire',
- kind: 'cron',
- time: '14:00',
- },
- {
- detail: '5 threads summarized · digest ready',
- event: 'gmail.draft',
- kind: 'gmail',
- time: '14:01',
- },
- {
- detail: 'weekly digest sent · 0 follow-ups',
- emphasis: 'highlight',
- event: 'gmail.send',
- kind: 'gmail',
- time: '18:00',
- },
-]
diff --git a/packages/shared/marketing/data/primitives.ts b/packages/shared/marketing/data/primitives.ts
new file mode 100644
index 00000000..a31ca17a
--- /dev/null
+++ b/packages/shared/marketing/data/primitives.ts
@@ -0,0 +1,94 @@
+// "Built on primitives" mirrors eve's "Leverages all Vercel AI primitives":
+// a row of category cards, each listing the real products behind it, plus a
+// channels/connections block. Everything here is real to the outname stack.
+
+export interface PrimitiveProduct {
+ name: string
+ role: string
+}
+
+export interface PrimitiveCard {
+ eyebrow: string
+ id: string
+ products: readonly PrimitiveProduct[]
+ summary: string
+}
+
+export const primitiveCards: readonly PrimitiveCard[] = [
+ {
+ eyebrow: 'Runtime',
+ id: 'runtime',
+ products: [
+ {
+ name: 'Vercel Workflow',
+ role: 'Heartbeat, dreaming, and sub-agent runs — checkpointed and resumable.',
+ },
+ ],
+ summary: 'Durable, event-driven execution.',
+ },
+ {
+ eyebrow: 'Compute',
+ id: 'compute',
+ products: [
+ {
+ name: 'Vercel Sandbox',
+ role: 'A persistent, isolated filesystem and skill execution per agent.',
+ },
+ ],
+ summary: 'A filesystem of its own.',
+ },
+ {
+ eyebrow: 'Inference',
+ id: 'inference',
+ products: [
+ {
+ name: 'Vercel AI Gateway',
+ role: 'Default gateway for model calls and streaming.',
+ },
+ { name: 'LLM Gateway', role: 'Alternate provider, same interface.' },
+ { name: 'OpenRouter', role: 'Hundreds of models behind one key.' },
+ ],
+ summary: 'Swap providers without touching the agent.',
+ },
+ {
+ eyebrow: 'Foundation',
+ id: 'foundation',
+ products: [
+ { name: 'Next.js 16', role: 'The single control plane.' },
+ {
+ name: 'Neon Postgres',
+ role: 'Typed control-plane database via Drizzle.',
+ },
+ {
+ name: 'Upstash Redis',
+ role: 'Coordination, caching, and rate limits.',
+ },
+ { name: 'Better Auth', role: 'Passwordless email one-time codes.' },
+ ],
+ summary: 'Control plane, data, and sign-in.',
+ },
+]
+
+export const channelsCard = {
+ channels: ['in-app chat', 'Slack'],
+ connections: [
+ 'GitHub',
+ 'Cal.com',
+ 'Resend',
+ 'Firecrawl',
+ 'PostHog',
+ 'Parallel',
+ 'Typefully',
+ 'X',
+ 'Supabase',
+ 'v0',
+ 'Vercel',
+ 'Context7',
+ ],
+ eyebrow: 'Channels & connections',
+ product: {
+ name: 'Chat SDK',
+ role: 'In-app chat and Slack today; new channels drop in on the same agent.',
+ },
+ summary: 'One agent, every channel.',
+} as const