authorgravatar for me@t3.ggTheo Browne <me@t3.gg> 2026-05-13 18:31:06-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-05-13 18:31:06-07:00
log34bb18c8cf2327338bc14a216537328bd58a69fc
tree535299c965d93ba5f27c235b6cd2ab7b0029555f
parent90eea047a967ea2edae543e966627ec0a394ef81
signature Signed by PGP key B5690EEEBB952194

feat(marketing): Made marketing site less cringe (#2681)


38 files changed, 1479 insertions(+), 199 deletions(-)

.gitignore+1
...@@ -23,5 +23,6 @@ __screenshots__/...@@ -23,5 +23,6 @@ __screenshots__/
23.tanstack23.tanstack
24squashfs-root/24squashfs-root/
25.vercel25.vercel
26.gstack/
26dist-electron/27dist-electron/
27.electron-runtime/28.electron-runtime/
apps/marketing/public/apple-touch-icon.webp created
Binary files /dev/null and b/apps/marketing/public/apple-touch-icon.webp differ
apps/marketing/public/favicon-16x16.webp created
Binary files /dev/null and b/apps/marketing/public/favicon-16x16.webp differ
apps/marketing/public/favicon-32x32.webp created
Binary files /dev/null and b/apps/marketing/public/favicon-32x32.webp differ
apps/marketing/public/harnesses/claude-ai-icon.svg created+1
...@@ -0,0 +1 @@
1<svg xmlns="http://www.w3.org/2000/svg" width="256" height="257" preserveAspectRatio="xMidYMid" viewBox="0 0 256 257"><path fill="#D97757" d="m50.228 170.321 50.357-28.257.843-2.463-.843-1.361h-2.462l-8.426-.518-28.775-.778-24.952-1.037-24.175-1.296-6.092-1.297L0 125.796l.583-3.759 5.12-3.434 7.324.648 16.202 1.101 24.304 1.685 17.629 1.037 26.118 2.722h4.148l.583-1.685-1.426-1.037-1.101-1.037-25.147-17.045-27.22-18.017-14.258-10.37-7.713-5.25-3.888-4.925-1.685-10.758 7-7.713 9.397.649 2.398.648 9.527 7.323 20.35 15.75L94.817 91.9l3.889 3.24 1.555-1.102.195-.777-1.75-2.917-14.453-26.118-15.425-26.572-6.87-11.018-1.814-6.61c-.648-2.723-1.102-4.991-1.102-7.778l7.972-10.823L71.42 0 82.05 1.426l4.472 3.888 6.61 15.101 10.694 23.786 16.591 32.34 4.861 9.592 2.592 8.879.973 2.722h1.685v-1.556l1.36-18.211 2.528-22.36 2.463-28.776.843-8.1 4.018-9.722 7.971-5.25 6.222 2.981 5.12 7.324-.713 4.73-3.046 19.768-5.962 30.98-3.889 20.739h2.268l2.593-2.593 10.499-13.934 17.628-22.036 7.778-8.749 9.073-9.657 5.833-4.601h11.018l8.1 12.055-3.628 12.443-11.342 14.388-9.398 12.184-13.48 18.147-8.426 14.518.778 1.166 2.01-.194 30.46-6.481 16.462-2.982 19.637-3.37 8.88 4.148.971 4.213-3.5 8.62-20.998 5.184-24.628 4.926-36.682 8.685-.454.324.519.648 16.526 1.555 7.065.389h17.304l32.21 2.398 8.426 5.574 5.055 6.805-.843 5.184-12.962 6.611-17.498-4.148-40.83-9.721-14-3.5h-1.944v1.167l11.666 11.406 21.387 19.314 26.767 24.887 1.36 6.157-3.434 4.86-3.63-.518-23.526-17.693-9.073-7.972-20.545-17.304h-1.36v1.814l4.73 6.935 25.017 37.59 1.296 11.536-1.814 3.76-6.481 2.268-7.13-1.297-14.647-20.544-15.1-23.138-12.185-20.739-1.49.843-7.194 77.448-3.37 3.953-7.778 2.981-6.48-4.925-3.436-7.972 3.435-15.749 4.148-20.544 3.37-16.333 3.046-20.285 1.815-6.74-.13-.454-1.49.194-15.295 20.999-23.267 31.433-18.406 19.702-4.407 1.75-7.648-3.954.713-7.064 4.277-6.286 25.47-32.405 15.36-20.092 9.917-11.6-.065-1.686h-.583L44.07 198.125l-12.055 1.555-5.185-4.86.648-7.972 2.463-2.593 20.35-13.999-.064.065Z"></path></svg>
\ No newline at end of file
apps/marketing/public/harnesses/cursor_light.svg created+1
...@@ -0,0 +1 @@
1<?xml version="1.0" encoding="UTF-8"?><svg id="cursor_light__Ebene_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 466.73 532.09"><defs></defs><path class="cursor_light__st0" d="M457.43,125.94L244.42,2.96c-6.84-3.95-15.28-3.95-22.12,0L9.3,125.94c-5.75,3.32-9.3,9.46-9.3,16.11v247.99c0,6.65,3.55,12.79,9.3,16.11l213.01,122.98c6.84,3.95,15.28,3.95,22.12,0l213.01-122.98c5.75-3.32,9.3-9.46,9.3-16.11v-247.99c0-6.65-3.55-12.79-9.3-16.11h-.01ZM444.05,151.99l-205.63,356.16c-1.39,2.4-5.06,1.42-5.06-1.36v-233.21c0-4.66-2.49-8.97-6.53-11.31L24.87,145.67c-2.4-1.39-1.42-5.06,1.36-5.06h411.26c5.84,0,9.49,6.33,6.57,11.39h-.01Z"></path></svg>
\ No newline at end of file
apps/marketing/public/harnesses/openai_dark.svg created+1
...@@ -0,0 +1 @@
1<svg xmlns="http://www.w3.org/2000/svg" width="256" height="260" preserveAspectRatio="xMidYMid" viewBox="0 0 256 260"><path fill="#fff" d="M239.184 106.203a64.716 64.716 0 0 0-5.576-53.103C219.452 28.459 191 15.784 163.213 21.74A65.586 65.586 0 0 0 52.096 45.22a64.716 64.716 0 0 0-43.23 31.36c-14.31 24.602-11.061 55.634 8.033 76.74a64.665 64.665 0 0 0 5.525 53.102c14.174 24.65 42.644 37.324 70.446 31.36a64.72 64.72 0 0 0 48.754 21.744c28.481.025 53.714-18.361 62.414-45.481a64.767 64.767 0 0 0 43.229-31.36c14.137-24.558 10.875-55.423-8.083-76.483Zm-97.56 136.338a48.397 48.397 0 0 1-31.105-11.255l1.535-.87 51.67-29.825a8.595 8.595 0 0 0 4.247-7.367v-72.85l21.845 12.636c.218.111.37.32.409.563v60.367c-.056 26.818-21.783 48.545-48.601 48.601Zm-104.466-44.61a48.345 48.345 0 0 1-5.781-32.589l1.534.921 51.722 29.826a8.339 8.339 0 0 0 8.441 0l63.181-36.425v25.221a.87.87 0 0 1-.358.665l-52.335 30.184c-23.257 13.398-52.97 5.431-66.404-17.803ZM23.549 85.38a48.499 48.499 0 0 1 25.58-21.333v61.39a8.288 8.288 0 0 0 4.195 7.316l62.874 36.272-21.845 12.636a.819.819 0 0 1-.767 0L41.353 151.53c-23.211-13.454-31.171-43.144-17.804-66.405v.256Zm179.466 41.695-63.08-36.63L161.73 77.86a.819.819 0 0 1 .768 0l52.233 30.184a48.6 48.6 0 0 1-7.316 87.635v-61.391a8.544 8.544 0 0 0-4.4-7.213Zm21.742-32.69-1.535-.922-51.619-30.081a8.39 8.39 0 0 0-8.492 0L99.98 99.808V74.587a.716.716 0 0 1 .307-.665l52.233-30.133a48.652 48.652 0 0 1 72.236 50.391v.205ZM88.061 139.097l-21.845-12.585a.87.87 0 0 1-.41-.614V65.685a48.652 48.652 0 0 1 79.757-37.346l-1.535.87-51.67 29.825a8.595 8.595 0 0 0-4.246 7.367l-.051 72.697Zm11.868-25.58 28.138-16.217 28.188 16.218v32.434l-28.086 16.218-28.188-16.218-.052-32.434Z"></path></svg>
\ No newline at end of file
apps/marketing/public/harnesses/opencode-dark.svg created+1
...@@ -0,0 +1 @@
1<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512"><svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="512" height="512" fill="#131010"></rect><path d="M320 224V352H192V224H320Z" fill="#5A5858"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M384 416H128V96H384V416ZM320 160H192V352H320V160Z" fill="white"></path></svg></svg>
\ No newline at end of file
apps/marketing/public/icon.webp created
Binary files /dev/null and b/apps/marketing/public/icon.webp differ
apps/marketing/public/pfps/BennettBuhner.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/BennettBuhner.webp differ
apps/marketing/public/pfps/DavidKPiano.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/DavidKPiano.webp differ
apps/marketing/public/pfps/Josikinz.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/Josikinz.webp differ
apps/marketing/public/pfps/Shay_Benshabtay.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/Shay_Benshabtay.webp differ
apps/marketing/public/pfps/_winter_wonders.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/_winter_wonders.webp differ
apps/marketing/public/pfps/aronprins.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/aronprins.webp differ
apps/marketing/public/pfps/developedbyed.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/developedbyed.webp differ
apps/marketing/public/pfps/ex0t1clol.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/ex0t1clol.webp differ
apps/marketing/public/pfps/gnukeith.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/gnukeith.webp differ
apps/marketing/public/pfps/iamkaffe.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/iamkaffe.webp differ
apps/marketing/public/pfps/jetpackjoe_.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/jetpackjoe_.webp differ
apps/marketing/public/pfps/kostyniuk00.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/kostyniuk00.webp differ
apps/marketing/public/pfps/leodev.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/leodev.webp differ
apps/marketing/public/pfps/mil000.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/mil000.webp differ
apps/marketing/public/pfps/peculiarnewbie.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/peculiarnewbie.webp differ
apps/marketing/public/pfps/pocarles.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/pocarles.webp differ
apps/marketing/public/pfps/tannerlinsley.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/tannerlinsley.webp differ
apps/marketing/public/pfps/teja2495.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/teja2495.webp differ
apps/marketing/public/pfps/uwunetes.webp created
Binary files /dev/null and b/apps/marketing/public/pfps/uwunetes.webp differ
apps/marketing/public/screenshot.jpeg deleted
Binary files a/apps/marketing/public/screenshot.jpeg and /dev/null differ
apps/marketing/public/screenshot.webp created
Binary files /dev/null and b/apps/marketing/public/screenshot.webp differ
apps/marketing/public/updated-screenshot.webp created
Binary files /dev/null and b/apps/marketing/public/updated-screenshot.webp differ
apps/marketing/src/components/TuxIcon.astro created+53
...@@ -0,0 +1,53 @@
1---
2interface Props {
3 class?: string;
4 idPrefix: string;
5}
6
7const { class: className, idPrefix } = Astro.props;
8---
9
10<svg
11 class={className}
12 xmlns="http://www.w3.org/2000/svg"
13 viewBox="0 0 256 295"
14 aria-hidden="true"
15>
16 <defs>
17 <linearGradient id={`${idPrefix}0`} x1="48.548%" x2="51.047%" y1="115.276%" y2="41.364%">
18 <stop offset="0%" stop-color="#FFEED7" />
19 <stop offset="100%" stop-color="#BDBFC2" />
20 </linearGradient>
21 <linearGradient id={`${idPrefix}6`} x1="49.984%" x2="49.984%" y1="89.845%" y2="40.632%">
22 <stop offset="0%" stop-color="#FFEED7" />
23 <stop offset="100%" stop-color="#BDBFC2" />
24 </linearGradient>
25 <linearGradient id={`${idPrefix}8`} x1="49.841%" x2="50.241%" y1="13.229%" y2="94.673%">
26 <stop offset="0%" stop-color="#FFF" stop-opacity=".8" />
27 <stop offset="100%" stop-color="#FFF" stop-opacity="0" />
28 </linearGradient>
29 <linearGradient id={`${idPrefix}c`} x1="53.467%" x2="38.949%" y1="48.921%" y2="98.1%">
30 <stop offset="0%" stop-color="#FFA63F" />
31 <stop offset="100%" stop-color="#FF0" />
32 </linearGradient>
33 <linearGradient id={`${idPrefix}e`} x1="30.581%" x2="65.887%" y1="34.024%" y2="89.175%">
34 <stop offset="0%" stop-color="#FFA63F" />
35 <stop offset="100%" stop-color="#FF0" />
36 </linearGradient>
37 <linearGradient id={`${idPrefix}i`} x1="49.733%" x2="50.558%" y1="17.609%" y2="99.385%">
38 <stop offset="0%" stop-color="#FFA63F" />
39 <stop offset="100%" stop-color="#FF0" />
40 </linearGradient>
41 </defs>
42 <g fill="none">
43 <path fill="#000" d="M63.213 215.474c-11.387-16.346-13.591-69.606 12.947-102.39C89.292 97.383 92.69 86.455 93.7 71.67c.734-16.805-11.846-66.851 35.537-70.616 48.027-3.857 45.364 43.526 45.088 68.596-.183 21.12 15.52 33.15 26.355 49.68 19.927 30.303 18.274 82.461-3.765 110.745-27.916 35.354-51.791 20.018-67.678 21.304-29.752 1.745-30.762 17.54-66.024-35.905" />
44 <path fill={`url(#${idPrefix}6)`} d="M81.027 145.684c6.52-14.785 20.386-40.772 20.662-60.883 0-15.978 47.843-19.835 51.7-3.856 3.856 15.978 13.59 39.853 19.834 51.424 6.245 11.478 24.335 48.118 5.051 80.074-17.356 28.284-69.973 50.69-98.073-3.856-9.55-18.917-7.806-42.333.826-62.903" />
45 <path fill={`url(#${idPrefix}8)`} d="M166.428 151.285c0 16.162-15.519 37.1-42.15 36.916-27.456.183-39.118-20.754-39.118-36.916 0-16.161 18.182-29.293 40.588-29.293 22.498.092 40.68 13.132 40.68 29.293" />
46 <path fill="#000" stroke="#000" stroke-width=".977" d="M176.805 117.86c13.59 11.02 38.292 49.587 2.204 74.748-11.846 7.806 10.468 32.508 23.049 19.927 43.618-43.894-1.102-94.308-16.53-111.664-13.774-15.151-25.987 3.49-8.723 16.989z" />
47 <path fill="#000" stroke="#000" stroke-width="1.25" d="M79.925 122.727c-8.907 14.509-30.211 48.669-1.652 66.484 38.384 23.6 27.548 47.108-7.53 25.895-49.404-29.568-5.97-89.257 13.774-112.03 22.59-25.529 4.316 4.683-4.592 19.65z" />
48 <path fill={`url(#${idPrefix}c)`} stroke="#E68C3F" stroke-width="6.25" d="M51.835 258.542c-20.57-10.928-50.414 2.112-39.578-27.457 2.204-6.704-3.214-16.805.275-23.325 4.133-7.989 13.04-6.244 18.366-11.57 5.234-5.51 8.54-15.06 18.366-13.59 9.734 1.468 16.254 13.406 23.049 28.099 5.05 10.468 22.865 25.253 21.672 37.007-1.47 17.998-21.948 21.396-42.15 10.836z" transform="translate(10)" />
49 <path fill={`url(#${idPrefix}e)`} stroke="#E68C3F" stroke-width="6.251" d="M194.445 253.49c15.06-18.273 48.578-14.508 25.988-39.577-4.775-5.418-3.306-16.989-9.183-21.947-6.887-6.061-14.509-1.102-21.488-4.224-6.979-3.398-14.325-9.918-22.865-5.327-8.54 4.684-9.459 16.805-10.285 32.783-.735 11.479-11.203 30.671-5.602 41.231 8.081 16.346 29.11 14.142 43.435-2.938z" transform="translate(10)" />
50 <path fill={`url(#${idPrefix}i)`} stroke="#E68C3F" stroke-width="3.75" d="M97.107 66.344c3.673-3.398 12.58-13.774 29.477-2.939 3.122 2.02 5.693 2.204 11.662 4.775 12.03 4.96 6.336 16.897-6.52 20.937-5.51 1.745-10.468 8.449-20.386 7.806-8.54-.46-10.744-6.06-15.978-9.091-9.275-5.234-10.652-12.305-5.602-16.07 5.051-3.765 6.98-5.143 7.347-5.418z" transform="translate(10)" />
51 <path fill="#000" d="M133.186 57.712c-.092 5.234 2.48 9.458 5.877 9.458 3.306 0 6.153-4.224 6.245-9.366.091-5.234-2.48-9.459-5.878-9.459-3.397 0-6.152 4.225-6.244 9.367m-21.212.092c.459 4.316-1.194 7.989-3.582 8.356-2.387.276-4.683-2.938-5.142-7.254-.46-4.316 1.194-7.99 3.581-8.357 2.388-.275 4.684 2.939 5.143 7.255" />
52 </g>
53</svg>
apps/marketing/src/layouts/Layout.astro+250-68
...@@ -6,7 +6,7 @@ interface Props {...@@ -6,7 +6,7 @@ interface Props {
66
7const {7const {
8 title = "T3 Code",8 title = "T3 Code",
9 description = "T3 Code — The best way to code with AI.",9 description = "T3 Code — The open-source control plane for coding agents.",
10} = Astro.props;10} = Astro.props;
11---11---
1212
...@@ -18,7 +18,7 @@ const {...@@ -18,7 +18,7 @@ const {
18 <link rel="preconnect" href="https://fonts.googleapis.com" />18 <link rel="preconnect" href="https://fonts.googleapis.com" />
19 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />19 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
20 <link20 <link
21 href="https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,400;9..40,500;9..40,600&display=swap"21 href="https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,400;9..40,500;9..40,600&family=JetBrains+Mono:wght@400;500&display=swap"
22 rel="stylesheet"22 rel="stylesheet"
23 />23 />
24 <link rel="icon" href="/favicon.ico" sizes="48x48" />24 <link rel="icon" href="/favicon.ico" sizes="48x48" />
...@@ -30,18 +30,25 @@ const {...@@ -30,18 +30,25 @@ const {
30 <body>30 <body>
31 <div class="page">31 <div class="page">
32 <nav class="nav">32 <nav class="nav">
33 <a href="/" class="nav-brand">33 <div class="nav-inner">
34 <img src="/icon.png" alt="T3" class="nav-icon" />34 <a href="/" class="nav-brand" aria-label="T3 Code home">
35 </a>35 <span class="nav-brand-name">T3 Code</span>
36 <a36 </a>
37 href="https://github.com/pingdotgg/t3code"37 <div class="nav-right">
38 target="_blank"38 <a
39 rel="noopener noreferrer"39 class="nav-gh"
40 class="nav-github"40 href="https://github.com/pingdotgg/t3code"
41 >41 target="_blank"
42 GitHub42 rel="noopener noreferrer"
43 <span class="nav-github-arrow" aria-hidden="true">&#8599;</span>43 >
44 </a>44 <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
45 <path d="M12 .5C5.65.5.5 5.65.5 12a11.5 11.5 0 007.86 10.93c.58.1.79-.25.79-.56v-2c-3.2.69-3.88-1.37-3.88-1.37-.52-1.33-1.27-1.69-1.27-1.69-1.04-.71.08-.7.08-.7 1.15.08 1.76 1.18 1.76 1.18 1.02 1.76 2.68 1.25 3.33.96.1-.75.4-1.25.72-1.54-2.55-.29-5.24-1.27-5.24-5.67 0-1.25.45-2.28 1.18-3.08-.12-.29-.51-1.45.11-3.02 0 0 .96-.31 3.15 1.18a10.96 10.96 0 015.74 0c2.19-1.49 3.15-1.18 3.15-1.18.62 1.57.23 2.73.11 3.02.74.8 1.18 1.83 1.18 3.08 0 4.41-2.7 5.38-5.27 5.66.41.36.78 1.06.78 2.13v3.16c0 .31.21.67.8.56A11.5 11.5 0 0023.5 12C23.5 5.65 18.35.5 12 .5z"/>
46 </svg>
47 <span>GitHub</span>
48 </a>
49 <a class="btn btn-primary" href="/#download">Download</a>
50 </div>
51 </div>
45 </nav>52 </nav>
4653
47 <main class="main">54 <main class="main">
...@@ -49,23 +56,54 @@ const {...@@ -49,23 +56,54 @@ const {
49 </main>56 </main>
5057
51 <footer class="footer">58 <footer class="footer">
52 <span class="footer-copy">&copy; {new Date().getFullYear()} T3 Tools Inc</span>59 <div class="footer-inner">
53 <div class="footer-links">60 <div class="footer-brand">
54 <a href="https://github.com/pingdotgg/t3code" target="_blank" rel="noopener noreferrer">GitHub</a>61 <img src="/icon.webp" alt="" />
55 <a href="https://discord.gg/jn4EGJjrvv" target="_blank" rel="noopener noreferrer">Discord</a>62 <span>&copy; {new Date().getFullYear()} T3 Tools Inc · MIT licensed</span>
63 </div>
64 <div class="footer-links">
65 <a href="https://github.com/pingdotgg/t3code" target="_blank" rel="noopener noreferrer">GitHub</a>
66 <a href="https://discord.gg/jn4EGJjrvv" target="_blank" rel="noopener noreferrer">Discord</a>
67 <a href="/download">Download</a>
68 </div>
56 </div>69 </div>
57 </footer>70 </footer>
58 </div>71 </div>
72
73 <script>
74 const nav = document.querySelector(".nav");
75 const onScroll = () => {
76 if (!nav) return;
77 if (window.scrollY > 12) nav.classList.add("is-scrolled");
78 else nav.classList.remove("is-scrolled");
79 };
80 window.addEventListener("scroll", onScroll, { passive: true });
81 onScroll();
82 </script>
59 </body>83 </body>
60</html>84</html>
6185
62<style is:global>86<style is:global>
63 :root {87 :root {
64 --bg: #09090b;88 --bg: #09090b;
89 --bg-elev: #0c0c0e;
90 --bg-card: #111113;
65 --fg: #fafafa;91 --fg: #fafafa;
66 --fg-muted: #a1a1aa;92 --fg-muted: #a1a1aa;
67 --fg-dim: #71717a;93 --fg-dim: #71717a;
94 --fg-faint: #52525b;
68 --border: rgba(255, 255, 255, 0.08);95 --border: rgba(255, 255, 255, 0.08);
96 --border-strong: rgba(255, 255, 255, 0.14);
97 --accent-h: 250;
98 --accent: oklch(0.68 0.17 var(--accent-h));
99 --accent-dim: oklch(0.68 0.17 var(--accent-h) / 0.15);
100 --ok: oklch(0.72 0.16 150);
101 --warn: oklch(0.76 0.15 75);
102 --font-sans: "DM Sans", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
103 --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
104 --radius: 12px;
105 --radius-sm: 8px;
106 --radius-lg: 16px;
69 }107 }
70108
71 * {109 * {
...@@ -76,16 +114,19 @@ const {...@@ -76,16 +114,19 @@ const {
76114
77 html {115 html {
78 color-scheme: dark;116 color-scheme: dark;
117 scroll-behavior: smooth;
79 }118 }
80119
81 body {120 body {
82 background: var(--bg);121 background: var(--bg);
83 color: var(--fg);122 color: var(--fg);
84 font-family: "DM Sans", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;123 font-family: var(--font-sans);
124 font-feature-settings: "ss01", "ss02";
85 -webkit-font-smoothing: antialiased;125 -webkit-font-smoothing: antialiased;
86 -moz-osx-font-smoothing: grayscale;126 -moz-osx-font-smoothing: grayscale;
87 min-height: 100vh;127 min-height: 100vh;
88 overflow-x: hidden;128 overflow-x: hidden;
129 line-height: 1.5;
89 }130 }
90131
91 body::after {132 body::after {
...@@ -105,11 +146,103 @@ const {...@@ -105,11 +146,103 @@ const {
105 text-decoration: none;146 text-decoration: none;
106 }147 }
107148
108 img {149 button {
150 font-family: inherit;
151 cursor: pointer;
152 border: 0;
153 background: none;
154 color: inherit;
155 }
156
157 img,
158 svg {
109 display: block;159 display: block;
110 max-width: 100%;160 max-width: 100%;
111 }161 }
112162
163 .eyebrow {
164 font-family: var(--font-mono);
165 font-size: 11px;
166 letter-spacing: 0.14em;
167 text-transform: uppercase;
168 color: var(--fg-dim);
169 font-weight: 500;
170 }
171
172 .display {
173 font-weight: 500;
174 letter-spacing: -0.035em;
175 line-height: 1.05;
176 }
177
178 .container {
179 width: 100%;
180 max-width: 1240px;
181 margin: 0 auto;
182 padding: 0 32px;
183 }
184
185 .btn {
186 display: inline-flex;
187 align-items: center;
188 justify-content: center;
189 gap: 8px;
190 font-weight: 500;
191 font-size: 14px;
192 padding: 10px 18px;
193 border-radius: 8px;
194 transition: transform 0.18s ease, background 0.18s ease,
195 border-color 0.18s ease, color 0.18s ease;
196 white-space: nowrap;
197 }
198
199 .btn-primary {
200 background: var(--fg);
201 color: #09090b;
202 font-weight: 600;
203 }
204
205 .btn-primary:hover {
206 transform: translateY(-1px);
207 background: #fff;
208 }
209
210 .btn-primary:active {
211 transform: translateY(0);
212 }
213
214 .btn-ghost {
215 color: var(--fg-muted);
216 border: 1px solid var(--border);
217 background: transparent;
218 }
219
220 .btn-ghost:hover {
221 color: var(--fg);
222 border-color: var(--border-strong);
223 background: rgba(255, 255, 255, 0.02);
224 }
225
226 .btn-lg {
227 padding: 14px 22px;
228 font-size: 15px;
229 border-radius: 10px;
230 }
231
232 .tile {
233 position: relative;
234 border: 1px solid var(--border);
235 border-radius: var(--radius);
236 background: linear-gradient(180deg, rgba(255, 255, 255, 0.015), rgba(255, 255, 255, 0));
237 overflow: hidden;
238 }
239
240 :focus-visible {
241 outline: 2px solid var(--accent);
242 outline-offset: 2px;
243 border-radius: 4px;
244 }
245
113 @keyframes fade-in {246 @keyframes fade-in {
114 from {247 from {
115 opacity: 0;248 opacity: 0;
...@@ -120,11 +253,26 @@ const {...@@ -120,11 +253,26 @@ const {
120 transform: translateY(0);253 transform: translateY(0);
121 }254 }
122 }255 }
256
257 @keyframes pulse {
258 50% { opacity: 0.4; }
259 }
260
261 @keyframes spin {
262 to { transform: rotate(360deg); }
263 }
264
265 @keyframes floatDrift {
266 0%, 100% { translate: 0 0; }
267 50% { translate: 0 -10px; }
268 }
269
270 @keyframes blink {
271 50% { opacity: 0; }
272 }
123</style>273</style>
124274
125<style>275<style>
126 /* ── Page ── */
127
128 .page {276 .page {
129 min-height: 100vh;277 min-height: 100vh;
130 display: flex;278 display: flex;
...@@ -132,97 +280,131 @@ const {...@@ -132,97 +280,131 @@ const {
132 overflow-x: hidden;280 overflow-x: hidden;
133 }281 }
134282
135 /* ── Navbar ── */
136
137 .nav {283 .nav {
138 display: flex;284 position: sticky;
139 align-items: center;285 top: 0;
140 justify-content: space-between;286 z-index: 50;
141 padding: 1.5rem 2.5rem;287 backdrop-filter: blur(18px);
142 opacity: 0.5;288 -webkit-backdrop-filter: blur(18px);
143 transition: opacity 0.4s ease;289 background: color-mix(in srgb, var(--bg) 75%, transparent);
290 border-bottom: 1px solid transparent;
291 transition: border-color 0.3s ease;
144 }292 }
145293
146 .nav:hover {294 .nav.is-scrolled {
147 opacity: 1;295 border-bottom-color: var(--border);
148 }296 }
149297
150 .nav-brand {298 .nav-inner {
299 max-width: 1240px;
300 margin: 0 auto;
301 padding: 12px 32px;
151 display: flex;302 display: flex;
152 align-items: center;303 align-items: center;
304 justify-content: space-between;
305 gap: 24px;
153 }306 }
154307
155 .nav-icon {308 .nav-brand {
156 width: 28px;309 display: inline-flex;
157 height: 28px;310 align-items: center;
158 border-radius: 6px;311 color: var(--fg);
312 transition: color 0.2s ease;
159 }313 }
160314
161 .nav-github {315 .nav-brand:hover {
162 display: flex;316 color: #fff;
163 align-items: center;
164 gap: 0.35rem;
165 color: var(--fg-muted);
166 font-size: 0.875rem;
167 transition: color 0.3s ease;
168 }317 }
169318
170 .nav-github:hover {319 .nav-brand-name {
171 color: var(--fg);320 font-size: 16px;
321 font-weight: 650;
322 letter-spacing: -0.025em;
323 line-height: 1;
172 }324 }
173325
174 .nav-github-arrow {326 .nav-right {
175 display: inline-block;327 display: inline-flex;
176 transition: transform 0.3s ease;328 align-items: center;
329 gap: 8px;
177 }330 }
178331
179 .nav-github:hover .nav-github-arrow {332 .nav-gh {
180 transform: translateX(2px) translateY(-1px);333 display: inline-flex;
334 align-items: center;
335 gap: 6px;
336 padding: 7px 12px;
337 border: 1px solid var(--border);
338 border-radius: 8px;
339 color: var(--fg-muted);
340 font-family: var(--font-mono);
341 font-size: 12px;
342 transition: color 0.2s ease, background 0.2s ease, border-color 0.2s ease;
181 }343 }
182344
183 /* ── Main content ── */345 .nav-gh:hover {
346 color: var(--fg);
347 background: rgba(255, 255, 255, 0.04);
348 border-color: var(--border-strong);
349 }
184350
185 .main {351 .main {
186 flex: 1;352 flex: 1;
187 display: flex;353 display: flex;
188 flex-direction: column;354 flex-direction: column;
189 align-items: center;
190 }355 }
191356
192 /* ── Footer ── */
193
194 .footer {357 .footer {
358 margin-top: auto;
359 border-top: 1px solid var(--border);
360 padding: 40px 0 32px;
361 }
362
363 .footer-inner {
364 max-width: 1240px;
365 margin: 0 auto;
366 padding: 0 32px;
195 display: flex;367 display: flex;
368 flex-wrap: wrap;
369 gap: 24px;
196 align-items: center;370 align-items: center;
197 justify-content: space-between;371 justify-content: space-between;
198 padding: 1.5rem 2.5rem;372 }
199 font-size: 0.8rem;373
374 .footer-brand {
375 display: flex;
376 align-items: center;
377 gap: 10px;
378 font-size: 13px;
200 color: var(--fg-dim);379 color: var(--fg-dim);
201 }380 }
202381
382 .footer-brand img {
383 width: 20px;
384 height: 20px;
385 border-radius: 4px;
386 }
387
203 .footer-links {388 .footer-links {
204 display: flex;389 display: flex;
205 gap: 1.25rem;390 gap: 20px;
206 }391 }
207392
208 .footer-links a {393 .footer-links a {
394 font-size: 13px;
209 color: var(--fg-dim);395 color: var(--fg-dim);
210 transition: color 0.3s ease;396 transition: color 0.2s ease;
211 }397 }
212398
213 .footer-links a:hover {399 .footer-links a:hover {
214 color: var(--fg);400 color: var(--fg);
215 }401 }
216402
217 /* ── Mobile ── */403 @media (max-width: 820px) {
218404 .nav-inner,
219 @media (max-width: 640px) {405 .footer-inner {
220 .nav {406 padding-left: 20px;
221 padding: 1.25rem;407 padding-right: 20px;
222 }
223
224 .footer {
225 padding: 1.25rem;
226 }408 }
227 }409 }
228</style>410</style>
apps/marketing/src/lib/tweets.ts created+123
...@@ -0,0 +1,123 @@
1export type Tweet = {
2 handle: string;
3 content: string;
4 excerpt?: string;
5 link: string;
6};
7
8export const tweets = [
9 {
10 handle: "Shay_Benshabtay",
11 content:
12 "T3 code is not perfect, but it's damn good. Open and fun , I can make my own fork for my uses and use the great tooling with my own needs.",
13 link: "https://x.com/Shay_Benshabtay/status/2054668503857156326",
14 },
15 {
16 handle: "teja2495",
17 content:
18 "I’ve completely switched to T3 Code for all my workflows. I just switch between different subscriptions and harnesses depending on what I need.",
19 excerpt: "I’ve completely switched to T3 Code for all my workflows.",
20 link: "https://x.com/teja2495/status/2052420254991581623",
21 },
22 {
23 handle: "developedbyed",
24 content: "might say alpha but T3 code is pretty awesome, really fast too",
25 link: "https://x.com/developedbyed/status/2030627970532921605",
26 },
27 {
28 handle: "tannerlinsley",
29 content:
30 "The minute T3 Code supports Claude Code, it could potentially become my daily driver. There's something special there.",
31 link: "https://x.com/tannerlinsley/status/2031102771529920966",
32 },
33 {
34 handle: "aronprins",
35 content:
36 "I already loved T3 Code by @theo and @jullerino, but their Connections implementation is next level epic and for this they should both earn maximum repect 🔥🫡",
37 excerpt: "I already loved T3 Code, but their Connections implementation is next level epic.",
38 link: "https://x.com/aronprins/status/2045102518196183109",
39 },
40 {
41 handle: "BennettBuhner",
42 content:
43 "T3 Code is literally Codex but better; all your favorite models and harnesses, accessible anywhere! The app is great but the website is even greater, so instead of needing to SSH into a machine, T3 IS my SSH!",
44 excerpt:
45 "T3 Code is literally Codex but better; all your favorite models and harnesses, accessible anywhere.",
46 link: "https://x.com/BennettBuhner/status/2054667115697754387",
47 },
48 {
49 handle: "ex0t1clol",
50 content: "T3 Code is proof electron apps don't have to suck",
51 link: "https://x.com/ex0t1clol/status/2054666870008021197",
52 },
53 {
54 handle: "Josikinz",
55 content:
56 "T3 code is better because it’s like if the codex Mac app didn’t make my computer run like shit 😋",
57 link: "https://x.com/Josikinz/status/2030367951694745870",
58 },
59 {
60 handle: "jetpackjoe_",
61 content: "T3 code is pretty alright I guess",
62 link: "https://x.com/jetpackjoe_/status/2054666792933404959",
63 },
64 {
65 handle: "mil000",
66 content: "T3 code saved my relationship!",
67 link: "https://x.com/mil000/status/2030120041451246071",
68 },
69 {
70 handle: "_winter_wonders",
71 content: "Heartbreaking: AI-hater has to admit T3 Code is really good.",
72 link: "https://x.com/_winter_wonders/status/2052350198764970434",
73 },
74 {
75 handle: "kostyniuk00",
76 content:
77 "I was not expecting a year ago, that my anti-AI colleagues would thank me a year later, for persuading them to try T3 Code Beta, that really helped them with organizing their workflows. \n\nFantastic product by @jullerino and @theo. Go try it out if you haven’t yet!",
78 excerpt:
79 "My anti-AI colleagues thanked me for persuading them to try T3 Code Beta. Fantastic product.",
80 link: "https://x.com/kostyniuk00/status/2052041388179468521",
81 },
82 {
83 handle: "gnukeith",
84 content:
85 "I tried T3 Code it actually fixed issues that Opus couldn’t solve in Claude Code + Theo has replied with “UwU” under my post. Dario has not.",
86 link: "https://x.com/gnukeith/status/2054670073579630730",
87 },
88 {
89 handle: "peculiarnewbie",
90 content: "T3 Code is iOS and other harnesses are androids",
91 link: "https://x.com/peculiarnewbie/status/2054671685027233827",
92 },
93 {
94 handle: "leodev",
95 content:
96 "T3 Code is probably the first coding gui that didn't suck performance wise and had a smart team behind it.",
97 link: "https://x.com/leodev/status/2054679746353537042",
98 },
99 {
100 handle: "pocarles",
101 content:
102 "Only using Codex and T3 now.\n\nI thought all AI coding harnesses had roughly the same impact. Using T3 Code taught me how wrong I was. The interface between you and the model changes everything.",
103 excerpt:
104 "Using T3 Code taught me how wrong I was. The interface between you and the model changes everything.",
105 link: "https://x.com/pocarles/status/2054673964274758046",
106 },
107 {
108 handle: "DavidKPiano",
109 content: "It's like Claude Code if they didn't vibe-code the entire thing",
110 link: "https://x.com/DavidKPiano/status/2054682983504719930",
111 },
112 {
113 handle: "iamkaffe",
114 content: "T3Code was the first one to truly care about Linux users.",
115 link: "https://x.com/iamkaffe/status/2054675539311411280",
116 },
117 {
118 handle: "uwunetes",
119 content:
120 "claude code make me go *whine whine whine* and t3 code make me go woof woof awooooo!!!",
121 link: "https://x.com/uwunetes/status/2054683356022120640",
122 },
123] satisfies Tweet[];
apps/marketing/src/pages/download.astro+8-2
...@@ -4,6 +4,7 @@ import { RELEASES_URL } from "../lib/releases";...@@ -4,6 +4,7 @@ import { RELEASES_URL } from "../lib/releases";
4---4---
55
6<Layout title="Download — T3 Code" description="Download T3 Code for macOS, Windows, or Linux.">6<Layout title="Download — T3 Code" description="Download T3 Code for macOS, Windows, or Linux.">
7 <div class="download-page">
7 <h1 class="heading">Download T3 Code</h1>8 <h1 class="heading">Download T3 Code</h1>
8 <p class="subheading">9 <p class="subheading">
9 <span id="version-label">Loading latest release&hellip;</span>10 <span id="version-label">Loading latest release&hellip;</span>
...@@ -64,6 +65,7 @@ import { RELEASES_URL } from "../lib/releases";...@@ -64,6 +65,7 @@ import { RELEASES_URL } from "../lib/releases";
64 GitHub releases page<span aria-hidden="true"> &#8599;</span>65 GitHub releases page<span aria-hidden="true"> &#8599;</span>
65 </a>66 </a>
66 </p>67 </p>
68 </div>
67</Layout>69</Layout>
6870
69<script>71<script>
...@@ -111,7 +113,11 @@ import { RELEASES_URL } from "../lib/releases";...@@ -111,7 +113,11 @@ import { RELEASES_URL } from "../lib/releases";
111</script>113</script>
112114
113<style>115<style>
114 .main {116 .download-page {
117 flex: 1;
118 display: flex;
119 flex-direction: column;
120 align-items: center;
115 padding: 8vh 1.5rem 4rem;121 padding: 8vh 1.5rem 4rem;
116 }122 }
117123
...@@ -257,7 +263,7 @@ import { RELEASES_URL } from "../lib/releases";...@@ -257,7 +263,7 @@ import { RELEASES_URL } from "../lib/releases";
257 /* ── Mobile ── */263 /* ── Mobile ── */
258264
259 @media (max-width: 640px) {265 @media (max-width: 640px) {
260 .main {266 .download-page {
261 padding: 5vh 1.25rem 4rem;267 padding: 5vh 1.25rem 4rem;
262 }268 }
263269
apps/marketing/src/pages/index.astro+1020-129
...@@ -1,26 +1,372 @@...@@ -1,26 +1,372 @@
1---1---
2import Layout from "../layouts/Layout.astro";2import Layout from "../layouts/Layout.astro";
3import TuxIcon from "../components/TuxIcon.astro";
4import { tweets } from "../lib/tweets";
5
6const desktopEndorsementRows = [
7 tweets.filter((_, index) => index % 2 === 0),
8 tweets.filter((_, index) => index % 2 === 1),
9];
10
11const mobileEndorsementRows = [
12 tweets.filter((_, index) => index % 3 === 0),
13 tweets.filter((_, index) => index % 3 === 1),
14 tweets.filter((_, index) => index % 3 === 2),
15];
3---16---
417
5<Layout>18<Layout>
6 <h1 class="tagline">T3 Code is the best way to code with AI.</h1>19 <!-- ── Hero ──────────────────────────────────────────────────── -->
720 <section class="hero">
8 <a21 <div class="hero-grid" aria-hidden="true"></div>
9 id="download-btn"22
10 href="https://github.com/pingdotgg/t3code/releases"23 <div class="hero-float" aria-hidden="true">
11 class="hero-button"24 <span class="hero-float-mark hf-claude" title="Claude Code">
12 >25 <img src="/harnesses/claude-ai-icon.svg" alt="" />
13 <svg class="hero-button-icon hero-button-icon--apple" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 814 1000" aria-hidden="true"><path fill="currentColor" d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-164-39.5c-76.5 0-103.7 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z"/></svg>26 </span>
14 <svg class="hero-button-icon hero-button-icon--windows" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 88 88" aria-hidden="true"><path fill="currentColor" d="m0 12.402 35.687-4.86.016 34.423-35.67.203zm35.67 33.529.028 34.453L.028 75.48.026 45.7zm4.326-39.025L87.314 0v41.527l-47.318.376zm47.329 39.349-.011 41.34-47.318-6.678-.066-34.739z"/></svg>27 <span class="hero-float-mark hf-codex" title="Codex">
15 <svg class="hero-button-icon hero-button-icon--linux" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 295" aria-hidden="true"><defs><linearGradient id="lt0" x1="48.548%" x2="51.047%" y1="115.276%" y2="41.364%"><stop offset="0%" stop-color="#FFEED7"/><stop offset="100%" stop-color="#BDBFC2"/></linearGradient><linearGradient id="lt6" x1="49.984%" x2="49.984%" y1="89.845%" y2="40.632%"><stop offset="0%" stop-color="#FFEED7"/><stop offset="100%" stop-color="#BDBFC2"/></linearGradient><linearGradient id="lt8" x1="49.841%" x2="50.241%" y1="13.229%" y2="94.673%"><stop offset="0%" stop-color="#FFF" stop-opacity=".8"/><stop offset="100%" stop-color="#FFF" stop-opacity="0"/></linearGradient><linearGradient id="ltc" x1="53.467%" x2="38.949%" y1="48.921%" y2="98.1%"><stop offset="0%" stop-color="#FFA63F"/><stop offset="100%" stop-color="#FF0"/></linearGradient><linearGradient id="lte" x1="30.581%" x2="65.887%" y1="34.024%" y2="89.175%"><stop offset="0%" stop-color="#FFA63F"/><stop offset="100%" stop-color="#FF0"/></linearGradient><linearGradient id="lti" x1="49.733%" x2="50.558%" y1="17.609%" y2="99.385%"><stop offset="0%" stop-color="#FFA63F"/><stop offset="100%" stop-color="#FF0"/></linearGradient></defs><g fill="none"><path fill="#000" d="M63.213 215.474c-11.387-16.346-13.591-69.606 12.947-102.39C89.292 97.383 92.69 86.455 93.7 71.67c.734-16.805-11.846-66.851 35.537-70.616 48.027-3.857 45.364 43.526 45.088 68.596-.183 21.12 15.52 33.15 26.355 49.68 19.927 30.303 18.274 82.461-3.765 110.745-27.916 35.354-51.791 20.018-67.678 21.304-29.752 1.745-30.762 17.54-66.024-35.905"/><path fill="url(#lt6)" d="M81.027 145.684c6.52-14.785 20.386-40.772 20.662-60.883 0-15.978 47.843-19.835 51.7-3.856 3.856 15.978 13.59 39.853 19.834 51.424 6.245 11.478 24.335 48.118 5.051 80.074-17.356 28.284-69.973 50.69-98.073-3.856-9.55-18.917-7.806-42.333.826-62.903"/><path fill="url(#lt8)" d="M166.428 151.285c0 16.162-15.519 37.1-42.15 36.916-27.456.183-39.118-20.754-39.118-36.916 0-16.161 18.182-29.293 40.588-29.293 22.498.092 40.68 13.132 40.68 29.293"/><path fill="#000" stroke="#000" stroke-width=".977" d="M176.805 117.86c13.59 11.02 38.292 49.587 2.204 74.748-11.846 7.806 10.468 32.508 23.049 19.927 43.618-43.894-1.102-94.308-16.53-111.664-13.774-15.151-25.987 3.49-8.723 16.989z"/><path fill="#000" stroke="#000" stroke-width="1.25" d="M79.925 122.727c-8.907 14.509-30.211 48.669-1.652 66.484 38.384 23.6 27.548 47.108-7.53 25.895-49.404-29.568-5.97-89.257 13.774-112.03 22.59-25.529 4.316 4.683-4.592 19.65z"/><path fill="url(#ltc)" stroke="#E68C3F" stroke-width="6.25" d="M51.835 258.542c-20.57-10.928-50.414 2.112-39.578-27.457 2.204-6.704-3.214-16.805.275-23.325 4.133-7.989 13.04-6.244 18.366-11.57 5.234-5.51 8.54-15.06 18.366-13.59 9.734 1.468 16.254 13.406 23.049 28.099 5.05 10.468 22.865 25.253 21.672 37.007-1.47 17.998-21.948 21.396-42.15 10.836z" transform="translate(10)"/><path fill="url(#lte)" stroke="#E68C3F" stroke-width="6.251" d="M194.445 253.49c15.06-18.273 48.578-14.508 25.988-39.577-4.775-5.418-3.306-16.989-9.183-21.947-6.887-6.061-14.509-1.102-21.488-4.224-6.979-3.398-14.325-9.918-22.865-5.327-8.54 4.684-9.459 16.805-10.285 32.783-.735 11.479-11.203 30.671-5.602 41.231 8.081 16.346 29.11 14.142 43.435-2.938z" transform="translate(10)"/><path fill="url(#lti)" stroke="#E68C3F" stroke-width="3.75" d="M97.107 66.344c3.673-3.398 12.58-13.774 29.477-2.939 3.122 2.02 5.693 2.204 11.662 4.775 12.03 4.96 6.336 16.897-6.52 20.937-5.51 1.745-10.468 8.449-20.386 7.806-8.54-.46-10.744-6.06-15.978-9.091-9.275-5.234-10.652-12.305-5.602-16.07 5.051-3.765 6.98-5.143 7.347-5.418z" transform="translate(10)"/><path fill="#000" d="M133.186 57.712c-.092 5.234 2.48 9.458 5.877 9.458 3.306 0 6.153-4.224 6.245-9.366.091-5.234-2.48-9.459-5.878-9.459-3.397 0-6.152 4.225-6.244 9.367m-21.212.092c.459 4.316-1.194 7.989-3.582 8.356-2.387.276-4.683-2.938-5.142-7.254-.46-4.316 1.194-7.99 3.581-8.357 2.388-.275 4.684 2.939 5.143 7.255"/></g></svg>28 <img src="/harnesses/openai_dark.svg" alt="" />
16 <span id="download-label">Download now</span>29 </span>
17 </a>30 <span class="hero-float-mark hf-opencode" title="OpenCode">
1831 <img src="/harnesses/opencode-dark.svg" alt="" />
19 <a href="/download" class="other-platforms">Other platforms</a>32 </span>
2033 <span class="hero-float-mark hf-cursor" title="Cursor">
21 <div class="screenshot-wrap">34 <img src="/harnesses/cursor_light.svg" alt="" />
22 <img src="/screenshot.jpeg" alt="T3 Code" class="screenshot" />35 </span>
23 </div>36 </div>
37
38 <div class="container hero-inner">
39 <h1 class="hero-title display">
40 The open-source<br />control plane<br />for coding agents.
41 </h1>
42
43 <p class="hero-sub">
44 Orchestrate Claude Code, Codex, OpenCode and Cursor from one surface.
45 Bring your own subscription. Fork the whole thing.
46 </p>
47
48 <div class="hero-actions">
49 <a
50 id="download-btn"
51 href="https://github.com/pingdotgg/t3code/releases"
52 class="btn btn-primary btn-lg"
53 >
54 <svg class="dl-icon dl-icon--apple" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 814 1000" aria-hidden="true"><path fill="currentColor" d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-164-39.5c-76.5 0-103.7 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z"/></svg>
55 <svg class="dl-icon dl-icon--windows" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 88 88" aria-hidden="true"><path fill="currentColor" d="m0 12.402 35.687-4.86.016 34.423-35.67.203zm35.67 33.529.028 34.453L.028 75.48.026 45.7zm4.326-39.025L87.314 0v41.527l-47.318.376zm47.329 39.349-.011 41.34-47.318-6.678-.066-34.739z"/></svg>
56 <TuxIcon class="dl-icon dl-icon--linux" idPrefix="hero-linux-" />
57 <span id="download-label">Download for macOS</span>
58 </a>
59 <a href="https://github.com/pingdotgg/t3code" target="_blank" rel="noopener noreferrer" class="btn btn-ghost btn-lg">
60 <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
61 <path d="M12 .5C5.65.5.5 5.65.5 12a11.5 11.5 0 007.86 10.93c.58.1.79-.25.79-.56v-2c-3.2.69-3.88-1.37-3.88-1.37-.52-1.33-1.27-1.69-1.27-1.69-1.04-.71.08-.7.08-.7 1.15.08 1.76 1.18 1.76 1.18 1.02 1.76 2.68 1.25 3.33.96.1-.75.4-1.25.72-1.54-2.55-.29-5.24-1.27-5.24-5.67 0-1.25.45-2.28 1.18-3.08-.12-.29-.51-1.45.11-3.02 0 0 .96-.31 3.15 1.18a10.96 10.96 0 015.74 0c2.19-1.49 3.15-1.18 3.15-1.18.62 1.57.23 2.73.11 3.02.74.8 1.18 1.83 1.18 3.08 0 4.41-2.7 5.38-5.27 5.66.41.36.78 1.06.78 2.13v3.16c0 .31.21.67.8.56A11.5 11.5 0 0023.5 12C23.5 5.65 18.35.5 12 .5z"/>
62 </svg>
63 Star on GitHub
64 </a>
65 </div>
66
67 <div class="hero-preview">
68 <figure class="hero-screenshot-frame">
69 <img
70 src="/updated-screenshot.webp"
71 alt="T3 Code app showing multiple coding agent threads in one workspace"
72 width="2508"
73 height="1682"
74 loading="eager"
75 decoding="async"
76 />
77 </figure>
78 </div>
79 </div>
80 </section>
81
82 <!-- ── Endorsements ─────────────────────────────────────────── -->
83 <section id="endorsements" class="sec-endorsements" aria-labelledby="endorsements-title">
84 <div class="container">
85 <div class="endorsements-head">
86 <h2 id="endorsements-title">Developers love T3 Code</h2>
87 <p>Real reactions from people building with T3 Code today.</p>
88 </div>
89 </div>
90
91 <div class="endorsement-carousel endorsement-carousel--desktop" aria-label="Developer endorsements">
92 {
93 desktopEndorsementRows.map((row, rowIndex) => (
94 <div class:list={["endorsement-row", rowIndex === 1 && "is-reverse"]}>
95 <div class="endorsement-track">
96 {[0, 1].map((groupIndex) => (
97 <div class="endorsement-track-group" aria-hidden={groupIndex === 1 ? "true" : undefined}>
98 {row.map((tweet) => (
99 <a
100 class="endorsement-card"
101 href={tweet.link}
102 target="_blank"
103 rel="noopener noreferrer"
104 aria-label={`Read ${tweet.handle}'s post on X`}
105 tabindex={groupIndex === 1 ? "-1" : undefined}
106 >
107 <div class="endorsement-author">
108 <img
109 src={`/pfps/${tweet.handle}.webp`}
110 alt=""
111 width="28"
112 height="28"
113 loading="lazy"
114 decoding="async"
115 />
116 <div class="endorsement-handle">@{tweet.handle}</div>
117 </div>
118 <p>{tweet.excerpt ?? tweet.content}</p>
119 </a>
120 ))}
121 </div>
122 ))}
123 </div>
124 </div>
125 ))
126 }
127 </div>
128
129 <div class="endorsement-carousel endorsement-carousel--mobile" aria-label="Developer endorsements">
130 {
131 mobileEndorsementRows.map((row, rowIndex) => (
132 <div class:list={["endorsement-row", rowIndex === 1 && "is-reverse"]}>
133 <div class="endorsement-track">
134 {[0, 1].map((groupIndex) => (
135 <div class="endorsement-track-group" aria-hidden={groupIndex === 1 ? "true" : undefined}>
136 {row.map((tweet) => (
137 <a
138 class="endorsement-card"
139 href={tweet.link}
140 target="_blank"
141 rel="noopener noreferrer"
142 aria-label={`Read ${tweet.handle}'s post on X`}
143 tabindex={groupIndex === 1 ? "-1" : undefined}
144 >
145 <div class="endorsement-author">
146 <img
147 src={`/pfps/${tweet.handle}.webp`}
148 alt=""
149 width="28"
150 height="28"
151 loading="lazy"
152 decoding="async"
153 />
154 <div class="endorsement-handle">@{tweet.handle}</div>
155 </div>
156 <p>{tweet.excerpt ?? tweet.content}</p>
157 </a>
158 ))}
159 </div>
160 ))}
161 </div>
162 </div>
163 ))
164 }
165 </div>
166 </section>
167
168 <!-- ── Harnesses ─────────────────────────────────────────────── -->
169 <section id="harnesses" class="sec-harness">
170 <div class="container">
171 <div class="section-head">
172 <h2>Bring your own sub</h2>
173 <p>
174 T3 Code doesn't resell tokens. Plug in Claude Code, Codex, OpenCode,
175 or Cursor with the credentials you already have — we orchestrate
176 them, you keep your plan.
177 </p>
178 </div>
179
180 <div class="harness-grid">
181 <div class="harness">
182 <div class="harness-mark"><img src="/harnesses/claude-ai-icon.svg" alt="" /></div>
183 <div class="harness-meta">
184 <div class="harness-name">Claude Code</div>
185 <div class="harness-tag">claude auth login</div>
186 </div>
187 </div>
188 <div class="harness">
189 <div class="harness-mark"><img src="/harnesses/openai_dark.svg" alt="" /></div>
190 <div class="harness-meta">
191 <div class="harness-name">Codex CLI</div>
192 <div class="harness-tag">codex login</div>
193 </div>
194 </div>
195 <div class="harness">
196 <div class="harness-mark"><img src="/harnesses/opencode-dark.svg" alt="" /></div>
197 <div class="harness-meta">
198 <div class="harness-name">OpenCode</div>
199 <div class="harness-tag">opencode auth</div>
200 </div>
201 </div>
202 <div class="harness">
203 <div class="harness-mark"><img src="/harnesses/cursor_light.svg" alt="" /></div>
204 <div class="harness-meta">
205 <div class="harness-name">Cursor</div>
206 <div class="harness-tag">cursor-agent</div>
207 </div>
208 </div>
209 </div>
210
211 <div class="harness-footer">
212 <div class="harness-footer-item"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l5 5L20 6"/></svg> No keys resold. No quota caps.</div>
213 <div class="harness-footer-item"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l5 5L20 6"/></svg> Switch models mid-thread.</div>
214 <div class="harness-footer-item"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l5 5L20 6"/></svg> More harnesses shipping weekly.</div>
215 </div>
216 </div>
217 </section>
218
219 <!-- ── Git ──────────────────────────────────────────────────── -->
220 <section id="git" class="sec-git">
221 <div class="container git-inner">
222 <div class="git-visual">
223 <div class="pr-card tile">
224 <div class="pr-head">
225 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.2"/><circle cx="6" cy="18" r="2.2"/><circle cx="18" cy="6" r="2.2"/><path d="M6 8v8M18 8v5a3 3 0 01-3 3h-3M13 13l-2 3 2 3"/></svg>
226 <span class="pr-title">Add marketing hero animation</span>
227 <span class="pr-status">Ready</span>
228 </div>
229 <div class="pr-meta">
230 <span><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.2"/><circle cx="6" cy="18" r="2.2"/><circle cx="18" cy="6" r="2.2"/><path d="M6 8v8M6 12a6 6 0 006-6h6"/></svg> feat/marketing-hero → main</span>
231 <span>+142 −38</span>
232 <span>3 commits</span>
233 </div>
234 <div class="pr-files">
235 <div><code>apps/marketing/src/pages/index.astro</code> <span>+14 −2</span></div>
236 <div><code>apps/marketing/src/layouts/Layout.astro</code> <span>+8 −0</span></div>
237 <div><code>apps/marketing/public/hero.css</code> <span>+120 −36</span></div>
238 </div>
239 <div class="pr-foot">
240 <button class="btn btn-ghost" style="font-size:12px;padding:6px 10px">View diff</button>
241 <button class="btn btn-primary" style="font-size:12px;padding:6px 12px">
242 <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 .5C5.65.5.5 5.65.5 12a11.5 11.5 0 007.86 10.93c.58.1.79-.25.79-.56v-2c-3.2.69-3.88-1.37-3.88-1.37-.52-1.33-1.27-1.69-1.27-1.69-1.04-.71.08-.7.08-.7 1.15.08 1.76 1.18 1.76 1.18 1.02 1.76 2.68 1.25 3.33.96.1-.75.4-1.25.72-1.54-2.55-.29-5.24-1.27-5.24-5.67 0-1.25.45-2.28 1.18-3.08-.12-.29-.51-1.45.11-3.02 0 0 .96-.31 3.15 1.18a10.96 10.96 0 015.74 0c2.19-1.49 3.15-1.18 3.15-1.18.62 1.57.23 2.73.11 3.02.74.8 1.18 1.83 1.18 3.08 0 4.41-2.7 5.38-5.27 5.66.41.36.78 1.06.78 2.13v3.16c0 .31.21.67.8.56A11.5 11.5 0 0023.5 12C23.5 5.65 18.35.5 12 .5z"/></svg>
243 Open pull request
244 </button>
245 </div>
246 </div>
247 <div class="pr-trail">
248 <div class="pr-trail-dot"></div>
249 <div class="pr-trail-line"></div>
250 <div class="pr-trail-dot"></div>
251 </div>
252 <div class="pr-button-shell">
253 <button class="pr-button">
254 <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.2"/><circle cx="6" cy="18" r="2.2"/><circle cx="18" cy="6" r="2.2"/><path d="M6 8v8M18 8v5a3 3 0 01-3 3h-3M13 13l-2 3 2 3"/></svg>
255 Commit &amp; push
256 <span class="pr-button-kbd">⌘⏎</span>
257 </button>
258 </div>
259 </div>
260
261 <div class="git-copy">
262 <div class="section-head" style="margin-bottom:0">
263 <h2>One button to commit, push, and make a PR.</h2>
264 <p>
265 Every agent thread writes to its own branch. When it's good, one
266 button opens the PR on GitHub with a generated title, body and
267 changelog. No terminal dance required.
268 </p>
269 <ul class="checklist" style="margin-top:24px">
270 <li><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l5 5L20 6"/></svg> Auto-generated PR titles &amp; bodies</li>
271 <li><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l5 5L20 6"/></svg> Inline diff review before you push</li>
272 <li><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l5 5L20 6"/></svg> Draft PRs, stack PRs, amend PRs</li>
273 <li><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l5 5L20 6"/></svg> Works with your existing GitHub auth</li>
274 </ul>
275 </div>
276 </div>
277 </div>
278 </section>
279
280 <!-- ── Open source ───────────────────────────────────────────── -->
281 <section id="open" class="sec-open">
282 <div class="container">
283 <div class="section-head open-head">
284 <div class="eyebrow">Open source</div>
285 <h2>If you don't like something, fork it.</h2>
286 <p>
287 T3 Code is as open as they come. We built this app to be modifiable,
288 customizable, and forkable. Go nuts - that's the whole point.
289 </p>
290 </div>
291
292 <div class="open-grid">
293 <div class="tile open-term">
294 <div class="open-term-head">
295 <span></span><span></span><span></span>
296 <span class="open-term-title">~/code</span>
297 </div>
298 <div class="open-term-body">
299 <div><span class="prompt">$</span> gh repo fork pingdotgg/t3code --clone</div>
300 <div class="dim">✓ Cloned t3code into ./t3code</div>
301 <div><span class="prompt">$</span> cd t3code &amp;&amp; bun install</div>
302 <div class="dim">✓ 1 284 packages installed in 4.2s</div>
303 <div><span class="prompt">$</span> bun dev</div>
304 <div class="dim">▲ T3 Code dev server → <span class="accent">http://localhost:4001</span></div>
305 <div class="cursor"><span class="prompt">$</span><span class="caret"></span></div>
306 </div>
307 </div>
308
309 <div class="open-stats">
310 <div class="tile open-stat">
311 <div class="open-stat-val">MIT</div>
312 <div class="open-stat-lbl">License · commercial-friendly</div>
313 </div>
314 <div class="tile open-stat">
315 <div class="open-stat-val">TypeScript</div>
316 <div class="open-stat-lbl">End-to-end, strictly typed</div>
317 </div>
318 <div class="tile open-stat">
319 <div class="open-stat-val">1 monorepo</div>
320 <div class="open-stat-lbl">Desktop · web · server · harnesses</div>
321 </div>
322 <div class="tile open-stat">
323 <div class="open-stat-val">No telemetry</div>
324 <div class="open-stat-lbl">Unless you opt in. Full stop.</div>
325 </div>
326 </div>
327 </div>
328
329 <div class="open-ctas">
330 <a class="btn btn-ghost" href="https://github.com/pingdotgg/t3code" target="_blank" rel="noopener noreferrer">
331 <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 .5C5.65.5.5 5.65.5 12a11.5 11.5 0 007.86 10.93c.58.1.79-.25.79-.56v-2c-3.2.69-3.88-1.37-3.88-1.37-.52-1.33-1.27-1.69-1.27-1.69-1.04-.71.08-.7.08-.7 1.15.08 1.76 1.18 1.76 1.18 1.02 1.76 2.68 1.25 3.33.96.1-.75.4-1.25.72-1.54-2.55-.29-5.24-1.27-5.24-5.67 0-1.25.45-2.28 1.18-3.08-.12-.29-.51-1.45.11-3.02 0 0 .96-.31 3.15 1.18a10.96 10.96 0 015.74 0c2.19-1.49 3.15-1.18 3.15-1.18.62 1.57.23 2.73.11 3.02.74.8 1.18 1.83 1.18 3.08 0 4.41-2.7 5.38-5.27 5.66.41.36.78 1.06.78 2.13v3.16c0 .31.21.67.8.56A11.5 11.5 0 0023.5 12C23.5 5.65 18.35.5 12 .5z"/></svg>
332 Star on GitHub
333 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M7 17L17 7M8 7h9v9"/></svg>
334 </a>
335 <a class="btn btn-ghost" href="https://github.com/pingdotgg/t3code/fork" target="_blank" rel="noopener noreferrer">
336 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="5" r="2.2"/><circle cx="18" cy="5" r="2.2"/><circle cx="12" cy="19" r="2.2"/><path d="M6 7.2v2A3 3 0 009 12.2h6A3 3 0 0018 9.2v-2M12 14v2.8"/></svg>
337 Fork the repo
338 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M7 17L17 7M8 7h9v9"/></svg>
339 </a>
340 <a class="btn btn-ghost" href="https://github.com/pingdotgg/t3code/blob/main/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer">
341 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="2.5" y="4.5" width="19" height="15" rx="2"/><path d="M7 10l3 2-3 2M12 16h5"/></svg>
342 Read CONTRIBUTING.md
343 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M7 17L17 7M8 7h9v9"/></svg>
344 </a>
345 </div>
346 </div>
347 </section>
348
349 <!-- ── Final CTA ─────────────────────────────────────────────── -->
350 <section id="download" class="sec-cta">
351 <div class="container cta-inner">
352 <h2 class="display cta-title">
353 Your agents deserve better than a terminal.
354 </h2>
355 <p class="cta-sub">
356 T3 Code is free, open source and fast. Install it, plug in the harness
357 you already pay for, and let your agents get to work.
358 </p>
359 <div class="cta-actions">
360 <a id="cta-download-btn" class="btn btn-primary btn-lg" href="https://github.com/pingdotgg/t3code/releases">
361 <svg class="dl-icon dl-icon--apple" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 814 1000" aria-hidden="true"><path fill="currentColor" d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-164-39.5c-76.5 0-103.7 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z"/></svg>
362 <svg class="dl-icon dl-icon--windows" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 88 88" aria-hidden="true"><path fill="currentColor" d="m0 12.402 35.687-4.86.016 34.423-35.67.203zm35.67 33.529.028 34.453L.028 75.48.026 45.7zm4.326-39.025L87.314 0v41.527l-47.318.376zm47.329 39.349-.011 41.34-47.318-6.678-.066-34.739z"/></svg>
363 <TuxIcon class="dl-icon dl-icon--linux" idPrefix="cta-linux-" />
364 <span id="cta-download-label">Download for macOS</span>
365 </a>
366 <a class="btn btn-ghost btn-lg" href="/download">Windows · Linux · other</a>
367 </div>
368 </div>
369 </section>
24</Layout>370</Layout>
25371
26<script>372<script>
...@@ -32,11 +378,7 @@ import Layout from "../layouts/Layout.astro";...@@ -32,11 +378,7 @@ import Layout from "../layouts/Layout.astro";
32 const ua = navigator.userAgent;378 const ua = navigator.userAgent;
33 if (/Win/i.test(ua)) return { os: "win", label: "Download for Windows" };379 if (/Win/i.test(ua)) return { os: "win", label: "Download for Windows" };
34 if (/Mac/i.test(ua)) {380 if (/Mac/i.test(ua)) {
35 return {381 return { os: "mac", label: "Download for macOS", arch: "arm64" };
36 os: "mac",
37 label: `Download for macOS`,
38 arch: "arm64",
39 };
40 }382 }
41 if (/Linux/i.test(ua)) return { os: "linux", label: "Download for Linux" };383 if (/Linux/i.test(ua)) return { os: "linux", label: "Download for Linux" };
42 return null;384 return null;
...@@ -44,23 +386,15 @@ import Layout from "../layouts/Layout.astro";...@@ -44,23 +386,15 @@ import Layout from "../layouts/Layout.astro";
44386
45 function pickAsset(assets: ReleaseAsset[], platform: Platform): string | null {387 function pickAsset(assets: ReleaseAsset[], platform: Platform): string | null {
46 if (platform.os === "win") {388 if (platform.os === "win") {
47 return (389 return assets.find((a) => a.name.endsWith("-x64.exe"))?.browser_download_url ?? null;
48 assets.find((a) => a.name.endsWith("-x64.exe"))
49 ?.browser_download_url ?? null
50 );
51 }390 }
52 if (platform.os === "mac") {391 if (platform.os === "mac") {
53 const preferred = assets.find((a) =>392 const preferred = assets.find((a) => a.name.endsWith(`-${platform.arch}.dmg`));
54 a.name.endsWith(`-${platform.arch}.dmg`),
55 );
56 const fallback = assets.find((a) => a.name.endsWith(".dmg"));393 const fallback = assets.find((a) => a.name.endsWith(".dmg"));
57 return (preferred ?? fallback)?.browser_download_url ?? null;394 return (preferred ?? fallback)?.browser_download_url ?? null;
58 }395 }
59 if (platform.os === "linux") {396 if (platform.os === "linux") {
60 return (397 return assets.find((a) => a.name.endsWith(".AppImage"))?.browser_download_url ?? null;
61 assets.find((a) => a.name.endsWith(".AppImage"))
62 ?.browser_download_url ?? null
63 );
64 }398 }
65 return null;399 return null;
66 }400 }
...@@ -68,24 +402,33 @@ import Layout from "../layouts/Layout.astro";...@@ -68,24 +402,33 @@ import Layout from "../layouts/Layout.astro";
68 async function init() {402 async function init() {
69 const btn = document.getElementById("download-btn") as HTMLAnchorElement | null;403 const btn = document.getElementById("download-btn") as HTMLAnchorElement | null;
70 const label = document.getElementById("download-label");404 const label = document.getElementById("download-label");
71 if (!btn || !label) return;405 const ctaBtn = document.getElementById("cta-download-btn") as HTMLAnchorElement | null;
406 const ctaLabel = document.getElementById("cta-download-label");
72407
73 const platform = detectPlatform();408 const platform = detectPlatform();
74 if (!platform) return;409 if (!platform) return;
75
76 document.documentElement.dataset.platform = platform.os;410 document.documentElement.dataset.platform = platform.os;
77 label.textContent = platform.label;411 if (label) label.textContent = platform.label;
412 if (ctaLabel) ctaLabel.textContent = platform.label;
78413
79 try {414 try {
80 const release = await fetchLatestRelease();415 const release = await fetchLatestRelease();
81 const url = pickAsset(release.assets ?? [], platform);416 const url = pickAsset(release.assets ?? [], platform);
82 if (url) {417 if (url) {
83 btn.href = url;418 if (btn) {
84 btn.removeAttribute("target");419 btn.href = url;
85 btn.removeAttribute("rel");420 btn.removeAttribute("target");
421 btn.removeAttribute("rel");
422 }
423 if (ctaBtn) {
424 ctaBtn.href = url;
425 ctaBtn.removeAttribute("target");
426 ctaBtn.removeAttribute("rel");
427 }
86 }428 }
87 } catch {429 } catch {
88 btn.href = RELEASES_URL;430 if (btn) btn.href = RELEASES_URL;
431 if (ctaBtn) ctaBtn.href = RELEASES_URL;
89 }432 }
90 }433 }
91434
...@@ -93,145 +436,693 @@ import Layout from "../layouts/Layout.astro";...@@ -93,145 +436,693 @@ import Layout from "../layouts/Layout.astro";
93</script>436</script>
94437
95<style>438<style>
96 .main {439 /* ── Section base ─────────────────────────────────────────── */
97 padding-top: 10vh;440 section {
441 position: relative;
442 padding: 96px 0;
443 border-top: 1px solid var(--border);
444 }
445
446 .section-head {
447 margin-bottom: 56px;
448 max-width: 720px;
98 }449 }
99450
100 /* ── Tagline ── */451 .section-head .eyebrow {
452 margin-bottom: 14px;
453 display: block;
454 }
101455
102 .tagline {456 .section-head h2 {
457 font-size: clamp(32px, 4vw, 48px);
103 font-weight: 500;458 font-weight: 500;
104 font-size: clamp(2rem, 5vw, 3.5rem);
105 letter-spacing: -0.035em;459 letter-spacing: -0.035em;
106 line-height: 1.15;460 line-height: 1.05;
107 text-align: center;461 margin-bottom: 18px;
108 margin: 0 0 6vh;462 }
109 opacity: 0;463
110 animation: fade-in 1s ease-out forwards;464 .section-head p {
465 color: var(--fg-muted);
466 font-size: 18px;
467 max-width: 620px;
468 letter-spacing: -0.005em;
111 }469 }
112470
113 /* ── Hero button ── */471 .checklist {
472 list-style: none;
473 display: flex;
474 flex-direction: column;
475 gap: 12px;
476 }
114477
115 .hero-button {478 .checklist li {
116 display: inline-flex;479 display: flex;
117 align-items: center;480 align-items: center;
118 gap: 0.55rem;481 gap: 10px;
119 background: #fafafa;482 color: var(--fg-muted);
120 color: #09090b;483 font-size: 15px;
121 padding: 0.75rem 2rem;484 }
122 border-radius: 999px;485
123 font-weight: 600;486 .checklist li svg {
124 font-size: 0.9rem;487 color: var(--ok);
125 margin-bottom: 1.25rem;488 flex-shrink: 0;
126 opacity: 0;489 }
127 animation: fade-in 1s ease-out 0.15s forwards;490
128 transition: transform 0.25s ease, box-shadow 0.25s ease;491 /* ── Hero ─────────────────────────────────────────────────── */
492 .hero {
493 padding: 72px 0 60px;
494 position: relative;
495 overflow: hidden;
496 border-top: 0;
497 }
498
499 .hero-grid {
500 position: absolute;
501 inset: 0;
502 pointer-events: none;
503 background-image:
504 linear-gradient(to right, rgba(255, 255, 255, 0.035) 1px, transparent 1px),
505 linear-gradient(to bottom, rgba(255, 255, 255, 0.035) 1px, transparent 1px);
506 background-size: 48px 48px;
507 mask-image: radial-gradient(ellipse 80% 60% at 50% 40%, black 40%, transparent 100%);
508 -webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 40%, black 40%, transparent 100%);
509 }
510
511 .hero-inner {
512 position: relative;
513 text-align: center;
514 }
515
516 .hero-title {
517 font-size: clamp(38px, 5.6vw, 76px);
518 margin: 28px auto 22px;
519 max-width: 20ch;
520 text-wrap: balance;
129 }521 }
130522
131 .hero-button:hover {523 .hero-sub {
132 transform: scale(1.03);524 color: var(--fg-muted);
133 box-shadow: 0 0 24px rgba(255, 255, 255, 0.08);525 font-size: clamp(16px, 1.4vw, 19px);
526 max-width: 640px;
527 margin: 0 auto 36px;
528 letter-spacing: -0.005em;
529 line-height: 1.55;
134 }530 }
135531
136 .hero-button:active {532 .hero-actions {
137 transform: scale(0.98);533 display: flex;
534 gap: 10px;
535 justify-content: center;
536 flex-wrap: wrap;
537 margin-bottom: 56px;
138 }538 }
139539
140 .hero-button-icon {540 /* Download button icons (platform-aware) */
541 .dl-icon {
141 display: none;542 display: none;
142 width: 1em;543 width: 14px;
143 height: 1em;544 height: 14px;
144 flex-shrink: 0;545 flex-shrink: 0;
145 }546 }
146547
147 :global([data-platform="mac"]) .hero-button-icon--apple {548 :global([data-platform="mac"]) .dl-icon--apple { display: block; }
148 display: block;549 :global([data-platform="win"]) .dl-icon--windows { display: block; }
550 :global([data-platform="linux"]) .dl-icon--linux { display: block; }
551 :global(:not([data-platform])) .dl-icon--apple { display: block; }
552
553 /* Floating harness marks */
554 .hero-float {
555 position: absolute;
556 inset: 0;
557 pointer-events: none;
558 z-index: 1;
559 }
560
561 .hero-float-mark {
562 position: absolute;
563 width: 96px;
564 height: 96px;
565 border-radius: 24px;
566 display: grid;
567 place-items: center;
568 background: rgba(20, 20, 24, 0.9);
569 border: 1px solid var(--border);
570 backdrop-filter: blur(10px);
571 -webkit-backdrop-filter: blur(10px);
572 box-shadow:
573 0 20px 48px -16px rgba(0, 0, 0, 0.65),
574 0 2px 0 0 rgba(255, 255, 255, 0.04) inset;
575 animation: floatDrift 9s ease-in-out infinite;
149 }576 }
150577
151 :global([data-platform="win"]) .hero-button-icon--windows {578 .hero-float-mark img {
579 width: 54px;
580 height: 54px;
152 display: block;581 display: block;
582 object-fit: contain;
583 }
584
585 .hero-float-mark.hf-claude { background: radial-gradient(circle at 30% 25%, rgba(217, 119, 87, 0.22), rgba(20, 20, 24, 0.92) 65%); top: 8%; left: 7%; animation-delay: 0s; transform: rotate(-8deg); }
586 .hero-float-mark.hf-codex { background: radial-gradient(circle at 30% 25%, rgba(255, 255, 255, 0.08), rgba(20, 20, 24, 0.92) 65%); top: 6%; right: 7%; animation-delay: -2.5s; transform: rotate(6deg); }
587 .hero-float-mark.hf-opencode { background: radial-gradient(circle at 30% 25%, rgba(255, 255, 255, 0.06), rgba(20, 20, 24, 0.92) 65%); top: 32%; left: 5%; animation-delay: -5s; transform: rotate(4deg); }
588 .hero-float-mark.hf-cursor { background: radial-gradient(circle at 30% 25%, rgba(255, 255, 255, 0.08), rgba(20, 20, 24, 0.92) 65%); top: 30%; right: 5%; animation-delay: -7s; transform: rotate(-5deg); }
589
590 @media (max-width: 1180px) {
591 .hero-float-mark { width: 76px; height: 76px; border-radius: 20px; }
592 .hero-float-mark img { width: 42px; height: 42px; }
593 .hero-float-mark.hf-claude { top: 4%; left: 3%; }
594 .hero-float-mark.hf-codex { top: 2%; right: 3%; }
595 .hero-float-mark.hf-opencode { top: 26%; left: 2%; }
596 .hero-float-mark.hf-cursor { top: 24%; right: 2%; }
597 }
598
599 @media (max-width: 820px) {
600 .hero {
601 padding-top: 132px;
602 }
603
604 .hero-title {
605 font-size: clamp(40px, 11vw, 56px);
606 margin-top: 14px;
607 }
608
609 .hero-actions {
610 margin-bottom: 96px;
611 }
612
613 .hero-float {
614 position: absolute;
615 inset: 0;
616 display: block;
617 }
618
619 .hero-float-mark {
620 position: absolute;
621 width: 78px;
622 height: 78px;
623 border-radius: 20px;
624 }
625
626 .hero-float-mark img {
627 width: 44px;
628 height: 44px;
629 }
630
631 /* Two above the title, two flanking the call-to-action area. */
632 .hero-float-mark.hf-claude {
633 top: 44px;
634 left: 10px;
635 transform: rotate(-10deg);
636 }
637
638 .hero-float-mark.hf-codex {
639 top: 44px;
640 right: 10px;
641 transform: rotate(8deg);
642 }
643
644 .hero-float-mark.hf-opencode {
645 top: 474px;
646 left: 4px;
647 right: auto;
648 transform: rotate(-6deg);
649 }
650
651 .hero-float-mark.hf-cursor {
652 top: 474px;
653 right: 4px;
654 left: auto;
655 transform: rotate(7deg);
656 }
153 }657 }
154658
155 :global([data-platform="linux"]) .hero-button-icon--linux {659 .hero-preview {
660 max-width: 1180px;
661 margin: 0 auto;
662 transform: perspective(2000px) rotateX(2deg);
663 transition: transform 0.6s ease;
664 }
665
666 .hero-preview:hover {
667 transform: perspective(2000px) rotateX(0deg);
668 }
669
670 .hero-screenshot-frame {
671 position: relative;
672 overflow: hidden;
673 aspect-ratio: 2508 / 1682;
674 border-radius: 14px;
675 background: #0a0a0c;
676 box-shadow: 0 28px 64px -28px rgba(0, 0, 0, 0.75);
677 }
678
679 .hero-screenshot-frame picture {
156 display: block;680 display: block;
681 width: 100%;
682 height: 100%;
683 }
684
685 .hero-screenshot-frame img {
686 width: calc(100% + 4px);
687 height: calc(100% + 4px);
688 margin: -2px;
689 object-fit: cover;
690 object-position: center top;
691 }
692
693 /* ── Harnesses ─────────────────────────────────────────── */
694 .sec-harness { background: #09090b; }
695
696 .harness-grid {
697 display: grid;
698 grid-template-columns: repeat(4, 1fr);
699 gap: 0;
700 border: 1px solid var(--border);
701 border-radius: var(--radius);
702 overflow: hidden;
703 }
704
705 .harness {
706 padding: 22px 20px;
707 display: flex; align-items: center; gap: 14px;
708 border-right: 1px solid var(--border);
709 background: linear-gradient(180deg, rgba(255, 255, 255, 0.015), transparent);
710 transition: background 0.2s ease;
157 }711 }
712 .harness:last-child { border-right: 0; }
713 .harness:hover { background: rgba(255, 255, 255, 0.025); }
158714
159 /* ── Other platforms link ── */715 .harness-mark {
716 color: var(--fg); opacity: 0.95;
717 flex-shrink: 0; width: 28px; height: 28px;
718 display: grid; place-items: center;
719 }
720 .harness-mark img { width: 22px; height: 22px; object-fit: contain; }
160721
161 .other-platforms {722 .harness-meta { flex: 1; min-width: 0; }
162 font-size: 0.825rem;723 .harness-name {
163 color: var(--fg-dim);724 font-size: 14px; font-weight: 500;
164 margin-bottom: 5vh;725 letter-spacing: -0.01em; margin-bottom: 2px;
165 opacity: 0;726 }
166 animation: fade-in 1s ease-out 0.3s forwards;727 .harness-tag {
167 transition: color 0.3s ease;728 font-family: var(--font-mono);
168 text-decoration: underline;729 font-size: 11px; color: var(--fg-dim);
169 text-decoration-color: rgba(113, 113, 122, 0.4);
170 text-underline-offset: 3px;
171 }730 }
172731
173 .other-platforms:hover {732 .harness-footer {
733 display: flex; gap: 24px; flex-wrap: wrap;
734 margin-top: 28px; padding-top: 24px;
735 border-top: 1px dashed var(--border);
736 font-size: 13px; color: var(--fg-muted);
737 }
738 .harness-footer-item {
739 display: inline-flex; gap: 8px; align-items: center;
174 color: var(--fg-muted);740 color: var(--fg-muted);
175 text-decoration-color: var(--fg-muted);
176 }741 }
742 .harness-footer-item svg { color: var(--ok); }
177743
178 /* ── Screenshot ── */744 /* ── Endorsements ─────────────────────────────────────── */
745 .sec-endorsements {
746 overflow: hidden;
747 }
179748
180 .screenshot-wrap {749 .endorsements-head {
181 margin: 0 auto;750 max-width: 720px;
182 width: min(95vw, 1400px);751 margin-bottom: 56px;
183 opacity: 0;
184 transform: scale(0.98);
185 animation: screenshot-in 1s ease-out 0.15s forwards;
186 }752 }
187753
188 .screenshot {754 .endorsements-head h2 {
189 width: 100%;755 font-size: clamp(32px, 4vw, 48px);
190 display: block;756 font-weight: 500;
191 border-radius: 16px;757 letter-spacing: -0.035em;
192 border: 1px solid rgba(255, 255, 255, 0.06);758 line-height: 1.05;
193 mask-image: linear-gradient(to bottom, black 80%, transparent 100%);759 margin-bottom: 18px;
194 -webkit-mask-image: linear-gradient(to bottom, black 80%, transparent 100%);
195 }760 }
196761
197 .screenshot-wrap::after {762 .endorsements-head p {
763 color: var(--fg-muted);
764 font-size: 18px;
765 max-width: 620px;
766 letter-spacing: -0.005em;
767 }
768
769 .endorsement-carousel {
770 position: relative;
771 display: flex;
772 flex-direction: column;
773 gap: 12px;
774 }
775
776 .endorsement-carousel--mobile {
777 display: none;
778 }
779
780 .endorsement-carousel::before,
781 .endorsement-carousel::after {
198 content: "";782 content: "";
199 display: block;783 position: absolute;
200 width: 100%;784 top: 0;
201 height: 120px;785 bottom: 0;
202 background: inherit;786 z-index: 2;
203 margin-top: -1px;787 width: max(48px, calc((100vw - 1240px) / 2 + 56px));
204 opacity: 0.04;788 pointer-events: none;
205 transform: scaleY(-1);789 }
206 mask-image: linear-gradient(to bottom, black 0%, transparent 60%);790
207 -webkit-mask-image: linear-gradient(to bottom, black 0%, transparent 60%);791 .endorsement-carousel::before {
792 left: 0;
793 background: linear-gradient(90deg, var(--bg), transparent);
794 }
795
796 .endorsement-carousel::after {
797 right: 0;
798 background: linear-gradient(270deg, var(--bg), transparent);
799 }
800
801 .endorsement-row {
802 overflow: hidden;
803 }
804
805 .endorsement-track {
806 width: max-content;
807 display: flex;
808 animation: endorsementMarquee 76s linear infinite;
809 will-change: transform;
810 }
811
812 .endorsement-track-group {
813 display: flex;
814 gap: 12px;
815 padding-right: 12px;
816 }
817
818 .endorsement-row.is-reverse .endorsement-track {
819 animation-direction: reverse;
820 animation-duration: 84s;
821 }
822
823 .endorsement-carousel:hover .endorsement-track,
824 .endorsement-carousel:focus-within .endorsement-track {
825 animation-play-state: paused;
826 }
827
828 .endorsement-card {
829 position: relative;
830 width: clamp(264px, 22vw, 308px);
831 height: 132px;
832 padding: 14px 16px;
833 display: flex;
834 flex-direction: column;
835 gap: 10px;
836 border: 1px solid var(--border);
837 border-radius: 10px;
838 background: rgba(255, 255, 255, 0.012);
839 transition:
840 border-color 0.18s ease,
841 background 0.18s ease;
842 }
843
844 .endorsement-card:hover {
845 border-color: var(--border-strong);
846 background: rgba(255, 255, 255, 0.03);
847 }
848
849 .endorsement-author {
850 display: flex;
851 align-items: center;
852 gap: 8px;
853 min-width: 0;
854 }
855
856 .endorsement-author img {
857 width: 28px;
858 height: 28px;
859 border-radius: 50%;
860 object-fit: cover;
861 flex-shrink: 0;
862 }
863
864 .endorsement-handle {
865 color: var(--fg-muted);
866 font-size: 13px;
867 font-weight: 500;
868 letter-spacing: -0.005em;
869 overflow: hidden;
870 text-overflow: ellipsis;
871 white-space: nowrap;
872 }
873
874 .endorsement-card p {
875 color: var(--fg);
876 font-size: 13.5px;
877 line-height: 1.4;
878 letter-spacing: -0.003em;
879 display: -webkit-box;
880 overflow: hidden;
881 -webkit-box-orient: vertical;
882 -webkit-line-clamp: 3;
883 }
884
885 /* ── Git ──────────────────────────────────────────────── */
886 .git-inner {
887 display: grid;
888 grid-template-columns: 1.1fr 1fr;
889 gap: 64px; align-items: center;
890 }
891
892 .git-visual {
893 position: relative;
894 display: flex; flex-direction: column;
895 align-items: stretch; gap: 20px;
896 }
897
898 .pr-card { padding: 20px; }
899 .pr-head {
900 display: flex; align-items: center; gap: 10px;
901 margin-bottom: 12px;
902 }
903 .pr-head svg { color: var(--ok); }
904 .pr-title { font-weight: 500; font-size: 15px; flex: 1; }
905 .pr-status {
906 font-family: var(--font-mono); font-size: 10px;
907 color: var(--ok); padding: 2px 8px;
908 border: 1px solid var(--ok); border-radius: 999px;
909 letter-spacing: 0.08em; text-transform: uppercase;
910 }
911 .pr-meta {
912 display: flex; gap: 14px;
913 font-family: var(--font-mono); font-size: 11px;
914 color: var(--fg-dim); margin-bottom: 14px; flex-wrap: wrap;
915 }
916 .pr-meta span { display: inline-flex; align-items: center; gap: 5px; }
917 .pr-files {
918 border: 1px solid var(--border); border-radius: 8px;
919 overflow: hidden; margin-bottom: 16px;
920 }
921 .pr-files > div {
922 display: flex; justify-content: space-between;
923 padding: 8px 12px; font-family: var(--font-mono);
924 font-size: 11px; border-top: 1px solid var(--border);
925 color: var(--fg-muted);
926 }
927 .pr-files > div:first-child { border-top: 0; }
928 .pr-files span { color: var(--fg-dim); }
929 .pr-foot { display: flex; justify-content: flex-end; gap: 8px; }
930
931 .pr-trail {
932 display: flex; flex-direction: column;
933 align-items: center; justify-content: center;
934 gap: 0; margin: -4px 0;
935 }
936 .pr-trail-dot {
937 width: 8px; height: 8px; border-radius: 999px;
938 background: var(--border-strong);
939 }
940 .pr-trail-line {
941 width: 1px; height: 28px;
942 background: linear-gradient(180deg, var(--border-strong), var(--accent));
943 }
944
945 .pr-button-shell { display: flex; justify-content: center; }
946 .pr-button {
947 display: inline-flex; align-items: center; gap: 10px;
948 padding: 12px 20px;
949 background: var(--fg); color: #09090b;
950 font-weight: 600; font-size: 13px;
951 border-radius: 10px;
952 box-shadow: 0 8px 24px -8px rgba(255, 255, 255, 0.2);
953 }
954 .pr-button-kbd {
955 font-family: var(--font-mono); font-size: 10px;
956 background: rgba(0, 0, 0, 0.1);
957 padding: 2px 6px; border-radius: 4px;
958 }
959
960 /* ── Open source ──────────────────────────────────────── */
961 .open-head {
962 text-align: center;
963 margin: 0 auto 56px;
964 }
965 .open-head p { margin: 0 auto; }
966
967 .open-grid {
968 display: grid;
969 grid-template-columns: 1.25fr 1fr;
970 gap: 20px; margin-bottom: 32px;
971 }
972
973 .open-term { padding: 0; overflow: hidden; }
974 .open-term-head {
975 display: flex; align-items: center; gap: 6px;
976 padding: 10px 14px; border-bottom: 1px solid var(--border);
977 background: rgba(255, 255, 255, 0.02);
978 }
979 .open-term-head span {
980 width: 10px; height: 10px; border-radius: 999px;
981 background: #2a2a30; display: block;
982 }
983 .open-term-title {
984 margin-left: 10px;
985 font-family: var(--font-mono); font-size: 11px;
986 color: var(--fg-dim); flex: 1; text-align: center;
987 background: transparent !important;
988 width: auto !important; height: auto !important;
989 border-radius: 0 !important;
990 }
991
992 .open-term-body {
993 padding: 20px 22px;
994 font-family: var(--font-mono); font-size: 13px;
995 line-height: 1.7; color: var(--fg);
996 }
997 .open-term-body > div {
998 white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
999 }
1000 .open-term-body .prompt { color: var(--accent); margin-right: 8px; }
1001 .open-term-body .dim { color: var(--fg-dim); }
1002 .open-term-body .accent { color: var(--accent); }
1003 .open-term-body .cursor { display: flex; align-items: center; }
1004 .caret {
1005 display: inline-block;
1006 width: 7px; height: 14px;
1007 background: var(--fg);
1008 margin-left: 4px;
1009 animation: blink 1s steps(2) infinite;
1010 }
1011
1012 .open-stats {
1013 display: grid;
1014 grid-template-columns: 1fr 1fr;
1015 gap: 12px;
1016 }
1017 .open-stat {
1018 padding: 22px;
1019 display: flex; flex-direction: column; gap: 6px;
1020 }
1021 .open-stat-val {
1022 font-size: 22px; font-weight: 500;
1023 letter-spacing: -0.015em;
1024 }
1025 .open-stat-lbl {
1026 font-family: var(--font-mono); font-size: 10.5px;
1027 color: var(--fg-dim); letter-spacing: 0.04em;
1028 }
1029
1030 .open-ctas {
1031 display: flex; gap: 10px;
1032 justify-content: center; flex-wrap: wrap;
1033 }
1034
1035 /* ── Final CTA ────────────────────────────────────────── */
1036 .sec-cta {
1037 text-align: center;
1038 padding: 120px 0;
1039 position: relative;
1040 overflow: hidden;
1041 }
1042 .sec-cta::before {
1043 content: "";
1044 position: absolute;
1045 inset: auto 0 -50% 0;
1046 height: 60%;
1047 background: radial-gradient(ellipse at center, var(--accent-dim) 0%, transparent 60%);
208 pointer-events: none;1048 pointer-events: none;
1049 opacity: 0.6;
1050 }
1051 .cta-inner { position: relative; }
1052 .cta-title {
1053 font-size: clamp(40px, 6vw, 72px);
1054 }
1055 .cta-sub {
1056 color: var(--fg-muted);
1057 font-size: 18px;
1058 max-width: 560px;
1059 margin: 20px auto 36px;
1060 line-height: 1.55;
1061 letter-spacing: -0.005em;
1062 }
1063 .cta-actions {
1064 display: flex; gap: 10px;
1065 justify-content: center; flex-wrap: wrap;
1066 margin-bottom: 24px;
209 }1067 }
2101068
211 @keyframes screenshot-in {1069 @keyframes endorsementMarquee {
212 from {1070 from {
213 opacity: 0;1071 transform: translateX(0);
214 transform: scale(0.98);
215 }1072 }
216 to {1073 to {
217 opacity: 1;1074 transform: translateX(-50%);
218 transform: scale(1);
219 }1075 }
220 }1076 }
2211077
222 /* ── Mobile ── */1078 /* ── Responsive ────────────────────────────────────────── */
2231079 @media (max-width: 960px) {
224 @media (max-width: 640px) {1080 .hero-preview {
225 .main {1081 width: min(860px, calc(100vw - 24px));
226 padding-top: 7vh;1082 margin-left: 50%;
1083 transform: translateX(-50%) perspective(1600px) rotateX(1.5deg);
227 }1084 }
2281085 .hero-preview:hover {
229 .tagline {1086 transform: translateX(-50%) perspective(1600px) rotateX(0deg);
230 margin-bottom: 4vh;
231 }1087 }
1088 .harness-grid { grid-template-columns: 1fr 1fr; }
1089 .harness { border-right: 0; border-bottom: 1px solid var(--border); }
1090 .harness:nth-child(odd) { border-right: 1px solid var(--border); }
1091 .git-inner { grid-template-columns: 1fr; gap: 40px; }
1092 .open-grid { grid-template-columns: 1fr; }
1093 }
2321094
233 .screenshot-wrap {1095 @media (max-width: 820px) {
234 width: 95vw;1096 section { padding: 64px 0; }
1097 .sec-cta { padding: 96px 0; }
1098 .container { padding-left: 20px; padding-right: 20px; }
1099 .hero-preview { display: none; }
1100 .endorsements-head {
1101 margin-bottom: 40px;
1102 }
1103 .endorsement-carousel--desktop {
1104 display: none;
1105 }
1106 .endorsement-carousel--mobile {
1107 display: flex;
1108 }
1109 .endorsement-carousel::before,
1110 .endorsement-carousel::after {
1111 width: 28px;
1112 }
1113 .endorsement-track {
1114 animation-duration: 68s;
1115 }
1116 .endorsement-row.is-reverse .endorsement-track {
1117 animation-duration: 76s;
1118 }
1119 .endorsement-card {
1120 width: 268px;
1121 height: 132px;
1122 padding: 14px;
1123 }
1124 .endorsement-card p {
1125 font-size: 13px;
235 }1126 }
236 }1127 }
237</style>1128</style>
apps/marketing/tweets.md created+19
...@@ -0,0 +1,19 @@
1https://x.com/Shay_Benshabtay/status/2054668503857156326
2https://x.com/teja2495/status/2052420254991581623
3https://x.com/developedbyed/status/2030627970532921605
4https://x.com/tannerlinsley/status/2031102771529920966
5https://x.com/aronprins/status/2045102518196183109
6https://x.com/BennettBuhner/status/2054667115697754387
7https://x.com/ex0t1clol/status/2054666870008021197
8https://x.com/Josikinz/status/2030367951694745870
9https://x.com/jetpackjoe_/status/2054666792933404959
10https://x.com/mil000/status/2030120041451246071
11https://x.com/_winter_wonders/status/2052350198764970434
12https://x.com/kostyniuk00/status/2052041388179468521
13https://x.com/gnukeith/status/2054670073579630730
14https://x.com/peculiarnewbie/status/2054671685027233827
15https://x.com/leodev/status/2054679746353537042
16https://x.com/pocarles/status/2054673964274758046
17https://x.com/DavidKPiano/status/2054682983504719930
18https://x.com/iamkaffe/status/2054675539311411280
19https://x.com/uwunetes/status/2054683356022120640
bun.lock+1
...@@ -154,6 +154,7 @@...@@ -154,6 +154,7 @@
154 "name": "@t3tools/client-runtime",154 "name": "@t3tools/client-runtime",
155 "dependencies": {155 "dependencies": {
156 "@t3tools/contracts": "workspace:*",156 "@t3tools/contracts": "workspace:*",
157 "@t3tools/shared": "workspace:*",
157 "effect": "catalog:",158 "effect": "catalog:",
158 },159 },
159 "devDependencies": {160 "devDependencies": {