From 4f1c2190ef771f906f863d35e73a2a269bb43f39 Mon Sep 17 00:00:00 2001 From: psrth Date: Tue, 1 Sep 2026 23:39:28 -0700 Subject: [PATCH 1/8] site: import landing page as is --- site/.gitignore | 6 + site/README.md | 14 + site/app/apple-icon.png | Bin 0 -> 4218 bytes site/app/globals.css | 294 +++++ site/app/icon.svg | 11 + site/app/layout.tsx | 51 + site/app/page.tsx | 122 ++ site/components/Background.tsx | 35 + site/components/EvalBlock.tsx | 24 + site/components/Footer.tsx | 20 + site/components/GitHubMark.tsx | 7 + site/components/Illustration.tsx | 81 ++ site/components/InstallBlock.tsx | 26 + site/components/Mark.tsx | 10 + site/components/Nav.tsx | 24 + site/components/Reveal.tsx | 30 + site/components/Row.tsx | 8 + site/components/ThemeToggle.tsx | 35 + site/components/Toasts.tsx | 26 + .../illustrations/MessageThread.tsx | 29 + .../illustrations/SandboxLifecycle.tsx | 41 + site/components/illustrations/SlackCard.tsx | 53 + site/components/illustrations/Terminal.tsx | 62 + site/components/terrain/Terrain.tsx | 99 ++ site/components/terrain/field.ts | 125 ++ site/components/terrain/sim.ts | 435 +++++++ site/lib/evalPrompt.ts | 29 + site/lib/site.ts | 4 + site/next.config.ts | 8 + site/package-lock.json | 1105 +++++++++++++++++ site/package.json | 24 + site/public/og.png | Bin 0 -> 27140 bytes site/tsconfig.json | 21 + 33 files changed, 2859 insertions(+) create mode 100644 site/.gitignore create mode 100644 site/README.md create mode 100644 site/app/apple-icon.png create mode 100644 site/app/globals.css create mode 100644 site/app/icon.svg create mode 100644 site/app/layout.tsx create mode 100644 site/app/page.tsx create mode 100644 site/components/Background.tsx create mode 100644 site/components/EvalBlock.tsx create mode 100644 site/components/Footer.tsx create mode 100644 site/components/GitHubMark.tsx create mode 100644 site/components/Illustration.tsx create mode 100644 site/components/InstallBlock.tsx create mode 100644 site/components/Mark.tsx create mode 100644 site/components/Nav.tsx create mode 100644 site/components/Reveal.tsx create mode 100644 site/components/Row.tsx create mode 100644 site/components/ThemeToggle.tsx create mode 100644 site/components/Toasts.tsx create mode 100644 site/components/illustrations/MessageThread.tsx create mode 100644 site/components/illustrations/SandboxLifecycle.tsx create mode 100644 site/components/illustrations/SlackCard.tsx create mode 100644 site/components/illustrations/Terminal.tsx create mode 100644 site/components/terrain/Terrain.tsx create mode 100644 site/components/terrain/field.ts create mode 100644 site/components/terrain/sim.ts create mode 100644 site/lib/evalPrompt.ts create mode 100644 site/lib/site.ts create mode 100644 site/next.config.ts create mode 100644 site/package-lock.json create mode 100644 site/package.json create mode 100644 site/public/og.png create mode 100644 site/tsconfig.json diff --git a/site/.gitignore b/site/.gitignore new file mode 100644 index 0000000..7a03b74 --- /dev/null +++ b/site/.gitignore @@ -0,0 +1,6 @@ +node_modules +.next +out +next-env.d.ts +*.tsbuildinfo +.DS_Store diff --git a/site/README.md b/site/README.md new file mode 100644 index 0000000..7a9044e --- /dev/null +++ b/site/README.md @@ -0,0 +1,14 @@ +# iris — landing page + +Static Next.js site for iris. Implements the "LANDING v3" Paper artboard. + +``` +npm install +npm run dev # http://localhost:3000 +npm run build # static export to ./out +``` + +- `app/` — layout (fonts, theme bootstrap), page copy, global styles and tokens. +- `components/terrain/` — the hero: `field.ts` (height field, camera, visibility), `sim.ts` (mesh render, gradient-descent agents, sandboxes), `Terrain.tsx` (canvas + controls). +- `components/illustrations/` — the four use-case illustrations. Greyed by default; they activate and animate on hover or when scrolled into view (`components/Illustration.tsx`). +- Theme follows the system setting, with a toggle in the nav (stored in `localStorage`). Append `?theme=dark` or `?theme=light` to force one. diff --git a/site/app/apple-icon.png b/site/app/apple-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ab95ced15a2f70cec5f15c6b31387fbe7c38ea00 GIT binary patch literal 4218 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 literal 0 HcmV?d00001 diff --git a/site/app/globals.css b/site/app/globals.css new file mode 100644 index 0000000..5660f8e --- /dev/null +++ b/site/app/globals.css @@ -0,0 +1,294 @@ +/* ---- tokens ---------------------------------------------------------------- */ +:root { + color-scheme: light; + --bg: #ffffff; + --ink: #111111; + --body: #444444; + --muted: #7e7e7e; + --muted-2: #9a9a9a; + --hairline: #eaeaea; + --hairline-2: #e5e5e5; + --line: #dadada; + --dash: #9a9a9a; + --surface: #ffffff; + --surface-2: #f0f0f0; + --chip: #f0f0f0; + --cobalt: #2447d6; + --vermilion: #de4a2c; + --moss: #3b8a4e; + --amber: #c8901a; + --violet: #7b4fd6; + --mesh-line: #dadada; + --mesh-fill: #ffffff; + --imessage: #1b8cff; + --ease-out: cubic-bezier(0.23, 1, 0.32, 1); + --sh-cmd: #2f8f3f; + --sh-flag: #1f8fa8; + --sh-op: #b8860b; + --sh-claude: #d97a2b; +} +[data-theme="dark"] { + color-scheme: dark; + --bg: #000a0f; + --ink: #f2f2f2; + --body: #bdbdbd; + --muted: #8a8a8a; + --muted-2: #6f6f6f; + --hairline: #242424; + --hairline-2: #2a2a2a; + --line: #363636; + --dash: #6f6f6f; + --surface: #141414; + --surface-2: #232323; + --chip: #000a0f; + --cobalt: #5b78f0; + --vermilion: #f0653f; + --moss: #52b36c; + --amber: #e0a83a; + --violet: #9c78f0; + --mesh-line: #2c2c2c; + --mesh-fill: #000a0f; + --imessage: #1b8cff; + --sh-cmd: #5fbf6f; + --sh-flag: #4fc1d1; + --sh-op: #e0b640; + --sh-claude: #f0955a; +} + +/* ---- base ------------------------------------------------------------------ */ +* { box-sizing: border-box; } +html, body { margin: 0; background: var(--bg); color: var(--ink); } +body { + font-family: var(--font-mono), ui-monospace, SFMono-Regular, Menlo, monospace; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + overflow-x: hidden; +} +a { color: inherit; text-decoration: none; } +.bgShader { position: fixed; inset: 0; z-index: 0; pointer-events: none; } +.page { position: relative; z-index: 1; } +button { font: inherit; color: inherit; } + +.lane { max-width: 824px; margin: 0 auto; padding: 0 20px; } +.wide { max-width: 1160px; margin: 0 auto; padding: 0 20px; } +.sans { font-family: var(--font-inter), system-ui, -apple-system, sans-serif; } + +/* ---- nav ------------------------------------------------------------------- */ +.nav { + display: flex; align-items: center; justify-content: space-between; + height: 128px; padding-top: 24px; + border-bottom: 1px solid var(--hairline); + font-family: var(--font-inter), system-ui, sans-serif; +} +.brand { display: flex; gap: 10px; align-items: center; font-size: 13px; letter-spacing: 0.02em; } +.brand svg { color: var(--ink); } +.brandName { font-weight: 600; color: var(--ink); } +.brandSub { font-weight: 500; color: var(--muted-2); } +.navRight { display: flex; align-items: center; gap: 12px; } +.square { + width: 32px; height: 32px; display: inline-flex; align-items: center; justify-content: center; + background: var(--chip); color: var(--ink); border: 0; padding: 0; cursor: pointer; + transition: background 0.2s; +} +.square:hover { background: var(--line); } +.square.plain { background: transparent; } +.square.plain:hover { background: var(--chip); } +.ghbtn { + display: inline-flex; align-items: center; gap: 8px; height: 32px; padding: 0 12px; + background: var(--chip); color: var(--ink); font-size: 12px; font-weight: 500; letter-spacing: 0.02em; + transition: background 0.2s; +} +.ghbtn:hover { background: var(--line); } + +/* ---- typography ------------------------------------------------------------ */ +.label { + font-family: var(--font-mono), monospace; font-weight: 500; font-size: 12px; line-height: 22px; + letter-spacing: 0.1em; color: var(--ink); text-transform: uppercase; +} +.copy p { + margin: 0 0 14px; font-weight: 400; font-size: 12px; line-height: 22px; + letter-spacing: 0.05em; color: var(--body); text-transform: uppercase; +} +.copy p:last-child { margin-bottom: 0; } +.sub { + display: block; font-weight: 500; font-size: 12px; line-height: 22px; + letter-spacing: 0.05em; color: var(--ink); text-transform: uppercase; +} +pre.cmd.copyable { cursor: pointer; outline: none; } +pre.cmd .sh-claude { color: var(--sh-claude); } +pre.cmd .sh-p { color: var(--muted-2); } +pre.cmd .sh-cmd { color: var(--sh-cmd); } +pre.cmd .sh-flag { color: var(--sh-flag); } +pre.cmd .sh-op { color: var(--sh-op); } +.copy .linkBtn { all: unset; cursor: pointer; font: inherit; letter-spacing: inherit; text-transform: inherit; color: inherit; } +.copy .linkBtn:focus-visible { outline: 1px solid var(--ink); outline-offset: 2px; } +.copy .link { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--muted-2); transition: color 150ms ease; } +@media (hover: hover) and (pointer: fine) { .copy .link:hover { color: var(--ink); } } +pre.cmd { + margin: 0; font-family: inherit; font-weight: 400; font-size: 12px; line-height: 22px; + letter-spacing: 0.05em; color: var(--ink); white-space: pre; overflow-x: auto; +} + +/* ---- rows ------------------------------------------------------------------ */ +.row { display: grid; grid-template-columns: 184px 1fr; padding: 36px 0; } +/* first row: text sits as far below the hairline as the nav buttons sit above it */ +.lane.first .reveal:first-child .row { padding-top: 50px; padding-bottom: 22px; } +.lane.first .reveal:last-child .row { padding-top: 22px; } +.rowBody { min-width: 0; } +.how { display: flex; flex-direction: column; gap: 22px; margin-top: 22px; } +.howItem .sub { margin-bottom: 2px; } +.uc { margin-bottom: 40px; } +.uc:last-child { margin-bottom: 0; } + +/* ---- terrain --------------------------------------------------------------- */ +.terrain { padding: 4px 0 56px; } +.terrainWrap { width: 100%; overflow: hidden; display: flex; justify-content: center; } +.terrainWrap canvas { display: block; flex: none; } +.terrainBar { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding-top: 6px; } +.chips { display: flex; gap: 8px; } +.chip { + font-family: var(--font-mono), monospace; font-weight: 500; font-size: 11px; line-height: 14px; letter-spacing: 0.1em; + color: var(--ink); background: transparent; border: 1px solid var(--ink); height: 28px; padding: 0 12px; cursor: pointer; + transition: background 0.15s, color 0.15s; +} +.chip:hover:not(:disabled) { background: var(--ink); color: var(--bg); } +.chip:disabled { opacity: 0.3; cursor: default; } +.readout { font-size: 11px; line-height: 14px; letter-spacing: 0.1em; color: var(--muted); white-space: nowrap; } + +/* ---- illustrations: greyed until hovered / scrolled into view -------------- */ +.illus { + margin-top: 14px; + opacity: 0.4; filter: grayscale(1); + transition: opacity 0.5s ease, filter 0.5s ease; + font-family: var(--font-inter), system-ui, sans-serif; color: var(--ink); +} +.illus.active { opacity: 1; filter: none; } + +.typing { display: inline-flex; gap: 4px; height: 19px; align-items: center; } +.typing i { width: 5px; height: 5px; border-radius: 50%; background: var(--muted); animation: blink 1s infinite; } +.typing i:nth-child(2) { animation-delay: 0.2s; } +.typing i:nth-child(3) { animation-delay: 0.4s; } +@keyframes blink { 0%, 80%, 100% { opacity: 0.25; } 40% { opacity: 1; } } +.caret { display: inline-block; width: 1px; height: 12px; background: currentColor; margin-left: 2px; vertical-align: -2px; animation: caret 1s steps(2) infinite; } +@keyframes caret { 50% { opacity: 0; } } + +/* slack card */ +.slack { display: flex; gap: 12px; padding: 16px; border: 1px solid var(--hairline-2); } +.avatar { + width: 28px; height: 28px; flex: none; background: var(--ink); color: var(--bg); + font-size: 10px; font-weight: 500; line-height: 28px; text-align: center; letter-spacing: 0.06em; +} +.slackBody { min-width: 0; flex: 1; } +.slackMeta { display: flex; gap: 10px; align-items: baseline; font-size: 13px; } +.slackMeta b { font-weight: 600; } +.slackMeta span { font-size: 11px; color: var(--muted); } +.slack p { margin: 0; font-size: 13px; line-height: 19px; } +.typewrap { position: relative; } +.typewrap .ghost { visibility: hidden; } +.typewrap .live { position: absolute; left: 0; top: 0; right: 0; } +.typewrap .typing.overlay { position: absolute; left: 0; top: 0; } +.tokenChip { + display: inline-flex; align-items: center; gap: 8px; height: 28px; padding: 0 10px; margin-top: 10px; + border: 1px solid var(--line); font-size: 12px; font-weight: 500; + opacity: 0; transform: translateY(4px); transition: opacity 0.4s, transform 0.4s; +} +.tokenChip.in { opacity: 1; transform: none; } +.tokenChip small { font-size: 10px; letter-spacing: 0.06em; color: var(--muted); font-weight: 500; } +.tokenChip .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--vermilion); } + +/* sandbox lifecycle (svg) */ +.life { display: block; width: 100%; height: auto; padding: 20px; border: 1px solid var(--hairline-2); overflow: visible; } +.life .box { fill: none; stroke: var(--dash); stroke-dasharray: 4 3; opacity: 0; transition: opacity 0.5s; } +.life .box.faint { stroke: var(--line); } +.life .hollow { fill: none; stroke: var(--moss); stroke-width: 1.5; opacity: 0; transition: opacity 0.5s; } +.life .solid { fill: var(--moss); opacity: 0; transition: opacity 0.5s; } +.life .arrow { fill: none; stroke: var(--line); opacity: 0; transition: opacity 0.4s; } +.life .cap { font-size: 11px; letter-spacing: 0.04em; fill: var(--muted); opacity: 0; transition: opacity 0.5s; } +.life .cap.faint { fill: var(--muted-2); } +.life .cap.strong { fill: var(--ink); font-weight: 600; } +.life .bar { stroke: var(--ink); transform-box: fill-box; transform-origin: left; transform: scaleX(0); transition: transform 0.5s ease; } +.life .bar.on { transform: scaleX(1); } +.life .logline { stroke: var(--ink); stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset 0.9s ease; } +.life .logline.on { stroke-dashoffset: 0; } +.life .on { opacity: 1; } + +/* message thread */ +.thread { display: flex; flex-direction: column; gap: 8px; padding: 16px; border: 1px solid var(--hairline-2); } +.msg { + max-width: 68%; padding: 9px 13px; font-size: 13px; line-height: 19px; border-radius: 16px; + opacity: 0; transform: translateY(6px); transition: opacity 0.35s ease, transform 0.35s ease; +} +.msg.in { opacity: 1; transform: none; } +.msg.me { align-self: flex-end; background: var(--imessage); color: #fff; border-bottom-right-radius: 4px; } +.msg.them { align-self: flex-start; background: var(--surface-2); color: var(--ink); border-bottom-left-radius: 4px; } +.msg.typingB { padding: 9px 12px; } +.slot { position: relative; display: flex; flex-direction: column; align-items: flex-start; } +.msg.overlay { position: absolute; left: 0; top: 0; } +.status { align-self: flex-end; font-size: 10px; letter-spacing: 0.06em; color: var(--muted); padding: 0 6px; opacity: 0; transition: opacity 0.35s; } +.status.in { opacity: 1; } + +/* terminal */ +.term { border: 1px solid var(--hairline-2); } +.termBar { display: flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px; border-bottom: 1px solid var(--hairline-2); font-size: 12px; color: var(--muted); } +.termBar i { width: 8px; height: 8px; border-radius: 50%; border: 1px solid var(--muted-2); flex: none; } +.termBar span { padding-left: 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.termBody { + padding: 12px 16px 14px; overflow-x: auto; + font-family: var(--font-mono), monospace; font-size: 11px; line-height: 20px; letter-spacing: 0.02em; color: var(--ink); +} +.termBody pre { margin: 0; font: inherit; white-space: pre; min-height: 20px; } +.line { opacity: 0; transition: opacity 0.3s; } +.line.in { opacity: 1; } +.trow { display: flex; align-items: center; gap: 10px; height: 20px; opacity: 0; transition: opacity 0.3s; } +.trow.in { opacity: 1; } +.trow i { width: 7px; height: 7px; border-radius: 50%; flex: none; } +.trow.cobalt i { background: var(--cobalt); } +.trow.vermilion i { background: var(--vermilion); } +.trow.moss i { background: var(--moss); } +.trow.human i { border: 1px solid var(--ink); } +.trow.human pre { color: var(--muted); } + +/* ---- reveal: fade blocks in once as they enter the viewport ---------------- */ +.js .reveal { + opacity: 0; transform: translateY(8px); + transition: opacity 300ms var(--ease-out), transform 300ms var(--ease-out); +} +.js .reveal[data-visible] { opacity: 1; transform: none; } +.nav { animation: navIn 300ms var(--ease-out) both; } +@keyframes navIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } } + +/* ---- toast (sonner, unstyled) ---------------------------------------------- */ +.toast { + display: flex; align-items: center; height: 36px; padding: 0 14px; + background: var(--surface); color: var(--ink); border: 1px solid var(--hairline-2); + font-family: var(--font-mono), monospace; font-size: 11px; letter-spacing: 0.1em; white-space: nowrap; + width: max-content; margin-left: auto; +} + +/* ---- footer ---------------------------------------------------------------- */ +.footerSpace { height: 200px; } +.footer { + display: flex; align-items: center; justify-content: space-between; height: 96px; + border-top: 1px solid var(--hairline); + font-family: var(--font-inter), system-ui, sans-serif; font-size: 12px; letter-spacing: 0.02em; color: var(--muted); +} + +/* ---- responsive ------------------------------------------------------------ */ +@media (max-width: 719px) { + .nav { height: 88px; padding-top: 12px; } + .terrain .wide { padding: 0; } + .life { padding: 14px; } + .life .cap { font-size: 15px; } + .row { grid-template-columns: 1fr; gap: 6px; padding: 28px 0; } + .terrainBar { flex-wrap: wrap; } + .msg { max-width: 84%; } + .footerSpace { height: 120px; } + .footer { height: 80px; } +} + +@media (prefers-reduced-motion: reduce) { + .js .reveal { transform: none; transition: opacity 200ms ease; } + .nav { animation: none; } + .illus, .msg, .tokenChip, .life *, .line, .trow { transition: none; } + .typing i, .caret { animation: none; } +} diff --git a/site/app/icon.svg b/site/app/icon.svg new file mode 100644 index 0000000..4a7592d --- /dev/null +++ b/site/app/icon.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/site/app/layout.tsx b/site/app/layout.tsx new file mode 100644 index 0000000..31e7e8c --- /dev/null +++ b/site/app/layout.tsx @@ -0,0 +1,51 @@ +import type { Metadata, Viewport } from "next"; +import { DM_Mono, Inter } from "next/font/google"; +import { SITE_DESCRIPTION, SITE_TITLE } from "@/lib/site"; +import Toasts from "@/components/Toasts"; +import Background from "@/components/Background"; +import "./globals.css"; + +const inter = Inter({ subsets: ["latin"], variable: "--font-inter", display: "swap" }); +const dmMono = DM_Mono({ subsets: ["latin"], weight: ["400", "500"], variable: "--font-mono", display: "swap" }); + +export const metadata: Metadata = { + metadataBase: new URL("https://iris-tl.dev"), + title: SITE_TITLE, + description: SITE_DESCRIPTION, + openGraph: { + title: SITE_TITLE, + description: SITE_DESCRIPTION, + url: "https://iris-tl.dev", + siteName: "iris", + images: [{ url: "/og.png", width: 1200, height: 630, alt: "iris — transport layer for AI agents" }], + type: "website", + }, + twitter: { card: "summary_large_image", title: SITE_TITLE, description: SITE_DESCRIPTION, images: ["/og.png"] }, +}; + +export const viewport: Viewport = { + width: "device-width", + initialScale: 1, + themeColor: [ + { media: "(prefers-color-scheme: light)", color: "#FFFFFF" }, + { media: "(prefers-color-scheme: dark)", color: "#000a0f" }, + ], +}; + +// Resolve the theme before first paint: ?theme= override, stored preference, else the system setting. +const themeScript = `(function(){try{var q=new URLSearchParams(location.search).get('theme');var s=q||localStorage.getItem('iris-theme');var d=s?s==='dark':matchMedia('(prefers-color-scheme: dark)').matches;document.documentElement.setAttribute('data-theme',d?'dark':'light');}catch(e){}document.documentElement.classList.add('js');})();`; + +export default function RootLayout({ children }: { children: React.ReactNode }) { + return ( + + +