Promote AgentCompany-New to the repository root and retire the old app

The legacy application - its src, tests, landing site, promo assets, docs,
release tooling, CI workflows, and root configs - leaves the tree; it stays
reachable in history. Everything under AgentCompany-New moves up unchanged:
same package name, so the production userData/database path is untouched,
and e2e/build scripts already resolved paths relative to the project. The
developer cred.txt stays gitignored at its new location. Full verify:ci
passes from the new root.
This commit is contained in:
ZacharyZhang-NY committed 2026-07-07 00:04:13 -04:00
1 parent 2350f744e3
commit 07d0b4587d
1904 files changed
+1133 -282075

No files matched your search

-5
View File
@@ -1,5 +0,0 @@
.next/
.wrangler/
out/
node_modules/
npm-debug.log*
-14
View File
@@ -1,14 +0,0 @@
# AgentCompany Landing
Next.js landing page for the AgentCompany desktop release lane.
## Copy Sources
| Surface | Source |
|---|---|
| Download cards | `landing/components/release-links.generated.ts` |
| Platform FAQ | `landing/lib/platform-support.ts` |
| Hero, How It Works, software JSON-LD features | `landing/lib/product-narrative.ts` |
| Runtime download URLs | generated from `scripts/generate-landing-release-links.mjs` |
The public story mirrors the first-run desktop flow: Welcome, Requirements, Providers, Company, Team Models, Mode, Mission, Launch.
-21
View File
@@ -1,21 +0,0 @@
/*
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://static.cloudflareinsights.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com data:; img-src 'self' data:; connect-src 'self' https://cloudflareinsights.com; base-uri 'self'; form-action 'self'; frame-ancestors 'none'
Permissions-Policy: camera=(), microphone=(), geolocation=()
Referrer-Policy: strict-origin-when-cross-origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
/screenshots/*
Cache-Control: public, max-age=31536000, immutable
/assets/*
Cache-Control: public, max-age=31536000, immutable
/_next/static/*
Cache-Control: public, max-age=31536000, immutable
/favicon.ico
Cache-Control: public, max-age=31536000, immutable
/icon.png
Cache-Control: public, max-age=31536000, immutable
-128
View File
@@ -1,128 +0,0 @@
@import "tailwindcss";
@theme {
--font-sans: "Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
--font-serif: "Space Grotesk", "Inter", ui-sans-serif, system-ui, sans-serif;
--font-mono: "Space Mono", ui-monospace, SFMono-Regular, monospace;
}
/* ── Light Theme (Cohere) ── */
:root {
--bg: #ffffff;
--bg-subtle: #fafafa;
--panel: #ffffff;
--panel-soft: #fafafa;
--text: #000000;
--text-secondary: #212121;
--muted: #93939f;
--muted-strong: #565650;
--accent: #1863dc;
--accent-hover: #1352b8;
--accent-soft: rgba(24, 99, 220, 0.06);
--text-on-accent: #ffffff;
--cta: #000000;
--cta-hover: #212121;
--cta-soft: rgba(0, 0, 0, 0.04);
--text-on-cta: #ffffff;
--text-on-cta-muted: rgba(255, 255, 255, 0.75);
--text-on-cta-faint: rgba(255, 255, 255, 0.60);
--border: rgba(0, 0, 0, 0.06);
--border-cool: #d9d9dd;
--glow-warm: rgba(24, 99, 220, 0.04);
--glow-accent: rgba(24, 99, 220, 0.03);
--section-alt: rgba(0, 0, 0, 0.015);
}
/* ── Dark Theme (Cohere) ── */
.dark {
--bg: #17171c;
--bg-subtle: #1e1e24;
--panel: #212126;
--panel-soft: #2a2a30;
--text: #fafafa;
--text-secondary: #d9d9dd;
--muted: #93939f;
--muted-strong: #b8b8b2;
--accent: #1863dc;
--accent-hover: #2070e8;
--accent-soft: rgba(24, 99, 220, 0.12);
--text-on-accent: #ffffff;
--cta: #fafafa;
--cta-hover: #e5e5e5;
--cta-soft: rgba(250, 250, 250, 0.06);
--text-on-cta: #17171c;
--text-on-cta-muted: rgba(23, 23, 28, 0.75);
--text-on-cta-faint: rgba(23, 23, 28, 0.60);
--border: rgba(250, 250, 250, 0.08);
--border-cool: #333338;
--glow-warm: rgba(24, 99, 220, 0.06);
--glow-accent: rgba(24, 99, 220, 0.04);
--section-alt: rgba(24, 99, 220, 0.025);
}
/* ── Base ── */
html {
scroll-behavior: smooth;
}
body {
background-color: var(--bg);
color: var(--text);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
line-height: 1.65;
}
::selection {
background-color: var(--accent);
color: var(--text-on-accent);
}
:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
:focus:not(:focus-visible) {
outline: none;
}
/* ── Scrollbar ── */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: var(--border);
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--muted);
}
* {
scrollbar-width: thin;
scrollbar-color: var(--border) transparent;
}
/* ── Reduced Motion ── */
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
-203
View File
@@ -1,203 +0,0 @@
import type { Metadata } from "next";
import "./globals.css";
import { ThemeProvider } from "../components/theme-provider";
import {
landingHowItWorksNarrative,
landingStructuredDataNarrative,
} from "../lib/product-narrative";
import { platformSupportSummary } from "../lib/platform-support";
const description =
"Local-first desktop control plane for autonomous AI companies. Set a goal, let an AI CEO assemble specialists, delegate work, and deliver code, research, content, and operations from your desktop.";
export const metadata: Metadata = {
metadataBase: new URL("https://agent-company.dev"),
title: "AgentCompany - Launch an Autonomous AI Company from Your Desktop",
description,
keywords: [
"AI company",
"autonomous AI agents",
"AI automation",
"multi-agent system",
"AI CEO",
"AI agent orchestration",
"autonomous agents desktop app",
"AI task delegation",
"AI team management",
"AI code generation",
"AI content generation",
"AI research automation",
"self-organizing AI",
"AI workforce",
"Claude Code",
"Codex CLI",
"Gemini CLI",
"multi-agent framework",
"AI company builder",
],
openGraph: {
title: "AgentCompany - Launch an Autonomous AI Company from Your Desktop",
description,
url: "https://agent-company.dev/",
siteName: "AgentCompany",
locale: "en_US",
images: [
{
url: "/screenshots/Dashboard.jpeg",
width: 1920,
height: 1080,
alt: "AgentCompany dashboard showing autonomous AI agents managing a company",
},
],
type: "website",
},
twitter: {
card: "summary_large_image",
title: "AgentCompany - Launch an Autonomous AI Company from Your Desktop",
description,
images: ["/screenshots/Dashboard.jpeg"],
},
robots: {
index: true,
follow: true,
},
icons: {
icon: "/favicon.ico",
apple: "/icon.png",
},
};
const themeScript = `
(function(){try{var t=localStorage.getItem("agentcompany-theme");if(t==="dark"||(!t&&window.matchMedia("(prefers-color-scheme:dark)").matches)){document.documentElement.classList.add("dark")}}catch(e){}})();
`;
const softwareJsonLd = {
"@context": "https://schema.org",
"@type": "SoftwareApplication",
name: "AgentCompany",
applicationCategory: "BusinessApplication",
operatingSystem: "macOS, Windows, Linux",
url: "https://agent-company.dev",
downloadUrl: "https://agent-company.dev/#download",
screenshot: "https://agent-company.dev/screenshots/Dashboard.jpeg",
softwareVersion: landingStructuredDataNarrative.softwareVersion,
description,
featureList: landingStructuredDataNarrative.featureList,
author: { "@type": "Organization", name: "AgentCompany", url: "https://agent-company.dev" },
};
const organizationJsonLd = {
"@context": "https://schema.org",
"@type": "Organization",
name: "AgentCompany",
url: "https://agent-company.dev",
logo: "https://agent-company.dev/icon.png",
};
const howToJsonLd = {
"@context": "https://schema.org",
"@type": "HowTo",
name: "How to Launch an Autonomous AI Company with AgentCompany",
description: "Complete the AgentCompany desktop first-run flow and queue the first mission.",
step: landingHowItWorksNarrative.steps.map((step) => ({
"@type": "HowToStep",
position: step.number,
name: step.title,
text: step.description,
})),
};
const faqJsonLd = {
"@context": "https://schema.org",
"@type": "FAQPage",
mainEntity: [
{
"@type": "Question",
name: "What is AgentCompany?",
acceptedAnswer: {
"@type": "Answer",
text: "AgentCompany is a local-first desktop application for launching and operating autonomous AI companies. You define the mission, an AI CEO organizes the team, delegates work, and coordinates delivery across engineering, design, research, and operations.",
},
},
{
"@type": "Question",
name: "How do I download AgentCompany?",
acceptedAnswer: {
"@type": "Answer",
text: platformSupportSummary.downloadAnswer,
},
},
{
"@type": "Question",
name: "What platforms does AgentCompany support?",
acceptedAnswer: {
"@type": "Answer",
text: platformSupportSummary.platformAnswer,
},
},
{
"@type": "Question",
name: "What AI models can AgentCompany use?",
acceptedAnswer: {
"@type": "Answer",
text: "AgentCompany supports multiple AI runtimes as first-class connectors: Claude Code, Codex CLI, and Gemini CLI. You can connect your preferred provider during setup.",
},
},
{
"@type": "Question",
name: "How does the AI CEO work?",
acceptedAnswer: {
"@type": "Answer",
text: "When you create a company with a goal, the AI CEO agent analyzes the objective, creates the necessary departments, hires specialized agents for each role, builds an org chart, and delegates tasks. The CEO monitors progress, handles blockers, and coordinates cross-department work.",
},
},
{
"@type": "Question",
name: "Is my data private? Does it leave my machine?",
acceptedAnswer: {
"@type": "Answer",
text: "AgentCompany is local-first. All data is stored in a local SQLite database on your machine. Secrets are encrypted via an OS-level keychain. The only external communication is between your machine and your AI provider's API.",
},
},
{
"@type": "Question",
name: "What can an AI company actually deliver?",
acceptedAnswer: {
"@type": "Answer",
text: "AI companies built with AgentCompany can produce code, content, research, business documents, and more. The deliverables depend on the goal you set and the AI runtime you connect.",
},
},
{
"@type": "Question",
name: "How are updates delivered?",
acceptedAnswer: {
"@type": "Answer",
text: "Desktop updates are published to a Cloudflare-hosted release lane. macOS builds include the signed update metadata required for in-app update checks, while Windows and Linux builds are delivered from the same release host for manual installation.",
},
},
],
};
export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<meta name="googlebot" content="index, follow, max-video-preview:-1, max-image-preview:large, max-snippet:-1" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
<link
href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=Inter:wght@300;400;500;600;700&family=Space+Mono:wght@400;700&display=swap"
rel="stylesheet"
/>
<script dangerouslySetInnerHTML={{ __html: themeScript }} />
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(softwareJsonLd) }} />
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(organizationJsonLd) }} />
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(howToJsonLd) }} />
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(faqJsonLd) }} />
</head>
<body className="bg-[var(--bg)] text-[var(--text)] antialiased transition-colors duration-300">
<ThemeProvider>{children}</ThemeProvider>
</body>
</html>
);
}
-34
View File
@@ -1,34 +0,0 @@
import { DownloadSection } from "../components/download-section";
import { FAQ } from "../components/faq";
import { Features } from "../components/features";
import { Footer } from "../components/footer";
import { Hero } from "../components/hero";
import { HowItWorks } from "../components/how-it-works";
import { Navbar } from "../components/navbar";
import { RuntimesBar } from "../components/runtimes-bar";
export default function Page() {
return (
<>
<a
href="#main"
className="sr-only focus:not-sr-only focus:fixed focus:top-4 focus:left-4 focus:z-[100] focus:px-4 focus:py-2 focus:rounded-lg focus:bg-[var(--accent)] focus:text-[var(--text-on-accent)] focus:text-sm focus:font-medium"
>
Skip to content
</a>
<Navbar />
<main id="main">
<Hero />
<RuntimesBar />
<Features />
<HowItWorks />
<FAQ />
<DownloadSection />
</main>
<Footer />
</>
);
}
-158
View File
@@ -1,158 +0,0 @@
"use client";
import { useEffect, useRef } from "react";
const glyphs = " .'`^,:;Il!i><~+_-?][}{1)(|\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$";
function parseRgbHex(hex: string): [number, number, number] {
const value = hex.replace("#", "").trim();
if (value.length !== 6) return [128, 128, 128];
return [
Number.parseInt(value.slice(0, 2), 16),
Number.parseInt(value.slice(2, 4), 16),
Number.parseInt(value.slice(4, 6), 16),
];
}
export function AsciiBackground({
cssVar = "--accent",
baseOpacity = 0.08,
speed = 1,
}: {
cssVar?: string;
baseOpacity?: number;
speed?: number;
}) {
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const containerRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
const canvas = canvasRef.current;
const container = containerRef.current;
if (!canvas || !container) return;
const context = canvas.getContext("2d");
if (!context) return;
let width = 0;
let height = 0;
let rgb: [number, number, number] = [128, 128, 128];
let phase = 0;
let frame = 0;
let isVisible = true;
const pointer = { x: -9999, y: -9999 };
const updateColor = () => {
const value = getComputedStyle(document.documentElement).getPropertyValue(cssVar).trim();
if (value.startsWith("#")) {
rgb = parseRgbHex(value);
}
};
updateColor();
const mutationObserver = new MutationObserver(updateColor);
mutationObserver.observe(document.documentElement, {
attributes: true,
attributeFilter: ["class"],
});
const intersectionObserver = new IntersectionObserver(
(entries) => {
const [entry] = entries;
isVisible = entry?.isIntersecting ?? true;
},
{ threshold: 0 },
);
intersectionObserver.observe(container);
const resize = () => {
width = container.clientWidth;
height = container.clientHeight;
const devicePixelRatio = Math.min(window.devicePixelRatio || 1, 2);
canvas.width = width * devicePixelRatio;
canvas.height = height * devicePixelRatio;
context.setTransform(devicePixelRatio, 0, 0, devicePixelRatio, 0, 0);
};
const handlePointer = (event: MouseEvent) => {
const rect = container.getBoundingClientRect();
pointer.x = event.clientX - rect.left;
pointer.y = event.clientY - rect.top;
};
const render = () => {
frame = requestAnimationFrame(render);
if (!isVisible) return;
context.clearRect(0, 0, width, height);
context.font = "14px monospace";
context.textAlign = "center";
context.textBaseline = "middle";
const columns = Math.ceil(width / 14);
const rows = Math.ceil(height / 14);
const [red, green, blue] = rgb;
const pointerX = pointer.x;
const pointerY = pointer.y;
for (let row = 0; row < rows; row += 1) {
for (let column = 0; column < columns; column += 1) {
const centerX = column * 14 + 7;
const centerY = row * 14 + 7;
const value =
Math.sin(0.05 * column + phase) * Math.cos(0.05 * row + phase) +
Math.sin(0.012 * column - 0.7 * phase) * Math.cos(0.1 * row) * 0.5;
if (Math.abs(value) < 0.3) continue;
const index = Math.floor(Math.abs(value) * glyphs.length);
let glyph = glyphs[index % glyphs.length];
if (!glyph.trim()) continue;
let alpha = Math.abs(value) * baseOpacity;
const deltaX = centerX - pointerX;
const deltaY = centerY - pointerY;
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance < 110) {
const intensity = 1 - distance / 110;
glyph = Math.random() > 0.5 ? "0" : "1";
alpha = 0.35 * intensity;
const drift = distance > 1 ? 7 * intensity : 0;
const offsetX = (deltaX / distance) * drift;
const offsetY = (deltaY / distance) * drift;
context.fillStyle = `rgba(${red},${green},${blue},${alpha})`;
context.fillText(glyph, centerX - offsetX, centerY - offsetY);
} else {
context.fillStyle = `rgba(${red},${green},${blue},${alpha})`;
context.fillText(glyph, centerX, centerY);
}
}
}
phase += 0.005 * speed;
};
resize();
window.addEventListener("resize", resize);
window.addEventListener("mousemove", handlePointer);
render();
return () => {
cancelAnimationFrame(frame);
window.removeEventListener("resize", resize);
window.removeEventListener("mousemove", handlePointer);
mutationObserver.disconnect();
intersectionObserver.disconnect();
};
}, [baseOpacity, cssVar, speed]);
return (
<div ref={containerRef} className="absolute inset-0 overflow-hidden pointer-events-none" aria-hidden="true">
<canvas ref={canvasRef} className="block w-full h-full" />
</div>
);
}
-105
View File
@@ -1,105 +0,0 @@
"use client";
import { useEffect, useState } from "react";
import { motion } from "framer-motion";
import { platformDownloads, releaseVersion } from "./release-links.generated";
import { DOWNLOAD_COUNT_SEED, getTrackedDownloadHref } from "../lib/downloads";
export function DownloadSection() {
const [downloadCount, setDownloadCount] = useState(DOWNLOAD_COUNT_SEED);
useEffect(() => {
let cancelled = false;
async function loadDownloadCount() {
try {
const response = await fetch("/api/download-stats", { cache: "no-store" });
if (!response.ok) {
throw new Error(`Failed to fetch download count: ${response.status}`);
}
const data = await response.json() as { downloads?: number };
if (!cancelled && typeof data.downloads === "number") {
setDownloadCount(data.downloads);
}
} catch {
// Keep the seeded count visible when the dynamic endpoint is unavailable.
}
}
void loadDownloadCount();
return () => {
cancelled = true;
};
}, []);
return (
<section id="download" className="py-24 lg:py-40 px-4 sm:px-6 lg:px-8">
<div className="mx-auto max-w-6xl">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.3 }}
transition={{ duration: 0.6, ease: [0.16, 1, 0.3, 1] }}
className="text-center mb-16 lg:mb-20"
>
<p className="font-mono text-xs font-medium uppercase tracking-[0.25em] text-[var(--accent)] mb-5">
Download
</p>
<h2 className="font-serif text-[clamp(2rem,1.5rem+2.5vw,3.25rem)] tracking-[-0.01em] text-[var(--text)]">
Install the Right Build for Your Machine
</h2>
<p className="text-[var(--muted)] text-lg mt-5 leading-relaxed">
Version {releaseVersion} · {downloadCount.toLocaleString("en-US")} downloads
</p>
</motion.div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 lg:gap-8">
{platformDownloads.map((download, index) => (
<motion.div
key={download.id}
initial={{ opacity: 0, y: 24 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.3 }}
transition={{ duration: 0.5, delay: 0.08 * index, ease: [0.16, 1, 0.3, 1] }}
className="rounded-[22px] border border-[var(--border)] bg-[var(--panel)] p-6 lg:p-7"
>
<p className="font-mono text-xs uppercase tracking-[0.25em] text-[var(--muted)] mb-4">
{download.title}
</p>
<p className="text-xs text-[var(--muted)] mb-4">{download.note}</p>
<div className="space-y-2.5">
{download.assets.map((asset) => (
<a
key={asset.id}
href={getTrackedDownloadHref(asset.id)}
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-between rounded-[16px] border border-[var(--border)] bg-[var(--panel-soft)] px-4 py-3 text-sm text-[var(--text)] transition-colors duration-200 hover:border-[var(--accent)] hover:text-[var(--accent)]"
>
<span className="font-semibold tracking-tight">{asset.label}</span>
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
className="shrink-0 ml-2 opacity-40"
>
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
<polyline points="7 10 12 15 17 10" />
<line x1="12" y1="15" x2="12" y2="3" />
</svg>
</a>
))}
</div>
</motion.div>
))}
</div>
</div>
</section>
);
}
-109
View File
@@ -1,109 +0,0 @@
"use client";
import { motion } from "framer-motion";
import { useState } from "react";
import { platformSupportSummary } from "../lib/platform-support";
const faqs = [
{
question: "What is AgentCompany?",
answer:
"AgentCompany is a local-first desktop application for launching and operating autonomous AI companies. You define the mission, an AI CEO organizes the team, delegates work, and coordinates delivery across engineering, design, research, and operations.",
},
{
question: "How do I download AgentCompany?",
answer: platformSupportSummary.downloadAnswer,
},
{
question: "What platforms does AgentCompany support?",
answer: platformSupportSummary.platformAnswer,
},
{
question: "What AI models can AgentCompany use?",
answer:
"AgentCompany supports multiple AI runtimes as first-class connectors: Claude Code (Anthropic), Codex CLI (OpenAI), and Gemini CLI (Google). You can connect your preferred provider during setup.",
},
{
question: "How does the AI CEO work?",
answer:
"When you create a company with a goal, the AI CEO agent analyzes the objective, creates the necessary departments (Engineering, Design, Marketing, etc.), hires specialized agents for each role, builds an org chart, and delegates tasks. The CEO monitors progress, handles blockers, and coordinates cross-department work — all autonomously.",
},
{
question: "Is my data private? Does it leave my machine?",
answer:
"AgentCompany is local-first. All data is stored in a local SQLite database on your machine. Secrets are encrypted via an OS-level keychain. The only external communication is between your machine and your AI provider's API — no data is sent to AgentCompany servers.",
},
{
question: "What can an AI company actually deliver?",
answer:
"AI companies built with AgentCompany can produce code (full applications, scripts, APIs), content (blog posts, marketing copy, social media), research (competitive analysis, market research), business documents (business plans, technical specs, strategies), and more. The deliverables depend on the goal you set and the AI runtime you connect.",
},
{
question: "How are updates delivered?",
answer:
"Desktop updates are published to a Cloudflare-hosted release lane. macOS builds include the signed update metadata required for in-app update checks, while the Windows and Linux installers and packages are distributed from the same release host.",
},
];
function FaqItem({ question, answer, index }: { question: string; answer: string; index: number }) {
const [open, setOpen] = useState(false);
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.3 }}
transition={{ duration: 0.5, delay: 0.06 * index, ease: [0.16, 1, 0.3, 1] }}
className="border-b border-[var(--border)] last:border-b-0"
>
<button
type="button"
onClick={() => setOpen((value) => !value)}
aria-expanded={open}
className="flex w-full items-center justify-between gap-4 py-6 text-left transition-colors duration-200 hover:text-[var(--accent)]"
>
<h3 className="text-base lg:text-lg font-semibold text-[var(--text)] pr-4">{question}</h3>
<span
className={`shrink-0 text-[var(--muted)] transition-transform duration-300 ${open ? "rotate-45" : ""}`}
aria-hidden="true"
>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<line x1="12" y1="5" x2="12" y2="19" />
<line x1="5" y1="12" x2="19" y2="12" />
</svg>
</span>
</button>
<div className={`overflow-hidden transition-all duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] ${open ? "max-h-96 pb-6" : "max-h-0"}`}>
<p className="text-[var(--muted-strong)] leading-relaxed text-base pr-12">{answer}</p>
</div>
</motion.div>
);
}
export function FAQ() {
return (
<section id="faq" className="py-24 lg:py-40 px-4 sm:px-6 lg:px-8">
<div className="mx-auto max-w-3xl">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.3 }}
transition={{ duration: 0.6, ease: [0.16, 1, 0.3, 1] }}
className="text-center mb-16 lg:mb-20"
>
<p className="font-mono text-xs font-medium uppercase tracking-[0.25em] text-[var(--accent)] mb-5">FAQ</p>
<h2 className="font-serif text-[clamp(2rem,1.5rem+2.5vw,3.25rem)] tracking-[-0.01em] text-[var(--text)]">
Frequently Asked Questions
</h2>
</motion.div>
<div className="border-t border-[var(--border)]">
{faqs.map((item, index) => (
<FaqItem key={item.question} question={item.question} answer={item.answer} index={index} />
))}
</div>
</div>
</section>
);
}
-191
View File
@@ -1,191 +0,0 @@
"use client";
import { motion } from "framer-motion";
const features = [
{
number: "01",
title: "One-Click Company Creation",
description:
"Name your company, describe your mission, connect your AI runtime, and launch. Your first agents start working in under a minute.",
image: "/screenshots/Onboarding.jpeg",
imageAlt: "Company creation onboarding flow with mission and runtime setup",
imageLeft: true,
},
{
number: "02",
title: "Self-Organizing Teams",
description:
"Your AI CEO builds the org chart. It identifies the roles needed, hires specialists, and creates reporting lines — all from a single goal.",
image: "/screenshots/Auto-OrgChart-Team.jpeg",
imageAlt: "AI-generated org chart showing self-organizing team structure",
imageLeft: false,
},
{
number: "03",
title: "Autonomous Task Management",
description:
"Goals break down into tasks automatically. Agents pick up work, report progress, and escalate blockers — you decide when to step in.",
image: "/screenshots/Auto-Task.jpeg",
imageAlt: "Autonomous task board with agents managing work items",
imageLeft: true,
},
{
number: "04",
title: "Real-Time Agent Communication",
description:
"Agents communicate through department channels and direct messages. Watch strategic decisions happen in real time, like a Slack workspace you built.",
image: "/screenshots/AI-Internal-Realtime-Message.jpeg",
imageAlt: "Real-time messaging between AI agents in department channels",
},
{
number: "05",
title: "Human-in-the-Loop Approvals",
description:
"Stay in control. Critical decisions surface for your review. Approve, reject, or redirect — your company respects the chain of command.",
image: "/screenshots/Approval-by-Human.jpeg",
imageAlt: "Approval interface showing human review of agent decisions",
},
{
number: "06",
title: "AI Document Generation",
description:
"Business plans, marketing strategies, technical specs — agents draft and iterate on real deliverables, stored in your document center.",
image: "/screenshots/Document-Center.jpeg",
imageAlt: "Document center with AI-generated business deliverables",
},
];
function FeaturePair({ feature }: { feature: (typeof features)[number] }) {
const { number, title, description, image, imageAlt, imageLeft } = feature;
const ease: [number, number, number, number] = [0.16, 1, 0.3, 1];
const media = (
<motion.div
variants={{
hidden: { opacity: 0, x: imageLeft ? -60 : 60 },
visible: { opacity: 1, x: 0, transition: { duration: 0.7, ease } },
}}
initial="hidden"
whileInView="visible"
viewport={{ once: true, amount: 0.3 }}
className={`order-2 ${imageLeft ? "lg:order-1" : "lg:order-2"}`}
>
<div className="rounded-[22px] overflow-hidden shadow-[0_4px_32px_-8px_rgba(0,0,0,0.06)] border border-[var(--border)] bg-[var(--panel)] transition-shadow duration-500 hover:shadow-[0_8px_48px_-12px_rgba(0,0,0,0.10)]">
<img src={image} alt={imageAlt} width="1920" height="1080" className="w-full h-auto block" loading="lazy" />
</div>
</motion.div>
);
const copy = (
<motion.div
variants={{
hidden: { opacity: 0, x: imageLeft ? 60 : -60 },
visible: { opacity: 1, x: 0, transition: { duration: 0.7, ease, delay: 0.1 } },
}}
initial="hidden"
whileInView="visible"
viewport={{ once: true, amount: 0.3 }}
className={`flex flex-col justify-center order-1 ${imageLeft ? "lg:order-2" : "lg:order-1"}`}
>
<span className="font-mono text-[5rem] lg:text-[6rem] font-bold leading-none text-[var(--accent)] opacity-[0.07] select-none -mb-10 lg:-mb-12">
{number}
</span>
<div className="relative">
<div className="flex items-center gap-3 mb-4">
<span className="block w-2 h-2 rounded-full bg-[var(--accent)]" />
<span className="font-mono text-sm text-[var(--muted)]">{number}</span>
</div>
<h2 className="text-2xl lg:text-[1.875rem] font-bold text-[var(--text)] mb-4 tracking-tight">{title}</h2>
<p className="text-[var(--muted-strong)] leading-relaxed text-base lg:text-lg">{description}</p>
</div>
</motion.div>
);
return (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-20 items-center">
{media}
{copy}
</div>
);
}
export function Features() {
return (
<section
id="features"
className="py-24 lg:py-40"
style={{ background: "linear-gradient(180deg, transparent 0%, var(--section-alt) 30%, var(--section-alt) 70%, transparent 100%)" }}
>
<div className="max-w-6xl mx-auto px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.3 }}
transition={{ duration: 0.6, ease: [0.16, 1, 0.3, 1] }}
className="text-center mb-24 lg:mb-36"
>
<span className="font-mono text-xs uppercase tracking-[0.25em] text-[var(--accent)] mb-5 block font-medium">
Features
</span>
<h2 className="font-serif text-[clamp(2rem,1.5rem+2.5vw,3.25rem)] tracking-[-0.01em] text-[var(--text)]">
Your Company, Under the Hood
</h2>
</motion.div>
<div className="space-y-24 lg:space-y-40">
{features.slice(0, 3).map((feature) => (
<FeaturePair key={feature.number} feature={feature} />
))}
</div>
<motion.div
className="mt-24 lg:mt-40 grid grid-cols-1 md:grid-cols-3 gap-6 lg:gap-8"
initial="hidden"
whileInView="visible"
viewport={{ once: true, amount: 0.2 }}
variants={{
hidden: {},
visible: {
transition: { staggerChildren: 0.12 },
},
}}
>
{features.slice(3).map((feature) => (
<motion.div
key={feature.number}
variants={{
hidden: { opacity: 0, y: 32 },
visible: {
opacity: 1,
y: 0,
transition: { duration: 0.6, ease: [0.16, 1, 0.3, 1] },
},
}}
className="group bg-[var(--panel)] rounded-[22px] border border-[var(--border)] overflow-hidden transition-all duration-300 hover:shadow-[0_8px_40px_-12px_rgba(0,0,0,0.08)] hover:-translate-y-1.5"
>
<div className="overflow-hidden">
<img
src={feature.image}
alt={feature.imageAlt}
width="640"
height="360"
className="w-full h-auto block transition-transform duration-500 group-hover:scale-[1.03]"
loading="lazy"
/>
</div>
<div className="p-6 lg:p-7">
<div className="flex items-center gap-3 mb-3">
<span className="block w-2 h-2 rounded-full bg-[var(--accent)]" />
<span className="font-mono text-sm text-[var(--muted)]">{feature.number}</span>
</div>
<h2 className="text-lg font-bold text-[var(--text)] mb-2 tracking-tight">{feature.title}</h2>
<p className="text-sm text-[var(--muted-strong)] leading-relaxed">{feature.description}</p>
</div>
</motion.div>
))}
</motion.div>
</div>
</section>
);
}
-91
View File
@@ -1,91 +0,0 @@
import { AsciiBackground } from "./ascii-background";
import { IconMark } from "./icon-mark";
import { CONTACT_EMAIL, WEBSITE_URL } from "./site-constants";
import { ThemeToggle } from "./theme-toggle";
import { getTrackedDownloadHref } from "../lib/downloads";
const footerGroups = [
{
title: "Product",
links: [
{ label: "Features", href: "#features" },
{ label: "How It Works", href: "#how-it-works" },
{ label: "FAQ", href: "#faq" },
{ label: "Download", href: "#download" },
],
},
{
title: "Downloads",
links: [
{ label: "Apple Silicon", href: getTrackedDownloadHref("macos-arm64-dmg"), external: true },
{ label: "Intel Mac", href: getTrackedDownloadHref("macos-x64-dmg"), external: true },
{ label: "Windows Installer", href: getTrackedDownloadHref("windows-universal-installer"), external: true },
{ label: "Linux x64 AppImage", href: getTrackedDownloadHref("linux-x64-appimage"), external: true },
],
},
{
title: "Company",
links: [
{ label: "Website", href: WEBSITE_URL, external: true },
{ label: "Contact", href: `mailto:${CONTACT_EMAIL}`, external: true },
{ label: "Download Center", href: "#download" },
],
},
];
export function Footer() {
const year = new Date().getFullYear();
return (
<footer className="relative border-t border-[var(--border)] overflow-hidden">
<AsciiBackground cssVar="--accent" baseOpacity={0.04} speed={0.5} />
<div className="relative z-10 mx-auto max-w-6xl px-6 lg:px-8 pt-16 lg:pt-20 pb-10 lg:pb-12">
<div className="flex flex-col lg:flex-row gap-y-12 gap-x-8">
<div className="shrink-0 lg:w-64 mb-4 lg:mb-0">
<a href="#" className="inline-flex items-center gap-2.5" aria-label="AgentCompany home">
<IconMark size={28} />
<span className="text-[var(--text)] font-semibold text-lg tracking-tight">AgentCompany</span>
</a>
<p className="mt-4 text-sm leading-relaxed text-[var(--muted)] max-w-xs">
Local-first desktop control plane for autonomous AI companies.
</p>
</div>
<div className="flex-1 flex flex-wrap gap-y-12 gap-x-8 justify-between">
{footerGroups.map((group) => (
<div key={group.title} className="min-w-[120px]">
<h3 className="text-sm font-semibold text-[var(--text)] tracking-tight mb-4">{group.title}</h3>
<ul className="space-y-3">
{group.links.map((link) => (
<li key={link.label}>
<a
href={link.href}
{...(link.external ? { target: "_blank", rel: "noopener noreferrer" } : {})}
className="text-sm text-[var(--muted)] hover:text-[var(--text)] transition-colors duration-200"
>
{link.label}
</a>
</li>
))}
</ul>
</div>
))}
</div>
</div>
<div className="mt-14 lg:mt-16 pt-6 border-t border-[var(--border)]" />
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
<div className="flex items-center gap-4 text-xs text-[var(--muted)]">
<span>© {year} AgentCompany</span>
</div>
<div className="flex items-center gap-1">
<ThemeToggle />
</div>
</div>
</div>
</footer>
);
}
-129
View File
@@ -1,129 +0,0 @@
"use client";
import { motion } from "framer-motion";
import { AsciiBackground } from "./ascii-background";
import { landingHeroNarrative } from "../lib/product-narrative";
const sharedEase: [number, number, number, number] = [0.16, 1, 0.3, 1];
function heroMotion(delay: number) {
return {
initial: { opacity: 0, y: 24 },
animate: { opacity: 1, y: 0 },
transition: { duration: 0.7, delay, ease: sharedEase },
};
}
function AppleIcon() {
return (
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.8-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z" />
</svg>
);
}
function WindowsIcon() {
return (
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M3 12V6.5l8-1.1V12H3zm0 .5h8v6.6l-8-1.1V12.5zM11.5 5.3l9.5-1.3v8h-9.5V5.3zm0 7.2h9.5v8l-9.5-1.3V12.5z" />
</svg>
);
}
function LinuxIcon() {
return (
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M12.5 2C10 2 8.2 4.2 8.2 7c0 1.5.3 2.2.7 3.2.3.8.7 1.7.7 3 0 .3 0 .6-.1.9-.2 1-.6 1.8-1.2 2.3-.8.7-1.8 1.1-2.8 1.6-.7.3-1.4.7-1.9 1.2-.4.4-.6.9-.6 1.4 0 .5.2.9.6 1.2.7.6 2 .7 3.1.7.8 0 1.6-.1 2.2-.2.6-.1 1.2-.3 1.9-.3.7 0 1.3.2 1.9.3.6.1 1.4.2 2.2.2 1.1 0 2.4-.1 3.1-.7.4-.3.6-.7.6-1.2 0-.5-.2-1-.6-1.4-.5-.5-1.2-.9-1.9-1.2-1-.5-2-1-2.8-1.6-.6-.5-1-1.3-1.2-2.3-.1-.3-.1-.6-.1-.9 0-1.3.4-2.2.7-3 .4-1 .7-1.7.7-3.2 0-2.8-1.8-5-4.3-5h-.2zm-1 5c0-.8.5-1.5 1.2-1.5s1.2.7 1.2 1.5-.5 1.5-1.2 1.5S11.5 7.8 11.5 7z" />
</svg>
);
}
export function Hero() {
return (
<section className="relative overflow-hidden pt-32 pb-24 lg:pt-44 lg:pb-36">
<AsciiBackground cssVar="--accent" baseOpacity={0.06} speed={1} />
<div
className="absolute inset-0 pointer-events-none"
aria-hidden="true"
style={{
background:
"radial-gradient(ellipse 80% 50% at 50% 0%, var(--glow-warm) 0%, transparent 70%), radial-gradient(ellipse 60% 40% at 50% 20%, var(--glow-accent) 0%, transparent 60%)",
}}
/>
<div className="relative mx-auto max-w-6xl px-4 sm:px-6 lg:px-8">
<div className="flex flex-col items-center text-center">
<motion.div {...heroMotion(0.05)}>
<span className="inline-flex items-center px-4 py-1.5 rounded-full text-xs font-semibold tracking-wide bg-[var(--accent-soft)] text-[var(--accent)] dark:text-[var(--muted-strong)] border border-[var(--border)]">
{landingHeroNarrative.eyebrow}
</span>
</motion.div>
<motion.h1
{...heroMotion(0.15)}
className="mt-8 font-serif text-[clamp(2.75rem,2rem+3.8vw,5rem)] font-normal leading-[1.0] tracking-[-0.03em] text-[var(--text)]"
>
{landingHeroNarrative.titleLine1} <br className="hidden sm:block" />
<span className="text-[var(--accent)]">{landingHeroNarrative.titleLine2}</span>
</motion.h1>
<motion.p
{...heroMotion(0.25)}
className="mt-7 max-w-2xl text-lg sm:text-xl leading-relaxed text-[var(--muted)]"
>
{landingHeroNarrative.description}
</motion.p>
<motion.div {...heroMotion(0.35)} className="mt-12">
<a
href="#download"
className="group inline-flex items-center justify-center px-8 py-4 rounded-full text-base font-medium bg-[var(--cta)] text-[var(--text-on-cta)] hover:bg-[var(--cta-hover)] hover:scale-[1.03] active:scale-[0.98] transition-all duration-200 will-change-transform"
>
See Downloads
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2.5"
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
className="ml-2 transition-transform duration-200 group-hover:translate-x-0.5 group-hover:-translate-y-0.5"
>
<path d="m7 7 10 10" />
<path d="M17 7v10H7" />
</svg>
</a>
</motion.div>
<motion.div {...heroMotion(0.45)} className="mt-5 flex items-center gap-3 text-xs text-[var(--muted)]">
<div className="flex items-center gap-1.5 opacity-70">
<AppleIcon />
<WindowsIcon />
<LinuxIcon />
</div>
<span>{landingHeroNarrative.availability}</span>
</motion.div>
</div>
<motion.div
initial={{ opacity: 0, y: 40, scale: 0.94 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
transition={{ duration: 0.9, delay: 0.5, ease: sharedEase }}
className="mt-20 lg:mt-24 mx-auto max-w-5xl"
>
<img
src="/screenshots/Dashboard.jpeg"
alt="AgentCompany dashboard showing autonomous AI agents managing a company"
width="1920"
height="1080"
className="w-full h-auto block rounded-[22px] border border-[var(--border)] shadow-[0_8px_40px_-8px_rgba(0,0,0,0.08)] transition-shadow duration-500"
loading="eager"
/>
</motion.div>
</div>
</section>
);
}
-149
View File
@@ -1,149 +0,0 @@
"use client";
import { motion, useInView } from "framer-motion";
import { useEffect, useRef, useState } from "react";
import { landingHowItWorksNarrative } from "../lib/product-narrative";
const demoMessages = landingHowItWorksNarrative.demoMessages;
const logTone: Record<(typeof demoMessages)[number]["role"], string> = {
system: "text-[var(--muted-strong)]",
};
const dotTone: Record<(typeof demoMessages)[number]["role"], string> = {
system: "bg-[var(--muted-strong)]",
};
const steps = landingHowItWorksNarrative.steps;
function DemoPanel() {
const anchorRef = useRef<HTMLDivElement | null>(null);
const isVisible = useInView(anchorRef, { once: true, amount: 0.4 });
const [visibleCount, setVisibleCount] = useState(0);
const logRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
if (!isVisible) return;
const timers = demoMessages.map((message, index) =>
window.setTimeout(() => setVisibleCount(index + 1), message.delay),
);
return () => timers.forEach((timer) => window.clearTimeout(timer));
}, [isVisible]);
useEffect(() => {
if (logRef.current) {
logRef.current.scrollTop = logRef.current.scrollHeight;
}
}, [visibleCount]);
return (
<div ref={anchorRef} className="relative">
<div className="rounded-[22px] overflow-hidden border border-[var(--border)] bg-[var(--panel)] shadow-[0_8px_40px_-8px_rgba(0,0,0,0.06)]">
<div className="flex items-center gap-2 px-4 py-3 bg-[var(--panel-soft)] border-b border-[var(--border)]">
<span className="w-3 h-3 rounded-full bg-[#ff5f57]" aria-hidden="true" />
<span className="w-3 h-3 rounded-full bg-[#febc2e]" aria-hidden="true" />
<span className="w-3 h-3 rounded-full bg-[#28c840]" aria-hidden="true" />
<span className="ml-2 text-xs text-[var(--muted)] font-mono">AgentCompany</span>
</div>
<div ref={logRef} role="log" aria-label="Agent activity demonstration" className="p-5 lg:p-6 font-mono text-sm leading-relaxed h-[340px] overflow-y-auto">
{demoMessages.slice(0, visibleCount).map((message, index) => (
<motion.div
key={`${message.agent}-${index}`}
initial={{ opacity: 0, y: 8 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3, ease: [0.16, 1, 0.3, 1] }}
className="flex gap-3 mb-3 last:mb-0"
>
<span className={`shrink-0 font-semibold inline-flex items-center gap-1.5 ${logTone[message.role]}`}>
<span
className={`w-1.5 h-1.5 rounded-full ${dotTone[message.role]}`}
aria-hidden="true"
/>
{message.agent}
</span>
<span className="text-[var(--text)]">{message.text}</span>
</motion.div>
))}
{visibleCount < demoMessages.length && isVisible && (
<span className="inline-block w-2 h-4 bg-[var(--accent)] animate-pulse rounded-sm" aria-hidden="true" />
)}
{visibleCount >= demoMessages.length && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.3 }}
className="mt-4 pt-4 border-t border-[var(--border)] flex items-center gap-2 text-[#059669]"
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<path d="m9 12 2 2 4-4" />
<circle cx="12" cy="12" r="10" />
</svg>
<span className="font-semibold">{landingHowItWorksNarrative.completionText}</span>
</motion.div>
)}
<div />
</div>
</div>
</div>
);
}
export function HowItWorks() {
return (
<section id="how-it-works" className="py-24 lg:py-40 px-4 sm:px-6 lg:px-8">
<div className="mx-auto max-w-6xl">
<div className="text-center mb-20 lg:mb-24">
<p className="font-mono text-xs font-medium uppercase tracking-[0.25em] text-[var(--accent)] mb-5">
How It Works
</p>
<h2 className="font-serif text-[clamp(2rem,1.5rem+2.5vw,3.25rem)] tracking-[-0.01em] text-[var(--text)]">
{landingHowItWorksNarrative.heading}
</h2>
</div>
<div className="grid grid-cols-1 lg:grid-cols-5 gap-12 lg:gap-16 items-start">
<div className="lg:col-span-2 relative">
<div className="absolute left-[15px] top-10 bottom-4 w-px bg-[var(--border)] hidden lg:block" aria-hidden="true" />
<div className="space-y-7">
{steps.map((step, index) => (
<motion.div
key={step.number}
initial={{ opacity: 0, x: -24 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true, amount: 0.5 }}
transition={{ duration: 0.5, delay: 0.12 * index, ease: [0.16, 1, 0.3, 1] }}
className="flex gap-5"
>
<div className="relative z-10 shrink-0 flex items-center justify-center w-8 h-8 rounded-full bg-[var(--accent)] text-[var(--text-on-accent)] text-sm font-bold shadow-[0_2px_12px_-2px_var(--accent)]">
{step.number}
</div>
<div className="pt-0.5">
<h3 className="text-base font-bold text-[var(--text)] mb-1.5 tracking-tight">{step.title}</h3>
<p className="text-sm leading-relaxed text-[var(--muted)]">{step.description}</p>
</div>
</motion.div>
))}
</div>
</div>
<motion.div
className="lg:col-span-3"
initial={{ opacity: 0, y: 32 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.3 }}
transition={{ duration: 0.7, ease: [0.16, 1, 0.3, 1] }}
>
<DemoPanel />
</motion.div>
</div>
</div>
</section>
);
}
-24
View File
@@ -1,24 +0,0 @@
export function IconMark({ size = 32 }: { size?: number }) {
return (
<svg
width={size}
height={size}
viewBox="0 0 1024 1024"
fill="none"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
>
<circle cx="512" cy="512" r="480" fill="#191919" />
<g transform="translate(268 255) scale(4)">
<path
fill="#FBFAF5"
d="M 76.604813 111.661926 C 65.070183 111.662621 53.987053 111.662621 42.757744 111.662621 C 45.2239 101.998177 45.297546 101.949265 53.830105 102.036659 C 57.279823 102.071999 60.730202 102.04248 64.259201 102.04248 C 62.159458 93.316338 61.799103 93.009819 51.340881 91.341682 C 59.312901 73.847687 67.193756 56.553749 75.587578 38.134155 C 86.933441 62.965954 97.804642 86.758881 108.711754 110.630394 C 100.707413 111.871689 92.355965 107.246559 88.107536 98.852119 C 84.207748 91.146538 80.800591 83.191696 77.172813 75.348343 C 76.340195 73.54818 75.492958 71.754791 74.614624 69.877441 C 69.107384 75.691788 68.008286 81.475128 71.005882 88.088753 C 74.413452 95.606903 77.813919 103.128281 81.452705 111.167984 C 79.55114 111.381325 78.303734 111.521271 76.604813 111.661926 Z"
/>
<path
fill="#FBFAF5"
d="M 26.805992 87.743256 C 38.616821 61.830872 50.261688 36.260269 62.470131 9.452141 C 65.732315 17.818909 71.145126 23.524567 66.258224 33.086182 C 55.518253 54.099815 46.339973 75.911873 36.533691 97.402336 C 32.699284 105.805443 26.495394 110.823158 16.012421 111.410957 C 19.72117 103.270836 23.180601 95.67794 26.805992 87.743256 Z"
/>
</g>
</svg>
);
}
-132
View File
@@ -1,132 +0,0 @@
"use client";
import { useEffect, useState } from "react";
import { IconMark } from "./icon-mark";
import { ThemeToggle } from "./theme-toggle";
const navLinks = [
{ label: "Features", href: "#features" },
{ label: "How It Works", href: "#how-it-works" },
{ label: "FAQ", href: "#faq" },
{ label: "Download", href: "#download" },
];
function MenuIcon({ open }: { open: boolean }) {
return (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
{open ? (
<>
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" />
</>
) : (
<>
<line x1="3" y1="6" x2="21" y2="6" />
<line x1="3" y1="12" x2="21" y2="12" />
<line x1="3" y1="18" x2="21" y2="18" />
</>
)}
</svg>
);
}
export function Navbar() {
const [mobileOpen, setMobileOpen] = useState(false);
const [scrolled, setScrolled] = useState(false);
useEffect(() => {
const handleScroll = () => setScrolled(window.scrollY > 8);
window.addEventListener("scroll", handleScroll, { passive: true });
handleScroll();
return () => window.removeEventListener("scroll", handleScroll);
}, []);
useEffect(() => {
const handleResize = () => {
if (window.innerWidth >= 768) {
setMobileOpen(false);
}
};
window.addEventListener("resize", handleResize, { passive: true });
return () => window.removeEventListener("resize", handleResize);
}, []);
return (
<nav
className={[
"fixed top-0 left-0 right-0 z-50 transition-all duration-300 backdrop-blur-xl",
scrolled ? "bg-[var(--panel)]/80 border-b border-[var(--border)] shadow-sm" : "bg-transparent border-b border-transparent",
].join(" ")}
>
<div className="mx-auto max-w-6xl px-4 sm:px-6 lg:px-8">
<div className="flex h-16 items-center justify-between">
<a href="#" className="flex items-center gap-2.5 shrink-0" aria-label="AgentCompany home">
<IconMark />
<span className="text-[var(--text)] font-serif text-xl font-normal tracking-[-0.4px]">AgentCompany</span>
</a>
<div className="hidden md:flex items-center gap-8">
{navLinks.map(({ label, href }) => (
<a key={href} href={href} className="text-sm text-[var(--muted)] hover:text-[var(--text)] transition-colors duration-200">
{label}
</a>
))}
</div>
<div className="hidden md:flex items-center gap-3">
<ThemeToggle />
<a
href="#download"
className="inline-flex items-center px-5 py-2 rounded-full text-sm font-medium bg-[var(--cta)] text-[var(--text-on-cta)] hover:bg-[var(--cta-hover)] hover:scale-[1.03] active:scale-[0.98] transition-all duration-200"
>
Download
</a>
</div>
<div className="flex md:hidden items-center gap-2">
<ThemeToggle />
<button
type="button"
onClick={() => setMobileOpen((current) => !current)}
aria-label={mobileOpen ? "Close navigation menu" : "Open navigation menu"}
aria-expanded={mobileOpen}
aria-controls="mobile-nav-menu"
className="inline-flex items-center justify-center w-11 h-11 rounded-lg text-[var(--muted)] hover:text-[var(--text)] hover:bg-[var(--panel-soft)] transition-colors duration-200"
>
<MenuIcon open={mobileOpen} />
</button>
</div>
</div>
</div>
<div
id="mobile-nav-menu"
className={[
"md:hidden overflow-hidden transition-all duration-300 ease-[cubic-bezier(0.16,1,0.3,1)]",
mobileOpen ? "max-h-64 opacity-100" : "max-h-0 opacity-0",
].join(" ")}
>
<div className="px-4 pb-4 pt-1 space-y-1 bg-[var(--panel)]/90 backdrop-blur-xl border-b border-[var(--border)]">
{navLinks.map(({ label, href }) => (
<a
key={href}
href={href}
onClick={() => setMobileOpen(false)}
className="block px-3 py-2.5 rounded-lg text-sm text-[var(--muted)] hover:text-[var(--text)] hover:bg-[var(--panel-soft)] transition-colors duration-200"
>
{label}
</a>
))}
<a
href="#download"
onClick={() => setMobileOpen(false)}
className="block px-3 py-2.5 rounded-full text-sm font-medium text-center bg-[var(--cta)] text-[var(--text-on-cta)] hover:bg-[var(--cta-hover)] transition-colors duration-200 mt-2"
>
Download
</a>
</div>
</div>
</nav>
);
}
@@ -1,109 +0,0 @@
export type PlatformDownloadAsset = {
architectures: ReleaseArchitecture[];
id: string;
label: string;
href: string;
note: string;
};
export type ReleaseArchitecture = "arm64" | "x64" | "x86";
export type PlatformDownload = {
id: "macos" | "windows" | "linux";
packageDescription: string;
title: string;
note: string;
assets: PlatformDownloadAsset[];
};
export const releaseVersion = "0.4.182";
export const platformDownloads: PlatformDownload[] = [
{
id: "macos",
packageDescription: "signed and notarized DMG builds",
title: "macOS",
note: "Signed + notarized DMG builds",
assets: [
{
architectures: ["arm64"],
id: "macos-arm64-dmg",
label: "Apple Silicon DMG",
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/AgentCompany-0.4.182-arm64.dmg",
note: "arm64",
},
{
architectures: ["x64"],
id: "macos-x64-dmg",
label: "Intel Mac DMG",
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/AgentCompany-0.4.182.dmg",
note: "x64",
},
],
},
{
id: "windows",
packageDescription: "an NSIS installer build",
title: "Windows",
note: "NSIS installer builds",
assets: [
{
architectures: ["arm64", "x64"],
id: "windows-universal-installer",
label: "Windows Universal Installer",
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/AgentCompany.Setup.0.4.182.exe",
note: "arm64 + x64",
},
],
},
{
id: "linux",
packageDescription: "AppImage, DEB, and RPM builds",
title: "Linux",
note: "AppImage, DEB, and RPM builds",
assets: [
{
architectures: ["x64"],
id: "linux-x64-appimage",
label: "Linux x64 AppImage",
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/AgentCompany-0.4.182.AppImage",
note: "x64",
},
{
architectures: ["x64"],
id: "linux-x64-deb",
label: "Linux x64 DEB",
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/agent-company_0.4.182_amd64.deb",
note: "x64",
},
{
architectures: ["x64"],
id: "linux-x64-rpm",
label: "Linux x64 RPM",
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/agent-company-0.4.182.x86_64.rpm",
note: "x64",
},
{
architectures: ["arm64"],
id: "linux-arm64-appimage",
label: "Linux ARM64 AppImage",
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/AgentCompany-0.4.182-arm64.AppImage",
note: "arm64",
},
{
architectures: ["arm64"],
id: "linux-arm64-deb",
label: "Linux ARM64 DEB",
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/agent-company_0.4.182_arm64.deb",
note: "arm64",
},
{
architectures: ["arm64"],
id: "linux-arm64-rpm",
label: "Linux ARM64 RPM",
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/agent-company-0.4.182.aarch64.rpm",
note: "arm64",
},
],
},
];
-117
View File
@@ -1,117 +0,0 @@
"use client";
import { motion } from "framer-motion";
function AnthropicIcon() {
return (
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M13.827 3.52h3.603L24 20.48h-3.603l-6.57-16.96zm-7.257 0H10.173L16.74 20.48H13.14L11.07 14.98H5.355l-1.937 5.5H0L6.57 3.52zm4.132 8.69L8.18 5.86l-2.522 6.35h5.244z" />
</svg>
);
}
function OpenAIIcon() {
return (
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M22.282 9.821a5.985 5.985 0 0 0-.516-4.91 6.046 6.046 0 0 0-6.51-2.9A6.065 6.065 0 0 0 4.981 4.18a5.998 5.998 0 0 0-3.998 2.9 6.047 6.047 0 0 0 .743 7.097 5.98 5.98 0 0 0 .51 4.911 6.051 6.051 0 0 0 6.515 2.9A5.985 5.985 0 0 0 13.26 24a6.056 6.056 0 0 0 5.772-4.206 5.99 5.99 0 0 0 3.997-2.9 6.056 6.056 0 0 0-.747-7.073zM13.26 22.43a4.476 4.476 0 0 1-2.876-1.04l.141-.081 4.779-2.758a.795.795 0 0 0 .392-.681v-6.737l2.02 1.168a.071.071 0 0 1 .038.052v5.583a4.504 4.504 0 0 1-4.494 4.494zM3.6 18.304a4.47 4.47 0 0 1-.535-3.014l.142.085 4.783 2.759a.771.771 0 0 0 .78 0l5.843-3.369v2.332a.08.08 0 0 1-.033.062L9.74 19.95a4.5 4.5 0 0 1-6.14-1.646zM2.34 7.896a4.485 4.485 0 0 1 2.366-1.973V11.6a.766.766 0 0 0 .388.676l5.815 3.355-2.02 1.168a.076.076 0 0 1-.071 0l-4.83-2.786A4.504 4.504 0 0 1 2.34 7.872zm16.597 3.855l-5.833-3.387L15.119 7.2a.076.076 0 0 1 .071 0l4.83 2.791a4.494 4.494 0 0 1-.676 8.105v-5.678a.79.79 0 0 0-.407-.667zm2.01-3.023l-.141-.085-4.774-2.782a.776.776 0 0 0-.785 0L9.409 9.23V6.897a.066.066 0 0 1 .028-.061l4.83-2.787a4.5 4.5 0 0 1 6.68 4.66zm-12.64 4.135l-2.02-1.164a.08.08 0 0 1-.038-.057V6.075a4.5 4.5 0 0 1 7.375-3.453l-.142.08L8.704 5.46a.795.795 0 0 0-.393.681zm1.097-2.365l2.602-1.5 2.607 1.5v2.999l-2.597 1.5-2.607-1.5z" />
</svg>
);
}
function GoogleIcon() {
return (
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M12 11.366v3.473h5.51c-.226 1.408-1.644 4.126-5.51 4.126-3.314 0-6.017-2.744-6.017-6.127S8.686 6.71 12 6.71c1.888 0 3.152.804 3.874 1.497l2.637-2.54C16.63 3.952 14.534 3 12 3 6.477 3 2 7.477 2 13s4.477 10 10 10c5.773 0 9.6-4.057 9.6-9.773 0-.656-.07-1.157-.156-1.657H12z" />
</svg>
);
}
function MoonshotIcon() {
return (
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20zm0 2a8 8 0 0 1 .5 15.98A10.5 10.5 0 0 0 17 12c0-3.14-1.37-5.96-3.54-7.9A8.03 8.03 0 0 1 12 4z" />
</svg>
);
}
function ZhipuIcon() {
return (
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M4 4h16v3H8.5l11 10H20v3H4v-3h11.5L4.5 7H4V4z" />
</svg>
);
}
function MiniMaxIcon() {
return (
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M2 20V4l5 8 5-8 5 8 5-8v16h-3V10.5l-2 4-5-8-5 8-2-4V20H2z" />
</svg>
);
}
function OllamaIcon() {
return (
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M12 2C8.13 2 5 5.13 5 9c0 2.38 1.19 4.47 3 5.74V17a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.87-3.13-7-7-7zm-2 15v-1h4v1h-4zm3.5-4.15l-.5.35V15h-2v-1.8l-.5-.35A4.98 4.98 0 0 1 7 9c0-2.76 2.24-5 5-5s5 2.24 5 5a4.98 4.98 0 0 1-3.5 4.85zM10 9.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm7 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" />
</svg>
);
}
function ApiIcon() {
return (
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" />
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" />
</svg>
);
}
const runtimes = [
{ name: "Claude Code", provider: "Anthropic", icon: AnthropicIcon },
{ name: "Codex CLI", provider: "OpenAI", icon: OpenAIIcon },
{ name: "Gemini CLI", provider: "Google", icon: GoogleIcon },
{ name: "Kimi", provider: "Moonshot AI", icon: MoonshotIcon },
{ name: "GLM", provider: "Zhipu AI", icon: ZhipuIcon },
{ name: "MiniMax", provider: "MiniMax", icon: MiniMaxIcon },
{ name: "Ollama", provider: "Local", icon: OllamaIcon },
{ name: "Anthropic Compatible API", provider: "Any Provider", icon: ApiIcon },
];
export function RuntimesBar() {
return (
<section className="border-y border-[var(--border)] py-12 lg:py-16">
<div className="mx-auto max-w-6xl px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 16 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.5 }}
transition={{ duration: 0.5, ease: [0.16, 1, 0.3, 1] }}
className="text-center"
>
<p className="font-mono text-xs uppercase tracking-[0.25em] text-[var(--muted)] mb-10">
Supported AI Runtimes
</p>
<div className="flex flex-wrap items-center justify-center gap-x-8 gap-y-6 lg:gap-x-12">
{runtimes.map((runtime) => {
const Icon = runtime.icon;
return (
<div key={runtime.name} className="flex items-center gap-2.5">
<span className="text-[var(--muted)] opacity-60">
<Icon />
</span>
<span className="text-base font-semibold tracking-tight text-[var(--text)]">
{runtime.name}
</span>
<span className="text-sm text-[var(--muted)] hidden sm:inline">
{runtime.provider}
</span>
</div>
);
})}
</div>
</motion.div>
</div>
</section>
);
}
-2
View File
@@ -1,2 +0,0 @@
export const WEBSITE_URL = "https://agent-company.dev";
export const CONTACT_EMAIL = "dev@agentcompany.ai";
-76
View File
@@ -1,76 +0,0 @@
"use client";
import { createContext, useCallback, useContext, useEffect, useState } from "react";
const storageKey = "agentcompany-theme";
type ThemeMode = "light" | "dark";
type ThemeContextValue = {
theme: ThemeMode;
setTheme: (theme: ThemeMode) => void;
toggleTheme: () => void;
};
const ThemeContext = createContext<ThemeContextValue | undefined>(undefined);
function resolveTheme(): ThemeMode {
if (typeof window === "undefined") {
return "light";
}
const stored = localStorage.getItem(storageKey);
if (stored === "light" || stored === "dark") {
return stored;
}
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
}
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setThemeState] = useState<ThemeMode>(resolveTheme);
useEffect(() => {
const root = document.documentElement;
if (theme === "dark") {
root.classList.add("dark");
} else {
root.classList.remove("dark");
}
localStorage.setItem(storageKey, theme);
}, [theme]);
useEffect(() => {
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
const handleChange = (event: MediaQueryListEvent) => {
if (!localStorage.getItem(storageKey)) {
setThemeState(event.matches ? "dark" : "light");
}
};
mediaQuery.addEventListener("change", handleChange);
return () => mediaQuery.removeEventListener("change", handleChange);
}, []);
const setTheme = useCallback((nextTheme: ThemeMode) => {
setThemeState(nextTheme);
}, []);
const toggleTheme = useCallback(() => {
setThemeState((currentTheme) => (currentTheme === "light" ? "dark" : "light"));
}, []);
return (
<ThemeContext.Provider value={{ theme, setTheme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
const context = useContext(ThemeContext);
if (!context) {
throw new Error("useTheme must be used within a ThemeProvider");
}
return context;
}
-42
View File
@@ -1,42 +0,0 @@
"use client";
import { useTheme } from "./theme-provider";
function SunIcon() {
return (
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<circle cx="12" cy="12" r="5" />
<line x1="12" y1="1" x2="12" y2="3" />
<line x1="12" y1="21" x2="12" y2="23" />
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64" />
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78" />
<line x1="1" y1="12" x2="3" y2="12" />
<line x1="21" y1="12" x2="23" y2="12" />
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36" />
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22" />
</svg>
);
}
function MoonIcon() {
return (
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
</svg>
);
}
export function ThemeToggle() {
const { theme, toggleTheme } = useTheme();
return (
<button
type="button"
onClick={toggleTheme}
aria-label={`Switch to ${theme === "light" ? "dark" : "light"} mode`}
className="relative inline-flex items-center justify-center w-11 h-11 rounded-lg transition-colors duration-200 cursor-pointer hover:bg-[var(--panel-soft)] text-[var(--muted)] hover:text-[var(--text)]"
>
{theme === "light" ? <MoonIcon /> : <SunIcon />}
</button>
);
}
-34
View File
@@ -1,34 +0,0 @@
import type { CounterDatabase, PagesHandler } from "../types";
import { DOWNLOAD_COUNT_SEED } from "../../lib/downloads";
interface Env {
DOWNLOAD_COUNTER_DB: CounterDatabase;
}
async function readDownloadCount(db: CounterDatabase) {
const result = await db
.prepare(`
SELECT
COALESCE(
(SELECT value FROM download_counter_settings WHERE key = 'base_downloads'),
?
) + COUNT(*) AS downloads
FROM unique_download_windows
`)
.bind(DOWNLOAD_COUNT_SEED)
.first<{ downloads: number }>();
return result?.downloads ?? DOWNLOAD_COUNT_SEED;
}
export const onRequestGet: PagesHandler<Env> = async (context) => {
const downloads = await readDownloadCount(context.env.DOWNLOAD_COUNTER_DB);
return Response.json(
{ downloads },
{
headers: {
"Cache-Control": "no-store",
},
},
);
};
-73
View File
@@ -1,73 +0,0 @@
import {
DOWNLOAD_DEDUP_WINDOW_MS,
getDownloadAsset,
} from "../../lib/downloads";
import type { CounterDatabase, PagesHandler } from "../types";
interface Env {
DOWNLOAD_COUNTER_DB: CounterDatabase;
DOWNLOAD_COUNTER_SALT?: string;
}
function getClientIp(request: Request) {
const cfConnectingIp = request.headers.get("CF-Connecting-IP")?.trim();
if (cfConnectingIp) {
return cfConnectingIp;
}
const forwardedFor = request.headers.get("X-Forwarded-For")?.split(",")[0]?.trim();
return forwardedFor || null;
}
function getWindowKey(now = Date.now()) {
return Math.floor(now / DOWNLOAD_DEDUP_WINDOW_MS);
}
async function sha256Hex(input: string) {
const buffer = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(input));
return Array.from(new Uint8Array(buffer), (byte) => byte.toString(16).padStart(2, "0")).join("");
}
async function countUniqueDownload(db: CounterDatabase, request: Request, assetId: string, salt: string | undefined) {
const clientIp = getClientIp(request);
if (!clientIp) {
return;
}
const ipHash = await sha256Hex(`${salt ?? ""}:${clientIp}`);
const windowKey = getWindowKey();
await db
.prepare(`
INSERT OR IGNORE INTO unique_download_windows (
ip_hash,
window_key,
first_asset_id,
created_at
) VALUES (?, ?, ?, datetime('now'))
`)
.bind(ipHash, windowKey, assetId)
.run();
}
export const onRequestGet: PagesHandler<Env> = async (context) => {
const url = new URL(context.request.url);
const assetId = url.searchParams.get("asset")?.trim();
if (!assetId) {
return new Response("Missing asset parameter.", { status: 400 });
}
const asset = getDownloadAsset(assetId);
if (!asset) {
return new Response("Unknown asset.", { status: 404 });
}
await countUniqueDownload(
context.env.DOWNLOAD_COUNTER_DB,
context.request,
asset.id,
context.env.DOWNLOAD_COUNTER_SALT,
);
return Response.redirect(asset.href, 302);
};
-17
View File
@@ -1,17 +0,0 @@
export interface CounterDbStatement {
bind(...values: unknown[]): {
first<T = unknown>(): Promise<T | null>;
run(): Promise<unknown>;
};
}
export interface CounterDatabase {
prepare(query: string): CounterDbStatement;
}
export interface PagesHandlerContext<Env> {
request: Request;
env: Env;
}
export type PagesHandler<Env> = (context: PagesHandlerContext<Env>) => Response | Promise<Response>;
-28
View File
@@ -1,28 +0,0 @@
import { platformDownloads, type PlatformDownloadAsset } from "../components/release-links.generated";
export const DOWNLOAD_COUNT_SEED = 13674;
export const DOWNLOAD_DEDUP_WINDOW_HOURS = 24;
export const DOWNLOAD_DEDUP_WINDOW_MS = DOWNLOAD_DEDUP_WINDOW_HOURS * 60 * 60 * 1000;
export type ReleaseDownloadAsset = PlatformDownloadAsset & {
platformId: "macos" | "windows" | "linux";
platformTitle: string;
};
export const downloadAssets: ReleaseDownloadAsset[] = platformDownloads.flatMap((platform) =>
platform.assets.map((asset) => ({
...asset,
platformId: platform.id,
platformTitle: platform.title,
})),
);
const downloadAssetMap = new Map(downloadAssets.map((asset) => [asset.id, asset]));
export function getDownloadAsset(assetId: string) {
return downloadAssetMap.get(assetId) ?? null;
}
export function getTrackedDownloadHref(assetId: string) {
return `/api/download?asset=${encodeURIComponent(assetId)}`;
}
-106
View File
@@ -1,106 +0,0 @@
import {
platformDownloads,
type PlatformDownload,
type PlatformDownloadAsset,
type ReleaseArchitecture,
} from "../components/release-links.generated";
const ARCHITECTURE_ORDER: ReleaseArchitecture[] = ["arm64", "x64", "x86"];
export type PlatformSupportSummary = {
downloadAnswer: string;
platformAnswer: string;
};
export const platformSupportSummary = buildPlatformSupportSummary(platformDownloads);
export function buildPlatformSupportSummary(downloads: PlatformDownload[]): PlatformSupportSummary {
const macos = requirePlatform(downloads, "macos");
const windows = requirePlatform(downloads, "windows");
const linux = requirePlatform(downloads, "linux");
return {
downloadAnswer:
`Use the download section on this page to choose the build that matches your architecture and package format. ` +
`${formatDownloadSentence(macos)} ${formatDownloadSentence(windows)} ${formatDownloadSentence(linux)}`,
platformAnswer:
`AgentCompany is available on ${formatAvailability(macos)}, ${formatAvailability(windows)}, ` +
`and ${formatAvailability(linux)}. It is built with Electron and the desktop feature set stays aligned across all supported targets.`,
};
}
function requirePlatform(downloads: PlatformDownload[], id: PlatformDownload["id"]): PlatformDownload {
const platform = downloads.find((download) => download.id === id);
if (!platform) {
throw new Error(`Missing ${id} release download metadata.`);
}
return platform;
}
function formatDownloadSentence(download: PlatformDownload): string {
const architectures = formatArchitectureList(collectArchitectures(download));
if (!download.packageDescription.trim()) {
throw new Error(`Release platform ${download.id} must include package format copy.`);
}
return `${download.title} ships as ${download.packageDescription} for ${architectures}.`;
}
function formatAvailability(download: PlatformDownload): string {
return `${download.title} (${formatArchitectureList(collectArchitectures(download), "comma")})`;
}
function collectArchitectures(download: PlatformDownload): ReleaseArchitecture[] {
const architectures = new Set<ReleaseArchitecture>();
for (const asset of download.assets) {
collectAssetArchitectures(download.id, asset).forEach((architecture) => architectures.add(architecture));
}
return [...architectures].sort((left, right) => architectureRank(left) - architectureRank(right));
}
function collectAssetArchitectures(
platformId: PlatformDownload["id"],
asset: PlatformDownloadAsset,
): ReleaseArchitecture[] {
if (asset.architectures.length === 0) {
throw new Error(`Release asset ${platformId}/${asset.id} must declare at least one architecture.`);
}
for (const architecture of asset.architectures) {
if (!isReleaseArchitecture(architecture)) {
throw new Error(`Release asset ${platformId}/${asset.id} declares unsupported architecture: ${architecture}`);
}
}
return asset.architectures;
}
function isReleaseArchitecture(value: string): value is ReleaseArchitecture {
return ARCHITECTURE_ORDER.includes(value as ReleaseArchitecture);
}
function architectureRank(architecture: ReleaseArchitecture): number {
return ARCHITECTURE_ORDER.indexOf(architecture);
}
function formatArchitectureList(
architectures: ReleaseArchitecture[],
style: "and" | "comma" = "and",
): string {
if (architectures.length === 0) {
throw new Error("Release download metadata must include at least one architecture.");
}
if (style === "comma") {
return architectures.join(", ");
}
if (architectures.length === 1) {
return architectures[0];
}
if (architectures.length === 2) {
return `${architectures[0]} and ${architectures[1]}`;
}
return `${architectures.slice(0, -1).join(", ")}, and ${architectures.at(-1)}`;
}
-80
View File
@@ -1,80 +0,0 @@
import { releaseVersion } from "../components/release-links.generated";
export const landingHeroNarrative = {
eyebrow: "AgentCompany Desktop",
titleLine1: "Launch an Autonomous AI Company",
titleLine2: "from Your Desktop",
description:
"Run AI CEO by default, switch to AI Co-Founder for human-reviewed decisions, and launch the first mission from a local desktop setup.",
availability: "Available on macOS, Windows, and Linux",
} as const;
export const onboardingFlowNarrative = {
prelude: "Welcome",
sections: [
{
number: 1,
title: "Requirements",
description: "Check Node.js because CLI runtimes call the local API through node -e.",
},
{
number: 2,
title: "Providers",
description: "Connect at least one runtime before company creation continues.",
},
{
number: 3,
title: "Company",
description: "Enter company name, description, and workspace.",
},
{
number: 4,
title: "Team Models",
description: "Enable the models available to the CEO and workers.",
},
{
number: 5,
title: "Mode",
description: "Use AI CEO by default, or choose AI Co-Founder for human-reviewed decisions.",
},
{
number: 6,
title: "Mission",
description: "Capture the first goal and acceptance description.",
},
{
number: 7,
title: "Launch",
description: "Create the company, CEO agent, workspace, kickoff task, and initial run handoff.",
},
],
} as const;
export const landingHowItWorksNarrative = {
heading: "Follow the Desktop First-Run Flow",
steps: onboardingFlowNarrative.sections,
completionText: "Initial run queued. Open Control Center.",
demoMessages: [
{ agent: "Requirements", role: "system", text: "Node.js ready. CLI runtimes can call the local API.", delay: 0 },
{ agent: "Providers", role: "system", text: "Runtime connected.", delay: 700 },
{ agent: "Company", role: "system", text: "Company profile and workspace saved.", delay: 1400 },
{ agent: "Team Models", role: "system", text: "Model pool enabled for CEO and workers.", delay: 2100 },
{ agent: "Mode", role: "system", text: "AI CEO mode selected.", delay: 2800 },
{ agent: "Mission", role: "system", text: "First goal and acceptance description captured.", delay: 3500 },
{ agent: "Launch", role: "system", text: "Company, CEO agent, kickoff task, and initial run created.", delay: 4400 },
],
} as const;
export const landingStructuredDataNarrative = {
softwareVersion: releaseVersion,
featureList: [
"Guided first-run setup",
"Node.js readiness check for CLI runtimes",
"Provider connection and model-pool selection",
"Multi-connector support (Claude Code, Codex CLI, Gemini CLI)",
"AI CEO autonomous operating mode",
"AI Co-Founder human-reviewed operating mode",
"Local-first SQLite storage",
"Cross-platform desktop releases for macOS, Windows, and Linux",
],
};
@@ -1,18 +0,0 @@
CREATE TABLE IF NOT EXISTS download_counter_settings (
key TEXT PRIMARY KEY,
value INTEGER NOT NULL
);
INSERT OR IGNORE INTO download_counter_settings (key, value)
VALUES ('base_downloads', 13674);
CREATE TABLE IF NOT EXISTS unique_download_windows (
ip_hash TEXT NOT NULL,
window_key INTEGER NOT NULL,
first_asset_id TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (ip_hash, window_key)
);
CREATE INDEX IF NOT EXISTS idx_unique_download_windows_created_at
ON unique_download_windows(created_at);
-6
View File
@@ -1,6 +0,0 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
-11
View File
@@ -1,11 +0,0 @@
import path from "node:path";
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
output: "export",
turbopack: {
root: path.join(__dirname),
},
};
export default nextConfig;
-1762
View File
File diff suppressed because it is too large. Load diff
-29
View File
@@ -1,29 +0,0 @@
{
"name": "agent-company-landing",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"preview": "wrangler pages dev out"
},
"dependencies": {
"framer-motion": "12.38.0",
"next": "16.2.6",
"react": "19.2.4",
"react-dom": "19.2.4"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.2.2",
"@types/node": "^24.9.1",
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2",
"tailwindcss": "^4.2.2",
"typescript": "^5.9.3"
},
"overrides": {
"postcss": "8.5.14"
}
}
-5
View File
@@ -1,5 +0,0 @@
export default {
plugins: {
"@tailwindcss/postcss": {},
},
};
-810
View File
@@ -1,810 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Design System Preview: Cohere (Dark)</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=Inter:wght@300;400;500;600;700&family=Space+Mono:wght@400;700&display=swap" rel="stylesheet">
<style>
:root {
/* Primary */
--color-black: #000000;
--color-near-black: #212121;
--color-deep-dark: #17171c;
/* Accent */
--color-interaction-blue: #1863dc;
--color-ring-blue: rgba(76, 110, 230, 0.5);
--color-focus-purple: #9b60aa;
/* Surface */
--color-white: #ffffff;
--color-snow: #fafafa;
--color-lightest-gray: #f2f2f2;
/* Neutrals */
--color-muted-slate: #93939f;
--color-border-cool: #d9d9dd;
--color-border-light: #e5e7eb;
/* Fonts */
--font-display: 'Space Grotesk', Inter, ui-sans-serif, system-ui, sans-serif;
--font-body: Inter, Arial, ui-sans-serif, system-ui, sans-serif;
--font-mono: 'Space Mono', Arial, ui-sans-serif, system-ui, monospace;
/* Dark mode tokens */
--bg-page: #17171c;
--bg-card: #212121;
--bg-nav: rgba(23, 23, 28, 0.95);
--text-primary: #fafafa;
--text-secondary: #d9d9dd;
--text-muted: #93939f;
--border-color: #333333;
--border-subtle: #2a2a2f;
--section-label-color: #93939f;
--accent: #1863dc;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: var(--bg-page);
color: var(--text-primary);
font-family: var(--font-body);
font-size: 16px;
line-height: 1.5;
font-weight: 400;
-webkit-font-smoothing: antialiased;
}
/* NAV */
.nav {
position: sticky;
top: 0;
z-index: 100;
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 40px;
background: var(--bg-nav);
backdrop-filter: blur(12px);
border-bottom: 1px solid var(--border-subtle);
}
.nav-brand {
font-family: var(--font-display);
font-size: 20px;
font-weight: 400;
letter-spacing: -0.4px;
display: flex;
align-items: center;
gap: 6px;
color: var(--text-primary);
}
.nav-brand svg { width: 28px; height: 28px; }
.nav-links { display: flex; gap: 32px; align-items: center; }
.nav-links a {
color: var(--text-secondary);
text-decoration: none;
font-size: 16px;
font-weight: 400;
font-family: var(--font-body);
transition: color 0.2s;
}
.nav-links a:hover { color: var(--accent); }
.nav-cta {
background: var(--color-white);
color: var(--color-black);
padding: 10px 24px;
border: none;
border-radius: 9999px;
font-size: 14px;
font-family: var(--font-body);
font-weight: 500;
cursor: pointer;
transition: opacity 0.2s;
}
.nav-cta:hover { opacity: 0.85; }
/* HERO */
.hero {
position: relative;
text-align: center;
padding: 120px 40px 100px;
overflow: hidden;
}
.hero h1 {
font-family: var(--font-display);
font-size: 72px;
font-weight: 400;
line-height: 1.0;
letter-spacing: -1.44px;
margin-bottom: 24px;
color: var(--text-primary);
}
.hero h1 span { color: var(--accent); }
.hero p {
color: var(--text-muted);
font-family: var(--font-body);
font-size: 18px;
font-weight: 400;
line-height: 1.4;
margin-bottom: 40px;
}
.hero-buttons { display: flex; gap: 16px; justify-content: center; }
.btn-ghost-primary {
background: transparent;
color: var(--text-primary);
padding: 12px 24px;
border: none;
font-size: 16px;
font-family: var(--font-body);
font-weight: 400;
cursor: pointer;
transition: color 0.2s, opacity 0.2s;
}
.btn-ghost-primary:hover { color: var(--accent); opacity: 0.8; }
.btn-light-solid {
background: var(--color-white);
color: var(--color-black);
padding: 12px 28px;
border: none;
border-radius: 9999px;
font-size: 16px;
font-family: var(--font-body);
font-weight: 400;
cursor: pointer;
transition: opacity 0.2s;
}
.btn-light-solid:hover { opacity: 0.85; }
/* SECTIONS */
.section {
max-width: 1200px;
margin: 0 auto;
padding: 80px 40px;
}
.section-title {
font-family: var(--font-mono);
font-size: 14px;
font-weight: 400;
text-transform: uppercase;
letter-spacing: 0.28px;
color: var(--section-label-color);
margin-bottom: 12px;
}
.section-heading {
font-family: var(--font-body);
font-size: 48px;
font-weight: 400;
line-height: 1.2;
letter-spacing: -0.48px;
margin-bottom: 48px;
color: var(--text-primary);
}
.section-divider {
border: none;
border-top: 1px solid var(--border-subtle);
margin: 0 40px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
}
/* PURPLE BAND */
.purple-band {
background: linear-gradient(135deg, #2d1b4e 0%, #1a1040 50%, #0d0a1a 100%);
padding: 80px 40px;
text-align: center;
}
.purple-band h2 {
font-family: var(--font-display);
font-size: 60px;
font-weight: 400;
line-height: 1.0;
letter-spacing: -1.2px;
color: #ffffff;
margin-bottom: 16px;
}
.purple-band p {
color: rgba(255,255,255,0.7);
font-size: 18px;
font-weight: 400;
line-height: 1.4;
}
/* COLOR PALETTE */
.color-group { margin-bottom: 40px; }
.color-group-title {
font-family: var(--font-body);
font-size: 20px;
font-weight: 400;
line-height: 1.2;
margin-bottom: 20px;
color: var(--text-secondary);
}
.color-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
gap: 16px;
}
.color-swatch {
border: 1px solid var(--border-color);
border-radius: 22px;
overflow: hidden;
}
.color-swatch-block {
height: 80px;
position: relative;
}
.color-swatch-info {
padding: 12px 16px;
background: var(--bg-card);
}
.color-swatch-name { font-size: 13px; font-weight: 500; margin-bottom: 2px; color: var(--text-primary); }
.color-swatch-hex { font-family: var(--font-mono); font-size: 12px; color: var(--text-muted); margin-bottom: 4px; }
.color-swatch-role { font-size: 12px; color: var(--text-muted); line-height: 1.4; }
/* TYPOGRAPHY */
.type-sample { margin-bottom: 32px; padding-bottom: 32px; border-bottom: 1px solid var(--border-subtle); }
.type-sample:last-child { border-bottom: none; }
.type-sample-text { margin-bottom: 8px; }
.type-sample-label {
font-family: var(--font-mono);
font-size: 12px;
color: var(--text-muted);
}
/* BUTTONS */
.button-row {
display: flex;
flex-wrap: wrap;
gap: 24px;
align-items: flex-start;
}
.button-demo { text-align: center; }
.button-demo-label {
font-family: var(--font-mono);
font-size: 11px;
color: var(--text-muted);
margin-top: 10px;
text-transform: uppercase;
letter-spacing: 0.28px;
}
.btn-ghost-cohere {
background: transparent;
color: var(--text-primary);
padding: 12px 24px;
border: none;
font-size: 16px;
font-family: var(--font-body);
font-weight: 400;
cursor: pointer;
transition: color 0.2s, opacity 0.2s;
}
.btn-ghost-cohere:hover { color: var(--accent); opacity: 0.8; }
.btn-light-cohere {
background: var(--color-white);
color: var(--color-black);
padding: 12px 28px;
border: none;
border-radius: 22px;
font-size: 16px;
font-family: var(--font-body);
font-weight: 400;
cursor: pointer;
}
.btn-light-pill {
background: var(--color-white);
color: var(--color-black);
padding: 12px 28px;
border: none;
border-radius: 9999px;
font-size: 14px;
font-family: var(--font-body);
font-weight: 500;
cursor: pointer;
}
.btn-outlined {
background: transparent;
color: var(--text-primary);
padding: 12px 24px;
border: 1px solid var(--border-color);
border-radius: 22px;
font-size: 16px;
font-family: var(--font-body);
font-weight: 400;
cursor: pointer;
transition: border-color 0.2s, color 0.2s;
}
.btn-outlined:hover { border-color: var(--accent); color: var(--accent); }
/* CARDS */
.card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 24px; }
.card {
background: var(--bg-card);
padding: 28px;
}
.card-signature {
border-radius: 22px;
border: 1px solid var(--border-color);
}
.card-dialog {
border-radius: 8px;
border: 1px solid var(--border-color);
}
.card-generous {
border-radius: 16px;
border: 1px solid var(--border-color);
}
.card h3 {
font-family: var(--font-body);
font-size: 24px;
font-weight: 400;
line-height: 1.3;
letter-spacing: normal;
margin-bottom: 12px;
color: var(--text-primary);
}
.card p { color: var(--text-muted); font-size: 16px; line-height: 1.5; font-weight: 400; }
.card-label {
font-family: var(--font-mono);
font-size: 14px;
text-transform: uppercase;
letter-spacing: 0.28px;
color: var(--text-muted);
margin-bottom: 16px;
}
/* SPACING */
.spacing-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; }
.spacing-item { text-align: center; }
.spacing-box {
background: rgba(24, 99, 220, 0.15);
border: 1px solid rgba(24, 99, 220, 0.3);
border-radius: 2px;
margin-bottom: 8px;
}
.spacing-label {
font-family: var(--font-mono);
font-size: 11px;
color: var(--text-muted);
}
/* RADIUS */
.radius-row { display: flex; flex-wrap: wrap; gap: 20px; align-items: center; }
.radius-item { text-align: center; }
.radius-box {
width: 80px;
height: 80px;
background: var(--bg-card);
border: 1px solid var(--border-color);
margin-bottom: 8px;
}
.radius-label {
font-family: var(--font-mono);
font-size: 11px;
color: var(--text-muted);
}
.radius-context {
font-size: 11px;
color: var(--text-muted);
margin-top: 2px;
}
/* ELEVATION */
.elevation-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 24px; }
.elevation-card {
background: var(--bg-card);
border-radius: 22px;
padding: 24px;
min-height: 140px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.elevation-flat { border: none; background: var(--bg-page); }
.elevation-bordered-light { border: 1px solid var(--border-subtle); }
.elevation-bordered-cool { border: 1px solid var(--border-color); }
.elevation-purple-band {
background: linear-gradient(135deg, #2d1b4e 0%, #1a1040 100%);
color: #ffffff;
}
.elevation-purple-band .elevation-name,
.elevation-purple-band .elevation-desc { color: #ffffff; }
.elevation-purple-band .elevation-level { color: rgba(255,255,255,0.6); }
.elevation-name { font-size: 16px; font-weight: 500; margin-bottom: 8px; color: var(--text-primary); }
.elevation-desc { font-size: 13px; color: var(--text-muted); line-height: 1.5; }
.elevation-level {
font-family: var(--font-mono);
font-size: 11px;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.28px;
margin-top: 12px;
}
/* RESPONSIVE */
@media (max-width: 768px) {
.nav { padding: 12px 20px; }
.nav-links a:not(.nav-cta-wrapper) { display: none; }
.hero { padding: 80px 20px 60px; }
.hero h1 { font-size: 42px; letter-spacing: -0.84px; }
.section { padding: 60px 20px; }
.section-heading { font-size: 32px; letter-spacing: -0.32px; }
.color-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
.card-grid { grid-template-columns: 1fr; }
.hero-buttons { flex-direction: column; align-items: center; }
.button-row { flex-direction: column; align-items: flex-start; }
.purple-band h2 { font-size: 36px; }
}
</style>
</head>
<body>
<!-- NAV -->
<nav class="nav">
<div class="nav-brand">
<svg viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="14" cy="14" r="13" stroke="currentColor" stroke-width="2"/>
<path d="M8 14 C8 10, 12 8, 14 8 C16 8, 20 10, 20 14 C20 18, 16 20, 14 20 C12 20, 8 18, 8 14Z" fill="currentColor" opacity="0.15"/>
<circle cx="14" cy="14" r="4" fill="currentColor"/>
</svg>
cohere
</div>
<div class="nav-links">
<a href="#colors">Colors</a>
<a href="#typography">Typography</a>
<a href="#buttons">Buttons</a>
<a href="#cards">Cards</a>
<a href="#spacing">Spacing</a>
<a href="#elevation">Elevation</a>
<button class="nav-cta">Get Started</button>
</div>
</nav>
<!-- HERO -->
<section class="hero">
<h1>Design System Preview:<br><span>Cohere</span></h1>
<p>Auto-generated design token catalog from DESIGN.md</p>
<div class="hero-buttons">
<button class="btn-light-solid">Explore Tokens</button>
<button class="btn-ghost-primary">View Source</button>
</div>
</section>
<hr class="section-divider">
<!-- COLORS -->
<section class="section" id="colors">
<div class="section-title">01 / Color Palette</div>
<h2 class="section-heading">Color Palette & Roles</h2>
<div class="color-group">
<h3 class="color-group-title">Primary</h3>
<div class="color-grid">
<div class="color-swatch">
<div class="color-swatch-block" style="background: #000000; border-bottom: 1px solid #333;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Cohere Black</div>
<div class="color-swatch-hex">#000000</div>
<div class="color-swatch-role">Primary headline text, maximum emphasis</div>
</div>
</div>
<div class="color-swatch">
<div class="color-swatch-block" style="background: #212121; border-bottom: 1px solid #333;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Near Black</div>
<div class="color-swatch-hex">#212121</div>
<div class="color-swatch-role">Standard body link color</div>
</div>
</div>
<div class="color-swatch">
<div class="color-swatch-block" style="background: #17171c; border-bottom: 1px solid #333;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Deep Dark</div>
<div class="color-swatch-hex">#17171c</div>
<div class="color-swatch-role">Navigation and dark-section text</div>
</div>
</div>
</div>
</div>
<div class="color-group">
<h3 class="color-group-title">Secondary & Accent</h3>
<div class="color-grid">
<div class="color-swatch">
<div class="color-swatch-block" style="background: #1863dc;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Interaction Blue</div>
<div class="color-swatch-hex">#1863dc</div>
<div class="color-swatch-role">Hover, focus states, active links</div>
</div>
</div>
<div class="color-swatch">
<div class="color-swatch-block" style="background: rgba(76,110,230,0.5);"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Ring Blue</div>
<div class="color-swatch-hex">#4c6ee6 @ 50%</div>
<div class="color-swatch-role">Keyboard focus indicators</div>
</div>
</div>
<div class="color-swatch">
<div class="color-swatch-block" style="background: #9b60aa;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Focus Purple</div>
<div class="color-swatch-hex">#9b60aa</div>
<div class="color-swatch-role">Input focus border color</div>
</div>
</div>
</div>
</div>
<div class="color-group">
<h3 class="color-group-title">Surface & Background</h3>
<div class="color-grid">
<div class="color-swatch">
<div class="color-swatch-block" style="background: #ffffff; border-bottom: 1px solid #e5e7eb;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Pure White</div>
<div class="color-swatch-hex">#ffffff</div>
<div class="color-swatch-role">Primary page background, card surface</div>
</div>
</div>
<div class="color-swatch">
<div class="color-swatch-block" style="background: #fafafa; border-bottom: 1px solid #e5e7eb;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Snow</div>
<div class="color-swatch-hex">#fafafa</div>
<div class="color-swatch-role">Subtle elevated surfaces, light sections</div>
</div>
</div>
<div class="color-swatch">
<div class="color-swatch-block" style="background: #f2f2f2; border-bottom: 1px solid #e5e7eb;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Lightest Gray</div>
<div class="color-swatch-hex">#f2f2f2</div>
<div class="color-swatch-role">Card borders, softest containment</div>
</div>
</div>
</div>
</div>
<div class="color-group">
<h3 class="color-group-title">Neutrals & Text</h3>
<div class="color-grid">
<div class="color-swatch">
<div class="color-swatch-block" style="background: #93939f;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Muted Slate</div>
<div class="color-swatch-hex">#93939f</div>
<div class="color-swatch-role">Footer links, tertiary text</div>
</div>
</div>
<div class="color-swatch">
<div class="color-swatch-block" style="background: #d9d9dd;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Border Cool</div>
<div class="color-swatch-hex">#d9d9dd</div>
<div class="color-swatch-role">Section borders, list separators</div>
</div>
</div>
<div class="color-swatch">
<div class="color-swatch-block" style="background: #e5e7eb;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Border Light</div>
<div class="color-swatch-hex">#e5e7eb</div>
<div class="color-swatch-role">Lighter border variant (gray-200)</div>
</div>
</div>
</div>
</div>
</section>
<hr class="section-divider">
<!-- PURPLE HERO BAND -->
<div class="purple-band">
<h2>Enterprise AI Platform</h2>
<p>Deep purple hero sections create dramatic visual breaks in the dark page flow</p>
</div>
<hr class="section-divider">
<!-- TYPOGRAPHY -->
<section class="section" id="typography">
<div class="section-title">02 / Typography Scale</div>
<h2 class="section-heading">Typography Rules</h2>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-display); font-size: 72px; font-weight: 400; line-height: 1.0; letter-spacing: -1.44px;">Display Hero</div>
<div class="type-sample-label">Display / Hero &mdash; CohereText &mdash; 72px / 400 / 1.00 / -1.44px</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-display); font-size: 60px; font-weight: 400; line-height: 1.0; letter-spacing: -1.2px;">Display Secondary</div>
<div class="type-sample-label">Display Secondary &mdash; CohereText &mdash; 60px / 400 / 1.00 / -1.2px</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-body); font-size: 48px; font-weight: 400; line-height: 1.2; letter-spacing: -0.48px;">Section Heading</div>
<div class="type-sample-label">Section Heading &mdash; Unica77 &mdash; 48px / 400 / 1.20 / -0.48px</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-body); font-size: 32px; font-weight: 400; line-height: 1.2; letter-spacing: -0.32px;">Sub-heading</div>
<div class="type-sample-label">Sub-heading &mdash; Unica77 &mdash; 32px / 400 / 1.20 / -0.32px</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-body); font-size: 24px; font-weight: 400; line-height: 1.3;">Feature Title</div>
<div class="type-sample-label">Feature Title &mdash; Unica77 &mdash; 24px / 400 / 1.30 / normal</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-body); font-size: 18px; font-weight: 400; line-height: 1.4;">Body Large text for intro paragraphs. Unica77 provides geometric Swiss precision for all functional UI text at the body-large tier.</div>
<div class="type-sample-label">Body Large &mdash; Unica77 &mdash; 18px / 400 / 1.40 / normal</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-body); font-size: 16px; font-weight: 400; line-height: 1.5;">Standard body text for paragraphs, navigation links, and button labels. Unica77 at its most common size, weight 400.</div>
<div class="type-sample-label">Body / Button &mdash; Unica77 &mdash; 16px / 400 / 1.50 / normal</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-body); font-size: 14px; font-weight: 500; line-height: 1.71;">Button Medium Label</div>
<div class="type-sample-label">Button Medium &mdash; Unica77 &mdash; 14px / 500 / 1.71 / normal</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-body); font-size: 14px; font-weight: 400; line-height: 1.4; color: var(--text-muted);">Caption and metadata text for descriptions</div>
<div class="type-sample-label">Caption &mdash; Unica77 &mdash; 14px / 400 / 1.40 / normal</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-mono); font-size: 14px; font-weight: 400; line-height: 1.4; text-transform: uppercase; letter-spacing: 0.28px; color: var(--text-muted);">UPPERCASE SECTION LABEL</div>
<div class="type-sample-label">Uppercase Label &mdash; CohereMono &mdash; 14px / 400 / 1.40 / 0.28px / uppercase</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-body); font-size: 12px; font-weight: 400; line-height: 1.4; color: var(--text-muted);">Smallest text for footer links and fine print</div>
<div class="type-sample-label">Small &mdash; Unica77 &mdash; 12px / 400 / 1.40 / normal</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-mono); font-size: 8px; font-weight: 400; line-height: 1.4; text-transform: uppercase; letter-spacing: 0.16px; color: var(--text-muted);">CODE MICRO LABEL</div>
<div class="type-sample-label">Code Micro &mdash; CohereMono &mdash; 8px / 400 / 1.40 / 0.16px / uppercase</div>
</div>
</section>
<hr class="section-divider">
<!-- BUTTONS -->
<section class="section" id="buttons">
<div class="section-title">03 / Button Variants</div>
<h2 class="section-heading">Buttons</h2>
<div class="button-row">
<div class="button-demo">
<button class="btn-ghost-cohere">Ghost Button</button>
<div class="button-demo-label">Ghost / Transparent</div>
</div>
<div class="button-demo">
<button class="btn-light-cohere">Light Solid</button>
<div class="button-demo-label">Light Solid (22px)</div>
</div>
<div class="button-demo">
<button class="btn-light-pill">Pill CTA</button>
<div class="button-demo-label">Light Pill (9999px)</div>
</div>
<div class="button-demo">
<button class="btn-outlined">Outlined</button>
<div class="button-demo-label">Outlined (22px)</div>
</div>
</div>
<p style="color: var(--text-muted); margin-top: 32px; font-size: 14px;">
Ghost buttons are the primary style &mdash; invisible until interacted with. On hover, text shifts to Interaction Blue (#1863dc) with 0.8 opacity. Focus: 2px solid Interaction Blue outline.
</p>
</section>
<hr class="section-divider">
<!-- CARDS -->
<section class="section" id="cards">
<div class="section-title">04 / Card Examples</div>
<h2 class="section-heading">Cards & Containers</h2>
<div class="card-grid">
<div class="card card-signature">
<div class="card-label">STANDARD CARD</div>
<h3>Signature 22px Radius</h3>
<p>The distinctive Cohere card with 22px border-radius and #333 border on dark surfaces. Creates cloud-like, organic softness on the dark canvas.</p>
</div>
<div class="card card-dialog">
<div class="card-label">DIALOG CARD</div>
<h3>Dialog 8px Radius</h3>
<p>Modal and dialog containers use a tighter 8px radius with #333 border. Functional, secondary containment for transient UI.</p>
</div>
<div class="card card-generous">
<div class="card-label">GENEROUS CARD</div>
<h3>Featured 16px Radius</h3>
<p>Medium-sized containers for featured content. Uses 16px radius as a middle step in the radius scale with subtle border.</p>
</div>
</div>
</section>
<hr class="section-divider">
<!-- SPACING -->
<section class="section" id="spacing">
<div class="section-title">05 / Spacing Scale</div>
<h2 class="section-heading">Spacing System</h2>
<p style="color: var(--text-muted); margin-bottom: 32px;">Base unit: 8px. Scale from 2px to 60px.</p>
<div class="spacing-row">
<div class="spacing-item"><div class="spacing-box" style="width: 8px; height: 8px;"></div><div class="spacing-label">2px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 18px; height: 18px;"></div><div class="spacing-label">6px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 24px; height: 24px;"></div><div class="spacing-label">8px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 30px; height: 30px;"></div><div class="spacing-label">10px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 36px; height: 36px;"></div><div class="spacing-label">12px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 48px; height: 48px;"></div><div class="spacing-label">16px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 60px; height: 60px;"></div><div class="spacing-label">20px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 66px; height: 66px;"></div><div class="spacing-label">22px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 72px; height: 72px;"></div><div class="spacing-label">24px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 84px; height: 84px;"></div><div class="spacing-label">28px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 96px; height: 96px;"></div><div class="spacing-label">32px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 120px; height: 120px;"></div><div class="spacing-label">40px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 168px; height: 168px;"></div><div class="spacing-label">56px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 180px; height: 180px;"></div><div class="spacing-label">60px</div></div>
</div>
</section>
<hr class="section-divider">
<!-- BORDER RADIUS -->
<section class="section">
<div class="section-title">06 / Border Radius Scale</div>
<h2 class="section-heading">Border Radius</h2>
<div class="radius-row">
<div class="radius-item"><div class="radius-box" style="border-radius: 4px;"></div><div class="radius-label">4px</div><div class="radius-context">Sharp &mdash; nav, tags</div></div>
<div class="radius-item"><div class="radius-box" style="border-radius: 8px;"></div><div class="radius-label">8px</div><div class="radius-context">Comfortable &mdash; dialogs</div></div>
<div class="radius-item"><div class="radius-box" style="border-radius: 16px;"></div><div class="radius-label">16px</div><div class="radius-context">Generous &mdash; featured</div></div>
<div class="radius-item"><div class="radius-box" style="border-radius: 20px;"></div><div class="radius-label">20px</div><div class="radius-context">Large &mdash; feature cards</div></div>
<div class="radius-item"><div class="radius-box" style="border-radius: 22px; border-color: var(--accent); border-width: 2px;"></div><div class="radius-label">22px</div><div class="radius-context">Signature &mdash; THE radius</div></div>
<div class="radius-item"><div class="radius-box" style="border-radius: 9999px;"></div><div class="radius-label">9999px</div><div class="radius-context">Pill &mdash; buttons, tags</div></div>
</div>
</section>
<hr class="section-divider">
<!-- ELEVATION -->
<section class="section" id="elevation">
<div class="section-title">07 / Elevation & Depth</div>
<h2 class="section-heading">Depth & Elevation</h2>
<div class="elevation-grid">
<div class="elevation-card elevation-flat">
<div><div class="elevation-name">Flat</div><div class="elevation-desc">No shadow, no border. Page background and text blocks.</div></div>
<div class="elevation-level">Level 0</div>
</div>
<div class="elevation-card elevation-bordered-light">
<div><div class="elevation-name">Bordered (Subtle)</div><div class="elevation-desc">1px solid #2a2a2f. Subtle dark containment lines.</div></div>
<div class="elevation-level">Level 1 &mdash; Subtle</div>
</div>
<div class="elevation-card elevation-bordered-cool">
<div><div class="elevation-name">Bordered (Standard)</div><div class="elevation-desc">1px solid #333. Standard dark-mode card borders.</div></div>
<div class="elevation-level">Level 1 &mdash; Standard</div>
</div>
<div class="elevation-card elevation-purple-band">
<div><div class="elevation-name">Purple Band</div><div class="elevation-desc">Full-width dark purple background. Hero sections, showcases.</div></div>
<div class="elevation-level">Level 2 &mdash; Dramatic</div>
</div>
</div>
<p style="color: var(--text-muted); margin-top: 32px; font-size: 14px; line-height: 1.6;">
Cohere is nearly shadow-free. Depth is communicated through background color contrast (elevated cards on dark canvas), border containment, and dramatic light-to-dark section alternation.
</p>
</section>
<div style="height: 80px;"></div>
</body>
</html>
-814
View File
@@ -1,814 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Design System Preview: Cohere (Light)</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=Inter:wght@300;400;500;600;700&family=Space+Mono:wght@400;700&display=swap" rel="stylesheet">
<style>
:root {
/* Primary */
--color-black: #000000;
--color-near-black: #212121;
--color-deep-dark: #17171c;
/* Accent */
--color-interaction-blue: #1863dc;
--color-ring-blue: rgba(76, 110, 230, 0.5);
--color-focus-purple: #9b60aa;
/* Surface */
--color-white: #ffffff;
--color-snow: #fafafa;
--color-lightest-gray: #f2f2f2;
/* Neutrals */
--color-muted-slate: #93939f;
--color-border-cool: #d9d9dd;
--color-border-light: #e5e7eb;
/* Fonts */
--font-display: 'Space Grotesk', Inter, ui-sans-serif, system-ui, sans-serif;
--font-body: Inter, Arial, ui-sans-serif, system-ui, sans-serif;
--font-mono: 'Space Mono', Arial, ui-sans-serif, system-ui, monospace;
/* Light mode tokens */
--bg-page: #ffffff;
--bg-card: #ffffff;
--bg-nav: rgba(255, 255, 255, 0.95);
--text-primary: #000000;
--text-secondary: #212121;
--text-muted: #93939f;
--border-color: #d9d9dd;
--border-subtle: #f2f2f2;
--section-label-color: #93939f;
--accent: #1863dc;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: var(--bg-page);
color: var(--text-primary);
font-family: var(--font-body);
font-size: 16px;
line-height: 1.5;
font-weight: 400;
-webkit-font-smoothing: antialiased;
}
/* NAV */
.nav {
position: sticky;
top: 0;
z-index: 100;
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 40px;
background: var(--bg-nav);
backdrop-filter: blur(12px);
border-bottom: 1px solid var(--border-subtle);
}
.nav-brand {
font-family: var(--font-display);
font-size: 20px;
font-weight: 400;
letter-spacing: -0.4px;
display: flex;
align-items: center;
gap: 6px;
color: var(--text-primary);
}
.nav-brand svg { width: 28px; height: 28px; }
.nav-links { display: flex; gap: 32px; align-items: center; }
.nav-links a {
color: var(--text-secondary);
text-decoration: none;
font-size: 16px;
font-weight: 400;
font-family: var(--font-body);
transition: color 0.2s;
}
.nav-links a:hover { color: var(--accent); }
.nav-cta {
background: var(--color-black);
color: var(--color-white);
padding: 10px 24px;
border: none;
border-radius: 9999px;
font-size: 14px;
font-family: var(--font-body);
font-weight: 500;
cursor: pointer;
transition: opacity 0.2s;
}
.nav-cta:hover { opacity: 0.85; }
/* HERO */
.hero {
position: relative;
text-align: center;
padding: 120px 40px 100px;
overflow: hidden;
}
.hero h1 {
font-family: var(--font-display);
font-size: 72px;
font-weight: 400;
line-height: 1.0;
letter-spacing: -1.44px;
margin-bottom: 24px;
color: var(--text-primary);
}
.hero h1 span { color: var(--accent); }
.hero p {
color: var(--text-muted);
font-family: var(--font-body);
font-size: 18px;
font-weight: 400;
line-height: 1.4;
margin-bottom: 40px;
}
.hero-buttons { display: flex; gap: 16px; justify-content: center; }
.btn-ghost-primary {
background: transparent;
color: var(--text-primary);
padding: 12px 24px;
border: none;
font-size: 16px;
font-family: var(--font-body);
font-weight: 400;
cursor: pointer;
transition: color 0.2s, opacity 0.2s;
}
.btn-ghost-primary:hover { color: var(--accent); opacity: 0.8; }
.btn-dark-solid {
background: var(--color-black);
color: var(--color-white);
padding: 12px 28px;
border: none;
border-radius: 9999px;
font-size: 16px;
font-family: var(--font-body);
font-weight: 400;
cursor: pointer;
transition: opacity 0.2s;
}
.btn-dark-solid:hover { opacity: 0.85; }
/* SECTIONS */
.section {
max-width: 1200px;
margin: 0 auto;
padding: 80px 40px;
}
.section-title {
font-family: var(--font-mono);
font-size: 14px;
font-weight: 400;
text-transform: uppercase;
letter-spacing: 0.28px;
color: var(--section-label-color);
margin-bottom: 12px;
}
.section-heading {
font-family: var(--font-body);
font-size: 48px;
font-weight: 400;
line-height: 1.2;
letter-spacing: -0.48px;
margin-bottom: 48px;
color: var(--text-primary);
}
.section-divider {
border: none;
border-top: 1px solid var(--border-subtle);
margin: 0 40px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
}
/* PURPLE BAND */
.purple-band {
background: linear-gradient(135deg, #2d1b4e 0%, #1a1040 50%, #17171c 100%);
padding: 80px 40px;
text-align: center;
}
.purple-band h2 {
font-family: var(--font-display);
font-size: 60px;
font-weight: 400;
line-height: 1.0;
letter-spacing: -1.2px;
color: #ffffff;
margin-bottom: 16px;
}
.purple-band p {
color: rgba(255,255,255,0.7);
font-size: 18px;
font-weight: 400;
line-height: 1.4;
}
/* COLOR PALETTE */
.color-group { margin-bottom: 40px; }
.color-group-title {
font-family: var(--font-body);
font-size: 20px;
font-weight: 400;
line-height: 1.2;
margin-bottom: 20px;
color: var(--text-secondary);
}
.color-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
gap: 16px;
}
.color-swatch {
border: 1px solid var(--border-color);
border-radius: 22px;
overflow: hidden;
}
.color-swatch-block {
height: 80px;
position: relative;
}
.color-swatch-info {
padding: 12px 16px;
background: var(--bg-card);
}
.color-swatch-name { font-size: 13px; font-weight: 500; margin-bottom: 2px; }
.color-swatch-hex { font-family: var(--font-mono); font-size: 12px; color: var(--text-muted); margin-bottom: 4px; }
.color-swatch-role { font-size: 12px; color: var(--text-muted); line-height: 1.4; }
/* TYPOGRAPHY */
.type-sample { margin-bottom: 32px; padding-bottom: 32px; border-bottom: 1px solid var(--border-subtle); }
.type-sample:last-child { border-bottom: none; }
.type-sample-text { margin-bottom: 8px; }
.type-sample-label {
font-family: var(--font-mono);
font-size: 12px;
color: var(--text-muted);
}
/* BUTTONS */
.button-row {
display: flex;
flex-wrap: wrap;
gap: 24px;
align-items: flex-start;
}
.button-demo { text-align: center; }
.button-demo-label {
font-family: var(--font-mono);
font-size: 11px;
color: var(--text-muted);
margin-top: 10px;
text-transform: uppercase;
letter-spacing: 0.28px;
}
.btn-ghost-cohere {
background: transparent;
color: var(--color-black);
padding: 12px 24px;
border: none;
font-size: 16px;
font-family: var(--font-body);
font-weight: 400;
cursor: pointer;
transition: color 0.2s, opacity 0.2s;
}
.btn-ghost-cohere:hover { color: var(--accent); opacity: 0.8; }
.btn-dark-cohere {
background: var(--color-black);
color: var(--color-white);
padding: 12px 28px;
border: none;
border-radius: 22px;
font-size: 16px;
font-family: var(--font-body);
font-weight: 400;
cursor: pointer;
}
.btn-dark-pill {
background: var(--color-black);
color: var(--color-white);
padding: 12px 28px;
border: none;
border-radius: 9999px;
font-size: 14px;
font-family: var(--font-body);
font-weight: 500;
cursor: pointer;
}
.btn-outlined {
background: transparent;
color: var(--text-primary);
padding: 12px 24px;
border: 1px solid var(--border-color);
border-radius: 22px;
font-size: 16px;
font-family: var(--font-body);
font-weight: 400;
cursor: pointer;
transition: border-color 0.2s, color 0.2s;
}
.btn-outlined:hover { border-color: var(--accent); color: var(--accent); }
.btn-ghost-focus:focus {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
/* CARDS */
.card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 24px; }
.card {
background: var(--bg-card);
padding: 28px;
}
.card-signature {
border-radius: 22px;
border: 1px solid var(--color-lightest-gray);
}
.card-dialog {
border-radius: 8px;
border: 1px solid var(--border-color);
}
.card-generous {
border-radius: 16px;
border: 1px solid var(--color-lightest-gray);
}
.card h3 {
font-family: var(--font-body);
font-size: 24px;
font-weight: 400;
line-height: 1.3;
letter-spacing: normal;
margin-bottom: 12px;
color: var(--text-primary);
}
.card p { color: var(--text-muted); font-size: 16px; line-height: 1.5; font-weight: 400; }
.card-label {
font-family: var(--font-mono);
font-size: 14px;
text-transform: uppercase;
letter-spacing: 0.28px;
color: var(--text-muted);
margin-bottom: 16px;
}
/* SPACING */
.spacing-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; }
.spacing-item { text-align: center; }
.spacing-box {
background: rgba(24, 99, 220, 0.08);
border: 1px solid rgba(24, 99, 220, 0.2);
border-radius: 2px;
margin-bottom: 8px;
}
.spacing-label {
font-family: var(--font-mono);
font-size: 11px;
color: var(--text-muted);
}
/* RADIUS */
.radius-row { display: flex; flex-wrap: wrap; gap: 20px; align-items: center; }
.radius-item { text-align: center; }
.radius-box {
width: 80px;
height: 80px;
background: var(--color-snow);
border: 1px solid var(--border-color);
margin-bottom: 8px;
}
.radius-label {
font-family: var(--font-mono);
font-size: 11px;
color: var(--text-muted);
}
.radius-context {
font-size: 11px;
color: var(--text-muted);
margin-top: 2px;
}
/* ELEVATION */
.elevation-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 24px; }
.elevation-card {
background: var(--bg-card);
border-radius: 22px;
padding: 24px;
min-height: 140px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.elevation-flat { border: none; background: var(--bg-page); }
.elevation-bordered-light { border: 1px solid var(--color-lightest-gray); }
.elevation-bordered-cool { border: 1px solid var(--border-color); }
.elevation-purple-band {
background: linear-gradient(135deg, #2d1b4e 0%, #1a1040 100%);
color: #ffffff;
}
.elevation-purple-band .elevation-name,
.elevation-purple-band .elevation-desc { color: #ffffff; }
.elevation-purple-band .elevation-level { color: rgba(255,255,255,0.6); }
.elevation-name { font-size: 16px; font-weight: 500; margin-bottom: 8px; }
.elevation-desc { font-size: 13px; color: var(--text-muted); line-height: 1.5; }
.elevation-level {
font-family: var(--font-mono);
font-size: 11px;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.28px;
margin-top: 12px;
}
/* RESPONSIVE */
@media (max-width: 768px) {
.nav { padding: 12px 20px; }
.nav-links a:not(.nav-cta-wrapper) { display: none; }
.hero { padding: 80px 20px 60px; }
.hero h1 { font-size: 42px; letter-spacing: -0.84px; }
.section { padding: 60px 20px; }
.section-heading { font-size: 32px; letter-spacing: -0.32px; }
.color-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
.card-grid { grid-template-columns: 1fr; }
.hero-buttons { flex-direction: column; align-items: center; }
.button-row { flex-direction: column; align-items: flex-start; }
.purple-band h2 { font-size: 36px; }
}
</style>
</head>
<body>
<!-- NAV -->
<nav class="nav">
<div class="nav-brand">
<svg viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="14" cy="14" r="13" stroke="currentColor" stroke-width="2"/>
<path d="M8 14 C8 10, 12 8, 14 8 C16 8, 20 10, 20 14 C20 18, 16 20, 14 20 C12 20, 8 18, 8 14Z" fill="currentColor" opacity="0.15"/>
<circle cx="14" cy="14" r="4" fill="currentColor"/>
</svg>
cohere
</div>
<div class="nav-links">
<a href="#colors">Colors</a>
<a href="#typography">Typography</a>
<a href="#buttons">Buttons</a>
<a href="#cards">Cards</a>
<a href="#spacing">Spacing</a>
<a href="#elevation">Elevation</a>
<button class="nav-cta">Get Started</button>
</div>
</nav>
<!-- HERO -->
<section class="hero">
<h1>Design System Preview:<br><span>Cohere</span></h1>
<p>Auto-generated design token catalog from DESIGN.md</p>
<div class="hero-buttons">
<button class="btn-dark-solid">Explore Tokens</button>
<button class="btn-ghost-primary">View Source</button>
</div>
</section>
<hr class="section-divider">
<!-- COLORS -->
<section class="section" id="colors">
<div class="section-title">01 / Color Palette</div>
<h2 class="section-heading">Color Palette & Roles</h2>
<div class="color-group">
<h3 class="color-group-title">Primary</h3>
<div class="color-grid">
<div class="color-swatch">
<div class="color-swatch-block" style="background: #000000; border-bottom: 1px solid #333;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Cohere Black</div>
<div class="color-swatch-hex">#000000</div>
<div class="color-swatch-role">Primary headline text, maximum emphasis</div>
</div>
</div>
<div class="color-swatch">
<div class="color-swatch-block" style="background: #212121; border-bottom: 1px solid #333;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Near Black</div>
<div class="color-swatch-hex">#212121</div>
<div class="color-swatch-role">Standard body link color</div>
</div>
</div>
<div class="color-swatch">
<div class="color-swatch-block" style="background: #17171c; border-bottom: 1px solid #333;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Deep Dark</div>
<div class="color-swatch-hex">#17171c</div>
<div class="color-swatch-role">Navigation and dark-section text</div>
</div>
</div>
</div>
</div>
<div class="color-group">
<h3 class="color-group-title">Secondary & Accent</h3>
<div class="color-grid">
<div class="color-swatch">
<div class="color-swatch-block" style="background: #1863dc;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Interaction Blue</div>
<div class="color-swatch-hex">#1863dc</div>
<div class="color-swatch-role">Hover, focus states, active links</div>
</div>
</div>
<div class="color-swatch">
<div class="color-swatch-block" style="background: rgba(76,110,230,0.5);"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Ring Blue</div>
<div class="color-swatch-hex">#4c6ee6 @ 50%</div>
<div class="color-swatch-role">Keyboard focus indicators</div>
</div>
</div>
<div class="color-swatch">
<div class="color-swatch-block" style="background: #9b60aa;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Focus Purple</div>
<div class="color-swatch-hex">#9b60aa</div>
<div class="color-swatch-role">Input focus border color</div>
</div>
</div>
</div>
</div>
<div class="color-group">
<h3 class="color-group-title">Surface & Background</h3>
<div class="color-grid">
<div class="color-swatch">
<div class="color-swatch-block" style="background: #ffffff; border-bottom: 1px solid #e5e7eb;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Pure White</div>
<div class="color-swatch-hex">#ffffff</div>
<div class="color-swatch-role">Primary page background, card surface</div>
</div>
</div>
<div class="color-swatch">
<div class="color-swatch-block" style="background: #fafafa; border-bottom: 1px solid #e5e7eb;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Snow</div>
<div class="color-swatch-hex">#fafafa</div>
<div class="color-swatch-role">Subtle elevated surfaces, light sections</div>
</div>
</div>
<div class="color-swatch">
<div class="color-swatch-block" style="background: #f2f2f2; border-bottom: 1px solid #e5e7eb;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Lightest Gray</div>
<div class="color-swatch-hex">#f2f2f2</div>
<div class="color-swatch-role">Card borders, softest containment</div>
</div>
</div>
</div>
</div>
<div class="color-group">
<h3 class="color-group-title">Neutrals & Text</h3>
<div class="color-grid">
<div class="color-swatch">
<div class="color-swatch-block" style="background: #93939f;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Muted Slate</div>
<div class="color-swatch-hex">#93939f</div>
<div class="color-swatch-role">Footer links, tertiary text</div>
</div>
</div>
<div class="color-swatch">
<div class="color-swatch-block" style="background: #d9d9dd;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Border Cool</div>
<div class="color-swatch-hex">#d9d9dd</div>
<div class="color-swatch-role">Section borders, list separators</div>
</div>
</div>
<div class="color-swatch">
<div class="color-swatch-block" style="background: #e5e7eb;"></div>
<div class="color-swatch-info">
<div class="color-swatch-name">Border Light</div>
<div class="color-swatch-hex">#e5e7eb</div>
<div class="color-swatch-role">Lighter border variant (gray-200)</div>
</div>
</div>
</div>
</div>
</section>
<hr class="section-divider">
<!-- PURPLE HERO BAND -->
<div class="purple-band">
<h2>Enterprise AI Platform</h2>
<p>Deep purple hero sections create dramatic visual breaks in the white page flow</p>
</div>
<hr class="section-divider">
<!-- TYPOGRAPHY -->
<section class="section" id="typography">
<div class="section-title">02 / Typography Scale</div>
<h2 class="section-heading">Typography Rules</h2>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-display); font-size: 72px; font-weight: 400; line-height: 1.0; letter-spacing: -1.44px;">Display Hero</div>
<div class="type-sample-label">Display / Hero &mdash; CohereText &mdash; 72px / 400 / 1.00 / -1.44px</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-display); font-size: 60px; font-weight: 400; line-height: 1.0; letter-spacing: -1.2px;">Display Secondary</div>
<div class="type-sample-label">Display Secondary &mdash; CohereText &mdash; 60px / 400 / 1.00 / -1.2px</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-body); font-size: 48px; font-weight: 400; line-height: 1.2; letter-spacing: -0.48px;">Section Heading</div>
<div class="type-sample-label">Section Heading &mdash; Unica77 &mdash; 48px / 400 / 1.20 / -0.48px</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-body); font-size: 32px; font-weight: 400; line-height: 1.2; letter-spacing: -0.32px;">Sub-heading</div>
<div class="type-sample-label">Sub-heading &mdash; Unica77 &mdash; 32px / 400 / 1.20 / -0.32px</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-body); font-size: 24px; font-weight: 400; line-height: 1.3;">Feature Title</div>
<div class="type-sample-label">Feature Title &mdash; Unica77 &mdash; 24px / 400 / 1.30 / normal</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-body); font-size: 18px; font-weight: 400; line-height: 1.4;">Body Large text for intro paragraphs. Unica77 provides geometric Swiss precision for all functional UI text at the body-large tier.</div>
<div class="type-sample-label">Body Large &mdash; Unica77 &mdash; 18px / 400 / 1.40 / normal</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-body); font-size: 16px; font-weight: 400; line-height: 1.5;">Standard body text for paragraphs, navigation links, and button labels. Unica77 at its most common size, weight 400.</div>
<div class="type-sample-label">Body / Button &mdash; Unica77 &mdash; 16px / 400 / 1.50 / normal</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-body); font-size: 14px; font-weight: 500; line-height: 1.71;">Button Medium Label</div>
<div class="type-sample-label">Button Medium &mdash; Unica77 &mdash; 14px / 500 / 1.71 / normal</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-body); font-size: 14px; font-weight: 400; line-height: 1.4; color: var(--text-muted);">Caption and metadata text for descriptions</div>
<div class="type-sample-label">Caption &mdash; Unica77 &mdash; 14px / 400 / 1.40 / normal</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-mono); font-size: 14px; font-weight: 400; line-height: 1.4; text-transform: uppercase; letter-spacing: 0.28px; color: var(--text-muted);">UPPERCASE SECTION LABEL</div>
<div class="type-sample-label">Uppercase Label &mdash; CohereMono &mdash; 14px / 400 / 1.40 / 0.28px / uppercase</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-body); font-size: 12px; font-weight: 400; line-height: 1.4; color: var(--text-muted);">Smallest text for footer links and fine print</div>
<div class="type-sample-label">Small &mdash; Unica77 &mdash; 12px / 400 / 1.40 / normal</div>
</div>
<div class="type-sample">
<div class="type-sample-text" style="font-family: var(--font-mono); font-size: 8px; font-weight: 400; line-height: 1.4; text-transform: uppercase; letter-spacing: 0.16px; color: var(--text-muted);">CODE MICRO LABEL</div>
<div class="type-sample-label">Code Micro &mdash; CohereMono &mdash; 8px / 400 / 1.40 / 0.16px / uppercase</div>
</div>
</section>
<hr class="section-divider">
<!-- BUTTONS -->
<section class="section" id="buttons">
<div class="section-title">03 / Button Variants</div>
<h2 class="section-heading">Buttons</h2>
<div class="button-row">
<div class="button-demo">
<button class="btn-ghost-cohere">Ghost Button</button>
<div class="button-demo-label">Ghost / Transparent</div>
</div>
<div class="button-demo">
<button class="btn-dark-cohere">Dark Solid</button>
<div class="button-demo-label">Dark Solid (22px)</div>
</div>
<div class="button-demo">
<button class="btn-dark-pill">Pill CTA</button>
<div class="button-demo-label">Dark Pill (9999px)</div>
</div>
<div class="button-demo">
<button class="btn-outlined">Outlined</button>
<div class="button-demo-label">Outlined (22px)</div>
</div>
</div>
<p style="color: var(--text-muted); margin-top: 32px; font-size: 14px;">
Ghost buttons are the primary style &mdash; invisible until interacted with. On hover, text shifts to Interaction Blue (#1863dc) with 0.8 opacity. Focus: 2px solid Interaction Blue outline.
</p>
</section>
<hr class="section-divider">
<!-- CARDS -->
<section class="section" id="cards">
<div class="section-title">04 / Card Examples</div>
<h2 class="section-heading">Cards & Containers</h2>
<div class="card-grid">
<div class="card card-signature">
<div class="card-label">STANDARD CARD</div>
<h3>Signature 22px Radius</h3>
<p>The distinctive Cohere card with 22px border-radius and 1px solid #f2f2f2 border. Creates cloud-like, organic softness on the white canvas.</p>
</div>
<div class="card card-dialog">
<div class="card-label">DIALOG CARD</div>
<h3>Dialog 8px Radius</h3>
<p>Modal and dialog containers use a tighter 8px radius with #d9d9dd border. Functional, secondary containment for transient UI.</p>
</div>
<div class="card card-generous">
<div class="card-label">GENEROUS CARD</div>
<h3>Featured 16px Radius</h3>
<p>Medium-sized containers for featured content. Uses 16px radius as a middle step in the radius scale with subtle #f2f2f2 border.</p>
</div>
</div>
</section>
<hr class="section-divider">
<!-- SPACING -->
<section class="section" id="spacing">
<div class="section-title">05 / Spacing Scale</div>
<h2 class="section-heading">Spacing System</h2>
<p style="color: var(--text-muted); margin-bottom: 32px;">Base unit: 8px. Scale from 2px to 60px.</p>
<div class="spacing-row">
<div class="spacing-item"><div class="spacing-box" style="width: 8px; height: 8px;"></div><div class="spacing-label">2px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 18px; height: 18px;"></div><div class="spacing-label">6px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 24px; height: 24px;"></div><div class="spacing-label">8px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 30px; height: 30px;"></div><div class="spacing-label">10px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 36px; height: 36px;"></div><div class="spacing-label">12px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 48px; height: 48px;"></div><div class="spacing-label">16px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 60px; height: 60px;"></div><div class="spacing-label">20px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 66px; height: 66px;"></div><div class="spacing-label">22px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 72px; height: 72px;"></div><div class="spacing-label">24px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 84px; height: 84px;"></div><div class="spacing-label">28px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 96px; height: 96px;"></div><div class="spacing-label">32px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 120px; height: 120px;"></div><div class="spacing-label">40px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 168px; height: 168px;"></div><div class="spacing-label">56px</div></div>
<div class="spacing-item"><div class="spacing-box" style="width: 180px; height: 180px;"></div><div class="spacing-label">60px</div></div>
</div>
</section>
<hr class="section-divider">
<!-- BORDER RADIUS -->
<section class="section">
<div class="section-title">06 / Border Radius Scale</div>
<h2 class="section-heading">Border Radius</h2>
<div class="radius-row">
<div class="radius-item"><div class="radius-box" style="border-radius: 4px;"></div><div class="radius-label">4px</div><div class="radius-context">Sharp &mdash; nav, tags</div></div>
<div class="radius-item"><div class="radius-box" style="border-radius: 8px;"></div><div class="radius-label">8px</div><div class="radius-context">Comfortable &mdash; dialogs</div></div>
<div class="radius-item"><div class="radius-box" style="border-radius: 16px;"></div><div class="radius-label">16px</div><div class="radius-context">Generous &mdash; featured</div></div>
<div class="radius-item"><div class="radius-box" style="border-radius: 20px;"></div><div class="radius-label">20px</div><div class="radius-context">Large &mdash; feature cards</div></div>
<div class="radius-item"><div class="radius-box" style="border-radius: 22px; border-color: var(--accent); border-width: 2px;"></div><div class="radius-label">22px</div><div class="radius-context">Signature &mdash; THE radius</div></div>
<div class="radius-item"><div class="radius-box" style="border-radius: 9999px;"></div><div class="radius-label">9999px</div><div class="radius-context">Pill &mdash; buttons, tags</div></div>
</div>
</section>
<hr class="section-divider">
<!-- ELEVATION -->
<section class="section" id="elevation">
<div class="section-title">07 / Elevation & Depth</div>
<h2 class="section-heading">Depth & Elevation</h2>
<div class="elevation-grid">
<div class="elevation-card elevation-flat">
<div><div class="elevation-name">Flat</div><div class="elevation-desc">No shadow, no border. Page background and text blocks.</div></div>
<div class="elevation-level">Level 0</div>
</div>
<div class="elevation-card elevation-bordered-light">
<div><div class="elevation-name">Bordered (Light)</div><div class="elevation-desc">1px solid #f2f2f2. Standard cards, subtle containment.</div></div>
<div class="elevation-level">Level 1 &mdash; Lightest Gray</div>
</div>
<div class="elevation-card elevation-bordered-cool">
<div><div class="elevation-name">Bordered (Cool)</div><div class="elevation-desc">1px solid #d9d9dd. Emphasized cards, list separators.</div></div>
<div class="elevation-level">Level 1 &mdash; Border Cool</div>
</div>
<div class="elevation-card elevation-purple-band">
<div><div class="elevation-name">Purple Band</div><div class="elevation-desc">Full-width dark purple background. Hero sections, showcases.</div></div>
<div class="elevation-level">Level 2 &mdash; Dramatic</div>
</div>
</div>
<p style="color: var(--text-muted); margin-top: 32px; font-size: 14px; line-height: 1.6;">
Cohere is nearly shadow-free. Depth is communicated through background color contrast (white cards on purple bands), border containment (cool gray borders), and dramatic light-to-dark section alternation.
</p>
</section>
<div style="height: 80px;"></div>
</body>
</html>
-21
View File
@@ -1,21 +0,0 @@
/*
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://static.cloudflareinsights.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com data:; img-src 'self' data:; connect-src 'self' https://cloudflareinsights.com; base-uri 'self'; form-action 'self'; frame-ancestors 'none'
Permissions-Policy: camera=(), microphone=(), geolocation=()
Referrer-Policy: strict-origin-when-cross-origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
/screenshots/*
Cache-Control: public, max-age=31536000, immutable
/assets/*
Cache-Control: public, max-age=31536000, immutable
/_next/static/*
Cache-Control: public, max-age=31536000, immutable
/favicon.ico
Cache-Control: public, max-age=31536000, immutable
/icon.png
Cache-Control: public, max-age=31536000, immutable
-7
View File
@@ -1,7 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" fill="none">
<circle cx="512" cy="512" r="480" fill="#191919"/>
<g transform="translate(268 255) scale(4)">
<path fill="#FBFAF5" d="M 76.604813 111.661926 C 65.070183 111.662621 53.987053 111.662621 42.757744 111.662621 C 45.2239 101.998177 45.297546 101.949265 53.830105 102.036659 C 57.279823 102.071999 60.730202 102.04248 64.259201 102.04248 C 62.159458 93.316338 61.799103 93.009819 51.340881 91.341682 C 59.312901 73.847687 67.193756 56.553749 75.587578 38.134155 C 86.933441 62.965954 97.804642 86.758881 108.711754 110.630394 C 100.707413 111.871689 92.355965 107.246559 88.107536 98.852119 C 84.207748 91.146538 80.800591 83.191696 77.172813 75.348343 C 76.340195 73.54818 75.492958 71.754791 74.614624 69.877441 C 69.107384 75.691788 68.008286 81.475128 71.005882 88.088753 C 74.413452 95.606903 77.813919 103.128281 81.452705 111.167984 C 79.55114 111.381325 78.303734 111.521271 76.604813 111.661926 Z"/>
<path fill="#FBFAF5" d="M 26.805992 87.743256 C 38.616821 61.830872 50.261688 36.260269 62.470131 9.452141 C 65.732315 17.818909 71.145126 23.524567 66.258224 33.086182 C 55.518253 54.099815 46.339973 75.911873 36.533691 97.402336 C 32.699284 105.805443 26.495394 110.823158 16.012421 111.410957 C 19.72117 103.270836 23.180601 95.67794 26.805992 87.743256 Z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 752 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 337 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 465 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 606 KiB

-36
View File
@@ -1,36 +0,0 @@
{
"compilerOptions": {
"target": "ES2022",
"lib": [
"dom",
"dom.iterable",
"es2022"
],
"allowJs": false,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"incremental": true,
"plugins": [
{
"name": "next"
}
]
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/dev/types/**/*.ts"
],
"exclude": [
"node_modules"
]
}
-11
View File
@@ -1,11 +0,0 @@
name = "agentcompany"
compatibility_date = "2026-04-03"
pages_build_output_dir = "out"
[vars]
DOWNLOAD_COUNTER_SALT = "agentcompany-download-counter-v1"
[[d1_databases]]
binding = "DOWNLOAD_COUNTER_DB"
database_name = "agentcompany-landing-downloads"
database_id = "dfa3f0f3-009b-4436-b519-5b50ae6b1cf9"