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
8 changes: 3 additions & 5 deletions components/CommercialOffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,12 @@ export default function CommercialOffer({ hostedOffer }) {
</p>
</div>
<div className="flex shrink-0 items-center gap-4 text-sm">
<a
href="https://docs.openadapt.ai/get-started/"
target="_blank"
rel="noopener noreferrer"
<Link
href="/start"
className="btn-ghost-ink inline-block"
>
Start locally
</a>
</Link>
<a
href="https://github.com/OpenAdaptAI/OpenAdapt"
target="_blank"
Expand Down
5 changes: 5 additions & 0 deletions components/Footer.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,11 @@ export default function Footer({
<div className={styles.column}>
<h2 className={styles.columnTitle}>Product</h2>
<ul className={styles.columnList}>
<li>
<FooterLink href="/start">
Run locally
</FooterLink>
</li>
<li>
<FooterLink href="/#product-status">
How it runs
Expand Down
8 changes: 3 additions & 5 deletions components/MastHead.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,9 @@ export default function Home({ githubStats }) {
>
Qualify one workflow
</Link>
<a
<Link
className="btn-ghost-ink"
href="https://docs.openadapt.ai/get-started/"
target="_blank"
rel="noopener noreferrer"
href="/start"
data-testid="local-quickstart-cta"
onClick={() =>
track(EVENTS.HERO_CTA_CLICK, {
Expand All @@ -88,7 +86,7 @@ export default function Home({ githubStats }) {
}
>
Run locally for free
</a>
</Link>
<a
className="btn-ghost-ink"
href="https://app.openadapt.ai/demo"
Expand Down
1 change: 1 addition & 0 deletions components/NavHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const SOLUTIONS_LINKS = [
]

const PRODUCT_LINKS = [
{ label: 'Run locally', href: '/start' },
{ label: 'How it works', href: '/how-it-works' },
{
label: 'Customer results',
Expand Down
6 changes: 1 addition & 5 deletions cypress/e2e/public-surface-coherence.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ describe('public surface coherence', () => {
.and('have.attr', 'href', '/qualify')
cy.get('[data-testid="local-quickstart-cta"]')
.should('be.visible')
.and(
'have.attr',
'href',
'https://docs.openadapt.ai/get-started/'
)
.and('have.attr', 'href', '/start')
cy.get('[data-testid="cloud-demo-cta"]')
.should('be.visible')
.and(
Expand Down
202 changes: 202 additions & 0 deletions pages/start.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import { useState } from 'react'
import Head from 'next/head'
import Link from 'next/link'

import Footer from '@components/Footer'
import { EVENTS, track } from 'utils/analytics'

const INSTALL = 'python -m pip install --upgrade openadapt'
const QUICKSTART = 'openadapt quickstart'

function Command({ command, event }) {
const [copyState, setCopyState] = useState('idle')

async function copy() {
try {
await navigator.clipboard.writeText(command)
setCopyState('copied')
track(event, { surface: 'local_quickstart' })
window.setTimeout(() => setCopyState('idle'), 1800)
} catch {
setCopyState('failed')
}
}

return (
<div className="mt-3 flex items-center gap-3 rounded-xl border border-hairline bg-panel p-3 sm:p-4">
<code className="min-w-0 flex-1 overflow-x-auto whitespace-nowrap text-sm text-ink">
{command}
</code>
<button
type="button"
className="btn-ghost-ink shrink-0"
onClick={copy}
aria-label={`Copy ${command}`}
aria-live="polite"
>
{copyState === 'copied'
? 'Copied'
: copyState === 'failed'
? 'Copy failed'
: 'Copy'}
</button>
</div>
)
}

export default function StartPage() {
return (
<div className="min-h-screen bg-ground text-ink">
<Head>
<title>Run OpenAdapt Locally for Free | OpenAdapt</title>
<meta
name="description"
content="Install OpenAdapt and complete your first local record, compile, certify, and replay loop with no account, model API, or Cloud service."
/>
<link rel="canonical" href="https://openadapt.ai/start" />
<meta
property="og:title"
content="Run OpenAdapt Locally for Free | OpenAdapt"
/>
<meta
property="og:description"
content="Reach a real local OpenAdapt run in two copy-and-paste commands, then inspect the workflow and its run evidence."
/>
<meta property="og:url" content="https://openadapt.ai/start" />
</Head>

<section className="border-b border-hairline px-5 py-16 md:py-24">
<div className="mx-auto max-w-4xl">
<p className="eyebrow">Free local quickstart · MIT licensed</p>
<h1 className="mt-3 max-w-3xl font-display text-3xl font-semibold tracking-tight md:text-5xl">
Get to your first local run in two commands.
</h1>
<p className="mt-5 max-w-2xl text-base leading-relaxed text-ink-2 md:text-lg">
The quickstart records a bundled synthetic tutorial,
compiles it into an inspectable workflow, applies its
explicit demo policy, and replays it locally. No account,
target application, model API, or Cloud service is needed.
</p>

<div className="mt-10 grid gap-8 md:grid-cols-[1fr_0.85fr]">
<div>
<div>
<p className="eyebrow">1 · Install</p>
<Command
command={INSTALL}
event={EVENTS.LOCAL_QUICKSTART_INSTALL_COPIED}
/>
</div>
<div className="mt-7">
<p className="eyebrow">2 · Run the whole loop</p>
<Command
command={QUICKSTART}
event={EVENTS.LOCAL_QUICKSTART_RUN_COPIED}
/>
</div>
<p className="mt-5 text-sm leading-relaxed text-ink-3">
Requires Python 3.10–3.12 on Windows, macOS, or
Linux. The first run downloads Chromium once
(about 150 MB), so it can take a few minutes.
</p>
</div>

<aside className="rounded-2xl border border-hairline bg-panel p-5 md:p-6">
<p className="eyebrow">What you get</p>
<ol className="mt-4 grid gap-4 text-sm leading-relaxed text-ink-2">
<li>
<strong className="text-ink">Recording</strong>
<br />
The demonstrated interaction and retained
target evidence.
</li>
<li>
<strong className="text-ink">
Workflow bundle
</strong>
<br />
The readable program OpenAdapt compiled.
</li>
<li>
<strong className="text-ink">Run report</strong>
<br />
The actions, evidence, result, and any halt
reason.
</li>
</ol>
<a
className="mt-5 inline-block text-sm underline underline-offset-4"
href="https://docs.openadapt.ai/get-started/"
target="_blank"
rel="noopener noreferrer"
onClick={() =>
track(EVENTS.DOCS_CLICK, {
location: 'local_quickstart',
})
}
>
Open the full walkthrough
</a>
</aside>
</div>
</div>
</section>

<section className="border-b border-hairline bg-panel px-5 py-16 md:py-20">
<div className="mx-auto max-w-4xl">
<p className="eyebrow">After your first run</p>
<h2 className="mt-2 max-w-2xl font-display text-2xl font-semibold tracking-tight md:text-3xl">
Connect Cloud or qualify the real work.
</h2>
<div className="mt-7 grid gap-5 md:grid-cols-2">
<article className="rounded-2xl border border-hairline bg-ground p-5 md:p-6">
<h3 className="font-display text-xl font-semibold">
Connect this computer
</h3>
<p className="mt-3 text-sm leading-relaxed text-ink-2">
Pair the local runtime with your Cloud workspace
for approved workflow handoff, run history, and
collaboration. Pairing is free; managed runs use
the Cloud plan.
</p>
<a
className="btn-ink mt-5 inline-block"
href="https://app.openadapt.ai/dashboard/settings/ingest"
onClick={() =>
track(EVENTS.LOCAL_TO_CLOUD_CLICK, {
location: 'local_quickstart',
})
}
>
Connect to Cloud
</a>
</article>
<article className="rounded-2xl border border-hairline bg-ground p-5 md:p-6">
<h3 className="font-display text-xl font-semibold">
Bring the actual workflow
</h3>
<p className="mt-3 text-sm leading-relaxed text-ink-2">
For consequential browser, desktop, RDP, or
Citrix work, qualify the exact application,
identities, effect verifier, failure cases, and
deployment boundary.
</p>
<Link
className="btn-ghost-ink mt-5 inline-block"
href="/qualify"
onClick={() =>
track(EVENTS.HERO_CTA_CLICK, {
cta: 'qualify_after_local_quickstart',
})
}
>
Qualify one workflow
</Link>
</article>
</div>
</div>
</section>
<Footer />
</div>
)
}
6 changes: 6 additions & 0 deletions public/sitemap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://openadapt.ai/start</loc>
<lastmod>2026-07-26</lastmod>
<changefreq>weekly</changefreq>
<priority>0.9</priority>
</url>
<url>
<loc>https://openadapt.ai/security</loc>
<lastmod>2026-07-16</lastmod>
Expand Down
3 changes: 3 additions & 0 deletions utils/analytics.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ export const EVENTS = {
BOOK_PILOT_CLICK: 'book_pilot_click',
GITHUB_CLICK: 'github_click',
INSTALL_COMMAND_COPIED: 'install_command_copied',
LOCAL_QUICKSTART_INSTALL_COPIED: 'local_quickstart_install_copied',
LOCAL_QUICKSTART_RUN_COPIED: 'local_quickstart_run_copied',
LOCAL_TO_CLOUD_CLICK: 'local_to_cloud_click',
DOCS_CLICK: 'docs_click',
DISCORD_CLICK: 'discord_click',
// Signup / hosted-app funnel: every outbound click to app.openadapt.ai
Expand Down
Loading