summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--packages/console/app/public/fonts/berkley-mono.woff2 (renamed from packages/ui/src/assets/fonts/tx-02.woff2)bin51664 -> 51664 bytes
-rw-r--r--packages/console/app/src/asset/lander/desktop-app-icon.pngbin0 -> 6172 bytes
-rw-r--r--packages/console/app/src/component/email-signup.tsx5
-rw-r--r--packages/console/app/src/routes/brand/index.css2
-rw-r--r--packages/console/app/src/routes/enterprise/index.css4
-rw-r--r--packages/console/app/src/routes/index.css133
-rw-r--r--packages/console/app/src/routes/index.tsx232
-rw-r--r--packages/console/app/src/routes/zen/index.css6
-rw-r--r--packages/console/app/src/style/token/font.css11
9 files changed, 283 insertions, 110 deletions
diff --git a/packages/ui/src/assets/fonts/tx-02.woff2 b/packages/console/app/public/fonts/berkley-mono.woff2
index d18fc3912..d18fc3912 100644
--- a/packages/ui/src/assets/fonts/tx-02.woff2
+++ b/packages/console/app/public/fonts/berkley-mono.woff2
Binary files differ
diff --git a/packages/console/app/src/asset/lander/desktop-app-icon.png b/packages/console/app/src/asset/lander/desktop-app-icon.png
new file mode 100644
index 000000000..a35c28f51
--- /dev/null
+++ b/packages/console/app/src/asset/lander/desktop-app-icon.png
Binary files differ
diff --git a/packages/console/app/src/component/email-signup.tsx b/packages/console/app/src/component/email-signup.tsx
index 4943921e7..65f81b5fc 100644
--- a/packages/console/app/src/component/email-signup.tsx
+++ b/packages/console/app/src/component/email-signup.tsx
@@ -25,11 +25,8 @@ 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>
+ <h3>Be the first to know when we release new products</h3>
<p>Join the waitlist for early access.</p>
</div>
<form data-slot="form" action={emailSignup} method="post">
diff --git a/packages/console/app/src/routes/brand/index.css b/packages/console/app/src/routes/brand/index.css
index d3c0d0523..1fc6c17d3 100644
--- a/packages/console/app/src/routes/brand/index.css
+++ b/packages/console/app/src/routes/brand/index.css
@@ -266,7 +266,7 @@
h1 {
font-size: 1.5rem;
- font-weight: 500;
+ font-weight: 700;
color: var(--color-text-strong);
margin-bottom: 1rem;
}
diff --git a/packages/console/app/src/routes/enterprise/index.css b/packages/console/app/src/routes/enterprise/index.css
index 0178e40a2..d3c47f08e 100644
--- a/packages/console/app/src/routes/enterprise/index.css
+++ b/packages/console/app/src/routes/enterprise/index.css
@@ -289,7 +289,7 @@
[data-component="enterprise-column-1"] {
h1 {
font-size: 1.5rem;
- font-weight: 500;
+ font-weight: 700;
color: var(--color-text-strong);
margin-bottom: 1rem;
}
@@ -441,7 +441,7 @@
h3 {
font-size: 16px;
- font-weight: 500;
+ font-weight: 700;
color: var(--color-text-strong);
margin-bottom: 12px;
}
diff --git a/packages/console/app/src/routes/index.css b/packages/console/app/src/routes/index.css
index 92de172e1..f04297104 100644
--- a/packages/console/app/src/routes/index.css
+++ b/packages/console/app/src/routes/index.css
@@ -16,6 +16,8 @@
--color-background-strong-hover: hsl(0, 5%, 18%);
--color-background-interactive: hsl(62, 84%, 88%);
--color-background-interactive-weaker: hsl(64, 74%, 95%);
+ --color-surface-raised-base: hsla(0, 100%, 3%, 0.01);
+ --color-surface-raised-base-active: hsla(0, 100%, 17%, 0.06);
--color-text: hsl(0, 1%, 39%);
--color-text-weak: hsl(0, 1%, 60%);
@@ -24,7 +26,7 @@
--color-text-inverted: hsl(0, 20%, 99%);
--color-border: hsl(30, 2%, 81%);
- --color-border-weak: hsl(0, 1%, 85%);
+ --color-border-weak: hsla(0, 100%, 3%, 0.12);
--color-icon: hsl(0, 1%, 55%);
}
@@ -62,6 +64,14 @@ body {
}
}
+[data-slot="br"] {
+ display: block;
+
+ @media (max-width: 60rem) {
+ display: none;
+ }
+}
+
[data-page="opencode"] {
background: var(--color-background);
--padding: 5rem;
@@ -322,7 +332,7 @@ body {
display: flex;
flex-direction: column;
max-width: 100%;
- padding: calc(var(--vertical-padding) * 2) var(--padding);
+ padding: calc(var(--vertical-padding) * 1.5) var(--padding);
@media (max-width: 30rem) {
padding: var(--vertical-padding) var(--padding);
@@ -465,6 +475,69 @@ body {
}
}
+ [data-component="desktop-app-available"] {
+ background: var(--color-surface-raised-base);
+ border: 1px solid var(--color-border-weak);
+ display: flex;
+ margin-bottom: 48px;
+
+ [data-slot="desktop-icon"] {
+ border-right: 1px solid var(--color-border-weak);
+ width: 56px;
+ height: 72px;
+ background: var(--color-surface-raised-base-active);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ position: relative;
+
+ img {
+ width: 40px;
+ height: 40px;
+ opacity: 100%;
+ }
+
+ [data-slot="dot"] {
+ border-radius: 100px;
+ width: 6px;
+ height: 6px;
+ background: var(--color-background-strong);
+ position: absolute;
+ bottom: 5px;
+ left: 24px;
+ opacity: 0;
+ }
+ }
+
+ &[data-animating] [data-slot="desktop-icon"] img {
+ animation: iconBounce 1s ease-in-out forwards;
+ }
+
+ &[data-animating] [data-slot="desktop-icon"] [data-slot="dot"] {
+ animation: dotFadeInOut 6s ease-out forwards;
+ }
+
+
+
+ [data-slot="desktop-copy"] {
+ display: flex;
+ align-items: center;
+ padding: 20px;
+ gap: 16px;
+ flex: 1;
+ cursor: default;
+
+ span {
+ color: var(--color-text-strong);
+ line-height: 1;
+ }
+
+ a {
+ color: var(--color-text-weak);
+ }
+ }
+ }
+
[data-slot="hero-copy"] {
[data-slot="releases"] {
background: none;
@@ -492,7 +565,7 @@ body {
h1 {
font-size: 38px;
color: var(--color-text-strong);
- font-weight: 500;
+ font-weight: 700;
margin-bottom: 8px;
@media (max-width: 60rem) {
@@ -502,7 +575,7 @@ body {
p {
color: var(--color-text);
- margin-bottom: 40px;
+ margin-bottom: 32px;
max-width: 82%;
@media (max-width: 50rem) {
@@ -518,7 +591,6 @@ body {
border-radius: 4px;
font-weight: 500;
cursor: pointer;
- margin-bottom: 80px;
display: flex;
width: fit-content;
gap: 12px;
@@ -596,7 +668,7 @@ body {
h3 {
font-size: 16px;
- font-weight: 500;
+ font-weight: 700;
color: var(--color-text-strong);
margin-bottom: 12px;
}
@@ -701,7 +773,7 @@ body {
[data-slot="privacy-title"] {
h3 {
font-size: 16px;
- font-weight: 500;
+ font-weight: 700;
color: var(--color-text-strong);
margin-bottom: 12px;
}
@@ -727,7 +799,7 @@ body {
[data-slot="zen-cta-copy"] {
strong {
color: var(--color-text-strong);
- font-weight: 500;
+ font-weight: 700;
margin-bottom: 16px;
display: block;
}
@@ -1140,3 +1212,48 @@ body {
}
}
}
+
+@keyframes iconBounce {
+ 0%, 100% {
+ transform: translateY(0);
+ }
+ 50% {
+ transform: translateY(-10px);
+ }
+}
+ 25% {
+ transform: translateY(-10px);
+ }
+ 50% {
+ transform: translateY(0);
+ }
+ 75% {
+ transform: translateY(-10px);
+ }
+}
+
+@keyframes dotAppear {
+ 0% {
+ opacity: 0;
+ transform: scale(0);
+ }
+ 100% {
+ opacity: 0.5;
+ transform: scale(1);
+ }
+}
+
+@keyframes dotFadeInOut {
+ 0%, 16% {
+ opacity: 0;
+ }
+ 20% {
+ opacity: 0.4;
+ }
+ 90% {
+ opacity: 0.4;
+ }
+ 100% {
+ opacity: 0;
+ }
+}
diff --git a/packages/console/app/src/routes/index.tsx b/packages/console/app/src/routes/index.tsx
index f46a4e028..0b135fb5e 100644
--- a/packages/console/app/src/routes/index.tsx
+++ b/packages/console/app/src/routes/index.tsx
@@ -3,6 +3,7 @@ import { Title, Meta, Link } from "@solidjs/meta"
// import { HttpHeader } from "@solidjs/start"
import video from "../asset/lander/opencode-min.mp4"
import videoPoster from "../asset/lander/opencode-poster.png"
+import desktopAppIcon from "../asset/lander/desktop-app-icon.png"
import { IconCopy, IconCheck } from "../component/icon"
import { A, createAsync } from "@solidjs/router"
import { EmailSignup } from "~/component/email-signup"
@@ -12,8 +13,9 @@ import { Header } from "~/component/header"
import { Footer } from "~/component/footer"
import { Legal } from "~/component/legal"
import { github } from "~/lib/github"
-import { createMemo } from "solid-js"
+import { createMemo, createSignal } from "solid-js"
import { config } from "~/config"
+import avatarDavid from "~/asset/lander/avatar-david.png"
function CopyStatus() {
return (
@@ -28,6 +30,18 @@ export default function Home() {
const githubData = createAsync(() => github())
const release = createMemo(() => githubData()?.release)
+ const [isAnimating, setIsAnimating] = createSignal(false)
+
+ const handleDesktopCopyHover = () => {
+ if (!isAnimating()) {
+ setIsAnimating(true)
+ // Animation duration is 6s for dot fade in/out
+ setTimeout(() => {
+ setIsAnimating(false)
+ }, 6000)
+ }
+ }
+
const handleCopyClick = (event: Event) => {
const button = event.currentTarget as HTMLButtonElement
const text = button.textContent
@@ -52,100 +66,117 @@ export default function Home() {
<div data-component="content">
<section data-component="hero">
+ <div data-component="desktop-app-available" data-animating={isAnimating() ? "" : undefined}>
+ <div data-slot="desktop-icon">
+ <img src={desktopAppIcon} alt="" />
+ <div data-slot="dot"></div>
+ </div>
+ <div data-slot="desktop-copy" onMouseEnter={handleDesktopCopyHover}>
+ <span>Now available on desktop for macOS, Windows, and Linux.</span> <a href="/download">Learn more</a>
+ </div>
+ </div>
+
<div data-slot="hero-copy">
- <a data-slot="releases" href={release()?.url ?? `${config.github.repoUrl}/releases`} target="_blank">
- What’s new in {release()?.name ?? "the latest release"}
- </a>
- <h1>The open source coding agent</h1>
+ {/*<a data-slot="releases"*/}
+ {/* href={release()?.url ?? `${config.github.repoUrl}/releases`}*/}
+ {/* target="_blank">*/}
+ {/* What’s new in {release()?.name ?? "the latest release"}*/}
+ {/*</a>*/}
+ <h1>The open source AI coding agent</h1>
<p>
- OpenCode includes free models or connect from any provider to <br />
- use other models, including Claude, GPT, Gemini and more.
+ Free models by default or connect any model from any provider, <span data-slot="br"></span>including
+ Claude, GPT, Gemini and more.
</p>
+ <a href="/download">
+ <span>Get started for free</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>
- <p data-slot="installation-instructions">Install and use. No account, no email, and no credit card.</p>
- <div data-slot="installation">
- <Tabs
- as="section"
- aria-label="Install options"
- class="tabs"
- data-component="tabs"
- data-active="curl"
- defaultValue="curl"
- >
- <Tabs.List data-slot="tablist">
- <Tabs.Trigger value="curl" data-slot="tab">
- curl
- </Tabs.Trigger>
- <Tabs.Trigger value="npm" data-slot="tab">
- npm
- </Tabs.Trigger>
- <Tabs.Trigger value="bun" data-slot="tab">
- bun
- </Tabs.Trigger>
- <Tabs.Trigger value="brew" data-slot="tab">
- brew
- </Tabs.Trigger>
- <Tabs.Trigger value="paru" data-slot="tab">
- paru
- </Tabs.Trigger>
- <Tabs.Indicator />
- </Tabs.List>
- <div data-slot="panels">
- <Tabs.Content as="pre" data-slot="panel" value="curl">
- <button data-copy data-slot="command" onClick={handleCopyClick}>
- <span data-slot="command-script">
- <span>curl -fsSL </span>
- <span data-slot="protocol">https://</span>
- <span data-slot="highlight">opencode.ai/install</span>
- <span> | bash</span>
- </span>
- <CopyStatus />
- </button>
- </Tabs.Content>
- <Tabs.Content as="pre" data-slot="panel" value="npm">
- <button data-copy data-slot="command" onClick={handleCopyClick}>
- <span>
- <span data-slot="protocol">npm i -g </span>
- <span data-slot="highlight">opencode-ai</span>
- </span>
- <CopyStatus />
- </button>
- </Tabs.Content>
- <Tabs.Content as="pre" data-slot="panel" value="bun">
- <button data-copy data-slot="command" onClick={handleCopyClick}>
- <span>
- <span data-slot="protocol">bun add -g </span>
- <span data-slot="highlight">opencode-ai</span>
- </span>
- <CopyStatus />
- </button>
- </Tabs.Content>
- <Tabs.Content as="pre" data-slot="panel" value="brew">
- <button data-copy data-slot="command" onClick={handleCopyClick}>
- <span>
- <span data-slot="protocol">brew install </span>
- <span data-slot="highlight">opencode</span>
- </span>
- <CopyStatus />
- </button>
- </Tabs.Content>
- <Tabs.Content as="pre" data-slot="panel" value="paru">
- <button data-copy data-slot="command" onClick={handleCopyClick}>
- <span>
- <span data-slot="protocol">paru -S </span>
- <span data-slot="highlight">opencode</span>
- </span>
- <CopyStatus />
- </button>
- </Tabs.Content>
- </div>
- </Tabs>
- </div>
- <p data-slot="installation-options">
- Available in terminal, web, and desktop (coming soon).
- <br />
- Extensions for VS Code, Cursor, Windsurf, and more.
- </p>
+ {/*<div data-slot="installation">*/}
+ {/* <Tabs*/}
+ {/* as="section"*/}
+ {/* aria-label="Install options"*/}
+ {/* class="tabs"*/}
+ {/* data-component="tabs"*/}
+ {/* data-active="curl"*/}
+ {/* defaultValue="curl"*/}
+ {/* >*/}
+ {/* <Tabs.List data-slot="tablist">*/}
+ {/* <Tabs.Trigger value="curl" data-slot="tab">*/}
+ {/* curl*/}
+ {/* </Tabs.Trigger>*/}
+ {/* <Tabs.Trigger value="npm" data-slot="tab">*/}
+ {/* npm*/}
+ {/* </Tabs.Trigger>*/}
+ {/* <Tabs.Trigger value="bun" data-slot="tab">*/}
+ {/* bun*/}
+ {/* </Tabs.Trigger>*/}
+ {/* <Tabs.Trigger value="brew" data-slot="tab">*/}
+ {/* brew*/}
+ {/* </Tabs.Trigger>*/}
+ {/* <Tabs.Trigger value="paru" data-slot="tab">*/}
+ {/* paru*/}
+ {/* </Tabs.Trigger>*/}
+ {/* <Tabs.Indicator />*/}
+ {/* </Tabs.List>*/}
+ {/* <div data-slot="panels">*/}
+ {/* <Tabs.Content as="pre" data-slot="panel" value="curl">*/}
+ {/* <button data-copy data-slot="command" onClick={handleCopyClick}>*/}
+ {/* <span data-slot="command-script">*/}
+ {/* <span>curl -fsSL </span>*/}
+ {/* <span data-slot="protocol">https://</span>*/}
+ {/* <span data-slot="highlight">opencode.ai/install</span>*/}
+ {/* <span> | bash</span>*/}
+ {/* </span>*/}
+ {/* <CopyStatus />*/}
+ {/* </button>*/}
+ {/* </Tabs.Content>*/}
+ {/* <Tabs.Content as="pre" data-slot="panel" value="npm">*/}
+ {/* <button data-copy data-slot="command" onClick={handleCopyClick}>*/}
+ {/* <span>*/}
+ {/* <span data-slot="protocol">npm i -g </span>*/}
+ {/* <span data-slot="highlight">opencode-ai</span>*/}
+ {/* </span>*/}
+ {/* <CopyStatus />*/}
+ {/* </button>*/}
+ {/* </Tabs.Content>*/}
+ {/* <Tabs.Content as="pre" data-slot="panel" value="bun">*/}
+ {/* <button data-copy data-slot="command" onClick={handleCopyClick}>*/}
+ {/* <span>*/}
+ {/* <span data-slot="protocol">bun add -g </span>*/}
+ {/* <span data-slot="highlight">opencode-ai</span>*/}
+ {/* </span>*/}
+ {/* <CopyStatus />*/}
+ {/* </button>*/}
+ {/* </Tabs.Content>*/}
+ {/* <Tabs.Content as="pre" data-slot="panel" value="brew">*/}
+ {/* <button data-copy data-slot="command" onClick={handleCopyClick}>*/}
+ {/* <span>*/}
+ {/* <span data-slot="protocol">brew install </span>*/}
+ {/* <span data-slot="highlight">opencode</span>*/}
+ {/* </span>*/}
+ {/* <CopyStatus />*/}
+ {/* </button>*/}
+ {/* </Tabs.Content>*/}
+ {/* <Tabs.Content as="pre" data-slot="panel" value="paru">*/}
+ {/* <button data-copy data-slot="command" onClick={handleCopyClick}>*/}
+ {/* <span>*/}
+ {/* <span data-slot="protocol">paru -S </span>*/}
+ {/* <span data-slot="highlight">opencode</span>*/}
+ {/* </span>*/}
+ {/* <CopyStatus />*/}
+ {/* </button>*/}
+ {/* </Tabs.Content>*/}
+ {/* </div>*/}
+ {/* </Tabs>*/}
+ {/*</div>*/}
</section>
<section data-component="video">
@@ -739,6 +770,17 @@ export default function Home() {
</svg>
</div>
<div>
+ <svg
+ width="24"
+ height="24"
+ viewBox="0 0 50 50"
+ fill="currentColor"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <path d="M49.04,24.001l-1.082-0.043h-0.001C36.134,23.492,26.508,13.866,26.042,2.043L25.999,0.96C25.978,0.424,25.537,0,25,0 s-0.978,0.424-0.999,0.96l-0.043,1.083C23.492,13.866,13.866,23.492,2.042,23.958L0.96,24.001C0.424,24.022,0,24.463,0,25 c0,0.537,0.424,0.978,0.961,0.999l1.082,0.042c11.823,0.467,21.449,10.093,21.915,21.916l0.043,1.083C24.022,49.576,24.463,50,25,50 s0.978-0.424,0.999-0.96l0.043-1.083c0.466-11.823,10.092-21.449,21.915-21.916l1.082-0.042C49.576,25.978,50,25.537,50,25 C50,24.463,49.576,24.022,49.04,24.001z"></path>
+ </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"
@@ -768,6 +810,14 @@ export default function Home() {
/>
</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.0962 3L10.0998 5.6577H1.59858L3.59417 3H12.0972H12.0962ZM22.3162 18.3432L20.3215 21H11.8497L13.8425 18.3432H22.3162ZM23 3L9.492 21H1L14.508 3H23Z"
+ fill="black"
+ />
+ </svg>
+ </div>
</div>
<A href="/zen">
<span>Learn about Zen </span>
diff --git a/packages/console/app/src/routes/zen/index.css b/packages/console/app/src/routes/zen/index.css
index fbdd15306..6a9f5706d 100644
--- a/packages/console/app/src/routes/zen/index.css
+++ b/packages/console/app/src/routes/zen/index.css
@@ -280,7 +280,7 @@ body {
h1 {
font-size: 28px;
color: var(--color-text-strong);
- font-weight: 500;
+ font-weight: 700;
margin-bottom: 16px;
display: block;
@@ -369,7 +369,7 @@ body {
h3 {
font-size: 16px;
- font-weight: 500;
+ font-weight: 700;
color: var(--color-text-strong);
margin-bottom: 12px;
}
@@ -442,7 +442,7 @@ body {
[data-slot="privacy-title"] {
h3 {
font-size: 16px;
- font-weight: 500;
+ font-weight: 700;
color: var(--color-text);
margin-bottom: 12px;
}
diff --git a/packages/console/app/src/style/token/font.css b/packages/console/app/src/style/token/font.css
index 67143e662..5a5f19da6 100644
--- a/packages/console/app/src/style/token/font.css
+++ b/packages/console/app/src/style/token/font.css
@@ -1,3 +1,11 @@
+@font-face {
+ font-family: "Berkeley Mono";
+ src: url("/fonts/berkley-mono.woff2") format("woff2");
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
body {
--font-size-2xs: 0.6875rem;
--font-size-xs: 0.75rem;
@@ -15,6 +23,7 @@ body {
--font-size-9xl: 8rem;
--font-mono:
- "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+ "Berkeley Mono", "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
+ "Courier New", monospace;
--font-sans: var(--font-mono);
}