Skip to content
53 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Merge site-audit: SEO routes, analytics with consent first in Europe, security page, founder and X account, docs header; the tour opens on the pull request and leads with Code, on the real shell, with Agents and Docs working today1/**
2 * Asking a visitor from the EU, EEA, UK or Switzerland before site
3 * analytics runs (lib/analytics-consent.ts): both answers are one click,
4 * and nothing is fetched or stored for analytics until they agree. The
5 * footer's "Cookie choices" asks again (components/footer.tsx).
6 */
7import { useEffect, useState, useSyncExternalStore } from "react";
8import { Link } from "react-router";
9
10import { analyticsHere, choice, choose, consentRequired, onChoice } from "../lib/analytics-consent";
11
12/** Whether this visitor is asked at all, known only once the page is in the browser. */
13export function useAsksFirst(): boolean {
14 const [asks, setAsks] = useState(false);
15 useEffect(() => setAsks(analyticsHere() && consentRequired()), []);
16 return asks;
17}
18
19export function AnalyticsConsent() {
20 const asks = useAsksFirst();
21 const chosen = useSyncExternalStore(onChoice, choice, () => null);
22 if (!asks || chosen) return null;
23 return (
24 <section
25 aria-label="Analytics cookie"
Phones reach every page: each mode's menu from the top bar or by tapping the tab you're on, Docs first in the avatar sheet, a project's pages as a swipeable strip; dialogs as bottom sheets above the keyboard, safe areas, menus kept on screen, 40px targets, touch-visible controls, save bars above the tab bar26 className="fixed inset-x-3 bottom-3 z-[60] max-md:bottom-[calc(var(--tabbar-h)+0.75rem)] max-md:in-data-[keyboard=open]:bottom-3 mx-auto max-w-lg rounded-2xl bg-surface p-4 text-sm shadow-2xl shadow-black/50 ring-1 ring-line-strong sm:inset-x-auto sm:right-4 sm:bottom-4"
Merge site-audit: SEO routes, analytics with consent first in Europe, security page, founder and X account, docs header; the tour opens on the pull request and leads with Code, on the real shell, with Agents and Docs working today27 >
28 <p className="leading-6 text-fg-soft">
29 May g1t count how its pages are used? It sets one analytics cookie, and names inside your workspaces are
30 removed before anything is sent.{" "}
31 <Link to="/policies/privacy#how-the-site-is-used" className="text-accent hover:underline">
32 What is sent
33 </Link>
34 </p>
35 <div className="mt-3 flex gap-2">
36 <button
37 type="button"
38 onClick={() => choose("yes")}
You choose how g1t looks: Auto follows your system, Light and Dark stay put, set from the account menu, the phone's You and help sheet, Settings → Account or the command palette; the page is drawn in your choice from the first byte, every colour has a light value that reads at 4.5:1 or better, code and diffs are highlighted for both, diagrams and the document editor follow along, the product tour and the g1t mark's avatar stay dark, and Dark is what you see until you choose; the workspaces guide says how.39 className="flex-1 rounded-lg bg-fg px-3 py-2 font-medium text-bg transition-colors hover:bg-fg-hover"
Merge site-audit: SEO routes, analytics with consent first in Europe, security page, founder and X account, docs header; the tour opens on the pull request and leads with Code, on the real shell, with Agents and Docs working today40 >
41 Allow
42 </button>
43 <button
44 type="button"
45 onClick={() => choose("no")}
46 className="flex-1 rounded-lg px-3 py-2 font-medium text-fg ring-1 ring-line-strong transition-colors hover:bg-raised"
47 >
48 No thanks
49 </button>
50 </div>
51 </section>
52 );
53}

This file's history is long; its oldest lines are credited to the oldest commit read.