diff options
| -rw-r--r-- | packages/console/app/src/asset/lander/brand-assets-dark.svg | 10 | ||||
| -rw-r--r-- | packages/console/app/src/asset/lander/brand-assets-light.svg | 10 | ||||
| -rw-r--r-- | packages/console/app/src/asset/lander/brand.png | bin | 0 -> 72109 bytes | |||
| -rw-r--r-- | packages/console/app/src/asset/lander/logo-dark.svg | 11 | ||||
| -rw-r--r-- | packages/console/app/src/asset/lander/logo-light.svg | 11 | ||||
| -rw-r--r-- | packages/console/app/src/asset/lander/wordmark-dark.svg | 3 | ||||
| -rw-r--r-- | packages/console/app/src/asset/lander/wordmark-light.svg | 3 | ||||
| -rw-r--r-- | packages/console/app/src/component/header-context-menu.css | 55 | ||||
| -rw-r--r-- | packages/console/app/src/component/header.tsx | 125 | ||||
| -rw-r--r-- | packages/console/app/src/routes/brand/index.css | 443 | ||||
| -rw-r--r-- | packages/console/app/src/routes/brand/index.tsx | 100 |
11 files changed, 766 insertions, 5 deletions
diff --git a/packages/console/app/src/asset/lander/brand-assets-dark.svg b/packages/console/app/src/asset/lander/brand-assets-dark.svg new file mode 100644 index 000000000..196ed8de2 --- /dev/null +++ b/packages/console/app/src/asset/lander/brand-assets-dark.svg @@ -0,0 +1,10 @@ +<svg width="22" height="26" viewBox="0 0 22 26" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M15 7H7V19H15V7ZM19 23H3V3H19V23Z" fill="url(#paint0_linear_1311_86681)" stroke="#F1ECEC"/> +<path d="M3 0V26M19 0V26M15 0V26M7 0V26M0 3H22M0 7H22M0 19H22M0 23H22" stroke="#4B4646" stroke-opacity="0.4"/> +<defs> +<linearGradient id="paint0_linear_1311_86681" x1="11" y1="3" x2="11" y2="23" gradientUnits="userSpaceOnUse"> +<stop stop-color="#1B1818"/> +<stop offset="1" stop-color="#2D2828"/> +</linearGradient> +</defs> +</svg> diff --git a/packages/console/app/src/asset/lander/brand-assets-light.svg b/packages/console/app/src/asset/lander/brand-assets-light.svg new file mode 100644 index 000000000..3f898f2a0 --- /dev/null +++ b/packages/console/app/src/asset/lander/brand-assets-light.svg @@ -0,0 +1,10 @@ +<svg width="22" height="26" viewBox="0 0 22 26" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M15 7H7V19H15V7ZM19 23H3V3H19V23Z" fill="url(#paint0_linear_1311_86671)" stroke="#8E8B8B"/> +<path d="M3 0V26M19 0V26M15 0V26M7 0V26M0 3H22M0 7H22M0 19H22M0 23H22" stroke="#110000" stroke-opacity="0.121569"/> +<defs> +<linearGradient id="paint0_linear_1311_86671" x1="11" y1="3" x2="11" y2="23" gradientUnits="userSpaceOnUse"> +<stop stop-color="#F9F8F8"/> +<stop offset="1" stop-color="#E9E8E8"/> +</linearGradient> +</defs> +</svg> diff --git a/packages/console/app/src/asset/lander/brand.png b/packages/console/app/src/asset/lander/brand.png Binary files differnew file mode 100644 index 000000000..6172775e5 --- /dev/null +++ b/packages/console/app/src/asset/lander/brand.png diff --git a/packages/console/app/src/asset/lander/logo-dark.svg b/packages/console/app/src/asset/lander/logo-dark.svg new file mode 100644 index 000000000..8a2f7ebbb --- /dev/null +++ b/packages/console/app/src/asset/lander/logo-dark.svg @@ -0,0 +1,11 @@ +<svg width="22" height="26" viewBox="0 0 22 26" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_1311_86675)"> +<path d="M15 19H7V11H15V19Z" fill="#4B4646"/> +<path d="M15 7H7V19H15V7ZM19 23H3V3H19V23Z" fill="#F1ECEC"/> +</g> +<defs> +<clipPath id="clip0_1311_86675"> +<rect width="16" height="20" fill="white" transform="translate(3 3)"/> +</clipPath> +</defs> +</svg> diff --git a/packages/console/app/src/asset/lander/logo-light.svg b/packages/console/app/src/asset/lander/logo-light.svg new file mode 100644 index 000000000..54f90aeda --- /dev/null +++ b/packages/console/app/src/asset/lander/logo-light.svg @@ -0,0 +1,11 @@ +<svg width="22" height="26" viewBox="0 0 22 26" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_1311_86665)"> +<path d="M15 19H7V11H15V19Z" fill="#BCBBBB"/> +<path d="M15 7H7V19H15V7ZM19 23H3V3H19V23Z" fill="#211E1E"/> +</g> +<defs> +<clipPath id="clip0_1311_86665"> +<rect width="16" height="20" fill="white" transform="translate(3 3)"/> +</clipPath> +</defs> +</svg> diff --git a/packages/console/app/src/asset/lander/wordmark-dark.svg b/packages/console/app/src/asset/lander/wordmark-dark.svg new file mode 100644 index 000000000..42f8e22a6 --- /dev/null +++ b/packages/console/app/src/asset/lander/wordmark-dark.svg @@ -0,0 +1,3 @@ +<svg width="22" height="26" viewBox="0 0 22 26" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M4.33203 7.99967V6.33301H10.9987M17.6654 7.99967V6.33301H10.9987M10.9987 6.33301V19.6663M10.9987 19.6663H9.33203M10.9987 19.6663H12.6654" stroke="#F1ECEC" stroke-width="2" stroke-linecap="square"/> +</svg> diff --git a/packages/console/app/src/asset/lander/wordmark-light.svg b/packages/console/app/src/asset/lander/wordmark-light.svg new file mode 100644 index 000000000..398278da6 --- /dev/null +++ b/packages/console/app/src/asset/lander/wordmark-light.svg @@ -0,0 +1,3 @@ +<svg width="22" height="26" viewBox="0 0 22 26" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M4.33203 7.99967V6.33301H10.9987M17.6654 7.99967V6.33301H10.9987M10.9987 6.33301V19.6663M10.9987 19.6663H9.33203M10.9987 19.6663H12.6654" stroke="black" stroke-width="2" stroke-linecap="square"/> +</svg> diff --git a/packages/console/app/src/component/header-context-menu.css b/packages/console/app/src/component/header-context-menu.css new file mode 100644 index 000000000..e88af0c58 --- /dev/null +++ b/packages/console/app/src/component/header-context-menu.css @@ -0,0 +1,55 @@ +.context-menu { + position: fixed; + z-index: 1000; + min-width: 160px; + border-radius: 8px; + background-color: var(--color-background); + box-shadow: 0 0 0 1px rgba(19, 16, 16, 0.08), 0 6px 8px -4px rgba(19, 16, 16, 0.12), 0 4px 3px -2px rgba(19, 16, 16, 0.12), 0 1px 2px -1px rgba(19, 16, 16, 0.12); + padding: 6px; + + @media (prefers-color-scheme: dark) { + box-shadow: 0 0 0 1px rgba(247, 237, 237, 0.1); + } +} + +.context-menu-item { + display: flex; + gap: 12px; + width: 100%; + padding: 8px 16px 8px 8px; + font-weight: 500; + cursor: pointer; + background: none; + border: none; + align-items: center; + color: var(--color-text); + font-size: var(--font-size-sm); + text-align: left; + cursor: pointer; + border-radius: 2px; + transition: background-color 0.2s ease; + + [data-slot="copy dark"] { + display: none; + } + + @media (prefers-color-scheme: dark) { + [data-slot="copy light"] { + display: none; + } + [data-slot="copy dark"] { + display: block; + } + } + + &:hover { + background-color: var(--color-background-weak-hover); + color: var(--color-text-strong); + } +} + +.context-menu-divider { + border: none; + border-top: 1px solid var(--color-border); + margin: var(--space-1) 0; +} diff --git a/packages/console/app/src/component/header.tsx b/packages/console/app/src/component/header.tsx index ea8921f30..8f686e389 100644 --- a/packages/console/app/src/component/header.tsx +++ b/packages/console/app/src/component/header.tsx @@ -1,9 +1,17 @@ import logoLight from "../asset/logo-ornate-light.svg" import logoDark from "../asset/logo-ornate-dark.svg" +import copyLogoLight from "../asset/lander/logo-light.svg" +import copyLogoDark from "../asset/lander/logo-dark.svg" +import copyWordmarkLight from "../asset/lander/wordmark-light.svg" +import copyWordmarkDark from "../asset/lander/wordmark-dark.svg" +import copyBrandAssetsLight from "../asset/lander/brand-assets-light.svg" +import copyBrandAssetsDark from "../asset/lander/brand-assets-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" +import { createEffect, onCleanup } from "solid-js" +import "./header-context-menu.css" export function Header(props: { zen?: boolean }) { const githubData = createAsync(() => github()) @@ -18,14 +26,121 @@ export function Header(props: { zen?: boolean }) { const [store, setStore] = createStore({ mobileMenuOpen: false, + contextMenuOpen: false, + contextMenuPosition: { x: 0, y: 0 }, }) + createEffect(() => { + const handleClickOutside = () => { + setStore("contextMenuOpen", false) + } + + const handleContextMenu = (event: MouseEvent) => { + event.preventDefault() + setStore("contextMenuOpen", false) + } + + if (store.contextMenuOpen) { + document.addEventListener("click", handleClickOutside) + document.addEventListener("contextmenu", handleContextMenu) + onCleanup(() => { + document.removeEventListener("click", handleClickOutside) + document.removeEventListener("contextmenu", handleContextMenu) + }) + } + }) + + const handleLogoContextMenu = (event: MouseEvent) => { + event.preventDefault() + setStore("contextMenuPosition", { x: event.clientX, y: event.clientY }) + setStore("contextMenuOpen", true) + } + + const copyWordmarkToClipboard = async () => { + try { + const wordmarkSvg = `<svg width="234" height="42" viewBox="0 0 234 42" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_1306_86249)"> +<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"/> +</g> +<defs> +<clipPath id="clip0_1306_86249"> +<rect width="234" height="42" fill="white"/> +</clipPath> +</defs> +</svg> +` + await navigator.clipboard.writeText(wordmarkSvg) + } catch (err) { + console.error("Failed to copy wordmark to clipboard:", err) + } + } + + const copyLogoToClipboard = async () => { + try { + const logoSvg = `<svg width="80" height="100" viewBox="0 0 80 100" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M60 80H20V40H60V80Z" fill="#BCBBBB"/> +<path d="M60 20H20V80H60V20ZM80 100H0V0H80V100Z" fill="#211E1E"/> +</svg> +` + await navigator.clipboard.writeText(logoSvg) + } catch (err) { + console.error("Failed to copy logo to clipboard:", err) + } + } + 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> + <div onContextMenu={handleLogoContextMenu}> + <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> + </div> + + <Show when={store.contextMenuOpen}> + <div + class="context-menu" + style={`left: ${store.contextMenuPosition.x}px; top: ${store.contextMenuPosition.y}px;`} + > + <button class="context-menu-item" onClick={copyLogoToClipboard}> + <img data-slot="copy light" src={copyLogoLight} + alt="Logo"/> + <img data-slot="copy dark" src={copyLogoDark} + alt="Logo"/> + Copy logo as SVG + </button> + <button class="context-menu-item" onClick={copyWordmarkToClipboard}> + <img data-slot="copy light" src={copyWordmarkLight} + alt="Wordmark"/> + <img data-slot="copy dark" src={copyWordmarkDark} + alt="Wordmark"/> + Copy wordmark as SVG + </button> + <button class="context-menu-item" + onClick={() => (window.location.href = "/brand")}> + <img data-slot="copy light" src={copyBrandAssetsLight} + alt="Brand Assets"/> + <img data-slot="copy dark" src={copyBrandAssetsDark} + alt="Brand Assets"/> + Brand assets + </button> + </div> + </Show> <nav data-component="nav-desktop"> <ul> <li> @@ -42,7 +157,7 @@ export function Header(props: { zen?: boolean }) { <li> <Switch> <Match when={props.zen}> - <a href="/auth">Login</a> + <a href="/auth">Login</a> </Match> <Match when={!props.zen}> <A href="/zen">Zen</A> diff --git a/packages/console/app/src/routes/brand/index.css b/packages/console/app/src/routes/brand/index.css new file mode 100644 index 000000000..8cb0cc032 --- /dev/null +++ b/packages/console/app/src/routes/brand/index.css @@ -0,0 +1,443 @@ +::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="enterprise"] { + --color-background: hsl(0, 20%, 99%); + --color-background-weak: hsl(0, 8%, 97%); + --color-background-weak-hover: hsl(0, 8%, 94%); + --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%, 60%); + --color-text-weaker: hsl(30, 2%, 81%); + --color-text-strong: hsl(0, 5%, 12%); + --color-text-inverted: hsl(0, 20%, 99%); + --color-text-success: hsl(119, 100%, 35%); + + --color-border: hsl(30, 2%, 81%); + --color-border-weak: hsl(0, 1%, 85%); + + --color-icon: hsl(0, 1%, 55%); + --color-success: hsl(142, 76%, 36%); + + background: var(--color-background); + font-family: var(--font-mono); + color: var(--color-text); + padding-bottom: 5rem; + + @media (prefers-color-scheme: dark) { + --color-background: hsl(0, 9%, 7%); + --color-background-weak: hsl(0, 6%, 10%); + --color-background-weak-hover: hsl(0, 6%, 15%); + --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-text-success: hsl(119, 60%, 72%); + + + --color-border: hsl(0, 3%, 28%); + --color-border-weak: hsl(0, 4%, 23%); + + --color-icon: hsl(10, 3%, 43%); + --color-success: hsl(142, 76%, 46%); + } + + /* Header and Footer styles - copied from index.css */ + [data-component="top"] { + padding: 24px 5rem; + 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; + + @media (max-width: 60rem) { + padding: 24px 1.5rem; + } + + 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: 2px; + text-decoration-thickness: 1px; + } + } + } + + @media (max-width: 40rem) { + display: none; + } + } + + [data-component="nav-mobile"] { + button > svg { + color: var(--color-icon); + } + } + + [data-component="nav-mobile-toggle"] { + border: none; + background: none; + outline: none; + height: 40px; + width: 40px; + cursor: pointer; + margin-right: -8px; + } + + [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="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: 2px; + text-decoration-thickness: 1px; + } + } + + [data-slot="cell"] + [data-slot="cell"] { + border-left: 1px solid var(--color-border-weak); + + @media (max-width: 40rem) { + border-left: none; + } + } + + /* 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="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="brand-content"] { + padding: 4rem 5rem; + + h2 { + font-size: 1.5rem; + font-weight: 500; + color: var(--color-text-strong); + margin-bottom: 1rem; + } + + h3 { + font-size: 1.25rem; + font-weight: 500; + color: var(--color-text-strong); + margin: 2rem 0 1rem 0; + } + + p { + line-height: 1.6; + margin-bottom: 2.5rem; + color: var(--color-text); + } + + [data-component="download-button"] { + padding: 8px 12px 8px 20px; + background: var(--color-background-strong); + color: var(--color-text-inverted); + border: none; + border-radius: 4px; + font-weight: 500; + cursor: pointer; + display: flex; + width: fit-content; + gap: 12px; + transition: background-color 0.2s ease; + text-decoration: none; + + + &:hover:not(:disabled) { + background: var(--color-background-strong-hover); + } + + &:disabled { + opacity: 0.6; + cursor: not-allowed; + } + } + + img { + width: 100%; + height: auto; + display: block; + margin-top: 4rem; + margin-bottom: 2rem; + } + + + @media (max-width: 60rem) { + padding: 2rem 1.5rem; + } + } + + + + + [data-component="faq"] { + border-top: 1px solid var(--color-border-weak); + padding: 4rem 5rem; + + @media (max-width: 60rem) { + padding: 2rem 1.5rem; + } + + [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); + } + } + + ul { + padding: 0; + + li { + list-style: none; + margin-bottom: 24px; + line-height: 200%; + + @media (max-width: 60rem) { + line-height: 180%; + } + } + } + + [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; + color: var(--color-text-weak); + margin-top: 2px; + + [data-closed] & { + display: block; + } + [data-expanded] & { + display: none; + } + } + [data-slot="faq-icon-minus"] { + flex-shrink: 0; + color: var(--color-text-weak); + margin-top: 2px; + + [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; + color: var(--color-text); + } + } + + [data-component="legal"] { + color: var(--color-text-weak); + text-align: center; + padding: 2rem 5rem; + + @media (max-width: 60rem) { + padding: 2rem 1.5rem; + } + + a { + color: var(--color-text-weak); + text-decoration: none; + } + } + + a { + color: var(--color-text-strong); + text-decoration: underline; + text-underline-offset: 2px; + text-decoration-thickness: 1px; + + &:hover { + text-decoration-thickness: 2px; + } + } +} diff --git a/packages/console/app/src/routes/brand/index.tsx b/packages/console/app/src/routes/brand/index.tsx new file mode 100644 index 000000000..53ce22bb9 --- /dev/null +++ b/packages/console/app/src/routes/brand/index.tsx @@ -0,0 +1,100 @@ +import "./index.css" +import { Title, Meta } from "@solidjs/meta" +import { Header } from "~/component/header" +import { Footer } from "~/component/footer" +import { Legal } from "~/component/legal" +import { Faq } from "~/component/faq" +import brand from "../../asset/lander/brand.png" + + +export default function Brand() { + + return ( + <main data-page="enterprise"> + <Title>OpenCode | Brand</Title> + <Meta name="description" content="OpenCode brand guidelines" /> + <div data-component="container"> + <Header /> + + <div data-component="content"> + <section data-component="brand-content"> + <h2>Brand guidelines</h2> + <p> + Resources and assets to help you work with the OpenCode brand. + </p> + <a data-component="download-button" href="#">Download brand assets<svg + width="24" height="24" viewBox="0 0 24 24" fill="none" + xmlns="http://www.w3.org/2000/svg"> + <path d="M12 6.5L12 17M7.5 13L12 17.5L16.5 13" stroke="currentColor" + stroke-width="1.5" stroke-linecap="square"/> + </svg> + </a> + <img src={brand} alt=""/> + + <p>If you need any help with anything brand related <a href="mailto:[email protected]">contact us</a>.</p> + </section> + + <section data-component="faq"> + <div data-slot="section-title"> + <h3>FAQ</h3> + </div> + <ul> + <li> + <Faq question="Does Opencode store our code or context data?"> + No. OpenCode never stores your code or context data. All + processing happens locally or directly with your AI provider. + </Faq> + </li> + <li> + <Faq question="Who owns the code generated with OpenCode?"> + You do. All code produced is yours, with no licensing + restrictions or ownership claims. + </Faq> + </li> + <li> + <Faq + question="How can we trial OpenCode inside our organization?"> + Simply install and run an internal trial with your team. Since + OpenCode doesn’t store any data, your developers can get + started right away. + </Faq> + </li> + <li> + <Faq + question="What happens if someone uses the `/share` feature?"> + By default, sharing is disabled. If enabled, conversations are + sent to our share service and cached through our CDN. For + enterprise use, we recommend disabling or self-hosting this + feature. + </Faq> + </li> + <li> + <Faq question="Can OpenCode integrate with our company’s SSO?"> + Yes. Enterprise deployments can include SSO integration so all + sessions and shared conversations are protected by your + authentication system. + </Faq> + </li> + <li> + <Faq question="Can OpenCode be self-hosted?"> + Absolutely. You can fully self-host OpenCode, including the + share feature, ensuring that data and pages are accessible + only after authentication. + </Faq> + </li> + <li> + <Faq + question="How do we get started with enterprise deployment?"> + Contact us to discuss pricing, implementation, and enterprise + options like SSO, private registries, and self-hosting. + </Faq> + </li> + </ul> + </section> + </div> + <Footer /> + </div> + <Legal /> + </main> + ) +} |
