Zen lander (#2907)

Co-authored-by: David Hill <iamdavidhill@gmail.com>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com>
Co-authored-by: Jay V <air@live.ca>
This commit is contained in:
Dax
2025-10-01 19:38:15 -04:00
committed by GitHub
parent 70da3a9399
commit a782e3dac2
42 changed files with 3846 additions and 660 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -1,2 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z"/></svg>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 14.3581L10.0541 17.7027L18 7" stroke="#8E8B8B" stroke-width="1.5" stroke-linecap="square"/>
</svg>

Before

Width:  |  Height:  |  Size: 212 B

After

Width:  |  Height:  |  Size: 207 B

View File

@@ -1,2 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 512 512"><rect width="336" height="336" x="128" y="128" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32" rx="57" ry="57"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="m383.5 128l.5-24a56.16 56.16 0 0 0-56-56H112a64.19 64.19 0 0 0-64 64v216a56.16 56.16 0 0 0 56 56h24"/></svg>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.75 8.75V2.75H21.25V15.25H15.25M15.25 8.75H2.75V21.25H15.25V8.75Z" stroke="#8E8B8B" stroke-width="1.5" stroke-linecap="square"/>
</svg>

Before

Width:  |  Height:  |  Size: 443 B

After

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 902 KiB

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 456 KiB

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 998 KiB

After

Width:  |  Height:  |  Size: 495 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 592 KiB

After

Width:  |  Height:  |  Size: 136 KiB

View File

@@ -1,19 +1,18 @@
<svg width="289" height="50" viewBox="0 0 289 50" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.5 16.5H24.5V33H8.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M48.5 16.5H64.5V33H48.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M120.5 16.5H136.5V33H120.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M160.5 16.5H176.5V33H160.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M192.5 16.5H208.5V33H192.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M232.5 16.5H248.5V33H232.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M264.5 0H288.5V8.5H272.5V16.5H288.5V25H272.5V33H288.5V41.5H264.5V0Z" fill="white" fill-opacity="0.95"/>
<path d="M248.5 0H224.5V41.5H248.5V33H232.5V8.5H248.5V0Z" fill="white" fill-opacity="0.95"/>
<path d="M256.5 8.5H248.5V33H256.5V8.5Z" fill="white" fill-opacity="0.95"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M184.5 0H216.5V41.5H184.5V0ZM208.5 8.5H192.5V33H208.5V8.5Z" fill="white" fill-opacity="0.95"/>
<path d="M144.5 8.5H136.5V41.5H144.5V8.5Z" fill="white" fill-opacity="0.5"/>
<path d="M136.5 0H112.5V41.5H120.5V8.5H136.5V0Z" fill="white" fill-opacity="0.5"/>
<path d="M80.5 0H104.5V8.5H88.5V16.5H104.5V25H88.5V33H104.5V41.5H80.5V0Z" fill="white" fill-opacity="0.5"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.5 0H72.5V41.5H48.5V49.5H40.5V0ZM64.5 8.5H48.5V33H64.5V8.5Z" fill="white" fill-opacity="0.5"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.5 0H32.5V41.5955H0.5V0ZM24.5 8.5H8.5V33H24.5V8.5Z" fill="white" fill-opacity="0.5"/>
<path d="M152.5 0H176.5V8.5H160.5V33H176.5V41.5H152.5V0Z" fill="white" fill-opacity="0.95"/>
<svg width="234" height="42" viewBox="0 0 234 42" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18 30H6V18H18V30Z" fill="#4B4646"/>
<path d="M18 12H6V30H18V12ZM24 36H0V6H24V36Z" fill="#B7B1B1"/>
<path d="M48 30H36V18H48V30Z" fill="#4B4646"/>
<path d="M36 30H48V12H36V30ZM54 36H36V42H30V6H54V36Z" fill="#B7B1B1"/>
<path d="M84 24V30H66V24H84Z" fill="#4B4646"/>
<path d="M84 24H66V30H84V36H60V6H84V24ZM66 18H78V12H66V18Z" fill="#B7B1B1"/>
<path d="M108 36H96V18H108V36Z" fill="#4B4646"/>
<path d="M108 12H96V36H90V6H108V12ZM114 36H108V12H114V36Z" fill="#B7B1B1"/>
<path d="M144 30H126V18H144V30Z" fill="#4B4646"/>
<path d="M144 12H126V30H144V36H120V6H144V12Z" fill="#F1ECEC"/>
<path d="M168 30H156V18H168V30Z" fill="#4B4646"/>
<path d="M168 12H156V30H168V12ZM174 36H150V6H174V36Z" fill="#F1ECEC"/>
<path d="M198 30H186V18H198V30Z" fill="#4B4646"/>
<path d="M198 12H186V30H198V12ZM204 36H180V6H198V0H204V36Z" fill="#F1ECEC"/>
<path d="M234 24V30H216V24H234Z" fill="#4B4646"/>
<path d="M216 12V18H228V12H216ZM234 24H216V30H234V36H210V6H234V24Z" fill="#F1ECEC"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,18 +1,18 @@
<svg width="288" height="50" viewBox="0 0 288 50" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 16.5H24V33H8V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M48 16.5H64V33H48V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M120 16.5H136V33H120V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M160 16.5H176V33H160V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M192 16.5H208V33H192V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M232 16.5H248V33H232V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M264 0H288V8.5H272V16.5H288V25H272V33H288V41.5H264V0Z" fill="black" fill-opacity="0.95"/>
<path d="M248 0H224V41.5H248V33H232V8.5H248V0Z" fill="black" fill-opacity="0.95"/>
<path d="M256 8.5H248V33H256V8.5Z" fill="black" fill-opacity="0.95"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M184 0H216V41.5H184V0ZM208 8.5H192V33H208V8.5Z" fill="black" fill-opacity="0.95"/>
<path d="M144 8.5H136V41.5H144V8.5Z" fill="black" fill-opacity="0.55"/>
<path d="M136 0H112V41.5H120V8.5H136V0Z" fill="black" fill-opacity="0.55"/>
<path d="M80 0H104V8.5H88V16.5H104V25H88V33H104V41.5H80V0Z" fill="black" fill-opacity="0.55"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M40 0H72V41.5H48V49.5H40V0ZM64 8.5H48V33H64V8.5Z" fill="black" fill-opacity="0.55"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 0H32V41.5955H0V0ZM24 8.5H8V33H24V8.5Z" fill="black" fill-opacity="0.55"/>
<path d="M152 0H176V8.5H160V33H176V41.5H152V0Z" fill="black" fill-opacity="0.95"/>
<svg width="234" height="42" viewBox="0 0 234 42" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18 30H6V18H18V30Z" fill="#CFCECD"/>
<path d="M18 12H6V30H18V12ZM24 36H0V6H24V36Z" fill="#656363"/>
<path d="M48 30H36V18H48V30Z" fill="#CFCECD"/>
<path d="M36 30H48V12H36V30ZM54 36H36V42H30V6H54V36Z" fill="#656363"/>
<path d="M84 24V30H66V24H84Z" fill="#CFCECD"/>
<path d="M84 24H66V30H84V36H60V6H84V24ZM66 18H78V12H66V18Z" fill="#656363"/>
<path d="M108 36H96V18H108V36Z" fill="#CFCECD"/>
<path d="M108 12H96V36H90V6H108V12ZM114 36H108V12H114V36Z" fill="#656363"/>
<path d="M144 30H126V18H144V30Z" fill="#CFCECD"/>
<path d="M144 12H126V30H144V36H120V6H144V12Z" fill="#211E1E"/>
<path d="M168 30H156V18H168V30Z" fill="#CFCECD"/>
<path d="M168 12H156V30H168V12ZM174 36H150V6H174V36Z" fill="#211E1E"/>
<path d="M198 30H186V18H198V30Z" fill="#CFCECD"/>
<path d="M198 12H186V30H198V12ZM204 36H180V6H198V0H204V36Z" fill="#211E1E"/>
<path d="M234 24V30H216V24H234Z" fill="#CFCECD"/>
<path d="M216 12V18H228V12H216ZM234 24H216V30H234V36H210V6H234V24Z" fill="#211E1E"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,12 +1,18 @@
<svg width="289" height="50" viewBox="0 0 289 50" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M264.5 0H288.5V8.5H272.5V16.5H288.5V25H272.5V33H288.5V41.5H264.5V0Z" fill="black"/>
<path d="M248.5 0H224.5V41.5H248.5V33H232.5V8.5H248.5V0Z" fill="black"/>
<path d="M256.5 8.5H248.5V33H256.5V8.5Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M184.5 0H216.5V41.5H184.5V0ZM208.5 8.5H192.5V33H208.5V8.5Z" fill="black"/>
<path d="M144.5 8.5H136.5V41.5H144.5V8.5Z" fill="black"/>
<path d="M136.5 0H112.5V41.5H120.5V8.5H136.5V0Z" fill="black"/>
<path d="M80.5 0H104.5V8.5H88.5V16.5H104.5V25H88.5V33H104.5V41.5H80.5V0Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.5 0H72.5V41.5H48.5V49.5H40.5V0ZM64.5 8.5H48.5V33H64.5V8.5Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.5 0H32.5V41.5955H0.5V0ZM24.5 8.5H8.5V33H24.5V8.5Z" fill="black"/>
<path d="M152.5 0H176.5V8.5H160.5V33H176.5V41.5H152.5V0Z" fill="black"/>
<svg width="234" height="42" viewBox="0 0 234 42" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18 30H6V18H18V30Z" fill="#CFCECD"/>
<path d="M18 12H6V30H18V12ZM24 36H0V6H24V36Z" fill="#656363"/>
<path d="M48 30H36V18H48V30Z" fill="#CFCECD"/>
<path d="M36 30H48V12H36V30ZM54 36H36V42H30V6H54V36Z" fill="#656363"/>
<path d="M84 24V30H66V24H84Z" fill="#CFCECD"/>
<path d="M84 24H66V30H84V36H60V6H84V24ZM66 18H78V12H66V18Z" fill="#656363"/>
<path d="M108 36H96V18H108V36Z" fill="#CFCECD"/>
<path d="M108 12H96V36H90V6H108V12ZM114 36H108V12H114V36Z" fill="#656363"/>
<path d="M144 30H126V18H144V30Z" fill="#CFCECD"/>
<path d="M144 12H126V30H144V36H120V6H144V12Z" fill="#211E1E"/>
<path d="M168 30H156V18H168V30Z" fill="#CFCECD"/>
<path d="M168 12H156V30H168V12ZM174 36H150V6H174V36Z" fill="#211E1E"/>
<path d="M198 30H186V18H198V30Z" fill="#CFCECD"/>
<path d="M198 12H186V30H198V12ZM204 36H180V6H198V0H204V36Z" fill="#211E1E"/>
<path d="M234 24V30H216V24H234Z" fill="#CFCECD"/>
<path d="M216 12V18H228V12H216ZM234 24H216V30H234V36H210V6H234V24Z" fill="#211E1E"/>
</svg>

Before

Width:  |  Height:  |  Size: 981 B

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,8 @@
<svg width="84" height="30" viewBox="0 0 84 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M24 24H6V18H18V12H24V24ZM6 18H0V12H6V18Z" fill="#4B4646"/>
<path d="M6 24H24V30H0V18H6V24ZM18 18H6V12H18V18ZM24 12H18V6H0V0H24V12Z" fill="#F1ECEC"/>
<path d="M54 18V24H36V18H54Z" fill="#4B4646"/>
<path d="M54 18H36V24H54V30H30V0H54V18ZM36 12H48V6H36V12Z" fill="#F1ECEC"/>
<path d="M78 30H66V12H78V30Z" fill="#4B4646"/>
<path d="M78 6H66V30H60V0H78V6ZM84 30H78V6H84V30Z" fill="#F1ECEC"/>
</svg>

After

Width:  |  Height:  |  Size: 499 B

View File

@@ -0,0 +1,8 @@
<svg width="84" height="30" viewBox="0 0 84 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M24 24H6V18H18V12H24V24ZM6 18H0V12H6V18Z" fill="#CFCECD"/>
<path d="M6 24H24V30H0V18H6V24ZM18 18H6V12H18V18ZM24 12H18V6H0V0H24V12Z" fill="#211E1E"/>
<path d="M54 18V24H36V18H54Z" fill="#CFCECD"/>
<path d="M54 18H36V24H54V30H30V0H54V18ZM36 12H48V6H36V12Z" fill="#211E1E"/>
<path d="M78 30H66V12H78V30Z" fill="#CFCECD"/>
<path d="M78 6H66V30H60V0H78V6ZM84 30H78V6H84V30Z" fill="#211E1E"/>
</svg>

After

Width:  |  Height:  |  Size: 499 B

View File

@@ -0,0 +1,49 @@
import { action, useSubmission } from "@solidjs/router"
import dock from "../asset/lander/dock.png"
import { Resource } from "sst"
import { Show } from "solid-js"
const emailSignup = action(async (formData: FormData) => {
"use server"
const emailAddress = formData.get("email")!
const listId = "8b9bb82c-9d5f-11f0-975f-0df6fd1e4945"
const response = await fetch(`https://api.emailoctopus.com/lists/${listId}/contacts`, {
method: "PUT",
headers: {
Authorization: `Bearer ${Resource.EMAILOCTOPUS_API_KEY.value}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
email_address: emailAddress,
}),
})
console.log(response)
return true
})
export function EmailSignup() {
const submission = useSubmission(emailSignup)
return (
<section data-component="email">
<div data-slot="dock">
<img src={dock} alt="" />
</div>
<div data-slot="section-title">
<h3>OpenCode will be available on desktop soon</h3>
<p>Join the waitlist for early access.</p>
</div>
<form data-slot="form" action={emailSignup} method="post">
<input type="email" name="email" placeholder="Email address" required />
<button type="submit" disabled={submission.pending}>
Subscribe
</button>
</form>
<Show when={submission.result}>
<div style="color: #03B000; margin-top: 24px;">Almost done, check your inbox and confirm your email address</div>
</Show>
<Show when={submission.error}>
<div style="color: #FF408F; margin-top: 24px;">{submission.error}</div>
</Show>
</section>
)
}

View File

@@ -0,0 +1,33 @@
import { Collapsible } from "@kobalte/core/collapsible"
import { ParentProps } from "solid-js"
export function Faq(props: ParentProps & { question: string }) {
return (
<Collapsible data-slot="faq-item">
<Collapsible.Trigger data-slot="faq-question">
<svg
data-slot="faq-icon-plus"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M12.5 11.5H19V12.5H12.5V19H11.5V12.5H5V11.5H11.5V5H12.5V11.5Z" fill="#6D717D" />
</svg>
<svg
data-slot="faq-icon-minus"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M5 11.5H19V12.5H5Z" fill="#6D717D" />
</svg>
<div data-slot="faq-question-text">{props.question}</div>
</Collapsible.Trigger>
<Collapsible.Content data-slot="faq-answer">{props.children}</Collapsible.Content>
</Collapsible>
)
}

View File

@@ -0,0 +1,34 @@
import { A, createAsync } from "@solidjs/router"
import { createMemo } from "solid-js"
import { github } from "~/lib/github"
export function Footer() {
const githubData = createAsync(() => github())
const starCount = createMemo(() =>
githubData()?.stars
? new Intl.NumberFormat("en-US", {
notation: "compact",
compactDisplay: "short",
}).format(githubData()!.stars!)
: "25K",
)
return (
<footer data-component="footer">
<div data-slot="cell">
<A href="https://github.com/sst/opencode" target="_blank">
GitHub <span>[{starCount()}]</span>
</A>
</div>
<div data-slot="cell">
<A href="/docs">Docs</A>
</div>
<div data-slot="cell">
<A href="https://opencode.ai/discord">Discord</A>
</div>
<div data-slot="cell">
<A href="https://x/opencode">X</A>
</div>
</footer>
)
}

View File

@@ -0,0 +1,127 @@
import logoLight from "../asset/logo-ornate-light.svg"
import logoDark from "../asset/logo-ornate-dark.svg"
import { A, createAsync } from "@solidjs/router"
import { createMemo, Match, Show, Switch } from "solid-js"
import { createStore } from "solid-js/store"
import { github } from "~/lib/github"
export function Header(props: { zen?: boolean }) {
const githubData = createAsync(() => github())
const starCount = createMemo(() =>
githubData()?.stars
? new Intl.NumberFormat("en-US", {
notation: "compact",
compactDisplay: "short",
}).format(githubData()?.stars!)
: "25K",
)
const [store, setStore] = createStore({
mobileMenuOpen: false,
})
return (
<section data-component="top">
<A href="/">
<img data-slot="logo light" src={logoLight} alt="opencode logo light" />
<img data-slot="logo dark" src={logoDark} alt="opencode logo dark" />
</A>
<nav data-component="nav-desktop">
<ul>
<li>
<A href="https://github.com/sst/opencode" target="_blank">
GitHub <span>[{starCount()}]</span>
</A>
</li>
<li>
<A href="/docs">Docs</A>
</li>
<li>
<Switch>
<Match when={props.zen}>
<A href="/auth">Login</A>
</Match>
<Match when={!props.zen}>
<A href="/zen">Zen</A>
</Match>
</Switch>
</li>
</ul>
</nav>
<nav data-component="nav-mobile">
<button
type="button"
data-component="nav-mobile-toggle"
aria-expanded="false"
aria-controls="nav-mobile-menu"
class="nav-toggle"
onClick={() => setStore("mobileMenuOpen", !store.mobileMenuOpen)}
>
<span class="sr-only">Open menu</span>
<Switch>
<Match when={store.mobileMenuOpen}>
<svg
class="icon icon-close"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12.7071 11.9993L18.0104 17.3026L17.3033 18.0097L12 12.7064L6.6967 18.0097L5.98959 17.3026L11.2929 11.9993L5.98959 6.69595L6.6967 5.98885L12 11.2921L17.3033 5.98885L18.0104 6.69595L12.7071 11.9993Z"
fill="currentColor"
/>
</svg>
</Match>
<Match when={!store.mobileMenuOpen}>
<svg
class="icon icon-hamburger"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M19 17H5V16H19V17Z" fill="currentColor" />
<path d="M19 8H5V7H19V8Z" fill="currentColor" />
</svg>
</Match>
</Switch>
</button>
<Show when={store.mobileMenuOpen}>
<div id="nav-mobile-menu" data-component="nav-mobile">
<nav data-component="nav-mobile-menu-list">
<ul>
<li>
<A href="/">Home</A>
</li>
<li>
<A href="https://github.com/sst/opencode" target="_blank">
GitHub <span>[{starCount()}]</span>
</A>
</li>
<li>
<A href="/docs">Docs</A>
</li>
<li>
<Switch>
<Match when={props.zen}>
<A href="/auth">Login</A>
</Match>
<Match when={!props.zen}>
<A href="/zen">Zen</A>
</Match>
</Switch>
</li>
</ul>
</nav>
</div>
</Show>
</nav>
</section>
)
}

View File

@@ -34,38 +34,21 @@ export function IconLogo(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
export function IconCopy(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
return (
<svg {...props} viewBox="0 0 512 512">
<rect
width="336"
height="336"
x="128"
y="128"
fill="none"
stroke="currentColor"
stroke-linejoin="round"
stroke-width="32"
rx="57"
ry="57"
></rect>
<svg {...props} width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="32"
d="m383.5 128l.5-24a56.16 56.16 0 0 0-56-56H112a64.19 64.19 0 0 0-64 64v216a56.16 56.16 0 0 0 56 56h24"
></path>
d="M8.75 8.75V2.75H21.25V15.25H15.25M15.25 8.75H2.75V21.25H15.25V8.75Z"
stroke="#8E8B8B"
stroke-width="1.5"
stroke-linecap="square"
/>
</svg>
)
}
export function IconCheck(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
return (
<svg {...props} viewBox="0 0 24 24">
<path
fill="currentColor"
d="M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z"
></path>
<svg {...props} width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.75 15.0938L9 20.25L21.25 3.75" stroke="#03B000" stroke-width="2" stroke-linecap="square" />
</svg>
)
}

View File

@@ -0,0 +1,9 @@
export function Legal() {
return (
<div data-component="legal">
<span>
©{new Date().getFullYear()} <a href="https://anoma.ly">Anomaly</a>
</span>
</div>
)
}

View File

@@ -0,0 +1,28 @@
import { query } from "@solidjs/router"
export const github = query(async () => {
"use server"
try {
const [meta, releases, contributors] = await Promise.all([
fetch("https://api.github.com/repos/sst/opencode").then((res) => res.json()),
fetch("https://api.github.com/repos/sst/opencode/releases").then((res) => res.json()),
fetch("https://api.github.com/repos/sst/opencode/contributors?per_page=1"),
])
const [release] = releases
const contributorCount = Number.parseInt(
contributors.headers
.get("Link")!
.match(/&page=(\d+)>; rel="last"/)!
.at(1)!,
)
return {
stars: meta.stargazers_count,
release: {
name: release.name,
url: release.html_url,
},
contributors: contributorCount,
}
} catch {}
return undefined
}, "github")

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,183 @@
import "./index.css"
import { Title } from "@solidjs/meta"
import { onCleanup, onMount } from "solid-js"
import logoLight from "../asset/logo-ornate-light.svg"
import logoDark from "../asset/logo-ornate-dark.svg"
import IMG_SPLASH from "../asset/lander/screenshot-splash.png"
import { IconCopy, IconCheck } from "../component/icon"
import { createAsync, query } from "@solidjs/router"
import { getActor } from "~/context/auth"
import { withActor } from "~/context/auth.withActor"
import { Account } from "@opencode/console-core/account.js"
function CopyStatus() {
return (
<div data-component="copy-status">
<IconCopy data-slot="copy" />
<IconCheck data-slot="check" />
</div>
)
}
const defaultWorkspace = query(async () => {
"use server"
const actor = await getActor()
if (actor.type === "account") {
const workspaces = await withActor(() => Account.workspaces())
return workspaces[0].id
}
}, "defaultWorkspace")
export default function Home() {
const workspace = createAsync(() => defaultWorkspace())
onMount(() => {
const commands = document.querySelectorAll("[data-copy]")
for (const button of commands) {
const callback = () => {
const text = button.textContent
if (text) {
navigator.clipboard.writeText(text)
button.setAttribute("data-copied", "")
setTimeout(() => {
button.removeAttribute("data-copied")
}, 1500)
}
}
button.addEventListener("click", callback)
onCleanup(() => {
button.removeEventListener("click", callback)
})
}
})
return (
<main data-page="home">
<Title>opencode | AI coding agent built for the terminal</Title>
<div data-component="content">
<section data-component="top">
<img data-slot="logo light" src={logoLight} alt="opencode logo light" />
<img data-slot="logo dark" src={logoDark} alt="opencode logo dark" />
<h1 data-slot="title">The AI coding agent built for the terminal</h1>
<div data-slot="login">
<a href="/auth">opencode zen</a>
</div>
</section>
<section data-component="cta">
<div data-slot="left">
<a href="/docs">Get Started</a>
</div>
<div data-slot="center">
<a href="/auth">opencode zen</a>
</div>
<div data-slot="right">
<button data-copy data-slot="command">
<span>
<span>curl -fsSL </span>
<span data-slot="protocol">https://</span>
<span data-slot="highlight">opencode.ai/install</span>
<span> | bash</span>
</span>
<CopyStatus />
</button>
</div>
</section>
<section data-component="features">
<ul data-slot="list">
<li>
<strong>Native TUI</strong> A responsive, native, themeable terminal UI
</li>
<li>
<strong>LSP enabled</strong> Automatically loads the right LSPs for the LLM
</li>
<li>
<strong>opencode zen</strong> A <a href="/docs/zen">curated list of models</a> provided by opencode{" "}
<label>New</label>
</li>
<li>
<strong>Multi-session</strong> Start multiple agents in parallel on the same project
</li>
<li>
<strong>Shareable links</strong> Share a link to any sessions for reference or to debug
</li>
<li>
<strong>Claude Pro</strong> Log in with Anthropic to use your Claude Pro or Max account
</li>
<li>
<strong>Use any model</strong> Supports 75+ LLM providers through{" "}
<a href="https://models.dev">Models.dev</a>, including local models
</li>
</ul>
</section>
<section data-component="install">
<div data-component="method">
<h3 data-component="title">npm</h3>
<button data-copy data-slot="button">
<span>
npm install -g <strong>opencode-ai</strong>
</span>
<CopyStatus />
</button>
</div>
<div data-component="method">
<h3 data-component="title">bun</h3>
<button data-copy data-slot="button">
<span>
bun install -g <strong>opencode-ai</strong>
</span>
<CopyStatus />
</button>
</div>
<div data-component="method">
<h3 data-component="title">homebrew</h3>
<button data-copy data-slot="button">
<span>
brew install <strong>sst/tap/opencode</strong>
</span>
<CopyStatus />
</button>
</div>
<div data-component="method">
<h3 data-component="title">paru</h3>
<button data-copy data-slot="button">
<span>
paru -S <strong>opencode-bin</strong>
</span>
<CopyStatus />
</button>
</div>
</section>
<section data-component="screenshots">
<figure>
<figcaption>opencode TUI with the tokyonight theme</figcaption>
<a href="/docs/cli">
<img src={IMG_SPLASH} alt="opencode TUI with tokyonight theme" />
</a>
</figure>
</section>
<footer data-component="footer">
<div data-slot="cell">
<a href="https://x.com/opencode">X.com</a>
</div>
<div data-slot="cell">
<a href="https://github.com/sst/opencode">GitHub</a>
</div>
<div data-slot="cell">
<a href="https://opencode.ai/discord">Discord</a>
</div>
</footer>
</div>
<div data-component="legal">
<span>
©2025 <a href="https://anoma.ly">Anomaly</a>
</span>
</div>
</main>
)
}

View File

@@ -0,0 +1,781 @@
::selection {
background: var(--color-background-interactive);
color: var(--color-text-strong);
@media (prefers-color-scheme: dark) {
background: var(--color-background-interactive);
color: var(--color-text-inverted);
}
}
[data-page="zen"] {
--color-background: hsl(0, 20%, 99%);
--color-background-weak: hsl(0, 8%, 97%);
--color-background-strong: hsl(0, 5%, 12%);
--color-background-strong-hover: hsl(0, 5%, 18%);
--color-background-interactive: hsl(62, 84%, 88%);
--color-background-interactive-weaker: hsl(64, 74%, 95%);
--color-text: hsl(0, 1%, 39%);
--color-text-weak: hsl(0, 1%, 74%);
--color-text-weaker: hsl(30, 2%, 81%);
--color-text-strong: hsl(0, 5%, 12%);
--color-text-inverted: hsl(0, 20%, 99%);
--color-border: hsl(30, 2%, 81%);
--color-border-weak: hsl(0, 1%, 85%);
--color-icon: hsl(0, 1%, 55%);
}
[data-page="zen"] {
@media (prefers-color-scheme: dark) {
--color-background: hsl(0, 9%, 7%);
--color-background-weak: hsl(0, 6%, 10%);
--color-background-strong: hsl(0, 15%, 94%);
--color-background-strong-hover: hsl(0, 15%, 97%);
--color-background-interactive: hsl(62, 100%, 90%);
--color-background-interactive-weaker: hsl(60, 20%, 8%);
--color-text: hsl(0, 4%, 71%);
--color-text-weak: hsl(0, 2%, 49%);
--color-text-weaker: hsl(0, 3%, 28%);
--color-text-strong: hsl(0, 15%, 94%);
--color-text-inverted: hsl(0, 9%, 7%);
--color-border: hsl(0, 3%, 28%);
--color-border-weak: hsl(0, 4%, 23%);
--color-icon: hsl(10, 3%, 43%);
}
}
[data-page="zen"] {
background: var(--color-background);
--padding: 5rem;
--vertical-padding: 4rem;
border-top: 1px solid var(--color-border-weak);
@media (max-width: 60rem) {
--padding: 1.5rem;
--vertical-padding: 3rem;
}
display: flex;
gap: var(--vertical-padding);
flex-direction: column;
font-family: var(--font-mono);
color: var(--color-text);
padding-bottom: 5rem;
a {
color: var(--color-text-strong);
text-decoration: underline;
text-underline-offset: var(--space-1);
text-decoration-thickness: 1px;
}
p {
line-height: 200%;
}
@media (max-width: 60rem) {
font-size: 15px;
}
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
transition: background-color 5000000s ease-in-out 0s;
}
[data-component="container"] {
max-width: 67.5rem;
margin: 0 auto;
border: 1px solid var(--color-border-weak);
border-top: none;
@media (max-width: 65rem) {
border: none;
}
}
[data-component="content"] {
}
[data-component="top"] {
padding: 24px var(--padding);
height: 80px;
position: sticky;
top: 0;
display: flex;
justify-content: space-between;
align-items: center;
background: var(--color-background);
border-bottom: 1px solid var(--color-border-weak);
z-index: 10;
img {
height: 34px;
width: auto;
}
[data-component="nav-desktop"] {
ul {
display: flex;
justify-content: space-between;
gap: 48px;
li {
display: inline-block;
a {
text-decoration: none;
span {
color: var(--color-text-weak);
}
}
a:hover {
text-decoration: underline;
text-underline-offset: var(--space-1);
text-decoration-thickness: 1px;
}
}
}
@media (max-width: 40rem) {
display: none;
}
}
[data-component="nav-mobile-toggle"] {
border: none;
background: none;
outline: none;
height: 40px;
width: 40px;
cursor: pointer;
}
[data-component="nav-mobile-toggle"]:hover {
background: var(--color-background-weak);
}
[data-component="nav-mobile"] {
display: none;
@media (max-width: 40rem) {
display: block;
[data-component="nav-mobile-icon"] {
cursor: pointer;
height: 40px;
width: 40px;
display: flex;
align-items: center;
justify-content: center;
}
[data-component="nav-mobile-menu-list"] {
position: fixed;
background: var(--color-background);
top: 80px;
left: 0;
right: 0;
height: 100vh;
ul {
list-style: none;
padding: 20px 0;
li {
a {
text-decoration: none;
padding: 20px;
display: block;
span {
color: var(--color-text-weak);
}
}
a:hover {
background: var(--color-background-weak);
}
}
}
}
}
}
[data-slot="logo dark"] {
display: none;
}
@media (prefers-color-scheme: dark) {
[data-slot="logo light"] {
display: none;
}
[data-slot="logo dark"] {
display: block;
}
}
}
[data-component="hero"] {
display: flex;
flex-direction: column;
padding: calc(var(--vertical-padding)*2) var(--padding);
[data-slot="zen logo dark"] {
display: none;
}
@media (max-width: 30rem) {
padding: var(--vertical-padding) var(--padding)
}
@media (prefers-color-scheme: dark) {
[data-slot="zen logo light"] {
display: none;
}
[data-slot="zen logo dark"] {
display: block;
}
}
}
[data-slot="hero-copy"] {
img {
margin-bottom: 24px;
}
strong {
font-size: 28px;
color: var(--color-text-strong);
font-weight: 500;
margin-bottom: 16px;
display: block;
@media (max-width: 60rem) {
font-size: 22px;
}
}
p {
color: var(--color-text);
margin-bottom: 24px;
max-width: 82%;
@media (max-width: 50rem) {
max-width: 100%;
}
}
a {
background: var(--color-background-strong);
padding: 8px 12px 8px 20px;
color: var(--color-text-inverted);
border: none;
border-radius: 4px;
font-weight: 500;
cursor: pointer;
margin-bottom: 56px;
display: flex;
width: fit-content;
gap: 12px;
text-decoration: none;
}
a:hover {
background: var(--color-background-strong-hover);
}
}
[data-slot="model-logos"] {
display: flex;
gap: 24px;
margin-bottom: 56px;
svg {
color: var(--color-background-strong);
}
@media (prefers-color-scheme: dark) {
svg {
color: var(--color-background-strong);
}
}
}
[data-slot="pricing-copy"] {
strong {
color: var(--color-text-strong);
font-weight: 500;
}
p:first-child {
margin-bottom: 24px;
color: var(--color-text);
display: flex;
gap: 8px;
@media (max-width: 40rem) {
flex-direction: column;
gap: 4px;
}
}
}
[data-component="comparison"] {
border-top: 1px solid var(--color-border-weak);
video {
width: 100%;
height: auto;
max-width: none;
max-height: none;
display: block;
}
}
[data-slot="section-title"] {
margin-bottom: 24px;
h3 {
font-size: 16px;
font-weight: 500;
color: var(--color-text-strong);
margin-bottom: 12px;
}
p {
margin-bottom: 12px;
color: var(--color-text);
}
}
[data-component="problem"] {
border-top: 1px solid var(--color-border-weak);
padding: var(--vertical-padding) var(--padding);
color: var(--color-text);
p {
margin-bottom: 24px;
}
ul {
padding: 0;
li {
list-style: none;
margin-bottom: 16px;
display: flex;
gap: 12px;
span {
color: var(--color-icon);
}
}
li:last-child {
margin-bottom: 0;
}
}
}
[data-component="how"] {
border-top: 1px solid var(--color-border-weak);
padding: var(--vertical-padding) var(--padding);
color: var(--color-text);
ul {
padding: 0;
li {
list-style: none;
margin-bottom: 16px;
display: flex;
gap: 12px;
span {
color: var(--color-icon);
}
strong {
font-weight: 500;
color: var(--color-text-strong);
}
}
li:last-child {
margin-bottom: 0;
}
}
}
[data-component="privacy"] {
border-top: 1px solid var(--color-border-weak);
padding: var(--vertical-padding) var(--padding);
color: var(--color-text);
[data-slot="privacy-title"] {
h3 {
font-size: 16px;
font-weight: 500;
color: var(--color-text);
margin-bottom: 12px;
}
div {
display: flex;
gap: 12px;
}
p {
}
span {
color: var(--color-icon);
line-height: 200%;
}
div {
display: flex;
gap: 12px;
}
}
}
[data-component="email"] {
border-top: 1px solid var(--color-border-weak);
padding: var(--vertical-padding) var(--padding);
color: var(--color-text);
[data-slot="dock"] {
border-radius: 14px;
border: 0.5px solid rgba(176, 176, 176, 0.6);
background: #f2f1f0;
margin-bottom: 32px;
overflow: hidden;
height: 64px;
width: 185px;
box-shadow:
0 6px 80px 0 rgba(0, 0, 0, 0.05),
0 2.507px 33.422px 0 rgba(0, 0, 0, 0.04),
0 1.34px 17.869px 0 rgba(0, 0, 0, 0.03),
0 0.751px 10.017px 0 rgba(0, 0, 0, 0.03),
0 0.399px 5.32px 0 rgba(0, 0, 0, 0.02),
0 0.166px 2.214px 0 rgba(0, 0, 0, 0.01);
img {
width: 100%;
height: auto;
}
@media (prefers-color-scheme: dark) {
background: #312d2d;
}
}
[data-slot="form"] {
position: relative;
input {
background: var(--color-background-weak);
border-radius: 6px;
border: 1px solid var(--color-border-weak);
padding: 20px;
display: flex;
flex-direction: column;
gap: 12px;
width: 100%;
@media (max-width: 30rem) {
padding-bottom: 80px;
}
}
input:focus {
background: var(--color-background-interactive-weaker);
outline: none;
border: none;
color: var(--color-text-strong);
border: 1px solid var(--color-background-strong); /* Tailwind blue-600 as example */
/* Tailwind-style ring */
box-shadow: 0 0 0 3px var(--color-background-interactive);
/* mimics "ring-2 ring-blue-600/50" */
}
button {
position: absolute;
height: 40px;
right: 12px;
background: var(--color-background-strong);
padding: 4px 20px;
color: var(--color-text-inverted);
border-radius: 4px;
font-weight: 500;
cursor: pointer;
top: 50%;
margin-top: -20px;
@media (max-width: 30rem) {
left: 20px;
right: 20px;
bottom: 20px;
top: auto;
}
}
}
}
[data-component="faq"] {
border-top: 1px solid var(--color-border-weak);
padding: var(--vertical-padding) var(--padding);
ul {
padding: 0;
li {
list-style: none;
margin-bottom: 24px;
line-height: 200%;
}
}
[data-slot="faq-question"] {
display: flex;
gap: 16px;
margin-bottom: 8px;
color: var(--color-text-strong);
font-weight: 500;
cursor: pointer;
background: none;
border: none;
padding: 0;
[data-slot="faq-icon-plus"] {
flex-shrink: 0;
[data-closed] & {
display: block;
}
[data-expanded] & {
display: none;
}
}
[data-slot="faq-icon-minus"] {
flex-shrink: 0;
[data-closed] & {
display: none;
}
[data-expanded] & {
display: block;
}
}
[data-slot="faq-question-text"] {
flex-grow: 1;
text-align: left;
}
}
[data-slot="faq-answer"] {
margin-left: 40px;
margin-bottom: 32px;
}
}
[data-component="testimonials"] {
border-top: 1px solid var(--color-border-weak);
padding: var(--vertical-padding) var(--padding);
display: flex;
flex-direction: column;
gap: 20px;
@media (max-width: 60rem) {
--padding: 1rem;
--vertical-padding: 1rem;
}
a {
text-decoration: none;
}
[data-slot="testimonial"] {
background: var(--color-background-weak);
border-radius: 6px;
border: 1px solid var(--color-border-weak);
padding: 20px;
display: flex;
flex-direction: column;
gap: 12px;
@media (max-width: 60rem) {
flex-direction: column-reverse;
gap: 24px;
padding: 24px 48px;
}
[data-slot="name"] {
display: flex;
gap: 16px;
strong {
font-weight: 500;
}
span {
color: var(--color-text);
}
@media (max-width: 60rem) {
flex-direction: column;
gap: 8px;
}
span {
display: inline-block;
}
img {
height: 24px;
width: 24px;
border-radius: 24px;
}
}
[data-slot="quote"] {
margin-left: 40px;
@media (max-width: 60rem) {
margin-left: 0;
}
span {
color: var(--color-text);
text-decoration: none;
}
}
}
[data-slot="button"] {
all: unset;
cursor: pointer;
display: flex;
align-items: center;
color: var(--color-text);
gap: var(--space-2-5);
font-size: 1rem;
@media (max-width: 24rem) {
font-size: 0.875rem;
}
strong {
color: var(--color-text-strong);
font-weight: 500;
}
@media (max-width: 40rem) {
justify-content: flex-start;
}
@media (max-width: 30rem) {
justify-content: center;
}
}
}
[data-component="copy-status"] {
@media (max-width: 38rem) {
display: none;
}
[data-slot="copy"] {
display: block;
width: var(--space-4);
height: var(--space-4);
color: var(--color-text-weaker);
[data-copied] & {
display: none;
}
}
[data-slot="check"] {
display: none;
width: var(--space-4);
height: var(--space-4);
color: var(--color-text-strong);
[data-copied] & {
display: block;
}
}
}
[data-component="footer"] {
border-top: 1px solid var(--color-border-weak);
display: flex;
flex-direction: row;
@media (max-width: 65rem) {
border-bottom: 1px solid var(--color-border-weak);
}
[data-slot="cell"] {
flex: 1;
text-align: center;
a {
text-decoration: none;
padding: 2rem 0;
width: 100%;
display: block;
span {
color: var(--color-text-weak);
@media (max-width: 40rem) {
display: none;
}
}
}
a:hover {
background: var(--color-background-weak);
text-decoration: underline;
text-underline-offset: var(--space-1);
text-decoration-thickness: 1px;
}
}
[data-slot="cell"] + [data-slot="cell"] {
border-left: 1px solid var(--color-border-weak);
}
/* Mobile: third column on its own row */
@media (max-width: 25rem) {
flex-wrap: wrap;
[data-slot="cell"] {
flex: 1 0 100%;
border-left: none;
border-top: 1px solid var(--color-border-weak);
}
[data-slot="cell"]:nth-child(1) {
border-top: none;
}
}
}
[data-component="legal"] {
color: var(--color-text-weak);
text-align: center;
a {
color: var(--color-text-weak);
text-decoration: none;
}
}
}

View File

@@ -0,0 +1,339 @@
import "./index.css"
import { Title, Meta, Link } from "@solidjs/meta"
import { HttpHeader } from "@solidjs/start"
import zenLogoLight from "../../asset/zen-ornate-light.svg"
import zenLogoDark from "../../asset/zen-ornate-dark.svg"
import compareVideo from "../../asset/lander/opencode-comparison-min.mp4"
import compareVideoPoster from "../../asset/lander/opencode-comparison-poster.png"
import avatarDax from "../../asset/lander/avatar-dax.png"
import avatarJay from "../../asset/lander/avatar-Jay.png"
import avatarFrank from "../../asset/lander/avatar-Frank.png"
import avatarAdam from "../../asset/lander/avatar-Adam.png"
import avatarDavid from "../../asset/lander/avatar-David.png"
import { A, createAsync, query } from "@solidjs/router"
import { getActor } from "~/context/auth"
import { withActor } from "~/context/auth.withActor"
import { Account } from "@opencode/console-core/account.js"
import { EmailSignup } from "~/component/email-signup"
import { Faq } from "~/component/faq"
import { Legal } from "~/component/legal"
import { Footer } from "~/component/footer"
import { Header } from "~/component/header"
const defaultWorkspace = query(async () => {
"use server"
const actor = await getActor()
if (actor.type === "account") {
const workspaces = await withActor(() => Account.workspaces())
return workspaces[0].id
}
}, "defaultWorkspace")
export default function Home() {
const workspace = createAsync(() => defaultWorkspace())
return (
<main data-page="zen">
<HttpHeader name="Cache-Control" value="public, max-age=1, s-maxage=3600, stale-while-revalidate=86400" />
<Title>OpenCode Zen | A curated set of reliable optimized models for coding agents</Title>
<Link rel="icon" type="image/svg+xml" href="/favicon-zen.svg" />
<Meta property="og:image" content="/social-share-zen.png" />
<Meta name="twitter:image" content="/social-share-zen.png" />
<div data-component="container">
<Header zen />
<div data-component="content">
<section data-component="hero">
<div data-slot="hero-copy">
<img data-slot="zen logo light" src={zenLogoLight} alt="zen logo light" />
<img data-slot="zen logo dark" src={zenLogoDark} alt="zen logo dark" />
<strong>Reliable optimized models for coding agents</strong>
<p>
Zen gives you access to a curated set of AI models that OpenCode has tested and benchmarked specifically
for coding agents. No need to worry about inconsistent performance and quality, use validated models
that work.
</p>
<div data-slot="model-logos">
<div>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask
id="mask0_79_128586"
style="mask-type:luminance"
maskUnits="userSpaceOnUse"
x="1"
y="1"
width="22"
height="22"
>
<path d="M23 1.5H1V22.2952H23V1.5Z" fill="white" />
</mask>
<g mask="url(#mask0_79_128586)">
<path
d="M9.43799 9.06943V7.09387C9.43799 6.92749 9.50347 6.80267 9.65601 6.71959L13.8206 4.43211C14.3875 4.1202 15.0635 3.9747 15.7611 3.9747C18.3775 3.9747 20.0347 5.9087 20.0347 7.96734C20.0347 8.11288 20.0347 8.27926 20.0128 8.44564L15.6956 6.03335C15.434 5.88785 15.1723 5.88785 14.9107 6.03335L9.43799 9.06943ZM19.1624 16.7637V12.0431C19.1624 11.7519 19.0315 11.544 18.7699 11.3984L13.2972 8.36234L15.0851 7.3849C15.2377 7.30182 15.3686 7.30182 15.5212 7.3849L19.6858 9.67238C20.8851 10.3379 21.6917 11.7519 21.6917 13.1243C21.6917 14.7047 20.7106 16.1604 19.1624 16.7636V16.7637ZM8.15158 12.6047L6.36369 11.6066C6.21114 11.5235 6.14566 11.3986 6.14566 11.2323V6.65735C6.14566 4.43233 7.93355 2.7478 10.3538 2.7478C11.2697 2.7478 12.1199 3.039 12.8396 3.55886L8.54424 5.92959C8.28268 6.07508 8.15181 6.28303 8.15181 6.57427V12.6049L8.15158 12.6047ZM12 14.7258L9.43799 13.3533V10.4421L12 9.06965L14.5618 10.4421V13.3533L12 14.7258ZM13.6461 21.0476C12.7303 21.0476 11.8801 20.7564 11.1604 20.2366L15.4557 17.8658C15.7173 17.7203 15.8482 17.5124 15.8482 17.2211V11.1905L17.658 12.1886C17.8105 12.2717 17.876 12.3965 17.876 12.563V17.1379C17.876 19.3629 16.0662 21.0474 13.6461 21.0474V21.0476ZM8.47863 16.4103L4.314 14.1229C3.11471 13.4573 2.30808 12.0433 2.30808 10.6709C2.30808 9.06965 3.31106 7.6348 4.85903 7.03168V11.773C4.85903 12.0642 4.98995 12.2721 5.25151 12.4177L10.7025 15.4328L8.91464 16.4103C8.76209 16.4934 8.63117 16.4934 8.47863 16.4103ZM8.23892 19.8207C5.77508 19.8207 3.96533 18.0531 3.96533 15.8696C3.96533 15.7032 3.98719 15.5368 4.00886 15.3704L8.30418 17.7412C8.56574 17.8867 8.82752 17.8867 9.08909 17.7412L14.5618 14.726V16.7015C14.5618 16.8679 14.4964 16.9927 14.3438 17.0758L10.1792 19.3633C9.61225 19.6752 8.93631 19.8207 8.23869 19.8207H8.23892ZM13.6461 22.2952C16.2844 22.2952 18.4865 20.5069 18.9882 18.1362C21.4301 17.5331 23 15.3495 23 13.1245C23 11.6688 22.346 10.2548 21.1685 9.23581C21.2775 8.79908 21.343 8.36234 21.343 7.92582C21.343 4.95215 18.8137 2.72691 15.892 2.72691C15.3034 2.72691 14.7365 2.80999 14.1695 2.99726C13.1882 2.08223 11.8364 1.5 10.3538 1.5C7.71557 1.5 5.51352 3.28829 5.01185 5.65902C2.56987 6.26214 1 8.44564 1 10.6707C1 12.1264 1.65404 13.5404 2.83147 14.5594C2.72246 14.9961 2.65702 15.4328 2.65702 15.8694C2.65702 18.8431 5.1863 21.0683 8.108 21.0683C8.69661 21.0683 9.26354 20.9852 9.83046 20.7979C10.8115 21.713 12.1634 22.2952 13.6461 22.2952Z"
fill="currentColor"
/>
</g>
</svg>
</div>
<div>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.7891 3.93164L20.2223 20.0677H23.7502L17.317 3.93164H13.7891Z" fill="currentColor" />
<path
d="M6.32538 13.6824L8.52662 8.01177L10.7279 13.6824H6.32538ZM6.68225 3.93164L0.25 20.0677H3.84652L5.16202 16.6791H11.8914L13.2067 20.0677H16.8033L10.371 3.93164H6.68225Z"
fill="currentColor"
/>
</svg>
</div>
<div>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M9.16861 16.0529L17.2018 9.85156C17.5957 9.54755 18.1586 9.66612 18.3463 10.1384C19.3339 12.6288 18.8926 15.6217 16.9276 17.6766C14.9626 19.7314 12.2285 20.1821 9.72948 19.1557L6.9995 20.4775C10.9151 23.2763 15.6699 22.5841 18.6411 19.4749C20.9979 17.0103 21.7278 13.6508 21.0453 10.6214L21.0515 10.6278C20.0617 6.17736 21.2948 4.39847 23.8207 0.760904C23.8804 0.674655 23.9402 0.588405 24 0.5L20.6762 3.97585V3.96506L9.16658 16.0551"
fill="currentColor"
/>
<path
d="M7.37742 16.7017C4.67579 14.0395 5.14158 9.91963 7.44676 7.54383C9.15135 5.78544 11.9442 5.06779 14.3821 6.12281L17.0005 4.87559C16.5288 4.52392 15.9242 4.14566 15.2305 3.87986C12.0948 2.54882 8.34069 3.21127 5.79171 5.8386C3.33985 8.36779 2.56881 12.2567 3.89286 15.5751C4.88192 18.0552 3.26056 19.8094 1.62731 21.5801C1.04853 22.2078 0.467774 22.8355 0 23.5L7.3754 16.7037"
fill="currentColor"
/>
</svg>
</div>
<div>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M12.6043 1.34016C12.9973 2.03016 13.3883 2.72215 13.7783 3.41514C13.7941 3.44286 13.8169 3.46589 13.8445 3.48187C13.8721 3.49786 13.9034 3.50624 13.9353 3.50614H19.4873C19.6612 3.50614 19.8092 3.61614 19.9332 3.83314L21.3872 6.40311C21.5772 6.74011 21.6272 6.88111 21.4112 7.24011C21.1512 7.6701 20.8982 8.1041 20.6512 8.54009L20.2842 9.19809C20.1782 9.39409 20.0612 9.47809 20.2442 9.71008L22.8962 14.347C23.0682 14.648 23.0072 14.841 22.8532 15.117C22.4162 15.902 21.9712 16.681 21.5182 17.457C21.3592 17.729 21.1662 17.832 20.8382 17.827C20.0612 17.811 19.2863 17.817 18.5113 17.843C18.4946 17.8439 18.4785 17.8489 18.4644 17.8576C18.4502 17.8664 18.4385 17.8785 18.4303 17.893C17.5361 19.4773 16.6344 21.0573 15.7253 22.633C15.5563 22.926 15.3453 22.996 15.0003 22.997C14.0033 23 12.9983 23.001 11.9833 22.999C11.8889 22.9987 11.7961 22.9735 11.7145 22.9259C11.6328 22.8783 11.5652 22.8101 11.5184 22.728L10.1834 20.405C10.1756 20.3898 10.1637 20.3771 10.149 20.3684C10.1343 20.3598 10.1174 20.3554 10.1004 20.356H4.98244C4.69744 20.386 4.42944 20.355 4.17745 20.264L2.57447 17.494C2.52706 17.412 2.50193 17.319 2.50158 17.2243C2.50123 17.1296 2.52567 17.0364 2.57247 16.954L3.77945 14.834C3.79665 14.8041 3.80569 14.7701 3.80569 14.7355C3.80569 14.701 3.79665 14.667 3.77945 14.637C3.15073 13.5485 2.52573 12.4579 1.90448 11.3651L1.11449 9.97008C0.954488 9.66008 0.941489 9.47409 1.20949 9.00509C1.67448 8.1921 2.13647 7.38011 2.59647 6.56911C2.72847 6.33512 2.90046 6.23512 3.18046 6.23412C4.04344 6.23048 4.90644 6.23015 5.76943 6.23312C5.79123 6.23295 5.81259 6.22704 5.83138 6.21597C5.85016 6.20491 5.8657 6.1891 5.87643 6.17012L8.68239 1.27516C8.72491 1.2007 8.78631 1.13875 8.86039 1.09556C8.93448 1.05238 9.01863 1.02948 9.10439 1.02917C9.62838 1.02817 10.1574 1.02917 10.6874 1.02317L11.7044 1.00017C12.0453 0.997165 12.4283 1.03217 12.6043 1.34016ZM9.17238 1.74316C9.16185 1.74315 9.15149 1.74592 9.14236 1.75119C9.13323 1.75645 9.12565 1.76403 9.12038 1.77316L6.25442 6.78811C6.24066 6.81174 6.22097 6.83137 6.19729 6.84505C6.17361 6.85873 6.14677 6.86599 6.11942 6.86611H3.25346C3.19746 6.86611 3.18346 6.89111 3.21246 6.94011L9.02239 17.096C9.04739 17.138 9.03539 17.158 8.98839 17.159L6.19342 17.174C6.15256 17.1727 6.11214 17.1828 6.07678 17.2033C6.04141 17.2238 6.01253 17.2539 5.99342 17.29L4.67344 19.6C4.62944 19.678 4.65244 19.718 4.74144 19.718L10.4574 19.726C10.5034 19.726 10.5374 19.746 10.5614 19.787L11.9643 22.241C12.0103 22.322 12.0563 22.323 12.1033 22.241L17.1093 13.481L17.8923 12.0991C17.897 12.0905 17.904 12.0834 17.9125 12.0785C17.9209 12.0735 17.9305 12.0709 17.9403 12.0709C17.9501 12.0709 17.9597 12.0735 17.9681 12.0785C17.9765 12.0834 17.9835 12.0905 17.9883 12.0991L19.4123 14.629C19.4229 14.648 19.4385 14.6637 19.4573 14.6746C19.4761 14.6855 19.4975 14.6912 19.5193 14.691L22.2822 14.671C22.2893 14.6711 22.2963 14.6693 22.3024 14.6658C22.3086 14.6623 22.3137 14.6572 22.3172 14.651C22.3206 14.6449 22.3224 14.638 22.3224 14.631C22.3224 14.624 22.3206 14.6172 22.3172 14.611L19.4173 9.52508C19.4068 9.50809 19.4013 9.48853 19.4013 9.46859C19.4013 9.44864 19.4068 9.42908 19.4173 9.41209L19.7102 8.90509L20.8302 6.92811C20.8542 6.88711 20.8422 6.86611 20.7952 6.86611H9.20038C9.14138 6.86611 9.12738 6.84011 9.15738 6.78911L10.5914 4.28413C10.6021 4.26706 10.6078 4.24731 10.6078 4.22714C10.6078 4.20697 10.6021 4.18721 10.5914 4.17014L9.22538 1.77416C9.22016 1.7647 9.21248 1.75682 9.20315 1.75137C9.19382 1.74591 9.18319 1.74307 9.17238 1.74316ZM15.4623 9.76308C15.5083 9.76308 15.5203 9.78308 15.4963 9.82308L14.6643 11.2881L12.0513 15.873C12.0464 15.8819 12.0392 15.8894 12.0304 15.8945C12.0216 15.8996 12.0115 15.9022 12.0013 15.902C11.9912 15.902 11.9813 15.8993 11.9725 15.8942C11.9637 15.8891 11.9564 15.8818 11.9513 15.873L8.49839 9.84108C8.47839 9.80708 8.48839 9.78908 8.52639 9.78708L8.74239 9.77508L15.4643 9.76308H15.4623Z"
fill="currentColor"
/>
</svg>
</div>
<div>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M12.6241 11.346L20.3848 3.44816C20.5309 3.29931 20.4487 3 20.2601 3H16.0842C16.0388 3 15.9949 3.01897 15.9594 3.05541L7.59764 11.5629C7.46721 11.6944 7.27446 11.5771 7.27446 11.3666V3.25183C7.27446 3.11242 7.18515 3 7.07594 3H4.19843C4.08932 3 4 3.11242 4 3.25183V20.7482C4 20.8876 4.08932 21 4.19843 21H7.07594C7.18515 21 7.27446 20.8876 7.27446 20.7482V17.1834C7.27446 17.1073 7.30136 17.0344 7.34815 16.987L9.94075 14.3486C10.0031 14.2853 10.0895 14.2757 10.159 14.3232L17.0934 19.5573C18.2289 20.3412 19.4975 20.8226 20.786 20.9652C20.9008 20.9778 21 20.8606 21 20.7133V17.3559C21 17.2276 20.9249 17.1232 20.8243 17.1073C20.0659 16.9853 19.326 16.6845 18.6569 16.222L12.6538 11.764C12.5291 11.6785 12.5135 11.4584 12.6241 11.346Z"
fill="currentColor"
/>
</svg>
</div>
</div>
<A href="/auth">
<span>Get started with Zen </span>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M6.5 12L17 12M13 16.5L17.5 12L13 7.5"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="square"
/>
</svg>
</A>
</div>
<div data-slot="pricing-copy">
<p>
<strong>Add $20 Pay as you go balance</strong> <span>(+$1.23 card processing fee)</span>
</p>
<p>Use with any agent. Set monthly spend limits. Cancel any time.</p>
</div>
</section>
<section data-component="comparison">
<video src={compareVideo} autoplay playsinline loop muted preload="auto" poster={compareVideoPoster}>
Your browser does not support the video tag.
</video>
</section>
<section data-component="problem">
<div data-slot="section-title">
<h3>What problem is Zen solving?</h3>
<p>
There are so many models available, but only a few work well with coding agents.
<br />
Most providers configure them differently with varying results.
</p>
</div>
<p>We're fixing this for everyone, not just OpenCode users.</p>
<ul>
<li>
<span>[*]</span> Testing select models and consulting their teams
</li>
<li>
<span>[*]</span> Working with providers to ensure theyre delivered properly
</li>
<li>
<span>[*]</span> Benchmarking all model-provider combinations we recommend
</li>
</ul>
</section>
<section data-component="how">
<div data-slot="section-title">
<h3>How Zen works</h3>
<p>While we suggest you use Zen with OpenCode, you can use Zen with any agent.</p>
</div>
<ul>
<li>
<span>[1]</span>
<div>
<strong>Sign up and add $20 balance</strong> - follow the{" "}
<a href="/docs/zen/#how-it-works" title="setup instructions">
setup instructions
</a>
</div>
</li>
<li>
<span>[2]</span>
<div>
<strong>Use Zen with transparent pricing</strong> - <a href="/docs/zen/#pricing">pay per request</a> with zero markups
</div>
</li>
<li>
<span>[3]</span>
<div>
<strong>Auto-top up</strong> - when your balance reaches $5 well automatically add $20
</div>
</li>
</ul>
</section>
<section data-component="privacy">
<div data-slot="privacy-title">
<h3>Your privacy is important to us</h3>
<div>
<span>[*]</span>
<p>
All Zen models are hosted in the US. Providers follow a zero-retention policy and do not use your data
for model training, with the <a href="/docs/zen/#privacy">following exceptions</a>.
</p>
</div>
</div>
</section>
<section data-component="testimonials">
{/*Dax*/}
<a href="https://x.com/iamdavidhill/status/1971693263498141817">
<div data-slot="testimonial">
<div data-slot="name">
<img src={avatarDax} alt="" />
<strong>Dax Raad</strong>
<span>ex-CEO, Terminal Products</span>
</div>
<div data-slot="quote">
It's clear from using <span>@OpenCode</span> Zen that the team behind it are smart, funny, and
excellent lovers.
</div>
</div>
</a>
{/*Jay*/}
<a href="https://x.com/iamdavidhill/status/1971693263498141817">
<div data-slot="testimonial">
<div data-slot="name">
<img src={avatarJay} alt="" />
<strong>Jay V</strong>
<span>ex-Founder, SEED, PM, Melt, Pop, Dapt, Cadmus, and ViewPoint</span>
</div>
<div data-slot="quote">
4 out 5 people on our team love using <span>@OpenCode</span> Zen.
</div>
</div>
</a>
{/*Adam*/}
<a href="https://x.com/iamdavidhill/status/1971693263498141817">
<div data-slot="testimonial">
<div data-slot="name">
<img src={avatarAdam} alt="" />
<strong>Adam Elmore</strong>
<span>ex-Hero, AWS</span>
</div>
<div data-slot="quote">
I can't recommend <span>@OpenCode</span> Zen enough. Seriously, its really good.
</div>
</div>
</a>
{/*David*/}
<a href="https://x.com/iamdavidhill/status/1971693263498141817">
<div data-slot="testimonial">
<div data-slot="name">
<img src={avatarDavid} alt="" />
<strong>David Hill</strong>
<span>ex-Head of Design, Laravel</span>
</div>
<div data-slot="quote">
With <span>@OpenCode</span> Zen I know all the models are tested and perfect for coding agents.
</div>
</div>
</a>
{/*Frank*/}
<a href="https://x.com/iamdavidhill/status/1971693263498141817">
<div data-slot="testimonial">
<div data-slot="name">
<img src={avatarFrank} alt="" />
<strong>Frank Wang</strong>
<span>ex-Intern, Nvidia (4 times)</span>
</div>
<div data-slot="quote">I wish I was still at Nvidia.</div>
</div>
</a>
</section>
<section data-component="faq">
<div data-slot="section-title">
<h3>FAQ</h3>
</div>
<ul>
<li>
<Faq question="What is OpenCode Zen?">
Zen is a curated set of AI models tested and benchmarked for coding agents created by the team behind
OpenCode.
</Faq>
</li>
<li>
<Faq question="What makes Zen more accurate?">
Zen only provides models that have been specifically tested and benchmarked for coding agents. You
wouldnt use a butter knife to cut steak, dont use poor models for coding.
</Faq>
</li>
<li>
<Faq question="Is Zen cheaper?">
Zen is not for profit. Zen passes through the costs from the model providers to you. The higher Zens
usage the more OpenCode can negotiate better rates and pass those to you.
</Faq>
</li>
<li>
<Faq question="How much does Zen cost?">
Zen <a href="/docs/zen/#pricing">charges per request</a> with zero markups, so you pay exactly what the model provider charges. Your
total cost depends on usage, and you can set monthly spend limits in your <A href="/auth">account</A>.
To cover costs, OpenCode adds only a small payment processing fee of $1.23 per $20 balance top-up.
</Faq>
</li>
<li>
<Faq question="What about data and privacy?">
All Zen models are hosted in the US. Providers follow a zero-retention policy and do not use your data
for model training, with the <a href="/docs/zen/#privacy">following exceptions</a>.
</Faq>
</li>
<li>
<Faq question="Can I set spend limits?">Yes, you can set monthly spending limits in your account.</Faq>
</li>
<li>
<Faq question="Can I cancel?">
Yes, you can disable billing at any time and use your remaining balance.
</Faq>
</li>
<li>
<Faq question="Can I use Zen with other coding agents?">
While Zen works great with OpenCode, you can use Zen with any agent. Follow the setup instructions in
your preferred coding agent.
</Faq>
</li>
</ul>
</section>
<EmailSignup />
<Footer />
</div>
</div>
<Legal />
</main>
)
}

View File

@@ -7,3 +7,15 @@ html {
body {
font-family: var(--font-sans);
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}