From 9b50861a326ea57c741dba85db2ebcf07f5cd67c Mon Sep 17 00:00:00 2001 From: christopherkindl <53372002+christopherkindl@users.noreply.github.com> Date: Mon, 10 Aug 2026 17:04:21 +0200 Subject: [PATCH 01/29] docs: redesign homepage --- .../docs/app/[lang]/(home)/components/cta.tsx | 2 +- .../(home)/graphics/monorepo-visual.tsx | 43 + .../(home)/graphics/provider-badges.tsx | 42 + .../app/[lang]/(home)/graphics/providers.tsx | 948 ------------------ .../(home)/graphics/remote-cache-visual.tsx | 21 + .../[lang]/(home)/graphics/sizing-string.ts | 3 +- .../app/[lang]/(home)/highlighted-code.tsx | 37 + apps/docs/app/[lang]/(home)/layout.tsx | 2 +- apps/docs/app/[lang]/(home)/page.tsx | 311 +++--- apps/docs/app/[lang]/layout.tsx | 2 +- apps/docs/app/styles/geistdocs.css | 6 +- apps/docs/components/geistdocs/footer.tsx | 59 -- apps/docs/components/logos.tsx | 6 +- .../remote-cache-counter/client.tsx | 13 +- apps/docs/components/testimonials.tsx | 20 +- apps/docs/components/ui/button.tsx | 60 -- apps/docs/geistdocs.tsx | 11 +- apps/docs/package.json | 2 +- pnpm-lock.yaml | 46 +- 19 files changed, 387 insertions(+), 1247 deletions(-) create mode 100644 apps/docs/app/[lang]/(home)/graphics/monorepo-visual.tsx create mode 100644 apps/docs/app/[lang]/(home)/graphics/provider-badges.tsx delete mode 100644 apps/docs/app/[lang]/(home)/graphics/providers.tsx create mode 100644 apps/docs/app/[lang]/(home)/graphics/remote-cache-visual.tsx create mode 100644 apps/docs/app/[lang]/(home)/highlighted-code.tsx delete mode 100644 apps/docs/components/geistdocs/footer.tsx delete mode 100644 apps/docs/components/ui/button.tsx diff --git a/apps/docs/app/[lang]/(home)/components/cta.tsx b/apps/docs/app/[lang]/(home)/components/cta.tsx index cf25a9b56e9d1..5e7dbc666aaac 100644 --- a/apps/docs/app/[lang]/(home)/components/cta.tsx +++ b/apps/docs/app/[lang]/(home)/components/cta.tsx @@ -1,5 +1,5 @@ import DynamicLink from "fumadocs-core/dynamic-link"; -import { Button } from "@/components/ui/button"; +import { Button } from "@vercel/geistdocs/components/button"; type CTAProps = { title: string; diff --git a/apps/docs/app/[lang]/(home)/graphics/monorepo-visual.tsx b/apps/docs/app/[lang]/(home)/graphics/monorepo-visual.tsx new file mode 100644 index 0000000000000..495912f8b8517 --- /dev/null +++ b/apps/docs/app/[lang]/(home)/graphics/monorepo-visual.tsx @@ -0,0 +1,43 @@ +import { SiNextdotjs, SiNuxt, SiSvelte } from "@icons-pack/react-simple-icons"; + +const tasks = [ + { label: "apps/web", Logo: SiNextdotjs, themeAware: true }, + { label: "apps/docs", Logo: SiSvelte }, + { label: "app/blog", Logo: SiNuxt }, +]; + +export function MonorepoVisual() { + return ( +
+ ); +} diff --git a/apps/docs/app/[lang]/(home)/graphics/provider-badges.tsx b/apps/docs/app/[lang]/(home)/graphics/provider-badges.tsx new file mode 100644 index 0000000000000..714ddc5656f64 --- /dev/null +++ b/apps/docs/app/[lang]/(home)/graphics/provider-badges.tsx @@ -0,0 +1,42 @@ +import { + SiCircleci, + SiGithub, + SiGitlab, + SiJenkins, + SiVercel, +} from "@icons-pack/react-simple-icons"; + +const providers = [ + { label: "GitHub", Logo: SiGithub, themeAware: true }, + { label: "GitLab", Logo: SiGitlab }, + { label: "Vercel", Logo: SiVercel, themeAware: true }, + { label: "Jenkins", Logo: SiJenkins, logoClassName: "dark:fill-gray-1000" }, + { + label: "CircleCI", + Logo: SiCircleci, + logoClassName: "dark:fill-gray-1000", + }, +]; + +export function ProviderBadges() { + return ( +- Turborepo is the build system for JavaScript and TypeScript - codebases +
+ Turborepo is the build system for JavaScript and TypeScript + codebases +
++ hours of compute saved due to remote caching
-- Optimize your local and CI tasks to save years of engineering time - and compute. -
-+ Optimize your local and CI tasks to save years of engineering time and + compute. +
++
{feature.description}
- Start a new repository or migrate an existing repo incrementally - in minutes. -
-+ Start a new repository or migrate an existing repo incrementally + in minutes. +
{title}
-- Turborepo is the build system for JavaScript and TypeScript - codebases + Turborepo is the build system for coding agents
- Turborepo is the build system for coding agents + Turborepo is the build system for JavaScript and TypeScript + codebases
+
Optimize your local and CI tasks to save years of engineering time and compute.
From c2a2f4a532541dc3c2e5ef9828c05baa8d0a6a81 Mon Sep 17 00:00:00 2001 From: christopherkindl <53372002+christopherkindl@users.noreply.github.com> Date: Mon, 10 Aug 2026 22:28:21 +0200 Subject: [PATCH 06/29] feat: Redesign documentation homepage --- .../graphics/agent-workflow-visuals.tsx | 214 ++++++++++++++++++ .../(home)/graphics/remote-cache-visual.tsx | 2 +- apps/docs/app/[lang]/(home)/page.tsx | 125 +++++++--- .../api/remote-cache-minutes-saved/route.ts | 12 +- .../remote-cache-counter/client.tsx | 10 +- .../remote-cache-counter/constants.ts | 1 + 6 files changed, 321 insertions(+), 43 deletions(-) create mode 100644 apps/docs/app/[lang]/(home)/graphics/agent-workflow-visuals.tsx create mode 100644 apps/docs/components/remote-cache-counter/constants.ts diff --git a/apps/docs/app/[lang]/(home)/graphics/agent-workflow-visuals.tsx b/apps/docs/app/[lang]/(home)/graphics/agent-workflow-visuals.tsx new file mode 100644 index 0000000000000..e793e42e89ad2 --- /dev/null +++ b/apps/docs/app/[lang]/(home)/graphics/agent-workflow-visuals.tsx @@ -0,0 +1,214 @@ +import { IconCheck } from "@vercel/geistdocs/assets/icons/icon-check"; +import type { ReactNode } from "react"; + +const validationTasks = [ + { name: "lint", time: "320ms" }, + { name: "test", time: "680ms" }, + { name: "build", time: "1.1s" }, +]; + +function ChatTail({ side }: { side: "left" | "right" }) { + return ( + + ); +} + +function ChatBubble({ + align, + children, +}: { + align: "start" | "end"; + children: ReactNode; +}) { + return ( +129 successful, 129 total
129 cached, 129 total
diff --git a/apps/docs/app/[lang]/(home)/page.tsx b/apps/docs/app/[lang]/(home)/page.tsx
index 2d351fbae25f2..afa5f33cf6b0b 100644
--- a/apps/docs/app/[lang]/(home)/page.tsx
+++ b/apps/docs/app/[lang]/(home)/page.tsx
@@ -1,4 +1,5 @@
import Link from "next/link";
+import type { ReactNode } from "react";
import {
CommandPromptContent,
CommandPromptCopy,
@@ -18,8 +19,19 @@ import { HighlightedCode } from "./highlighted-code";
import { ProviderBadges } from "./graphics/provider-badges";
import { RemoteCacheVisual } from "./graphics/remote-cache-visual";
import { MonorepoVisual } from "./graphics/monorepo-visual";
+import {
+ AgentSkillsVisual,
+ TurboDocsVisual,
+ ValidationLoopsVisual,
+} from "./graphics/agent-workflow-visuals";
+
+type HomepageFeature = {
+ title: string;
+ description: ReactNode;
+ illustration: ReactNode;
+};
-const FEATURES = [
+const FEATURES: HomepageFeature[] = [
{
title: "Works with any provider",
description:
@@ -40,6 +52,35 @@ const FEATURES = [
},
];
+const AGENT_FEATURES: HomepageFeature[] = [
+ {
+ title: "Faster validation loops",
+ description:
+ "Run only the checks affected by each change, so agents can verify their work and iterate without waiting on the entire repository.",
+ illustration:
- Turborepo is the build system for JavaScript and TypeScript
- codebases
+
+ Turborepo is a build system for JavaScript and TypeScript that runs
+ and caches tasks so developers, CI, and agents never repeat work.
+ turbo docs
+ {" "}
+ command lets agents search current Turborepo documentation from the
+ terminal, without interrupting their work.
+ >
+ ),
+ illustration:
- The build system that scales with your codebase
+ Your entire codebase, working at full speed
-
- Optimize your local and CI tasks to save years of engineering time and - compute. -
-- {feature.description} -
-+ {description} +
++ {feature.description} +
++ compute hours saved with Remote Caching +
+- hours of compute saved due to remote caching -
- -+ {counterFormatter.format(displayValue)} +
); } diff --git a/apps/docs/package.json b/apps/docs/package.json index 0995ba7da27d3..e19da76334a6d 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -28,9 +28,9 @@ "geist": "^1.7.2", "linkedom": "0.18.12", "lucide-react": "^0.555.0", - "motion": "^12.23.25", "next": "16.3.0", "next-themes": "^0.4.6", + "phase": "^0.0.7", "radix-ui": "latest", "react": "^19.2.3", "react-dom": "^19.2.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9e5df99a51a1e..1bd1fbc475f8f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -117,15 +117,15 @@ importers: lucide-react: specifier: ^0.555.0 version: 0.555.0(react@19.2.4) - motion: - specifier: ^12.23.25 - version: 12.33.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) next: specifier: 16.3.0 version: 16.3.0(@opentelemetry/api@1.9.0)(@types/node@24.10.11)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) next-themes: specifier: ^0.4.6 version: 0.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + phase: + specifier: ^0.0.7 + version: 0.0.7(react@19.2.4) radix-ui: specifier: latest version: 1.6.0(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -6865,20 +6865,6 @@ packages: resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} engines: {node: '>=0.4.x'} - framer-motion@12.33.0: - resolution: {integrity: sha512-ca8d+rRPcDP5iIF+MoT3WNc0KHJMjIyFAbtVLvM9eA7joGSpeqDfiNH/kCs1t4CHi04njYvWyj0jS4QlEK/rJQ==} - peerDependencies: - '@emotion/is-prop-valid': '*' - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@emotion/is-prop-valid': - optional: true - react: - optional: true - react-dom: - optional: true - framer-motion@12.38.0: resolution: {integrity: sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g==} peerDependencies: @@ -8291,32 +8277,12 @@ packages: mkdirp-classic@0.5.3: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} - motion-dom@12.33.0: - resolution: {integrity: sha512-XRPebVypsl0UM+7v0Hr8o9UAj0S2djsQWRdHBd5iVouVpMrQqAI0C/rDAT3QaYnXnHuC5hMcwDHCboNeyYjPoQ==} - motion-dom@12.38.0: resolution: {integrity: sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA==} - motion-utils@12.29.2: - resolution: {integrity: sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A==} - motion-utils@12.36.0: resolution: {integrity: sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==} - motion@12.33.0: - resolution: {integrity: sha512-TcND7PijsrTeIA9SRVUB8TOJQ+6mJnJ5K4a9oAJZvyI0Zy47Gq5oofU+VkTxbLcvDoKXnHspQcII2mnk3TbFsQ==} - peerDependencies: - '@emotion/is-prop-valid': '*' - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@emotion/is-prop-valid': - optional: true - react: - optional: true - react-dom: - optional: true - motion@12.38.0: resolution: {integrity: sha512-uYfXzeHlgThchzwz5Te47dlv5JOUC7OB4rjJ/7XTUgtBZD8CchMN8qEJ4ZVsUmTyYA44zjV0fBwsiktRuFnn+w==} peerDependencies: @@ -8734,6 +8700,15 @@ packages: pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + phase@0.0.7: + resolution: {integrity: sha512-LxWLJbqWm5Yh34A2RIdHUE48c93Rcs9cd3kKKqdGkphCdYvqp8qgUVkSM6au31zpW5N8LggCzW4ly0TWrAOEMg==} + engines: {node: 24.x} + peerDependencies: + react: '>=18' + peerDependenciesMeta: + react: + optional: true + picocolors@1.0.1: resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} @@ -16168,15 +16143,6 @@ snapshots: format@0.2.2: {} - framer-motion@12.33.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - motion-dom: 12.33.0 - motion-utils: 12.29.2 - tslib: 2.8.1 - optionalDependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - framer-motion@12.38.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: motion-dom: 12.38.0 @@ -18216,26 +18182,12 @@ snapshots: mkdirp-classic@0.5.3: optional: true - motion-dom@12.33.0: - dependencies: - motion-utils: 12.29.2 - motion-dom@12.38.0: dependencies: motion-utils: 12.36.0 - motion-utils@12.29.2: {} - motion-utils@12.36.0: {} - motion@12.33.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - framer-motion: 12.33.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - tslib: 2.8.1 - optionalDependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - motion@12.38.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: framer-motion: 12.38.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -18742,6 +18694,10 @@ snapshots: pend@1.2.0: {} + phase@0.0.7(react@19.2.4): + optionalDependencies: + react: 19.2.4 + picocolors@1.0.1: {} picocolors@1.1.1: {} From 10351e6690a55c89cec6944d3ddbb9ad170319e9 Mon Sep 17 00:00:00 2001 From: christopherkindl <53372002+christopherkindl@users.noreply.github.com> Date: Tue, 11 Aug 2026 11:56:31 +0200 Subject: [PATCH 08/29] feat: Synchronize hero gauge animation --- .../(home)/graphics/remote-cache-gauge.tsx | 40 +++++++++---------- .../remote-cache-counter/client.tsx | 7 +++- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/apps/docs/app/[lang]/(home)/graphics/remote-cache-gauge.tsx b/apps/docs/app/[lang]/(home)/graphics/remote-cache-gauge.tsx index 95d5042e2a1f4..4cd0769f06e00 100644 --- a/apps/docs/app/[lang]/(home)/graphics/remote-cache-gauge.tsx +++ b/apps/docs/app/[lang]/(home)/graphics/remote-cache-gauge.tsx @@ -1,6 +1,8 @@ "use client"; -import { useState } from "react"; +import { easeOutCubic } from "phase/ease"; +import { useTween } from "phase/react"; +import { useEffect, useState } from "react"; import { RemoteCacheCounterClient } from "@/components/remote-cache-counter/client"; @@ -15,6 +17,8 @@ const GAUGE_SEGMENTS = [ ] as const; const GAUGE_GAP = 0.35; +const GAUGE_INDICATOR_START = 61.905; +const GAUGE_INDICATOR_REST = 78.571; const roundSvgCoordinate = (value: number) => Math.round(value * 1000) / 1000; @@ -51,10 +55,20 @@ const GAUGE_TICKS = GAUGE_SEGMENTS.flatMap(({ length, start }, segmentIndex) => export function RemoteCacheGauge() { const [isAccelerating, setIsAccelerating] = useState(false); - const indicatorDasharray = isAccelerating ? "100 0" : "78.571 21.429"; - const indicatorRemainderDasharray = isAccelerating - ? "0 100 0 0" - : "0 78.571 21.429 0"; + const [hasStarted, setHasStarted] = useState(false); + const indicatorProgress = useTween({ + duration: 1200, + easing: easeOutCubic, + target: isAccelerating + ? 100 + : hasStarted + ? GAUGE_INDICATOR_REST + : GAUGE_INDICATOR_START, + }); + const indicatorDasharray = `${indicatorProgress} ${100 - indicatorProgress}`; + const indicatorRemainderDasharray = `0 ${indicatorProgress} ${100 - indicatorProgress} 0`; + + useEffect(() => setHasStarted(true), []); return (From 6a73951847286fc3f78db96fd3913df1960325e6 Mon Sep 17 00:00:00 2001 From: christopherkindl <53372002+christopherkindl@users.noreply.github.com> Date: Tue, 11 Aug 2026 15:59:22 +0200 Subject: [PATCH 09/29] feat: Refine homepage visuals and metrics --- .../(home)/graphics/monorepo-visual.tsx | 8 +- .../(home)/graphics/provider-badges.tsx | 18 +- .../(home)/graphics/remote-cache-gauge.tsx | 187 +++++++++++++----- .../app/[lang]/(home)/highlighted-code.tsx | 4 +- .../app/[lang]/(home)/open-source-metrics.tsx | 140 +++++++++++++ apps/docs/app/[lang]/(home)/page.tsx | 24 ++- apps/docs/components/testimonials.tsx | 8 +- 7 files changed, 317 insertions(+), 72 deletions(-) create mode 100644 apps/docs/app/[lang]/(home)/open-source-metrics.tsx diff --git a/apps/docs/app/[lang]/(home)/graphics/monorepo-visual.tsx b/apps/docs/app/[lang]/(home)/graphics/monorepo-visual.tsx index 495912f8b8517..01d7e58167c04 100644 --- a/apps/docs/app/[lang]/(home)/graphics/monorepo-visual.tsx +++ b/apps/docs/app/[lang]/(home)/graphics/monorepo-visual.tsx @@ -1,7 +1,7 @@ import { SiNextdotjs, SiNuxt, SiSvelte } from "@icons-pack/react-simple-icons"; const tasks = [ - { label: "apps/web", Logo: SiNextdotjs, themeAware: true }, + { label: "apps/web", Logo: SiNextdotjs }, { label: "apps/docs", Logo: SiSvelte }, { label: "app/blog", Logo: SiNuxt }, ]; @@ -17,15 +17,15 @@ export function MonorepoVisual() { $ turbo run build
- compute hours saved with Remote Caching -
-