mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-28 13:14:28 +01:00
wip: cloud stuff
This commit is contained in:
19
cloud/app/src/routes/[...404].tsx
Normal file
19
cloud/app/src/routes/[...404].tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import { Title } from "@solidjs/meta";
|
||||
import { HttpStatusCode } from "@solidjs/start";
|
||||
|
||||
export default function NotFound() {
|
||||
return (
|
||||
<main>
|
||||
<Title>Not Found</Title>
|
||||
<HttpStatusCode code={404} />
|
||||
<h1>Page Not Found</h1>
|
||||
<p>
|
||||
Visit{" "}
|
||||
<a href="https://start.solidjs.com" target="_blank">
|
||||
start.solidjs.com
|
||||
</a>{" "}
|
||||
to learn how to build SolidStart apps.
|
||||
</p>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
264
cloud/app/src/routes/index.css
Normal file
264
cloud/app/src/routes/index.css
Normal file
@@ -0,0 +1,264 @@
|
||||
[data-page="home"] {
|
||||
--color-bg: oklch(0.2097 0.008 274.53);
|
||||
--color-border: oklch(0.46 0.02 269.88);
|
||||
--color-text: #ffffff;
|
||||
--color-text-secondary: oklch(0.72 0.01 270.15);
|
||||
--color-text-dimmed: hsl(224, 7%, 46%);
|
||||
padding: var(--space-6);
|
||||
font-family: var(--font-mono);
|
||||
color: var(--color-text);
|
||||
|
||||
a {
|
||||
color: var(--color-text);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 0.1875rem;
|
||||
}
|
||||
|
||||
background: var(--color-bg);
|
||||
position: fixed;
|
||||
overflow-y: scroll;
|
||||
inset: 0;
|
||||
|
||||
[data-component="content"] {
|
||||
max-width: 67.5rem;
|
||||
margin: 0 auto;
|
||||
border: 2px solid var(--color-border);
|
||||
}
|
||||
|
||||
[data-component="top"] {
|
||||
padding: var(--space-12);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
gap: var(--space-4);
|
||||
|
||||
[data-slot="logo"] {
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
[data-slot="title"] {
|
||||
font-size: var(--font-size-2xl);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="cta"] {
|
||||
height: var(--space-19);
|
||||
border-top: 2px solid var(--color-border);
|
||||
display: flex;
|
||||
|
||||
[data-slot="left"] {
|
||||
display: flex;
|
||||
padding: 0 var(--space-12);
|
||||
text-transform: uppercase;
|
||||
text-decoration: underline;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-underline-offset: 0.1875rem;
|
||||
border-right: 2px solid var(--color-border);
|
||||
|
||||
a {
|
||||
color: var(--color-text);
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
[data-slot="right"] {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.625rem;
|
||||
padding: 0 var(--space-6);
|
||||
}
|
||||
|
||||
[data-slot="command"] {
|
||||
all: unset;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 1.125rem;
|
||||
font-family: var(--font-mono);
|
||||
gap: var(--space-2);
|
||||
}
|
||||
|
||||
[data-slot="highlight"] {
|
||||
color: var(--color-text);
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="features"] {
|
||||
border-top: 2px solid var(--color-border);
|
||||
padding: var(--space-12);
|
||||
|
||||
[data-slot="list"] {
|
||||
padding-left: var(--space-4);
|
||||
margin: 0;
|
||||
list-style: disc;
|
||||
|
||||
li {
|
||||
margin-bottom: var(--space-4);
|
||||
|
||||
strong {
|
||||
text-transform: uppercase;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
li:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="install"] {
|
||||
border-top: 2px solid var(--color-border);
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
|
||||
@media (max-width: 40rem) {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: auto;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="title"] {
|
||||
letter-spacing: -0.03125rem;
|
||||
text-transform: uppercase;
|
||||
font-weight: 400;
|
||||
font-size: var(--font-size-md);
|
||||
flex-shrink: 0;
|
||||
color: oklch(0.55 0.02 269.87);
|
||||
}
|
||||
|
||||
[data-component="method"] {
|
||||
padding: var(--space-4) var(--space-6);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
gap: var(--space-3);
|
||||
|
||||
&:nth-child(1) {}
|
||||
|
||||
&:nth-child(2) {
|
||||
border-left: 2px solid var(--color-border);
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
border-top: 2px solid var(--color-border);
|
||||
}
|
||||
|
||||
&:nth-child(4) {
|
||||
border-top: 2px solid var(--color-border);
|
||||
border-left: 2px solid var(--color-border);
|
||||
}
|
||||
|
||||
[data-slot="button"] {
|
||||
all: unset;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--color-text-secondary);
|
||||
gap: var(--space-2);
|
||||
|
||||
strong {
|
||||
color: var(--color-text);
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="screenshots"] {
|
||||
border-top: 2px solid var(--color-border);
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 0;
|
||||
|
||||
[data-slot="left"] {
|
||||
padding: var(--space-8) var(--space-6);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: "auto";
|
||||
}
|
||||
}
|
||||
|
||||
[data-slot="right"] {
|
||||
display: grid;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
border-left: 2px solid var(--color-border);
|
||||
}
|
||||
|
||||
[data-slot="filler"] {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
[data-slot="cell"] {
|
||||
padding: var(--space-8) var(--space-6);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-4);
|
||||
|
||||
&:nth-child(2) {
|
||||
border-top: 2px solid var(--color-border);
|
||||
}
|
||||
|
||||
img {
|
||||
width: 80%;
|
||||
height: "auto";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="copy-status"] {
|
||||
[data-slot="copy"] {
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
color: var(--color-text-dimmed);
|
||||
|
||||
[data-copied] & {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
[data-slot="check"] {
|
||||
display: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
color: white;
|
||||
|
||||
[data-copied] & {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="footer"] {
|
||||
border-top: 2px solid var(--color-border);
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
font-size: var(--font-size-lg);
|
||||
height: var(--space-20);
|
||||
|
||||
[data-slot="cell"] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-right: 2px solid var(--color-border);
|
||||
text-transform: uppercase;
|
||||
|
||||
&:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
169
cloud/app/src/routes/index.tsx
Normal file
169
cloud/app/src/routes/index.tsx
Normal file
@@ -0,0 +1,169 @@
|
||||
import { Title } from "@solidjs/meta"
|
||||
import { onCleanup, onMount } from "solid-js"
|
||||
import "./index.css"
|
||||
import logo from "../asset/logo-ornate-dark.svg"
|
||||
import IMG_SPLASH from "../asset/screenshot-splash.webp"
|
||||
import IMG_VSCODE from "../asset/screenshot-vscode.webp"
|
||||
import IMG_GITHUB from "../asset/screenshot-github.webp"
|
||||
import { IconCopy, IconCheck } from "../component/icon"
|
||||
|
||||
function CopyStatus() {
|
||||
return (
|
||||
<div data-component="copy-status">
|
||||
<IconCopy data-slot="copy" />
|
||||
<IconCheck data-slot="check" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function Home() {
|
||||
onMount(() => {
|
||||
const commands = document.querySelectorAll("[data-copy]")
|
||||
for (const button of commands) {
|
||||
const callback = () => {
|
||||
const text = button.textContent
|
||||
alert(text)
|
||||
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" src={logo} alt="logo" />
|
||||
<h1 data-slot="title">The AI coding agent built for the terminal.</h1>
|
||||
</section>
|
||||
|
||||
<section data-component="cta">
|
||||
<div data-slot="left">
|
||||
<a href="/docs">Get Started</a>
|
||||
</div>
|
||||
<div data-slot="right">
|
||||
<button data-copy data-slot="command" data-command="curl -fsSL https://opencode.ai/install | bash">
|
||||
<span>
|
||||
<span>curl -fsSL </span>
|
||||
<span data-slot="protocol">https://</span>
|
||||
<span data-slot="highlight">opencode.ai/install</span>
|
||||
| bash
|
||||
</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>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">
|
||||
<div data-slot="left">
|
||||
<div data-component="title">opencode TUI with tokyonight theme</div>
|
||||
<div data-slot="filler">
|
||||
<img src={IMG_SPLASH} alt="opencode TUI with tokyonight theme" />
|
||||
</div>
|
||||
</div>
|
||||
<div data-slot="right">
|
||||
<div data-slot="cell">
|
||||
<div data-component="title">opencode in VS Code</div>
|
||||
<div data-slot="filler">
|
||||
<img src={IMG_VSCODE} alt="opencode in VS Code" />
|
||||
</div>
|
||||
</div>
|
||||
<div data-slot="cell">
|
||||
<div data-component="title">opencode in GitHub</div>
|
||||
<div data-slot="filler">
|
||||
<img src={IMG_GITHUB} alt="opencode in GitHub" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer data-component="footer">
|
||||
<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>
|
||||
<div data-slot="cell">
|
||||
<span>
|
||||
©2025 <a href="https://anoma.ly">Anomaly Innovations</a>
|
||||
</span>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user