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.
| The front page is Home: where you're needed comes first, however long ago it started, with what's at stake and how long it has waited; then what happened since you were last here, in words, with the agent work that settled, what landed, what deployed, what was decided and what was spent, switchable to the last 24 hours or 7 days; then what's running now. Your last visit is kept with your account, so it's the same on every device; Today's old address leads here. The home guide says how. | 1 | import { Activity, BarChart3, Building2, MessagesSquare, Bell, BookMarked, BookOpen, Bookmark, Blocks, Bot, Box, Check, ChevronDown, ChevronLeft, ChevronRight, CircleDot, GripVertical, CircleUserRound, Code2, Coins, Compass, CreditCard, Fingerprint, GanttChart, Gauge, GitBranch, GitPullRequest, Globe, History, KanbanSquare, Keyboard, KeyRound, Layers, LayoutDashboard, LayoutGrid, LifeBuoy, ListTree, Lock, LogOut, Mail, Network, Package, PanelLeft, PlayCircle, Plug, Plus, Rocket, Search, ServerCog, Settings, Shapes, ShieldCheck, Scale, Smile, Sparkles, Store, House, Ticket, TrendingUp, UserPlus, UserRoundKey, Users, UsersRound, Webhook, X, ArrowLeftRight } from "lucide-react"; |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 2 | import { Fragment, type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from "react"; |
| Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar | 3 | import { Link, NavLink, useFetcher, useLocation, useNavigation, useRouteLoaderData, useSubmit } from "react-router"; |
| Usage while free is shown at cost; agents get rustfmt and clippy | 4 | |
| One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers | 5 | import { type Abilities, type ChatSidebarEntry, type InboxCounts, type WorkspaceAgent, type Membership, type Spike, type User, hasCodeAccess, mayCreateTeams, shownUsername } from "@g1t/contracts"; |
| Usage while free is shown at cost; agents get rustfmt and clippy | 6 | |
| Not found and error pages have one main landmark: their own when signed out, the shell's when signed in | 7 | import { InMain } from "./landmark"; |
| Usage, Billing settings and prepaid AI credit; fixes from the UX audit | 8 | import { CommandPalette, type PaletteCommand, PaletteKey, usePaletteShortcut } from "./command-palette"; |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 9 | import { NotificationsBell } from "./inbox"; |
| The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how. | 10 | import { SpendPill } from "./spend"; |
| Previews build from any branch; Agent in place of Ask AI; pin from the sidebar | 11 | import { PinButton } from "./pin-button"; |
| Merge branch 'worktree-agent-ae1299e92e4462012' | 12 | import { Hint } from "./ui/hint"; |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 13 | import { Sheet, SheetContent, SheetTitle } from "./ui/sheet"; |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 14 | import { StatusDot, useSiteStatus } from "./footer"; |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 15 | import { Logo, MarkGlyph } from "./logo"; |
| Usage, Billing settings and prepaid AI credit; fixes from the UX audit | 16 | import { Avatar, SoonPill } from "./ui"; |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 17 | import { Skeleton } from "./ui/skeleton"; |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 18 | import { Button } from "./ui/button"; |
| 19 | import { Separator } from "./ui/separator"; | |
| 20 | import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "./ui/breadcrumb"; | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 21 | import { |
| 22 | DropdownMenu, | |
| 23 | DropdownMenuContent, | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 24 | DropdownMenuGroup, |
| Usage while free is shown at cost; agents get rustfmt and clippy | 25 | DropdownMenuItem, |
| 26 | DropdownMenuLabel, | |
| 27 | DropdownMenuSeparator, | |
| 28 | DropdownMenuTrigger, | |
| 29 | } from "./ui/dropdown-menu"; | |
| Merge branch 'worktree-agent-ad7c6d88d93adc817' | 30 | import { type RoadmapItem, roadmapIn, roadmapItem } from "../lib/roadmap"; |
| The front page is Home: where you're needed comes first, however long ago it started, with what's at stake and how long it has waited; then what happened since you were last here, in words, with the agent work that settled, what landed, what deployed, what was decided and what was spent, switchable to the last 24 hours or 7 days; then what's running now. Your last visit is kept with your account, so it's the same on every device; Today's old address leads here. The home guide says how. | 31 | import { type ModeKey, SETTINGS_PAGES, homePagePath, modeOf } from "../lib/workspace-nav"; |
| Chat and workspace agents: channels, DMs and named agents you talk to | 32 | import { AgentsSidebar } from "./agents-mode"; |
| 33 | import { ChatSidebar } from "./chat/sidebar"; | |
| Artifacts is a mode in the rail, the shell and the phone's tab bar in place of Docs: its home lists everything you can open by day or as cards under All, Yours and Shared with you, with search, filters and tiles to start a doc (slides, designs and dashboards say they are coming soon), and its sidebar holds favorites, spaces, Private, Shared, projects' docs and the trash. | 34 | import { FoliosSidebar } from "./folios/sidebar"; |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 35 | import { Dock, ShortcutsDialog, WorkspaceSwitcher, sidebarKeyLabel } from "./dock"; |
| 36 | import { BottomBar, isConversation, useVisualViewport } from "./mobile"; | |
| Chat and workspace agents: channels, DMs and named agents you talk to | 37 | import { useChatSidebar } from "./chat/actions"; |
| 38 | import { unreadTotals } from "../lib/chat"; | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 39 | import { SETTINGS_CAPABILITY, type ViewerAccess, seesSettings } from "../lib/access"; |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 40 | import { projectPages } from "../lib/chrome"; |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 41 | import { ACCOUNT_SETTINGS, type AccountSettingsPage, FIRST_SETTINGS_PAGE, accountSettingsPage } from "../lib/account-settings"; |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 42 | import { type PinnableApp, sidebarCookie } from "../lib/apps"; |
| 43 | import { REASON_FILTERS, inboxReason, inboxView } from "../lib/inbox"; | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 44 | import { GithubMark } from "./github"; |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 45 | import { useInviteOnly } from "../lib/registration"; |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 46 | import { STATUS_URL, statusTitle } from "../lib/status"; |
| Navigation: the workspace's own page with tabs, pins and recent in the sidebar | 47 | import { type ShortcutProject, movedPin, recentWith } from "../lib/pins"; |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 48 | import type { AccountMenuData } from "../routes/settings-menu-json"; |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 49 | import { useLiveBadges } from "../lib/notify-client"; |
| One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers | 50 | import { OwnPresenceDot, OwnPresenceItems, StatusDialog } from "./presence"; |
| 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. | 51 | import { THEME_COMMANDS, ThemeMenuSwitch } from "./theme-switch"; |
| Usage while free is shown at cost; agents get rustfmt and clippy | 52 | |
| Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put | 53 | /** |
| 54 | * What the sidebar needs, worked out by the root loader. For a visitor who | |
| 55 | * is not signed in there is no workspace, no projects and no usage: only | |
| 56 | * the project being looked at, if they can see it. | |
| 57 | */ | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 58 | export type ShellData = { |
| 59 | /** The workspace the sidebar is about: the one being looked at, or their first. */ | |
| Workspace names and icons, and a component kit for every control | 60 | workspace: Membership | null; |
| Navigation: the workspace's own page with tabs, pins and recent in the sidebar | 61 | /** All its projects, by name, for the palette: `name` is the slug in their address. */ |
| 62 | repos: ShortcutProject[]; | |
| 63 | /** The person's pinned projects in it, in their order (lib/pins.ts). */ | |
| 64 | pinned?: ShortcutProject[]; | |
| 65 | /** What they opened there last, latest first, leaving out the pinned. */ | |
| 66 | recent?: ShortcutProject[]; | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 67 | /** Repositories shared with them in workspaces they do not belong to. */ |
| 68 | shared?: { namespace: string; name: string; isPrivate: boolean }[]; | |
| Projects: what a workspace builds and runs, first on every page | 69 | /** The project being looked at, if any, whoever owns it. */ |
| Usage while free is shown at cost; agents get rustfmt and clippy | 70 | repo: { |
| 71 | namespace: string; | |
| 72 | name: string; | |
| 73 | member: boolean; | |
| 74 | issues: number; | |
| 75 | pulls: number; | |
| 76 | } | null; | |
| Billing accounts, terms and enterprises; g1t is no longer free | 77 | /** Where the workspace stands against its usage limit, if billing is on. */ |
| 78 | limit: { | |
| 79 | exposureMicros: number; | |
| 80 | ceilingMicros: number | null; | |
| 81 | state: "ok" | "warning" | "stopped"; | |
| 82 | comped: boolean; | |
| 83 | } | null; | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 84 | /** Whether g1t charges nothing for now, while it is being built out. */ |
| 85 | free?: boolean; | |
| 86 | /** What its agents have cost since the start of the month. */ | |
| 87 | /** This month's usage: charged, or at cost while g1t is free. */ | |
| 88 | monthUsageMicros: number | null; | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 89 | /** Whether new compute is paused (a spend spike or a hold), and whether the viewer can answer it. */ |
| 90 | compute?: { paused: string | null; spike: Spike | null; owner: boolean } | null; | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 91 | /** What is unread in their notifications, for the dock and the bell. Absent for a visitor. */ |
| Inbox: a bell in the top bar opens it beside the page, and /inbox holds it all | 92 | inbox?: InboxCounts | null; |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 93 | /** |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 94 | * Chat, for the dock's badge: what is unread, and the |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 95 | * starred and latest conversations. Null when chat did not answer in time. |
| 96 | */ | |
| 97 | chat?: { unread: number; mentions: number; starred?: ChatSidebarEntry[]; recent?: ChatSidebarEntry[] } | null; | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 98 | /** The workspace's agents, g1t first, for the Agents sidebar; null when not known. */ |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 99 | agents?: ShellAgent[] | null; |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 100 | /** The apps this person pinned to their dock in the workspace (lib/apps.ts). */ |
| 101 | pins?: PinnableApp[]; | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 102 | }; |
| 103 | ||
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 104 | /** An agent as the shell lists it. */ |
| 105 | export type ShellAgent = Pick< | |
| 106 | WorkspaceAgent, | |
| An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how. | 107 | "id" | "handle" | "display_name" | "avatar" | "avatar_seed" | "role" | "status" | "title" | "builtin" |
| 108 | > & { | |
| 109 | scope?: WorkspaceAgent["scope"]; | |
| 110 | /** The visible teams it is on (team memberships); absent when they couldn't be read. */ | |
| 111 | teams?: { slug: string; name: string }[]; | |
| 112 | }; | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 113 | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 114 | function SidebarLink({ |
| 115 | to, | |
| 116 | icon, | |
| 117 | end, | |
| 118 | count, | |
| 119 | also, | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 120 | drill, |
| Merge branch 'worktree-agent-ad7c6d88d93adc817' | 121 | current: lit, |
| Usage while free is shown at cost; agents get rustfmt and clippy | 122 | children, |
| 123 | }: { | |
| 124 | to: string; | |
| 125 | icon: ReactNode; | |
| 126 | end?: boolean; | |
| 127 | count?: number; | |
| Projects: what a workspace builds and runs, first on every page | 128 | /** Other path prefixes under which this link is the current one. */ |
| 129 | also?: string | string[]; | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 130 | /** It opens a list of its own: a chevron says so, always or on hover. */ |
| 131 | drill?: boolean | "hover"; | |
| Merge branch 'worktree-agent-ad7c6d88d93adc817' | 132 | /** Whether it is the current row, when the list works that out itself. */ |
| 133 | current?: boolean; | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 134 | children: ReactNode; |
| 135 | }) { | |
| 136 | const { pathname } = useLocation(); | |
| Opening Notifications lights only the row you chose: a sidebar whose rows differ only by their query shows a row as loading only when the page on its way is that row's, not every row on the same path. | 137 | const navigation = useNavigation(); |
| 138 | // NavLink's own pending state compares paths only, so a list whose rows | |
| 139 | // differ by query (Notifications' views and reasons) would light every | |
| 140 | // row while one loads. Where the list says which row is current, a row | |
| 141 | // is pending only when the page on its way is that row's, query and all. | |
| 142 | const loading = navigation.location; | |
| 143 | const pendingHere = loading != null && `${loading.pathname}${loading.search}` === to; | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 144 | return ( |
| 145 | <NavLink | |
| 146 | to={to} | |
| 147 | end={end} | |
| 148 | prefetch="intent" | |
| 149 | className={({ isActive, isPending }) => { | |
| Projects: what a workspace builds and runs, first on every page | 150 | const current = |
| Merge branch 'worktree-agent-ad7c6d88d93adc817' | 151 | lit ?? |
| 152 | (isActive || [also ?? []].flat().some((prefix) => pathname === prefix || pathname.startsWith(prefix + "/"))); | |
| Opening Notifications lights only the row you chose: a sidebar whose rows differ only by their query shows a row as loading only when the page on its way is that row's, not every row on the same path. | 153 | const pending = lit === undefined ? isPending : pendingHere; |
| Usage while free is shown at cost; agents get rustfmt and clippy | 154 | return `group flex h-8 items-center gap-2.5 rounded-md px-2 text-[0.8125rem] transition-colors ${ |
| 155 | current | |
| 156 | ? "bg-raised font-medium text-fg" | |
| Opening Notifications lights only the row you chose: a sidebar whose rows differ only by their query shows a row as loading only when the page on its way is that row's, not every row on the same path. | 157 | : pending |
| Usage while free is shown at cost; agents get rustfmt and clippy | 158 | ? "bg-raised/60 text-fg" |
| 159 | : "text-muted hover:bg-raised/60 hover:text-fg" | |
| 160 | }`; | |
| 161 | }} | |
| 162 | > | |
| 163 | <span className="shrink-0 text-faint group-hover:text-muted">{icon}</span> | |
| 164 | <span className="min-w-0 grow truncate">{children}</span> | |
| 165 | {count != null && count > 0 && ( | |
| 166 | <span className="rounded bg-line px-1.5 text-[0.6875rem] tabular-nums text-muted"> | |
| 167 | {count} | |
| 168 | </span> | |
| 169 | )} | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 170 | {drill && ( |
| 171 | <ChevronRight | |
| 172 | size={14} | |
| 173 | aria-hidden="true" | |
| 174 | className={`-mr-0.5 shrink-0 text-faint transition-opacity ${drill === "hover" ? "opacity-0 group-hover:opacity-100 group-focus-visible:opacity-100" : ""}`} | |
| 175 | /> | |
| 176 | )} | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 177 | </NavLink> |
| 178 | ); | |
| 179 | } | |
| 180 | ||
| Pull requests say where they are live; the project menu shows what is coming | 181 | /** |
| 182 | * Something a project will have, shown where it will live so people can | |
| 183 | * see where g1t is going. Not a link: nothing is behind it yet. | |
| 184 | */ | |
| 185 | function SidebarSoon({ icon, children, about }: { icon: ReactNode; children: ReactNode; about: string }) { | |
| 186 | return ( | |
| Merge branch 'worktree-agent-ae1299e92e4462012' | 187 | <Hint label={about} side="right"> |
| 188 | <div aria-disabled="true" className="flex h-8 cursor-default items-center gap-2.5 rounded-md px-2 text-[0.8125rem] text-faint"> | |
| 189 | <span className="shrink-0 opacity-70">{icon}</span> | |
| 190 | <span className="grow truncate">{children}</span> | |
| 191 | <span className="sr-only">{about}</span> | |
| 192 | <SoonPill /> | |
| 193 | </div> | |
| 194 | </Hint> | |
| Pull requests say where they are live; the project menu shows what is coming | 195 | ); |
| 196 | } | |
| 197 | ||
| The project menu opens by section, and the workspace has its own panel | 198 | /** |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 199 | * A page that is coming, as a link to its roadmap page: faint, with Soon, |
| 200 | * and marked current on any of its section's Soon pages. | |
| The project menu opens by section, and the workspace has its own panel | 201 | */ |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 202 | function SidebarSoonLink({ |
| The project menu opens by section, and the workspace has its own panel | 203 | to, |
| 204 | also, | |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 205 | icon, |
| 206 | about, | |
| Merge branch 'worktree-agent-ad7c6d88d93adc817' | 207 | current: lit, |
| The project menu opens by section, and the workspace has its own panel | 208 | children, |
| 209 | }: { | |
| 210 | to: string; | |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 211 | also?: string[]; |
| 212 | icon: ReactNode; | |
| 213 | about: string; | |
| Merge branch 'worktree-agent-ad7c6d88d93adc817' | 214 | /** Whether it is the current row, when the list works that out itself. */ |
| 215 | current?: boolean; | |
| The project menu opens by section, and the workspace has its own panel | 216 | children: ReactNode; |
| 217 | }) { | |
| 218 | const { pathname } = useLocation(); | |
| 219 | return ( | |
| Sidebar: soon rows and the project row keep their styles inside a hint; tiny amounts read as zero | 220 | // The hint wraps a plain box: Radix's asChild merges className as a |
| 221 | // string, which would break NavLink's className function. | |
| Merge branch 'worktree-agent-ae1299e92e4462012' | 222 | <Hint label={about} side="right"> |
| Sidebar: soon rows and the project row keep their styles inside a hint; tiny amounts read as zero | 223 | <div> |
| The project menu opens by section, and the workspace has its own panel | 224 | <NavLink |
| 225 | to={to} | |
| 226 | prefetch="intent" | |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 227 | className={({ isActive }) => { |
| Merge branch 'worktree-agent-ad7c6d88d93adc817' | 228 | const current = lit ?? (isActive || (also ?? []).some((prefix) => pathname === prefix || pathname.startsWith(prefix + "/"))); |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 229 | return `group flex h-8 items-center gap-2.5 rounded-md px-2 text-[0.8125rem] transition-colors ${ |
| 230 | current ? "bg-raised font-medium text-fg" : "text-faint hover:bg-raised/60 hover:text-muted" | |
| The project menu opens by section, and the workspace has its own panel | 231 | }`; |
| 232 | }} | |
| 233 | > | |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 234 | <span className="shrink-0 opacity-80">{icon}</span> |
| The project menu opens by section, and the workspace has its own panel | 235 | <span className="min-w-0 grow truncate">{children}</span> |
| Usage, Billing settings and prepaid AI credit; fixes from the UX audit | 236 | <SoonPill /> |
| A menu shaped by how g1t works, Soon pages for every promise, and sudo for sales | 237 | </NavLink> |
| Sidebar: soon rows and the project row keep their styles inside a hint; tiny amounts read as zero | 238 | </div> |
| Merge branch 'worktree-agent-ae1299e92e4462012' | 239 | </Hint> |
| The project menu opens by section, and the workspace has its own panel | 240 | ); |
| 241 | } | |
| 242 | ||
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 243 | /** Icons for what spans projects. */ |
| 244 | const WORKSPACE_ICONS: Record<string, ReactNode> = { | |
| 245 | board: <KanbanSquare size={15} />, | |
| 246 | roadmap: <GanttChart size={15} />, | |
| Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member | 247 | teams: <UsersRound size={15} />, |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 248 | packages: <Package size={15} />, |
| 249 | fleet: <Bot size={15} />, | |
| 250 | }; | |
| A menu shaped by how g1t works, Soon pages for every promise, and sudo for sales | 251 | |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 252 | /** The Soon pages of a section, as paths, so its link is current on them. */ |
| 253 | function soonPaths(base: string, section: RoadmapItem["section"]): string[] { | |
| 254 | return roadmapIn(section).map((item) => `${base}/soon/${item.key}`); | |
| A menu shaped by how g1t works, Soon pages for every promise, and sudo for sales | 255 | } |
| 256 | ||
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 257 | function SidebarGroup({ |
| 258 | title, | |
| 259 | action, | |
| 260 | className = "", | |
| 261 | children, | |
| 262 | }: { | |
| 263 | title: string; | |
| 264 | action?: ReactNode; | |
| 265 | className?: string; | |
| 266 | children: ReactNode; | |
| 267 | }) { | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 268 | return ( |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 269 | <section className={className}> |
| Usage while free is shown at cost; agents get rustfmt and clippy | 270 | <div className="mb-1 flex h-6 items-center justify-between px-2"> |
| 271 | <h2 className="text-xs font-medium text-faint">{title}</h2> | |
| 272 | {action} | |
| 273 | </div> | |
| 274 | <div className="space-y-px">{children}</div> | |
| 275 | </section> | |
| 276 | ); | |
| 277 | } | |
| 278 | ||
| Workspace names and icons, and a component kit for every control | 279 | /** What a workspace is called where people read it: its display name, else its slug. */ |
| 280 | function displayName(membership: Membership): string { | |
| 281 | return membership.name?.trim() || membership.slug; | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 282 | } |
| 283 | ||
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 284 | /** |
| 285 | * The fine print, as one quiet row at the foot of the account menu and the | |
| 286 | * visitor's panel: each link a full-height target, left-aligned. In the | |
| 287 | * menu each is a menu item, so the arrow keys reach it. | |
| 288 | */ | |
| 289 | const LEGAL_LINKS: [string, string][] = [ | |
| 290 | ["Policies", "/policies"], | |
| 291 | ["Privacy", "/policies/privacy"], | |
| 292 | ["Security", "/security"], | |
| 293 | ]; | |
| 294 | const LEGAL_LINK = "flex h-7 items-center rounded px-1.5 text-xs text-faint outline-none transition-colors"; | |
| 295 | ||
| 296 | function MenuLegalRow() { | |
| 297 | return ( | |
| 298 | <div role="group" aria-label="Legal" className="flex items-center gap-0.5 px-0.5 pt-0.5"> | |
| 299 | {LEGAL_LINKS.map(([label, to], index) => ( | |
| 300 | <span key={to} className="flex items-center gap-0.5"> | |
| 301 | {index > 0 && ( | |
| 302 | <span aria-hidden="true" className="text-[0.625rem] text-line-strong"> | |
| 303 | · | |
| 304 | </span> | |
| 305 | )} | |
| 306 | <DropdownMenuItem asChild className={`${LEGAL_LINK} py-0 data-highlighted:bg-line data-highlighted:text-fg`}> | |
| 307 | <Link to={to}>{label}</Link> | |
| 308 | </DropdownMenuItem> | |
| 309 | </span> | |
| 310 | ))} | |
| 311 | </div> | |
| 312 | ); | |
| 313 | } | |
| 314 | ||
| 315 | /** Status's row: the live dot and two or three words, fetched when the menu opens. */ | |
| 316 | function StatusSummary({ open }: { open: boolean }) { | |
| 317 | const status = useSiteStatus(open); | |
| 318 | const words = statusTitle(status); | |
| 319 | return ( | |
| 320 | <span className="ml-auto flex min-w-0 items-center gap-1.5 pl-2 text-xs text-faint"> | |
| 321 | {/* The words say it; the dot's own words for screen readers would repeat them. */} | |
| 322 | <span aria-hidden="true" className="flex"> | |
| 323 | <StatusDot state={status?.overall.state ?? null} /> | |
| 324 | </span> | |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 325 | {words ? <span className="truncate">{words}</span> : <Skeleton className="h-3 w-20" />} |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 326 | </span> |
| 327 | ); | |
| 328 | } | |
| 329 | ||
| 330 | /** A menu row: an icon, words, and whatever sits at its end. */ | |
| 331 | const MENU_ROW = "h-9 gap-2.5 px-2.5 text-[0.8125rem]"; | |
| 332 | ||
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 333 | /** |
| 334 | * Your account, at the foot of the dock (or in the header, before you have | |
| 335 | * a workspace): who you are and your status, your profile and settings, | |
| 336 | * and help: the documentation, support, status and the keyboard's | |
| 337 | * shortcuts; then signing out and the fine print. | |
| 338 | */ | |
| 339 | function AccountMenu({ user, side = "right" }: { user: User; side?: "right" | "bottom" }) { | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 340 | const submit = useSubmit(); |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 341 | const [open, setOpen] = useState(false); |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 342 | const [keys, setKeys] = useState(false); |
| One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers | 343 | // Your status's dialog: outside the menu, so the menu closes behind it. |
| 344 | const [editing, setEditing] = useState(false); | |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 345 | // Name, primary address and invites left: asked for once, as soon as the |
| 346 | // pointer or focus reaches the button, so they are there when it opens. | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 347 | const details = useFetcher<AccountMenuData | null>({ key: "account-menu" }); |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 348 | const prefetch = () => { |
| 349 | if (details.state === "idle" && details.data === undefined) details.load("/settings/menu.json"); | |
| 350 | }; | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 351 | useEffect(() => { |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 352 | if (open) prefetch(); |
| 353 | // eslint-disable-next-line react-hooks/exhaustive-deps | |
| 354 | }, [open]); | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 355 | const me = details.data ?? null; |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 356 | // Still on its way: shapes where the words will be, the same size. |
| 357 | const loading = details.data === undefined && details.state !== "idle"; | |
| Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page) | 358 | // While anyone can sign up, listed once the data says there are invites to look back on. |
| 359 | const invitesListed = useInviteOnly() || me?.invites_page === true; | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 360 | const profile = `/u/${user.username}`; |
| Usage while free is shown at cost; agents get rustfmt and clippy | 361 | return ( |
| One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers | 362 | <> |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 363 | <DropdownMenu open={open} onOpenChange={setOpen}> |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 364 | {/* The avatar alone, with a dot that says how others see you (components/presence.tsx). */} |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 365 | <DropdownMenuTrigger |
| One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers | 366 | aria-label={`Account menu for ${shownUsername(user)}`} |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 367 | onPointerEnter={prefetch} |
| 368 | onFocus={prefetch} | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 369 | className="relative flex rounded-full outline-none transition-transform hover:scale-[1.04] focus-visible:ring-2 focus-visible:ring-accent data-[state=open]:ring-2 data-[state=open]:ring-line-strong" |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 370 | > |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 371 | <Avatar name={user.username} image={user.avatar} size={side === "right" ? 32 : 28} /> |
| 372 | <OwnPresenceDot ring={side === "right" ? "var(--color-dock)" : "var(--color-bg)"} className="absolute -right-0.5 -bottom-0.5" /> | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 373 | </DropdownMenuTrigger> |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 374 | <DropdownMenuContent align="end" side={side} sideOffset={side === "right" ? 14 : 6} collisionPadding={8} className="w-[17.5rem] p-1.5"> |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 375 | {/* Who is signed in, and a way to their profile. */} |
| 376 | <DropdownMenuItem asChild className="gap-3 px-2 py-2"> | |
| One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers | 377 | <Link to={profile} aria-label={`${me?.name ?? shownUsername(user)} (@${shownUsername(user)}), your profile`}> |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 378 | <Avatar name={user.username} image={user.avatar} size={36} /> |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 379 | <span className="flex min-w-0 grow flex-col leading-tight" aria-busy={loading}> |
| 380 | {loading ? ( | |
| 381 | <Skeleton className="my-[0.1875rem] h-3.5 w-28" /> | |
| 382 | ) : ( | |
| One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers | 383 | <span className="truncate text-sm font-medium text-fg">{me?.name ?? shownUsername(user)}</span> |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 384 | )} |
| One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers | 385 | <span className="truncate font-mono text-xs text-muted">@{shownUsername(user)}</span> |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 386 | {loading ? ( |
| 387 | <Skeleton className="mt-1 h-3 w-40" /> | |
| 388 | ) : ( | |
| 389 | me?.email && <span className="mt-0.5 truncate text-xs text-faint">{me.email}</span> | |
| 390 | )} | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 391 | </span> |
| Usage while free is shown at cost; agents get rustfmt and clippy | 392 | </Link> |
| 393 | </DropdownMenuItem> | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 394 | <DropdownMenuSeparator className="my-1.5" /> |
| One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers | 395 | {/* Your status, away, and pausing notifications. */} |
| 396 | <DropdownMenuGroup> | |
| 397 | <OwnPresenceItems className="min-h-9 py-1.5 text-[0.8125rem]" onEdit={() => setEditing(true)} /> | |
| 398 | </DropdownMenuGroup> | |
| 399 | <DropdownMenuSeparator className="my-1.5" /> | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 400 | <DropdownMenuGroup> |
| 401 | <DropdownMenuItem asChild className={MENU_ROW}> | |
| 402 | <Link to={profile}> | |
| 403 | <CircleUserRound /> | |
| 404 | Your profile | |
| 405 | </Link> | |
| 406 | </DropdownMenuItem> | |
| 407 | <DropdownMenuItem asChild className={MENU_ROW}> | |
| 408 | <Link to={FIRST_SETTINGS_PAGE}> | |
| 409 | <Settings /> | |
| 410 | Your settings | |
| 411 | </Link> | |
| 412 | </DropdownMenuItem> | |
| Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page) | 413 | {invitesListed && ( |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 414 | <DropdownMenuItem asChild className={MENU_ROW}> |
| 415 | <Link to="/settings/invites"> | |
| 416 | <Ticket /> | |
| Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page) | 417 | {ACCOUNT_SETTINGS.invites.title} |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 418 | {loading && <Skeleton className="ml-auto h-4 w-12 rounded-full" />} |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 419 | {me?.invites_left != null && ( |
| 420 | <span className="ml-auto rounded-full bg-line px-1.5 text-[0.6875rem] tabular-nums text-muted"> | |
| 421 | {me.invites_left} left | |
| 422 | </span> | |
| 423 | )} | |
| 424 | </Link> | |
| 425 | </DropdownMenuItem> | |
| Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page) | 426 | )} |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 427 | </DropdownMenuGroup> |
| 428 | <DropdownMenuSeparator className="my-1.5" /> | |
| 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. | 429 | {/* Auto, Light or Dark, switched in place (lib/theme.ts). */} |
| 430 | <ThemeMenuSwitch /> | |
| 431 | <DropdownMenuSeparator className="my-1.5" /> | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 432 | <DropdownMenuGroup> |
| 433 | <DropdownMenuItem asChild className={MENU_ROW}> | |
| 434 | <a href="https://docs.g1t.sh/"> | |
| 435 | <BookOpen /> | |
| 436 | Documentation | |
| 437 | </a> | |
| 438 | </DropdownMenuItem> | |
| 439 | <DropdownMenuItem asChild className={MENU_ROW}> | |
| 440 | <Link to="/support"> | |
| 441 | <LifeBuoy /> | |
| 442 | Support | |
| 443 | </Link> | |
| 444 | </DropdownMenuItem> | |
| 445 | <DropdownMenuItem asChild className={MENU_ROW}> | |
| 446 | <a href={STATUS_URL}> | |
| 447 | <Activity /> | |
| 448 | Status | |
| 449 | <StatusSummary open={open} /> | |
| 450 | </a> | |
| 451 | </DropdownMenuItem> | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 452 | <DropdownMenuItem className={MENU_ROW} onSelect={() => setKeys(true)}> |
| 453 | <Keyboard /> | |
| 454 | Keyboard shortcuts | |
| 455 | <PaletteKey className="ml-auto font-sans text-xs text-faint" /> | |
| 456 | </DropdownMenuItem> | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 457 | </DropdownMenuGroup> |
| 458 | <DropdownMenuSeparator className="my-1.5" /> | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 459 | {/* Submitted from here: the menu closes on select, and a button |
| 460 | that has left the page cannot submit a form. */} | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 461 | <DropdownMenuItem className={MENU_ROW} onSelect={() => submit(null, { method: "post", action: "/logout" })}> |
| Usage while free is shown at cost; agents get rustfmt and clippy | 462 | <LogOut /> |
| 463 | Sign out | |
| 464 | </DropdownMenuItem> | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 465 | <DropdownMenuSeparator className="my-1.5" /> |
| 466 | <MenuLegalRow /> | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 467 | </DropdownMenuContent> |
| 468 | </DropdownMenu> | |
| One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers | 469 | <StatusDialog open={editing} onOpenChange={setEditing} /> |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 470 | <ShortcutsDialog open={keys} onOpenChange={setKeys} /> |
| One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers | 471 | </> |
| Usage while free is shown at cost; agents get rustfmt and clippy | 472 | ); |
| 473 | } | |
| 474 | ||
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 475 | /** |
| Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar | 476 | * A workspace's settings pages, which the sidebar drills into: how it is |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 477 | * set up and connected (guardrails, secrets, integrations, |
| Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar | 478 | * webhooks), what it pays, its repositories, tokens and record. The main |
| 479 | * list keeps the places work happens and who belongs; every member can | |
| 480 | * still open these. | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 481 | */ |
| Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar | 482 | const SETTINGS_PAGE = |
| Merge branch 'worktree-agent-ad7c6d88d93adc817' | 483 | new RegExp(`^/([^/]+)/-/(${SETTINGS_PAGES.join("|")})(/|$)`); |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 484 | /** A project's settings pages, which the project's menu drills into. */ |
| Project settings move into the sidebar, grouped, with a heading per page | 485 | const REPO_SETTINGS_PAGE = /^\/([^/]+)\/([^/-][^/]*)\/settings(\/|$)/; |
| Usage while free is shown at cost; agents get rustfmt and clippy | 486 | |
| 487 | /** | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 488 | * The sidebar's lists are a stack, the way a phone pushes a screen: one |
| 489 | * drilled into slides in from the right over the full width, while the one | |
| 490 | * it covers drifts a quarter of the way left and fades, both on one long | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 491 | * ease-out, the fade quicker than the move so the two never blur together. |
| 492 | * Going back reverses it. | |
| 493 | */ | |
| 494 | const LAYER = | |
| 495 | "absolute inset-0 [transition:translate_380ms_cubic-bezier(0.32,0.72,0,1),opacity_220ms_ease-out] will-change-[translate,opacity] motion-reduce:transition-none"; | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 496 | /** One list, filling its layer. */ |
| Usage while free is shown at cost; agents get rustfmt and clippy | 497 | const PANEL = "h-full overflow-y-auto px-2 pb-4"; |
| 498 | ||
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 499 | /** One list in the stack: what it is, and its rows. */ |
| 500 | type Level = { key: string; node: ReactNode }; | |
| 501 | ||
| 502 | /** True once the page has hydrated, so what the server drew never animates in. */ | |
| 503 | function useHydrated(): boolean { | |
| 504 | const [hydrated, setHydrated] = useState(false); | |
| 505 | useEffect(() => setHydrated(true), []); | |
| 506 | return hydrated; | |
| 507 | } | |
| 508 | ||
| 509 | /** | |
| 510 | * Drilling in and out of the sidebar's lists. `trail` is the way from the | |
| 511 | * main list to the one shown, worked out from the address, so a link | |
| 512 | * straight to a settings page opens the sidebar already drilled in, and | |
| 513 | * leaving it comes back out. Lists deeper than the one shown stay in | |
| 514 | * place, off to the right, so going back slides them away rather than | |
| 515 | * dropping them. Moving to a list at the same depth (a workspace's settings | |
| 516 | * to a project) fades the new one in where it is. | |
| 517 | */ | |
| 518 | function Drill({ trail }: { trail: Level[] }) { | |
| 519 | const depth = trail.length - 1; | |
| 520 | const hydrated = useHydrated(); | |
| 521 | const stack = useRef<Level[]>(trail); | |
| 522 | const before = stack.current; | |
| 523 | const within = trail.every((level, index) => before[index]?.key === level.key); | |
| 524 | stack.current = within ? [...trail, ...before.slice(trail.length)] : trail; | |
| 525 | const levels = stack.current; | |
| 526 | // What was showing last time, to tell drilling in from moving across. | |
| 527 | const shown = useRef({ depth, keys: levels.map((level) => level.key) }); | |
| 528 | useEffect(() => { | |
| 529 | shown.current = { depth, keys: levels.map((level) => level.key) }; | |
| 530 | }); | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 531 | return ( |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 532 | <div className="relative min-h-0 grow overflow-hidden"> |
| 533 | {levels.map((level, index) => { | |
| 534 | const current = index === depth; | |
| 535 | const place = | |
| 536 | index < depth | |
| 537 | ? "pointer-events-none -translate-x-1/4 opacity-0" | |
| 538 | : current | |
| 539 | ? "translate-x-0 opacity-100" | |
| 540 | : "pointer-events-none translate-x-full opacity-0"; | |
| 541 | // A list that was not there before arrives: from the right when | |
| 542 | // drilling in, in place when moving across. | |
| 543 | const arriving = hydrated && current && !shown.current.keys.includes(level.key); | |
| 544 | const enter = arriving | |
| 545 | ? depth > shown.current.depth | |
| 546 | ? "starting:translate-x-full starting:opacity-0" | |
| 547 | : "starting:opacity-0" | |
| 548 | : ""; | |
| 549 | return ( | |
| 550 | <div key={level.key} className={`${LAYER} ${place} ${enter}`} inert={!current} aria-hidden={!current || undefined}> | |
| 551 | {level.node} | |
| 552 | </div> | |
| 553 | ); | |
| 554 | })} | |
| 555 | </div> | |
| 556 | ); | |
| 557 | } | |
| 558 | ||
| 559 | /** | |
| 560 | * The row at the top of a list drilled into: the list's name, which goes | |
| 561 | * back out, and what it belongs to, faint at the end. | |
| 562 | */ | |
| 563 | function BackRow({ to, label, context }: { to: string; label: ReactNode; context?: ReactNode }) { | |
| 564 | return ( | |
| 565 | <Link | |
| 566 | to={to} | |
| 567 | prefetch="intent" | |
| 568 | className="group mt-3 flex h-8 items-center gap-1.5 rounded-md pr-2 pl-1 text-[0.8125rem] font-medium text-fg transition-colors hover:bg-raised/60" | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 569 | > |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 570 | <ChevronLeft size={16} className="shrink-0 text-faint transition-transform group-hover:-translate-x-0.5 group-hover:text-muted" /> |
| 571 | <span className="min-w-0 shrink-0 truncate">{label}</span> | |
| 572 | {context && ( | |
| 573 | <span className="ml-auto min-w-0 truncate pl-2 font-mono text-[0.6875rem] font-normal text-faint">{context}</span> | |
| 574 | )} | |
| 575 | </Link> | |
| 576 | ); | |
| 577 | } | |
| 578 | ||
| 579 | /** A thin rule between groups of a list. */ | |
| 580 | function Rule() { | |
| 581 | return <div role="separator" className="mx-2 my-2.5 h-px bg-line" />; | |
| 582 | } | |
| 583 | ||
| Navigation: the workspace's own page with tabs, pins and recent in the sidebar | 584 | /** A quiet heading inside a group: Pinned, Recent. */ |
| 585 | function SidebarSubhead({ children }: { children: ReactNode }) { | |
| 586 | return <h3 className="px-2 pt-1.5 pb-0.5 text-[0.6875rem] font-medium tracking-wide text-faint">{children}</h3>; | |
| 587 | } | |
| 588 | ||
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 589 | /** |
| Navigation: the workspace's own page with tabs, pins and recent in the sidebar | 590 | * The workspace's projects as the sidebar keeps them, however many there |
| 591 | * are: the person's pins in their order, what they opened last, and the | |
| 592 | * way to all of them. Pins move by dragging, or with Alt and the arrow | |
| 593 | * keys; the projects service keeps the order. | |
| 594 | */ | |
| Merge branch 'worktree-agent-ad7c6d88d93adc817' | 595 | function SidebarProjects({ slug, shell, current }: { slug: string; shell: ShellData; current: boolean }) { |
| Navigation: the workspace's own page with tabs, pins and recent in the sidebar | 596 | const reorder = useFetcher({ key: `pins:${slug}` }); |
| 597 | const saved = shell.pinned ?? []; | |
| 598 | // While a new order is on its way, it shows as made. | |
| 599 | const asked = reorder.formData?.get("intent") === "reorder" ? reorder.formData.getAll("slug").map(String) : null; | |
| 600 | const pinned = asked | |
| 601 | ? asked.map((name) => saved.find((project) => project.name === name)).filter((project): project is ShortcutProject => project != null) | |
| 602 | : saved; | |
| 603 | const active = shell.repo ? { namespace: shell.repo.namespace, name: shell.repo.name, isPrivate: false } : null; | |
| 604 | const recent = recentWith(shell.recent ?? [], pinned, active, slug); | |
| 605 | const [dragging, setDragging] = useState<number | null>(null); | |
| 606 | const move = (from: number, by: number) => { | |
| 607 | const next = movedPin(pinned, from, by); | |
| 608 | if (!next) return; | |
| 609 | const form = new FormData(); | |
| 610 | form.set("intent", "reorder"); | |
| 611 | for (const project of next) form.append("slug", project.name); | |
| 612 | reorder.submit(form, { method: "post", action: `/${slug}/-/pins` }); | |
| 613 | }; | |
| Previews build from any branch; Agent in place of Ask AI; pin from the sidebar | 614 | // Each row pins or unpins in place: the pin shows on hover or focus, and |
| 615 | // stays shown on a pinned row's hover so it reads as "unpin". | |
| 616 | const row = (project: ShortcutProject, isPinned: boolean) => ( | |
| 617 | <div className="group/row relative"> | |
| 618 | <SidebarLink to={`/${project.namespace}/${project.name}`} icon={project.isPrivate ? <Lock size={15} /> : <Box size={15} />} drill="hover"> | |
| 619 | <span className="block truncate pr-6">{project.title ?? project.name}</span> | |
| 620 | </SidebarLink> | |
| 621 | <PinButton | |
| 622 | workspace={slug} | |
| 623 | slug={project.name} | |
| 624 | name={project.title ?? project.name} | |
| 625 | pinned={isPinned} | |
| 626 | small | |
| 627 | className="absolute top-1/2 right-6 -translate-y-1/2 opacity-0 transition-opacity group-hover/row:opacity-100 focus-within:opacity-100 [@media(hover:none)]:opacity-100" | |
| 628 | /> | |
| 629 | </div> | |
| Navigation: the workspace's own page with tabs, pins and recent in the sidebar | 630 | ); |
| 631 | return ( | |
| 632 | <SidebarGroup | |
| 633 | title="Projects" | |
| 634 | action={ | |
| New project and Import from GitHub work in the workspace you're in, as the sidebar shows it, with no workspace to pick on the page; a link that names another of your workspaces switches you to it first. The projects guide says so. | 635 | <Link to="/new" aria-label="New project" className="rounded p-0.5 text-faint hover:bg-raised hover:text-fg"> |
| Navigation: the workspace's own page with tabs, pins and recent in the sidebar | 636 | <Plus size={13} /> |
| 637 | </Link> | |
| 638 | } | |
| 639 | > | |
| Previews build from any branch; Agent in place of Ask AI; pin from the sidebar | 640 | {/* Only there once something is pinned: each row below has its own pin. */} |
| 641 | {pinned.length > 0 && ( | |
| 642 | <> | |
| 643 | <SidebarSubhead>Pinned</SidebarSubhead> | |
| Navigation: the workspace's own page with tabs, pins and recent in the sidebar | 644 | <ul aria-label="Pinned projects" className="space-y-px"> |
| 645 | {pinned.map((project, index) => ( | |
| 646 | <li | |
| 647 | key={project.name} | |
| 648 | draggable={pinned.length > 1} | |
| 649 | onDragStart={(event) => { | |
| 650 | setDragging(index); | |
| 651 | event.dataTransfer.effectAllowed = "move"; | |
| 652 | }} | |
| 653 | onDragOver={(event) => { | |
| 654 | if (dragging != null) event.preventDefault(); | |
| 655 | }} | |
| 656 | onDrop={(event) => { | |
| 657 | event.preventDefault(); | |
| 658 | if (dragging != null && dragging !== index) move(dragging, index - dragging); | |
| 659 | setDragging(null); | |
| 660 | }} | |
| 661 | onDragEnd={() => setDragging(null)} | |
| 662 | onKeyDown={(event) => { | |
| 663 | if (!event.altKey || (event.key !== "ArrowUp" && event.key !== "ArrowDown")) return; | |
| 664 | event.preventDefault(); | |
| 665 | move(index, event.key === "ArrowUp" ? -1 : 1); | |
| 666 | }} | |
| 667 | className={`group/pin relative ${dragging === index ? "opacity-50" : ""}`} | |
| 668 | > | |
| Previews build from any branch; Agent in place of Ask AI; pin from the sidebar | 669 | {row(project, true)} |
| Navigation: the workspace's own page with tabs, pins and recent in the sidebar | 670 | {pinned.length > 1 && ( |
| Merge branch 'worktree-agent-ae1299e92e4462012' | 671 | <Hint label="Drag, or Alt and an arrow key, to reorder" side="right"> |
| 672 | <span className="absolute top-1/2 -left-1.5 -translate-y-1/2 cursor-grab text-faint opacity-0 transition-opacity group-hover/pin:opacity-100"> | |
| 673 | <GripVertical size={12} aria-hidden="true" /> | |
| 674 | </span> | |
| 675 | </Hint> | |
| Navigation: the workspace's own page with tabs, pins and recent in the sidebar | 676 | )} |
| 677 | </li> | |
| 678 | ))} | |
| 679 | </ul> | |
| Previews build from any branch; Agent in place of Ask AI; pin from the sidebar | 680 | </> |
| Navigation: the workspace's own page with tabs, pins and recent in the sidebar | 681 | )} |
| 682 | {recent.length > 0 && ( | |
| 683 | <> | |
| 684 | <SidebarSubhead>Recent</SidebarSubhead> | |
| 685 | {recent.map((project) => ( | |
| Previews build from any branch; Agent in place of Ask AI; pin from the sidebar | 686 | <div key={`${project.namespace}/${project.name}`}>{row(project, false)}</div> |
| Navigation: the workspace's own page with tabs, pins and recent in the sidebar | 687 | ))} |
| 688 | </> | |
| 689 | )} | |
| 690 | <div className="pt-1"> | |
| Merge branch 'worktree-agent-ad7c6d88d93adc817' | 691 | <SidebarLink to={`/${slug}/-/projects`} icon={<LayoutGrid size={15} />} count={shell.repos.length} current={current}> |
| Navigation: the workspace's own page with tabs, pins and recent in the sidebar | 692 | All projects |
| 693 | </SidebarLink> | |
| 694 | </div> | |
| 695 | </SidebarGroup> | |
| 696 | ); | |
| 697 | } | |
| 698 | ||
| Merge branch 'worktree-agent-ad7c6d88d93adc817' | 699 | /** Insights, coming: the workspace's own page says what it will be. */ |
| 700 | const INSIGHTS = roadmapItem("insights"); | |
| 701 | ||
| Usage while free is shown at cost; agents get rustfmt and clippy | 702 | /** |
| 703 | * What the repository menu needs. Known from the address before the page's | |
| 704 | * data arrives, so the menu is right from the first frame; the counts fill | |
| 705 | * in once it does. | |
| 706 | */ | |
| 707 | type MenuRepo = { | |
| 708 | namespace: string; | |
| 709 | name: string; | |
| 710 | member: boolean; | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 711 | /** Whether they see its settings; from the repository's page once it loads. */ |
| 712 | settings?: boolean; | |
| 713 | /** What they may do there, once the repository's page loads. */ | |
| 714 | can?: Abilities; | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 715 | issues?: number; |
| 716 | pulls?: number; | |
| 717 | }; | |
| 718 | ||
| 719 | function sameRepo(a: { namespace: string; name: string } | null, b: { namespace: string; name: string } | null) { | |
| 720 | return ( | |
| 721 | a != null && | |
| 722 | b != null && | |
| 723 | a.namespace.toLowerCase() === b.namespace.toLowerCase() && | |
| 724 | a.name.toLowerCase() === b.name.toLowerCase() | |
| 725 | ); | |
| 726 | } | |
| 727 | ||
| 728 | /** | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 729 | * A project's own list, drilled into while you are in it: everything about |
| 730 | * the project, running and its code, and nothing else, with the way back | |
| 731 | * out to all of them. | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 732 | */ |
| Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put | 733 | function RepoMenu({ |
| 734 | repo, | |
| 735 | isPrivate, | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 736 | back, |
| Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put | 737 | }: { |
| 738 | repo: MenuRepo; | |
| 739 | isPrivate: boolean; | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 740 | /** Where the way back leads: the workspace's projects, mission control, or Explore. */ |
| 741 | back: { to: string; label: string }; | |
| Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put | 742 | }) { |
| Usage while free is shown at cost; agents get rustfmt and clippy | 743 | const base = `/${repo.namespace}/${repo.name}`; |
| Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put | 744 | // What a member sees, and what everyone who can see the project does. |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 745 | const shows = new Set(projectPages(repo.member, repo.can)); |
| Usage while free is shown at cost; agents get rustfmt and clippy | 746 | return ( |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 747 | <nav aria-label={`${repo.namespace}/${repo.name}`} className={PANEL}> |
| 748 | <BackRow to={back.to} label={back.label} /> | |
| Merge branch 'worktree-agent-ae1299e92e4462012' | 749 | <Hint label="Overview" side="right"> |
| Sidebar: soon rows and the project row keep their styles inside a hint; tiny amounts read as zero | 750 | <div> |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 751 | <NavLink |
| Usage while free is shown at cost; agents get rustfmt and clippy | 752 | to={base} |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 753 | end |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 754 | prefetch="intent" |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 755 | className={({ isActive }) => |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 756 | `mt-2 flex items-center gap-2 rounded-md px-2 py-1.5 transition-colors ${isActive ? "bg-raised" : "hover:bg-raised/60"}` |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 757 | } |
| Usage while free is shown at cost; agents get rustfmt and clippy | 758 | > |
| 759 | <span className="flex size-6 shrink-0 items-center justify-center rounded-md bg-raised text-muted ring-1 ring-line"> | |
| Projects: what a workspace builds and runs, first on every page | 760 | {isPrivate ? <Lock size={13} /> : <Box size={13} />} |
| Usage while free is shown at cost; agents get rustfmt and clippy | 761 | </span> |
| 762 | <span className="min-w-0 truncate font-mono text-[0.8125rem]"> | |
| 763 | <span className="text-faint">{repo.namespace}/</span> | |
| 764 | <span className="font-semibold text-fg">{repo.name}</span> | |
| 765 | </span> | |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 766 | </NavLink> |
| Sidebar: soon rows and the project row keep their styles inside a hint; tiny amounts read as zero | 767 | </div> |
| Merge branch 'worktree-agent-ae1299e92e4462012' | 768 | </Hint> |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 769 | {/* A project's pages, in the order people use them. A page with more |
| 770 | than one view shows them as tabs across its top. */} | |
| 771 | <Rule /> | |
| 772 | <div className="space-y-px"> | |
| Compare: any two branches, the commits one has that the other does not, and the diff, with Open a pull request | 773 | <SidebarLink to={`${base}/code`} also={[`${base}/tree`, `${base}/blob`, `${base}/commits`, `${base}/commit`, `${base}/branches`, `${base}/tags`, `${base}/compare`, ...soonPaths(base, "Code")]} icon={<Code2 size={15} />}> |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 774 | Code |
| 775 | </SidebarLink> | |
| Usage, Billing settings and prepaid AI credit; fixes from the UX audit | 776 | <SidebarLink to={`${base}/issues`} also={[`${base}/plans`, `${base}/milestones`, `${base}/labels`, ...soonPaths(base, "Issues")]} icon={<CircleDot size={15} />} count={repo.issues}> |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 777 | Issues |
| 778 | </SidebarLink> | |
| 779 | <SidebarLink to={`${base}/pulls`} also={[`${base}/pull`, `${base}/queue`]} icon={<GitPullRequest size={15} />} count={repo.pulls}> | |
| 780 | Pull requests | |
| 781 | </SidebarLink> | |
| Agents and memory, checks and conflicts, profiles, slug renames, custom domains | 782 | <SidebarLink to={`${base}/agents`} also={[`${base}/sessions`, `${base}/memory`, ...soonPaths(base, "Agents")]} icon={<Bot size={15} />}> |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 783 | Agents |
| Agents and memory, checks and conflicts, profiles, slug renames, custom domains | 784 | </SidebarLink> |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 785 | <SidebarLink to={`${base}/actions`} icon={<PlayCircle size={15} />}> |
| 786 | Workflows | |
| Projects: what a workspace builds and runs, first on every page | 787 | </SidebarLink> |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 788 | </div> |
| 789 | <Rule /> | |
| 790 | <div className="space-y-px"> | |
| Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put | 791 | {shows.has("deployments") ? ( |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 792 | <SidebarLink to={`${base}/deployments`} also={soonPaths(base, "Deployments")} icon={<Rocket size={15} />}> |
| 793 | Deployments | |
| 794 | </SidebarLink> | |
| 795 | ) : null} | |
| Observability gets its own page; tabs never overflow | 796 | <SidebarSoonLink to={`${base}/soon/logs`} also={soonPaths(base, "Observability")} icon={<Activity size={15} />} about="Logs, errors, uptime and analytics of the project's deployed apps."> |
| 797 | Observability | |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 798 | </SidebarSoonLink> |
| Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put | 799 | {shows.has("security") ? ( |
| Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API | 800 | <SidebarLink to={`${base}/security`} also={soonPaths(base, "Security")} icon={<ShieldCheck size={15} />}> |
| 801 | Security | |
| 802 | </SidebarLink> | |
| 803 | ) : null} | |
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 804 | <SidebarLink |
| 805 | to={`${base}/contributors`} | |
| 806 | also={[`${base}/activity`, `${base}/stargazers`, ...soonPaths(base, "Insights")]} | |
| 807 | icon={<BarChart3 size={15} />} | |
| 808 | > | |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 809 | Insights |
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 810 | </SidebarLink> |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 811 | </div> |
| 812 | {(repo.settings ?? shows.has("settings")) && ( | |
| 813 | <> | |
| 814 | <Rule /> | |
| 815 | <SidebarLink to={`${base}/settings`} icon={<Settings size={15} />} drill> | |
| A flat project menu with Code first, views as tabs, and Stripe for every owner | 816 | Settings |
| 817 | </SidebarLink> | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 818 | </> |
| 819 | )} | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 820 | </nav> |
| 821 | ); | |
| 822 | } | |
| 823 | ||
| Project settings move into the sidebar, grouped, with a heading per page | 824 | /** |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 825 | * A project's settings, drilled into from its list: what is about running |
| 826 | * it, then its agents, then its code and who can reach it. The way back | |
| 827 | * leads to the project. | |
| Project settings move into the sidebar, grouped, with a heading per page | 828 | */ |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 829 | function RepoSettingsMenu({ repo }: { repo: MenuRepo }) { |
| Project settings move into the sidebar, grouped, with a heading per page | 830 | const base = `/${repo.namespace}/${repo.name}`; |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 831 | // Each page shows to the roles that can use it, once the role is known. |
| 832 | const shows = (page: string) => !repo.can || repo.can[SETTINGS_CAPABILITY[page] ?? "administer"]; | |
| 833 | const running = shows("deployments"); | |
| 834 | const agents = shows("agents") || shows("guardrails"); | |
| Project settings move into the sidebar, grouped, with a heading per page | 835 | return ( |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 836 | <nav aria-label={`${repo.namespace}/${repo.name} settings`} className={PANEL}> |
| 837 | <BackRow to={base} label="Settings" context={`${repo.namespace}/${repo.name}`} /> | |
| 838 | {shows("") && ( | |
| 839 | <div className="mt-2 space-y-px"> | |
| 840 | <SidebarLink to={`${base}/settings`} end icon={<Settings size={15} />}> | |
| 841 | General | |
| 842 | </SidebarLink> | |
| 843 | </div> | |
| 844 | )} | |
| 845 | {running && ( | |
| 846 | <> | |
| 847 | {shows("") && <Rule />} | |
| 848 | <div className={shows("") ? "space-y-px" : "mt-2 space-y-px"}> | |
| 849 | <SidebarLink to={`${base}/settings/deployments`} icon={<Rocket size={15} />}> | |
| 850 | Deployments | |
| 851 | </SidebarLink> | |
| 852 | <SidebarLink to={`${base}/settings/domains`} icon={<Globe size={15} />}> | |
| 853 | Domains | |
| 854 | </SidebarLink> | |
| 855 | </div> | |
| 856 | </> | |
| 857 | )} | |
| 858 | {agents && ( | |
| 859 | <> | |
| 860 | <Rule /> | |
| 861 | <div className="space-y-px"> | |
| 862 | {shows("agents") && ( | |
| 863 | <SidebarLink to={`${base}/settings/agents`} icon={<Bot size={15} />}> | |
| 864 | Agents | |
| 865 | </SidebarLink> | |
| 866 | )} | |
| 867 | {shows("guardrails") && ( | |
| 868 | <SidebarLink to={`${base}/settings/guardrails`} icon={<ShieldCheck size={15} />}> | |
| 869 | Guardrails | |
| 870 | </SidebarLink> | |
| 871 | )} | |
| 872 | </div> | |
| 873 | </> | |
| 874 | )} | |
| 875 | <Rule /> | |
| 876 | <div className="space-y-px"> | |
| 877 | {shows("repository") && ( | |
| 878 | <SidebarLink to={`${base}/settings/repository`} icon={<BookMarked size={15} />}> | |
| 879 | Repository | |
| 880 | </SidebarLink> | |
| 881 | )} | |
| Merge branch 'mirroring' into artifacts-mode | 882 | {shows("mirroring") && ( |
| 883 | <SidebarLink to={`${base}/settings/mirroring`} icon={<ArrowLeftRight size={15} />}> | |
| 884 | Mirroring | |
| 885 | </SidebarLink> | |
| 886 | )} | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 887 | {shows("access") && ( |
| 888 | <SidebarLink to={`${base}/settings/access`} icon={<Users size={15} />}> | |
| 889 | Access | |
| 890 | </SidebarLink> | |
| 891 | )} | |
| Merge branch 'worktree-agent-a5a5de74d8863d554' into worktree-agent-a16631325aecf58ca | 892 | {shows("keys") && ( |
| 893 | <SidebarLink to={`${base}/settings/keys`} icon={<KeyRound size={15} />}> | |
| 894 | Deploy keys | |
| 895 | </SidebarLink> | |
| 896 | )} | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 897 | {shows("branches") && ( |
| 898 | <SidebarLink to={`${base}/settings/branches`} icon={<GitBranch size={15} />}> | |
| 899 | Branches and merging | |
| 900 | </SidebarLink> | |
| 901 | )} | |
| Merge rulesets: branch and tag rules, agent-first, enforced on push and merge | 902 | {shows("rules") && ( |
| 903 | <SidebarLink to={`${base}/settings/rules`} icon={<Scale size={15} />}> | |
| 904 | Rules | |
| 905 | </SidebarLink> | |
| 906 | )} | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 907 | {shows("secrets") && ( |
| 908 | <SidebarLink to={`${base}/settings/secrets`} icon={<Lock size={15} />}> | |
| 909 | Secrets and variables | |
| 910 | </SidebarLink> | |
| 911 | )} | |
| Merge branch 'worktree-agent-a3abfcce648e87dca' | 912 | {shows("actions") && ( |
| 913 | <SidebarLink to={`${base}/settings/actions`} icon={<PlayCircle size={15} />}> | |
| 914 | Actions | |
| 915 | </SidebarLink> | |
| 916 | )} | |
| 917 | {shows("environments") && ( | |
| 918 | <SidebarLink to={`${base}/settings/environments`} icon={<Layers size={15} />}> | |
| 919 | Environments | |
| 920 | </SidebarLink> | |
| 921 | )} | |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 922 | {shows("runners") && ( |
| 923 | <SidebarLink to={`${base}/settings/runners`} icon={<ServerCog size={15} />}> | |
| 924 | Runners | |
| 925 | </SidebarLink> | |
| 926 | )} | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 927 | {shows("webhooks") && ( |
| 928 | <SidebarLink to={`${base}/settings/webhooks`} icon={<Webhook size={15} />}> | |
| 929 | Webhooks | |
| 930 | </SidebarLink> | |
| 931 | )} | |
| 932 | </div> | |
| Project settings move into the sidebar, grouped, with a heading per page | 933 | </nav> |
| 934 | ); | |
| 935 | } | |
| 936 | ||
| Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page) | 937 | /** |
| 938 | * Whether the menus list Settings → Invites (invites to g1t): always while | |
| 939 | * sign-up takes an invite; once anyone can sign up, only for someone with | |
| 940 | * invites already made to look back on, which the account menu's data says. | |
| 941 | */ | |
| 942 | function useInvitesListed(): boolean { | |
| 943 | const inviteOnly = useInviteOnly(); | |
| 944 | const details = useFetcher<AccountMenuData | null>({ key: "account-menu" }); | |
| 945 | useEffect(() => { | |
| 946 | if (!inviteOnly && details.state === "idle" && details.data === undefined) details.load("/settings/menu.json"); | |
| 947 | // eslint-disable-next-line react-hooks/exhaustive-deps | |
| 948 | }, [inviteOnly]); | |
| 949 | return inviteOnly || details.data?.invites_page === true; | |
| 950 | } | |
| 951 | ||
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 952 | /** Your own settings, drilled into from Your settings: one page each. */ |
| 953 | function AccountSettingsMenu({ username }: { username: string }) { | |
| Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page) | 954 | const invites = useInvitesListed(); |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 955 | const link = (page: AccountSettingsPage, icon: ReactNode) => ( |
| 956 | <SidebarLink to={`/settings/${page}`} icon={icon}> | |
| 957 | {ACCOUNT_SETTINGS[page].title} | |
| 958 | </SidebarLink> | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 959 | ); |
| 960 | return ( | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 961 | <nav aria-label="Your settings" className={PANEL}> |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 962 | <BackRow to="/" label="Your settings" context={username} /> |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 963 | <div className="mt-2 space-y-px"> |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 964 | {link("profile", <CircleUserRound size={15} />)} |
| 965 | {link("emails", <Mail size={15} />)} | |
| Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page) | 966 | {invites && link("invites", <Ticket size={15} />)} |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 967 | </div> |
| 968 | <Rule /> | |
| 969 | <div className="space-y-px"> | |
| 970 | {link("keys", <Fingerprint size={15} />)} | |
| 971 | {link("tokens", <KeyRound size={15} />)} | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 972 | </div> |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 973 | <Rule /> |
| 974 | <div className="space-y-px"> | |
| Integrations are a directory of connectors, for a workspace and for each person | 975 | {link("integrations", <Blocks size={15} />)} |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 976 | {link("github", <GithubMark className="size-[15px]" />)} |
| 977 | {link("applications", <Plug size={15} />)} | |
| 978 | </div> | |
| 979 | <Rule /> | |
| 980 | <div className="space-y-px"> | |
| Merge main (membership, two-factor, GitHub repo roles) into tokens | 981 | {link("two-factor", <ShieldCheck size={15} />)} |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 982 | {link("security-log", <History size={15} />)} |
| 983 | </div> | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 984 | </nav> |
| 985 | ); | |
| 986 | } | |
| 987 | ||
| Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put | 988 | /** |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 989 | * Code's sidebar: its Overview, the projects, what spans them and what is |
| 990 | * coming; in a project, drilled into the project's own list, and its | |
| 991 | * settings one level further in. The address says which, so a link | |
| 992 | * straight to a project opens the sidebar already drilled in. | |
| Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put | 993 | */ |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 994 | function CodeSidebar({ |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 995 | user, |
| 996 | shell, | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 997 | missing = false, |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 998 | }: { |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 999 | user: User; |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 1000 | shell: ShellData; |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 1001 | /** The page is a 404: the address names nothing the viewer can see. */ |
| 1002 | missing?: boolean; | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 1003 | }) { |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1004 | const ws = shell.workspace; |
| 1005 | const { pathname } = useLocation(); | |
| 1006 | const going = useNavigation().location?.pathname; | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 1007 | // Where the sidebar is drilled to follows the page being gone to, so it |
| 1008 | // moves as the link is followed, not once the page arrives. | |
| 1009 | const target = going ?? pathname; | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 1010 | // On a 404, the address is not a place: no list is drilled into from it, |
| 1011 | // except the project's own when the project is real and visible and only | |
| 1012 | // something inside it is missing (a file, a commit, an issue). | |
| 1013 | const lost = missing && going == null; | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1014 | const active = shell.repo; |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 1015 | // In a repository, or on the way into one, its own list. |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1016 | const repoPath = /^\/([^/]+)\/([^/-][^/]*)(\/|$)/.exec(target); |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1017 | const reserved = new Set(["settings", "explore", "search", "new", "u", "pricing", "avatars", "workspaces", "login", "logout", "register", "verify", "forgot", "reset", "device", "oauth", "policies", "security", "support", "status", "invite", "notifications", "inbox", ".well-known"]); |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 1018 | // An invitation to a repository is answered before its menu means anything. |
| 1019 | const inRepo = | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 1020 | repoPath != null && |
| 1021 | !reserved.has(repoPath[1]) && | |
| 1022 | repoPath[2] !== "-" && | |
| 1023 | !/^\/[^/]+\/[^/]+\/invitations\/?$/.test(target) && | |
| 1024 | (!lost || sameRepo(active, { namespace: repoPath[1]!, name: repoPath[2]! })); | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 1025 | // A project's settings, one level further in. |
| Project settings move into the sidebar, grouped, with a heading per page | 1026 | const inRepoSettings = inRepo && REPO_SETTINGS_PAGE.test(target); |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1027 | // The repository the menu is for: the one loaded if it is the one being |
| 1028 | // gone to, else what the address says, at once. | |
| 1029 | const targetRepo = inRepo && repoPath ? { namespace: repoPath[1], name: repoPath[2] } : null; | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 1030 | const guessed: MenuRepo | null = targetRepo |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1031 | ? sameRepo(active, targetRepo) |
| 1032 | ? active | |
| 1033 | : { | |
| 1034 | ...targetRepo, | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1035 | member: (user.workspaces ?? []).some((m) => m.slug === targetRepo.namespace.toLowerCase()), |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1036 | } |
| 1037 | : null; | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 1038 | // The viewer's role there, from the repository's page once it has loaded. |
| 1039 | const page = useRouteLoaderData("routes/repo/layout") as | |
| 1040 | | { repo?: { namespace: string; name: string }; access?: ViewerAccess } | |
| 1041 | | undefined; | |
| 1042 | const menuRepo: MenuRepo | null = | |
| 1043 | guessed && page?.access && page.repo && sameRepo(page.repo, guessed) | |
| 1044 | ? { ...guessed, member: page.access.insider, settings: seesSettings(page.access), can: page.access.can } | |
| 1045 | : guessed; | |
| 1046 | ||
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1047 | // The way from Code's list to the one shown. |
| 1048 | const trail: Level[] = [{ key: "main", node: ws ? <CodeMenu shell={shell} slug={ws.slug} /> : null }]; | |
| 1049 | if (menuRepo) { | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 1050 | const key = `repo:${menuRepo.namespace}/${menuRepo.name}`.toLowerCase(); |
| 1051 | // Out of a project: to its workspace's projects when they are yours. | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1052 | const home = (user.workspaces ?? []).find((m) => m.slug === menuRepo.namespace.toLowerCase()); |
| 1053 | const back = home ? { to: `/${home.slug}/-/projects`, label: "All projects" } : { to: ws ? `/${ws.slug}/-/overview` : "/explore", label: "Code" }; | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 1054 | trail.push({ |
| 1055 | key, | |
| 1056 | node: ( | |
| 1057 | <RepoMenu | |
| 1058 | repo={menuRepo} | |
| 1059 | isPrivate={[...shell.repos, ...(shell.shared ?? [])].some((repo) => sameRepo(repo, menuRepo) && repo.isPrivate)} | |
| 1060 | back={back} | |
| 1061 | /> | |
| 1062 | ), | |
| 1063 | }); | |
| 1064 | if (inRepoSettings) trail.push({ key: `${key}:settings`, node: <RepoSettingsMenu repo={menuRepo} /> }); | |
| 1065 | } | |
| 1066 | ||
| Usage while free is shown at cost; agents get rustfmt and clippy | 1067 | return ( |
| 1068 | <div className="flex h-full flex-col"> | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1069 | <ModeHeader title="Code" /> |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 1070 | <Drill trail={trail} /> |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1071 | </div> |
| 1072 | ); | |
| 1073 | } | |
| 1074 | ||
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1075 | /** |
| 1076 | * A mode's sidebar heading: its name, quiet, under the workspace's | |
| 1077 | * switcher, with what it makes at the end. | |
| 1078 | */ | |
| 1079 | export function ModeHeader({ title, action }: { title: ReactNode; action?: ReactNode }) { | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1080 | return ( |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1081 | <div className="flex h-9 shrink-0 items-center gap-1 pr-1 pl-3"> |
| 1082 | <h2 className="min-w-0 grow truncate text-xs font-medium text-faint">{title}</h2> | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1083 | {action} |
| 1084 | </div> | |
| 1085 | ); | |
| 1086 | } | |
| 1087 | ||
| 1088 | /** | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1089 | * Code's own list (beside the dock): only code. Its Overview (Mission |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1090 | * control's code panels), the projects, what spans them, and what is |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1091 | * coming. The workspace's people, money and settings are elsewhere; |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1092 | * agents, context and memory are Agents'. |
| 1093 | */ | |
| 1094 | function CodeMenu({ shell, slug }: { shell: ShellData; slug: string }) { | |
| 1095 | const { pathname } = useLocation(); | |
| 1096 | const going = useNavigation().location?.pathname; | |
| 1097 | const path = going ?? pathname; | |
| 1098 | const at = (page: string) => path === `/${slug}/-/${page}` || path.startsWith(`/${slug}/-/${page}/`); | |
| 1099 | const shared = shell.shared ?? []; | |
| 1100 | return ( | |
| 1101 | <nav aria-label="Code" className={PANEL}> | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1102 | <div className="space-y-px"> |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1103 | <SidebarLink to={`/${slug}/-/overview`} icon={<LayoutDashboard size={15} />} current={at("overview")}> |
| 1104 | Overview | |
| 1105 | </SidebarLink> | |
| 1106 | </div> | |
| 1107 | <div className="mt-3"> | |
| 1108 | <SidebarProjects slug={slug} shell={shell} current={at("projects")} /> | |
| 1109 | </div> | |
| 1110 | <Rule /> | |
| 1111 | <div className="space-y-px"> | |
| 1112 | <SidebarLink to={`/${slug}/-/security`} icon={<ShieldCheck size={15} />} current={at("security") && !at("security/settings")}> | |
| 1113 | Security | |
| 1114 | </SidebarLink> | |
| 1115 | <SidebarLink to={`/${slug}/-/packages`} icon={<Package size={15} />} current={at("packages")}> | |
| 1116 | Packages | |
| 1117 | </SidebarLink> | |
| 1118 | {INSIGHTS && ( | |
| 1119 | <SidebarSoonLink to={`/${slug}/-/insights`} icon={<TrendingUp size={15} />} about={INSIGHTS.summary} current={at("insights")}> | |
| 1120 | {INSIGHTS.title} | |
| 1121 | </SidebarSoonLink> | |
| 1122 | )} | |
| 1123 | {roadmapIn("Workspace") | |
| 1124 | .filter((item) => item.key !== "insights" && item.key !== "teams" && item.key !== "fleet") | |
| 1125 | .map((item) => ( | |
| 1126 | <SidebarSoonLink key={item.key} to={`/${slug}/-/soon/${item.key}`} icon={WORKSPACE_ICONS[item.key] ?? <Sparkles size={15} />} about={item.summary}> | |
| 1127 | {item.title === "Board" ? "Boards" : item.title} | |
| 1128 | </SidebarSoonLink> | |
| 1129 | ))} | |
| 1130 | </div> | |
| 1131 | {shared.length > 0 && ( | |
| 1132 | <> | |
| 1133 | <Rule /> | |
| 1134 | <SidebarGroup title="Shared with you"> | |
| 1135 | {shared.map((repo) => ( | |
| 1136 | <SidebarLink | |
| 1137 | key={`${repo.namespace}/${repo.name}`} | |
| 1138 | to={`/${repo.namespace}/${repo.name}`} | |
| 1139 | icon={repo.isPrivate ? <Lock size={15} /> : <Box size={15} />} | |
| 1140 | drill="hover" | |
| 1141 | > | |
| 1142 | <span className="font-mono text-faint">{repo.namespace}/</span> | |
| 1143 | {repo.name} | |
| 1144 | </SidebarLink> | |
| 1145 | ))} | |
| 1146 | </SidebarGroup> | |
| 1147 | </> | |
| 1148 | )} | |
| 1149 | </nav> | |
| 1150 | ); | |
| 1151 | } | |
| 1152 | ||
| 1153 | /** Workspace pages that sit in its Settings list, drilled into from the Workspace sidebar. */ | |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 1154 | const WORKSPACE_SETTINGS = ["settings", "repositories", "tokens", "personal-access-tokens", "secrets", "actions", "webhooks", "emoji"]; |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1155 | |
| 1156 | /** | |
| 1157 | * The Workspace mode's sidebar: the workspace itself, for every member. | |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 1158 | * Its overview, money, machines, connections, policies and record, then its |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1159 | * settings as a list of their own. Owner-only pages stay owner-only. |
| 1160 | */ | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1161 | export function WorkspaceSidebar({ slug, owner }: { slug: string; owner: boolean }) { |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1162 | const { pathname } = useLocation(); |
| 1163 | const going = useNavigation().location?.pathname; | |
| 1164 | const path = going ?? pathname; | |
| 1165 | const page = path.startsWith(`/${slug}/-/`) ? path.slice(`/${slug}/-/`.length) : ""; | |
| 1166 | const top = page.split("/")[0] ?? ""; | |
| 1167 | const at = (...pages: string[]) => pages.some((p) => page === p || page.startsWith(`${p}/`)); | |
| 1168 | const inSettings = WORKSPACE_SETTINGS.includes(top); | |
| 1169 | const main = ( | |
| 1170 | <nav aria-label="Workspace" className={PANEL}> | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1171 | <div className="space-y-px"> |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1172 | <SidebarLink to={`/${slug}/-/workspace`} icon={<LayoutGrid size={15} />} current={at("workspace")}> |
| 1173 | Overview | |
| 1174 | </SidebarLink> | |
| 1175 | </div> | |
| The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how. | 1176 | <SidebarGroup title="Money" className="mt-3"> |
| 1177 | <SidebarLink to={`/${slug}/-/spend`} icon={<Coins size={15} />} current={at("spend")}> | |
| 1178 | Spend | |
| 1179 | </SidebarLink> | |
| The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how. | 1180 | <SidebarLink to={`/${slug}/-/usage`} icon={<BarChart3 size={15} />} current={at("usage")}> |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1181 | Usage |
| 1182 | </SidebarLink> | |
| The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how. | 1183 | <SidebarLink to={`/${slug}/-/gateway`} icon={<Network size={15} />} current={at("gateway")}> |
| 1184 | AI Gateway | |
| 1185 | </SidebarLink> | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1186 | <SidebarLink to={`/${slug}/-/billing`} icon={<CreditCard size={15} />} current={at("billing")}> |
| 1187 | Billing and plans | |
| 1188 | </SidebarLink> | |
| 1189 | </SidebarGroup> | |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 1190 | {owner && ( |
| 1191 | <SidebarGroup title="Compute" className="mt-3"> | |
| 1192 | <SidebarLink to={`/${slug}/-/runners`} icon={<ServerCog size={15} />} current={at("runners")}> | |
| 1193 | Runners | |
| 1194 | </SidebarLink> | |
| 1195 | </SidebarGroup> | |
| 1196 | )} | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1197 | <SidebarGroup title="Connections" className="mt-3"> |
| 1198 | <SidebarLink to={`/${slug}/-/integrations`} icon={<Plug size={15} />} current={at("integrations")}> | |
| 1199 | Integrations | |
| 1200 | </SidebarLink> | |
| 1201 | </SidebarGroup> | |
| 1202 | <SidebarGroup title="Security policies" className="mt-3"> | |
| 1203 | <SidebarLink to={`/${slug}/-/security/settings`} icon={<ShieldCheck size={15} />} current={at("security/settings")}> | |
| 1204 | Security settings | |
| 1205 | </SidebarLink> | |
| 1206 | <SidebarLink to={`/${slug}/-/guardrails`} icon={<Gauge size={15} />} current={at("guardrails")}> | |
| 1207 | Guardrails | |
| 1208 | </SidebarLink> | |
| 1209 | <SidebarLink to={`/${slug}/-/rules`} icon={<Scale size={15} />} current={at("rules")}> | |
| 1210 | Rules | |
| 1211 | </SidebarLink> | |
| 1212 | </SidebarGroup> | |
| 1213 | <Rule /> | |
| 1214 | <div className="space-y-px"> | |
| 1215 | <SidebarLink to={`/${slug}/-/audit`} icon={<History size={15} />} current={at("audit")}> | |
| 1216 | Audit log | |
| 1217 | </SidebarLink> | |
| 1218 | <SidebarLink to={owner ? `/${slug}/-/settings` : `/${slug}/-/repositories`} icon={<Settings size={15} />} drill current={inSettings}> | |
| 1219 | Settings | |
| 1220 | </SidebarLink> | |
| 1221 | </div> | |
| 1222 | </nav> | |
| 1223 | ); | |
| 1224 | const settings = ( | |
| 1225 | <nav aria-label="Workspace settings" className={PANEL}> | |
| 1226 | <BackRow to={`/${slug}/-/workspace`} label="Settings" context={slug} /> | |
| 1227 | <div className="mt-2 space-y-px"> | |
| 1228 | {owner && ( | |
| Chat controls, public profiles, shadcn selects, and no Docs tab in a project | 1229 | <SidebarLink to={`/${slug}/-/settings`} icon={<Settings size={15} />} end> |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1230 | General |
| 1231 | </SidebarLink> | |
| 1232 | )} | |
| Chat controls, public profiles, shadcn selects, and no Docs tab in a project | 1233 | <SidebarLink to={`/${slug}/-/settings/chat`} icon={<MessagesSquare size={15} />}> |
| 1234 | Chat | |
| 1235 | </SidebarLink> | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1236 | <SidebarLink to={`/${slug}/-/repositories`} icon={<BookMarked size={15} />}> |
| 1237 | Repositories | |
| 1238 | </SidebarLink> | |
| 1239 | <SidebarLink to={`/${slug}/-/tokens`} icon={<KeyRound size={15} />}> | |
| 1240 | Access tokens | |
| 1241 | </SidebarLink> | |
| 1242 | {owner && ( | |
| 1243 | <SidebarLink to={`/${slug}/-/personal-access-tokens`} icon={<UserRoundKey size={15} />}> | |
| 1244 | Personal access tokens | |
| 1245 | </SidebarLink> | |
| 1246 | )} | |
| 1247 | <SidebarLink to={`/${slug}/-/webhooks`} icon={<Webhook size={15} />}> | |
| 1248 | Webhooks | |
| 1249 | </SidebarLink> | |
| 1250 | <SidebarLink to={`/${slug}/-/emoji`} icon={<Smile size={15} />}> | |
| 1251 | Emoji | |
| 1252 | </SidebarLink> | |
| 1253 | </div> | |
| 1254 | <SidebarGroup title="Runs" className="mt-3"> | |
| 1255 | <SidebarLink to={`/${slug}/-/secrets`} icon={<Lock size={15} />}> | |
| 1256 | Secrets and variables | |
| 1257 | </SidebarLink> | |
| 1258 | <SidebarLink to={`/${slug}/-/actions`} icon={<PlayCircle size={15} />}> | |
| 1259 | Actions | |
| 1260 | </SidebarLink> | |
| 1261 | </SidebarGroup> | |
| 1262 | </nav> | |
| 1263 | ); | |
| 1264 | const trail: Level[] = [{ key: "workspace", node: main }]; | |
| 1265 | if (inSettings) trail.push({ key: "workspace:settings", node: settings }); | |
| 1266 | return ( | |
| 1267 | <div className="flex h-full flex-col"> | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1268 | <ModeHeader title="Workspace" /> |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1269 | <Drill trail={trail} /> |
| 1270 | </div> | |
| 1271 | ); | |
| 1272 | } | |
| 1273 | ||
| People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how. | 1274 | /** |
| 1275 | * People's sidebar: everyone in the workspace, people and agents; its | |
| 1276 | * teams; the org chart; and, to manage who belongs, members and invites. | |
| 1277 | */ | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1278 | function PeopleSidebar({ slug }: { slug: string }) { |
| 1279 | const { pathname } = useLocation(); | |
| 1280 | const going = useNavigation().location?.pathname; | |
| 1281 | const path = going ?? pathname; | |
| 1282 | const at = (page: string) => path === `/${slug}/-/${page}` || path.startsWith(`/${slug}/-/${page}/`); | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1283 | return ( |
| 1284 | <div className="flex h-full flex-col"> | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1285 | <ModeHeader title="People" /> |
| 1286 | <nav aria-label="People" className={PANEL}> | |
| 1287 | <div className="space-y-px"> | |
| 1288 | <SidebarLink to={`/${slug}/-/people`} icon={<Users size={15} />} current={at("people")}> | |
| 1289 | Everyone | |
| 1290 | </SidebarLink> | |
| 1291 | <SidebarLink to={`/${slug}/-/teams`} icon={<UsersRound size={15} />} current={at("teams")}> | |
| 1292 | Teams | |
| 1293 | </SidebarLink> | |
| People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how. | 1294 | <SidebarLink to={`/${slug}/-/org-chart`} icon={<Network size={15} />} current={at("org-chart")}> |
| 1295 | Org chart | |
| 1296 | </SidebarLink> | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1297 | </div> |
| People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how. | 1298 | <SidebarGroup title="Membership" className="mt-3"> |
| 1299 | <SidebarLink to={`/${slug}/-/members`} icon={<UserPlus size={15} />} current={at("members")}> | |
| 1300 | Members and invites | |
| 1301 | </SidebarLink> | |
| 1302 | </SidebarGroup> | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1303 | </nav> |
| 1304 | </div> | |
| 1305 | ); | |
| 1306 | } | |
| 1307 | ||
| 1308 | /** | |
| 1309 | * Notifications' sidebar: what you have not finished with, what you saved | |
| 1310 | * and what is done; then why you were told, which narrows any of them. | |
| 1311 | */ | |
| 1312 | function NotificationsSidebar({ counts }: { counts: InboxCounts | null }) { | |
| 1313 | const { search } = useLocation(); | |
| 1314 | const params = new URLSearchParams(search); | |
| 1315 | const view = inboxView(params.get("view")); | |
| 1316 | const reason = inboxReason(params.get("reason")); | |
| 1317 | const tab = params.get("tab"); | |
| 1318 | const address = (changes: Record<string, string | null>) => { | |
| 1319 | const merged: Record<string, string | null> = { tab, view: view === "inbox" ? null : view, reason, ...changes }; | |
| 1320 | const next = new URLSearchParams(); | |
| 1321 | for (const [name, value] of Object.entries(merged)) if (value) next.set(name, value); | |
| 1322 | const query = next.toString(); | |
| 1323 | return query ? `/notifications?${query}` : "/notifications"; | |
| 1324 | }; | |
| 1325 | const views = [ | |
| 1326 | { view: "inbox", label: "Everything", icon: <Bell size={15} />, count: counts?.unread }, | |
| 1327 | { view: "saved", label: "Saved", icon: <Bookmark size={15} /> }, | |
| 1328 | { view: "done", label: "Done", icon: <Check size={15} /> }, | |
| 1329 | ] as const; | |
| 1330 | return ( | |
| 1331 | <div className="flex h-full flex-col"> | |
| 1332 | <ModeHeader title="Notifications" /> | |
| 1333 | <nav aria-label="Notifications" className={PANEL}> | |
| 1334 | <div className="space-y-px"> | |
| 1335 | {views.map((entry) => ( | |
| 1336 | <SidebarLink | |
| 1337 | key={entry.view} | |
| 1338 | to={address({ view: entry.view === "inbox" ? null : entry.view, before: null })} | |
| 1339 | icon={entry.icon} | |
| 1340 | count={"count" in entry ? (entry.count ?? undefined) : undefined} | |
| 1341 | current={view === entry.view} | |
| 1342 | > | |
| 1343 | {entry.label} | |
| 1344 | </SidebarLink> | |
| 1345 | ))} | |
| 1346 | </div> | |
| 1347 | <SidebarGroup title="Why you were told" className="mt-4"> | |
| 1348 | {REASON_FILTERS.map((entry) => ( | |
| 1349 | <SidebarLink | |
| 1350 | key={entry.reason ?? "any"} | |
| 1351 | to={address({ reason: entry.reason, before: null })} | |
| 1352 | icon={<span className="block size-[15px]" />} | |
| 1353 | current={reason === entry.reason} | |
| 1354 | > | |
| 1355 | {entry.reason == null ? "Any reason" : entry.label} | |
| 1356 | </SidebarLink> | |
| 1357 | ))} | |
| 1358 | </SidebarGroup> | |
| 1359 | </nav> | |
| 1360 | </div> | |
| 1361 | ); | |
| 1362 | } | |
| 1363 | ||
| 1364 | /** Your own settings, beside the page: under the account menu, not any workspace's. */ | |
| 1365 | export function AccountSidebar({ username }: { username: string }) { | |
| 1366 | return ( | |
| 1367 | <div className="flex h-full flex-col"> | |
| 1368 | <ModeHeader title="Your account" /> | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1369 | <div className="min-h-0 grow"> |
| 1370 | <AccountSettingsMenu username={username} /> | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1371 | </div> |
| 1372 | </div> | |
| 1373 | ); | |
| 1374 | } | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1375 | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1376 | /** Words for the sections a path can end in. */ |
| 1377 | const SECTIONS: Record<string, string> = { | |
| 1378 | issues: "Issues", | |
| Usage, Billing settings and prepaid AI credit; fixes from the UX audit | 1379 | milestones: "Milestones", |
| 1380 | labels: "Labels", | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1381 | pulls: "Pull requests", |
| 1382 | queue: "Merge queue", | |
| 1383 | commits: "Commits", | |
| A menu shaped by how g1t works, Soon pages for every promise, and sudo for sales | 1384 | plans: "Outcomes", |
| 1385 | actions: "Workflows", | |
| 1386 | soon: "Soon", | |
| Deployments: a preview for every pull request, production on g1t.page | 1387 | deployments: "Deployments", |
| Projects: what a workspace builds and runs, first on every page | 1388 | repository: "Repository", |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 1389 | access: "Access", |
| 1390 | invitations: "Invitation", | |
| 1391 | repositories: "Repositories", | |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 1392 | branches: "Branches", |
| 1393 | tags: "Tags", | |
| Compare: any two branches, the commits one has that the other does not, and the diff, with Open a pull request | 1394 | compare: "Compare", |
| A menu shaped by how g1t works, Soon pages for every promise, and sudo for sales | 1395 | code: "Files", |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1396 | secrets: "Secrets and variables", |
| 1397 | settings: "Settings", | |
| Navigation: the workspace's own page with tabs, pins and recent in the sidebar | 1398 | people: "People", |
| People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how. | 1399 | "org-chart": "Org chart", |
| 1400 | members: "Members and invites", | |
| Navigation: the workspace's own page with tabs, pins and recent in the sidebar | 1401 | projects: "Projects", |
| 1402 | teams: "Teams", | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1403 | tokens: "Access tokens", |
| Settings: fine-grained tokens, workspace token Admin, workspace personal access token rules | 1404 | "personal-access-tokens": "Personal access tokens", |
| The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how. | 1405 | spend: "Spend", |
| 1406 | receipts: "Receipts", | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1407 | usage: "Usage", |
| Site: the AI Gateway page's breadcrumb reads "AI Gateway" | 1408 | gateway: "AI Gateway", |
| Secrets and variables: one list, rows per environment, for workflows and deployments | 1409 | billing: "Billing and plans", |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1410 | integrations: "Integrations", |
| 1411 | webhooks: "Webhooks", | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1412 | emoji: "Emoji", |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 1413 | domains: "Domains", |
| 1414 | guardrails: "Guardrails", | |
| Merge rulesets: branch and tag rules, agent-first, enforced on push and merge | 1415 | rules: "Rules", |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 1416 | audit: "Audit log", |
| Files pages say Files in the trail and keep the description in About only | 1417 | tree: "Files", |
| 1418 | blob: "Files", | |
| Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail | 1419 | agents: "Agents", |
| 1420 | context: "Context", | |
| 1421 | memory: "Memory", | |
| 1422 | security: "Security", | |
| 1423 | packages: "Packages", | |
| 1424 | runners: "Runners", | |
| Merge branch 'worktree-agent-a3abfcce648e87dca' | 1425 | environments: "Environments", |
| Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail | 1426 | workflows: "Workflows", |
| 1427 | observability: "Observability", | |
| 1428 | insights: "Insights", | |
| 1429 | sessions: "Sessions", | |
| Chat and workspace agents: channels, DMs and named agents you talk to | 1430 | chat: "Chat", |
| Artifacts is a mode in the rail, the shell and the phone's tab bar in place of Docs: its home lists everything you can open by day or as cards under All, Yours and Shared with you, with search, filters and tiles to start a doc (slides, designs and dashboards say they are coming soon), and its sidebar holds favorites, spaces, Private, Shared, projects' docs and the trash. | 1431 | artifacts: "Artifacts", |
| The front page is Home: where you're needed comes first, however long ago it started, with what's at stake and how long it has waited; then what happened since you were last here, in words, with the agent work that settled, what landed, what deployed, what was decided and what was spent, switchable to the last 24 hours or 7 days; then what's running now. Your last visit is kept with your account, so it's the same on every device; Today's old address leads here. The home guide says how. | 1432 | home: "Home", |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1433 | apps: "Apps", |
| The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how. | 1434 | marketplace: "Marketplace", |
| Chat and workspace agents: channels, DMs and named agents you talk to | 1435 | "code-access": "Code access", |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1436 | overview: "Overview", |
| 1437 | workspace: "Workspace", | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1438 | }; |
| 1439 | ||
| Merge branch 'worktree-agent-a3abfcce648e87dca' | 1440 | /** Settings pages whose name differs from the section's of the same word. */ |
| 1441 | const SETTINGS_SECTIONS: Record<string, string> = { branches: "Branches and merging", actions: "Actions" }; | |
| 1442 | ||
| Usage while free is shown at cost; agents get rustfmt and clippy | 1443 | /** Where the page is, as a trail of links: workspace / repository / section. */ |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1444 | function Breadcrumbs({ |
| 1445 | pathname, | |
| 1446 | missing, | |
| 1447 | repo, | |
| 1448 | workspace, | |
| 1449 | }: { | |
| 1450 | pathname: string; | |
| 1451 | missing?: boolean; | |
| 1452 | repo?: ShellData["repo"]; | |
| 1453 | /** The workspace you are in: the switcher names it, so the trail starts after it. */ | |
| 1454 | workspace: string | null; | |
| 1455 | }) { | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 1456 | // A 404 names nothing from the address, unless the project is real and |
| 1457 | // visible and only something inside it is missing. | |
| 1458 | const visibleRepo = /^\/([^/]+)\/([^/-][^/]*)(\/|$)/.exec(pathname); | |
| 1459 | if (missing && !(visibleRepo && sameRepo(repo ?? null, { namespace: visibleRepo[1]!, name: visibleRepo[2]! }))) { | |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 1460 | return <Here>Not found</Here>; |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 1461 | } |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1462 | const parts = pathname.split("/").filter(Boolean); |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1463 | const reserved = ["settings", "explore", "new", "search", "workspaces", "policies", "security", "support", "status", "invite", "notifications"]; |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 1464 | if (parts.length === 0) return <Here>Home</Here>; |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 1465 | // Your settings: Settings / Emails. |
| 1466 | if (parts[0] === "settings") { | |
| 1467 | const page = accountSettingsPage(pathname); | |
| Usage, Billing settings and prepaid AI credit; fixes from the UX audit | 1468 | return <Trail trail={[{ label: "Settings", to: FIRST_SETTINGS_PAGE }, ...(page ? [{ label: ACCOUNT_SETTINGS[page].title, to: `/settings/${page}` }] : [])]} />; |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 1469 | } |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1470 | if (reserved.includes(parts[0]!)) { |
| 1471 | const words: Record<string, string> = { | |
| 1472 | settings: "Account", | |
| 1473 | explore: "Explore", | |
| Projects live: fixes from walking them end to end | 1474 | new: "New project", |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1475 | search: "Search", |
| 1476 | workspaces: "New workspace", | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 1477 | policies: "Policies", |
| 1478 | security: "Security", | |
| 1479 | support: "Support", | |
| 1480 | status: "Status", | |
| 1481 | invite: "Invite", | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1482 | notifications: "Notifications", |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1483 | }; |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 1484 | return <Here>{words[parts[0]!]}</Here>; |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1485 | } |
| Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put | 1486 | // A person's profile, by their handle. |
| Chat controls, public profiles, shadcn selects, and no Docs tab in a project | 1487 | if (parts[0] === "u" && parts[1]) return <ProfileCrumb username={parts[1]} />; |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1488 | const [owner, second, third, fourth] = parts; |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1489 | const ours = workspace != null && owner!.toLowerCase() === workspace.toLowerCase(); |
| 1490 | const trail: Crumb[] = ours ? [] : [{ label: owner!, to: `/${owner}`, mono: true }]; | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1491 | if (second === "-") { |
| 1492 | const page = `/${owner}/-/${third}`; | |
| 1493 | if (third && SETTINGS_PAGE.test(page)) { | |
| 1494 | trail.push({ label: "Settings", to: `/${owner}/-/settings` }); | |
| 1495 | trail.push({ label: third === "settings" ? "General" : (SECTIONS[third] ?? third), to: page }); | |
| The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how. | 1496 | } else if (third) { |
| 1497 | trail.push({ label: SECTIONS[third] ?? third, to: page }); | |
| The Marketplace adds what g1t doesn't do and connects what you already use: extensions (Mail, Support, CRM, Recruiting, On-call, and bridges to a helpdesk, CRM or ERP you run, all Soon), starter kits, and integrations connected by the workspace or by each person; agents aren't installed there. Agent templates live in Agents, as starting points you configure, at Agents → Templates, and the Marketplace's old agent addresses lead there. The marketplace and agents guides say how. | 1498 | // The Marketplace names its tab (Marketplace / Extensions), and Agents its templates. |
| 1499 | const tabs: Record<string, string> = | |
| 1500 | third === "marketplace" ? { integrations: "Integrations", extensions: "Extensions", requests: "Requests" } : third === "agents" ? { templates: "Templates" } : {}; | |
| 1501 | const tab = fourth ? tabs[fourth] : undefined; | |
| The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how. | 1502 | if (tab) trail.push({ label: tab, to: `${page}/${fourth}` }); |
| 1503 | } | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1504 | } else if (second) { |
| 1505 | const repo = `/${owner}/${second}`; | |
| 1506 | trail.push({ label: second, to: repo, mono: true }); | |
| Usage, Billing settings and prepaid AI credit; fixes from the UX audit | 1507 | if (third === "pull" && fourth) trail.push({ label: `Pull request #${fourth}`, short: `#${fourth}`, to: `${repo}/pull/${fourth}` }); |
| 1508 | else if (third === "issues" && fourth && fourth !== "new") trail.push({ label: `Issue #${fourth}`, short: `#${fourth}`, to: `${repo}/issues/${fourth}` }); | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1509 | else if (third === "commit" && fourth) trail.push({ label: fourth.slice(0, 7), to: `${repo}/commit/${fourth}`, mono: true }); |
| Secrets and variables: one list, rows per environment, for workflows and deployments | 1510 | else if (third && SECTIONS[third]) { |
| 1511 | trail.push({ label: SECTIONS[third]!, to: `${repo}/${third}` }); | |
| 1512 | // A settings page names which one: Settings / Secrets and variables. | |
| 1513 | if (third === "settings" && fourth && SECTIONS[fourth]) { | |
| Merge branch 'worktree-agent-a3abfcce648e87dca' | 1514 | trail.push({ label: SETTINGS_SECTIONS[fourth] ?? SECTIONS[fourth]!, to: `${repo}/settings/${fourth}` }); |
| Secrets and variables: one list, rows per environment, for workflows and deployments | 1515 | } |
| 1516 | } | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1517 | } |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1518 | if (trail.length === 0) trail.push({ label: "Overview", to: `/${owner}` }); |
| Usage, Billing settings and prepaid AI credit; fixes from the UX audit | 1519 | return <Trail trail={trail} />; |
| 1520 | } | |
| 1521 | ||
| Chat controls, public profiles, shadcn selects, and no Docs tab in a project | 1522 | /** A profile's place in the top bar: the person's avatar and @handle, from the page once it has loaded. */ |
| 1523 | function ProfileCrumb({ username }: { username: string }) { | |
| One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers | 1524 | const page = useRouteLoaderData("routes/user") as { profile?: { username: string; displayUsername?: string | null; avatar: string | null } } | undefined; |
| Chat controls, public profiles, shadcn selects, and no Docs tab in a project | 1525 | const profile = page?.profile?.username.toLowerCase() === username.toLowerCase() ? page.profile : null; |
| 1526 | return ( | |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 1527 | <Breadcrumb className="min-w-0"> |
| 1528 | <BreadcrumbList> | |
| 1529 | <BreadcrumbItem> | |
| 1530 | <BreadcrumbPage asChild className="flex items-center gap-2 hover:bg-raised"> | |
| 1531 | <Link to={`/u/${profile?.username ?? username}`}> | |
| 1532 | <Avatar name={profile?.username ?? username} image={profile?.avatar ?? null} size={20} /> | |
| 1533 | <span className="truncate font-mono text-[0.8125rem]">@{profile ? shownUsername(profile) : username}</span> | |
| 1534 | </Link> | |
| 1535 | </BreadcrumbPage> | |
| 1536 | </BreadcrumbItem> | |
| 1537 | </BreadcrumbList> | |
| 1538 | </Breadcrumb> | |
| 1539 | ); | |
| 1540 | } | |
| 1541 | ||
| 1542 | /** A page with no trail to it, such as Today or Search: its name alone. */ | |
| 1543 | function Here({ children }: { children: ReactNode }) { | |
| 1544 | return ( | |
| 1545 | <Breadcrumb className="min-w-0"> | |
| 1546 | <BreadcrumbList> | |
| 1547 | <BreadcrumbItem> | |
| 1548 | <BreadcrumbPage>{children}</BreadcrumbPage> | |
| 1549 | </BreadcrumbItem> | |
| 1550 | </BreadcrumbList> | |
| 1551 | </Breadcrumb> | |
| Chat controls, public profiles, shadcn selects, and no Docs tab in a project | 1552 | ); |
| 1553 | } | |
| 1554 | ||
| Usage, Billing settings and prepaid AI credit; fixes from the UX audit | 1555 | /** One link of the trail; `short` is what a phone shows when it is the page itself. */ |
| 1556 | type Crumb = { label: string; to: string; mono?: boolean; short?: string }; | |
| 1557 | ||
| 1558 | /** | |
| 1559 | * The trail of links. On a phone there is room for one: the page itself, | |
| 1560 | * with a way back to where it sits; the whole trail from a wider screen up. | |
| 1561 | */ | |
| 1562 | function Trail({ trail }: { trail: Crumb[] }) { | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1563 | // Up on a phone, unless up is the workspace itself: its pages are the tabs. |
| 1564 | const up = trail.length > 1 && !/^\/[^/]+$/.test(trail[trail.length - 2]!.to) ? trail[trail.length - 2]! : null; | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1565 | return ( |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 1566 | <Breadcrumb className="flex min-w-0 items-center"> |
| Usage, Billing settings and prepaid AI credit; fixes from the UX audit | 1567 | {up && ( |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 1568 | <Button asChild variant="ghost" size="icon-bar" className="-ml-1 sm:hidden"> |
| 1569 | <Link to={up.to} prefetch="intent" aria-label={`Back to ${up.label}`}> | |
| 1570 | <ChevronLeft size={16} /> | |
| 1571 | </Link> | |
| 1572 | </Button> | |
| Usage, Billing settings and prepaid AI credit; fixes from the UX audit | 1573 | )} |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 1574 | <BreadcrumbList> |
| 1575 | {trail.map((crumb, index) => { | |
| 1576 | const last = index === trail.length - 1; | |
| 1577 | const label = | |
| 1578 | last && crumb.short ? ( | |
| 1579 | <> | |
| 1580 | <span className="sm:hidden">{crumb.short}</span> | |
| 1581 | <span className="hidden sm:inline">{crumb.label}</span> | |
| 1582 | </> | |
| 1583 | ) : ( | |
| 1584 | crumb.label | |
| 1585 | ); | |
| 1586 | const mono = crumb.mono ? "font-mono text-[0.8125rem]" : ""; | |
| 1587 | return ( | |
| 1588 | <Fragment key={index}> | |
| 1589 | {index > 0 && <BreadcrumbSeparator className="max-sm:hidden" />} | |
| 1590 | <BreadcrumbItem className={last ? "" : "max-sm:hidden"}> | |
| 1591 | {last ? ( | |
| 1592 | // The page you are on is still a link: to its own top, as the trail always was. | |
| 1593 | <BreadcrumbPage asChild className={`hover:bg-raised ${mono}`}> | |
| 1594 | <Link to={crumb.to} prefetch="intent"> | |
| 1595 | {label} | |
| 1596 | </Link> | |
| 1597 | </BreadcrumbPage> | |
| 1598 | ) : ( | |
| 1599 | <BreadcrumbLink asChild className={mono}> | |
| 1600 | <Link to={crumb.to} prefetch="intent"> | |
| 1601 | {label} | |
| 1602 | </Link> | |
| 1603 | </BreadcrumbLink> | |
| 1604 | )} | |
| 1605 | </BreadcrumbItem> | |
| 1606 | </Fragment> | |
| 1607 | ); | |
| 1608 | })} | |
| 1609 | </BreadcrumbList> | |
| 1610 | </Breadcrumb> | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1611 | ); |
| 1612 | } | |
| 1613 | ||
| Search across all of g1t, Explore, and a command palette | 1614 | type Command = PaletteCommand; |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1615 | |
| 1616 | /** Everything the palette can jump to, from what the sidebar already knows. */ | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1617 | function commandsFor(user: User, shell: ShellData): Command[] { |
| 1618 | const ws = shell.workspace; | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1619 | const commands: Command[] = [ |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1620 | ...(ws |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1621 | ? [ |
| The front page is Home: where you're needed comes first, however long ago it started, with what's at stake and how long it has waited; then what happened since you were last here, in words, with the agent work that settled, what landed, what deployed, what was decided and what was spent, switchable to the last 24 hours or 7 days; then what's running now. Your last visit is kept with your account, so it's the same on every device; Today's old address leads here. The home guide says how. | 1622 | { label: "Home", to: homePagePath(ws.slug), icon: <House size={15} /> }, |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1623 | { label: "Chat", to: `/${ws.slug}/-/chat`, icon: <MessagesSquare size={15} /> }, |
| 1624 | { label: "Agents", to: `/${ws.slug}/-/agents`, icon: <Sparkles size={15} /> }, | |
| 1625 | ...(hasCodeAccess(ws) ? [{ label: "Code overview", to: `/${ws.slug}/-/overview`, icon: <Code2 size={15} /> }] : []), | |
| 1626 | { label: "Artifacts", to: `/${ws.slug}/-/artifacts`, icon: <Shapes size={15} /> }, | |
| 1627 | { label: "Apps", hint: "Everything installed that you can use", to: `/${ws.slug}/-/apps`, icon: <LayoutGrid size={15} /> }, | |
| The Marketplace adds what g1t doesn't do and connects what you already use: extensions (Mail, Support, CRM, Recruiting, On-call, and bridges to a helpdesk, CRM or ERP you run, all Soon), starter kits, and integrations connected by the workspace or by each person; agents aren't installed there. Agent templates live in Agents, as starting points you configure, at Agents → Templates, and the Marketplace's old agent addresses lead there. The marketplace and agents guides say how. | 1628 | { label: "Marketplace", hint: "Extensions and integrations to add", to: `/${ws.slug}/-/marketplace`, icon: <Store size={15} /> }, |
| 1629 | { label: "Agent templates", hint: "Starting points for a new agent", to: `/${ws.slug}/-/agents/templates`, icon: <Bot size={15} /> }, | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1630 | { label: "Workspace", hint: "Billing, policies, settings", to: `/${ws.slug}/-/workspace`, icon: <Building2 size={15} /> }, |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1631 | ] |
| 1632 | : []), | |
| Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step | 1633 | ...(shell.repos.length > 0 |
| g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent | 1634 | ? [{ label: "Put an agent on it", hint: "Open an issue and assign g1t", to: "/?agent=new", icon: <Sparkles size={15} /> }] |
| Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step | 1635 | : []), |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1636 | { label: "Explore repositories", to: "/explore", icon: <Compass size={15} /> }, |
| Search across all of g1t, Explore, and a command palette | 1637 | { label: "Search g1t", hint: "Repositories, code, issues, people", to: "/search", icon: <Search size={15} /> }, |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1638 | { label: "Notifications", hint: "What needs you", to: "/notifications", icon: <Bell size={15} /> }, |
| Projects: what a workspace builds and runs, first on every page | 1639 | { label: "New project", to: "/new", icon: <Plus size={15} /> }, |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1640 | { label: "New workspace", to: "/workspaces/new", icon: <Plus size={15} /> }, |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 1641 | { label: "Your settings", to: FIRST_SETTINGS_PAGE, icon: <Settings size={15} /> }, |
| 1642 | ...(Object.keys(ACCOUNT_SETTINGS) as AccountSettingsPage[]) | |
| 1643 | .filter((page) => page !== "profile") | |
| 1644 | .map((page) => ({ label: ACCOUNT_SETTINGS[page].title, hint: "Your settings", to: `/settings/${page}`, icon: <Settings size={15} /> })), | |
| 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. | 1645 | ...THEME_COMMANDS, |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1646 | ]; |
| 1647 | const repo = shell.repo; | |
| 1648 | if (repo) { | |
| 1649 | const base = `/${repo.namespace}/${repo.name}`; | |
| 1650 | const name = `${repo.namespace}/${repo.name}`; | |
| 1651 | commands.unshift( | |
| Projects: what a workspace builds and runs, first on every page | 1652 | { label: "Overview", hint: name, to: base, icon: <LayoutGrid size={15} /> }, |
| 1653 | { label: "Code", hint: name, to: `${base}/code`, icon: <Code2 size={15} /> }, | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1654 | { label: "Issues", hint: name, to: `${base}/issues`, icon: <CircleDot size={15} /> }, |
| 1655 | { label: "New issue", hint: name, to: `${base}/issues/new`, icon: <Plus size={15} /> }, | |
| Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step | 1656 | ...(repo.member |
| 1657 | ? [{ label: `Put an agent on ${repo.name}`, hint: name, to: `${base}/issues/new?agent=1`, icon: <Sparkles size={15} /> }] | |
| 1658 | : []), | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1659 | { label: "Pull requests", hint: name, to: `${base}/pulls`, icon: <GitPullRequest size={15} /> }, |
| 1660 | { label: "Commits", hint: name, to: `${base}/commits`, icon: <History size={15} /> }, | |
| 1661 | ...(repo.member | |
| 1662 | ? [ | |
| 1663 | { label: "Plan work", hint: name, to: `${base}/plans`, icon: <ListTree size={15} /> }, | |
| Projects: what a workspace builds and runs, first on every page | 1664 | { label: "Deployments", hint: name, to: `${base}/deployments`, icon: <Rocket size={15} /> }, |
| 1665 | { label: "Secrets and variables", hint: name, to: `${base}/settings/secrets`, icon: <Lock size={15} /> }, | |
| 1666 | { label: "Project settings", hint: name, to: `${base}/settings`, icon: <Settings size={15} /> }, | |
| 1667 | { label: "Repository settings", hint: name, to: `${base}/settings/repository`, icon: <Settings size={15} /> }, | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1668 | ] |
| 1669 | : []), | |
| 1670 | ); | |
| 1671 | } | |
| 1672 | for (const membership of user.workspaces ?? []) { | |
| 1673 | commands.push( | |
| Workspace names and icons, and a component kit for every control | 1674 | { label: displayName(membership), hint: `Workspace · ${membership.slug}`, to: `/${membership.slug}`, icon: <Avatar name={membership.slug} image={membership.avatar} size={15} square /> }, |
| Navigation: the workspace's own page with tabs, pins and recent in the sidebar | 1675 | { label: "All projects", hint: membership.slug, to: `/${membership.slug}/-/projects`, icon: <LayoutGrid size={15} /> }, |
| 1676 | { label: "People", hint: membership.slug, to: `/${membership.slug}/-/people`, icon: <Users size={15} /> }, | |
| The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how. | 1677 | { label: "Spend", hint: `${membership.slug} · Budgets and receipts`, to: `/${membership.slug}/-/spend`, icon: <Coins size={15} /> }, |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1678 | { label: "Usage", hint: membership.slug, to: `/${membership.slug}/-/usage`, icon: <BarChart3 size={15} /> }, |
| Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens | 1679 | { label: "AI Gateway", hint: `${membership.slug} · Usage`, to: `/${membership.slug}/-/gateway`, icon: <Network size={15} /> }, |
| Projects: what a workspace builds and runs, first on every page | 1680 | { label: "Billing and plans", hint: `${membership.slug} · Settings`, to: `/${membership.slug}/-/billing`, icon: <CreditCard size={15} /> }, |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1681 | { label: "Access tokens", hint: `${membership.slug} · Settings`, to: `/${membership.slug}/-/tokens`, icon: <KeyRound size={15} /> }, |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 1682 | { label: "Integrations", hint: membership.slug, to: `/${membership.slug}/-/integrations`, icon: <Plug size={15} /> }, |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1683 | ); |
| 1684 | } | |
| 1685 | for (const listed of shell.repos) { | |
| 1686 | commands.push({ | |
| Projects: what a workspace builds and runs, first on every page | 1687 | label: listed.title ?? listed.name, |
| 1688 | hint: `${listed.namespace} · Project`, | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1689 | to: `/${listed.namespace}/${listed.name}`, |
| Projects: what a workspace builds and runs, first on every page | 1690 | icon: <Box size={15} />, |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1691 | }); |
| 1692 | } | |
| Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step | 1693 | // "Put an agent on …": one per project, after the projects themselves. |
| 1694 | for (const listed of shell.repos) { | |
| 1695 | if (repo && listed.namespace === repo.namespace && listed.name === repo.name) continue; | |
| 1696 | commands.push({ | |
| 1697 | label: `Put an agent on ${listed.title ?? listed.name}`, | |
| 1698 | hint: `${listed.namespace}/${listed.name}`, | |
| 1699 | to: `/${listed.namespace}/${listed.name}/issues/new?agent=1`, | |
| 1700 | icon: <Sparkles size={15} />, | |
| 1701 | }); | |
| 1702 | } | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1703 | return commands; |
| 1704 | } | |
| 1705 | ||
| 1706 | /** | |
| Merge branch 'worktree-agent-aca4790ea223aa235' | 1707 | * The page while the next one loads: after a moment it dims, under the |
| 1708 | * bar below, so it is plainly on its way out rather than frozen, and the | |
| 1709 | * next page fades up from there. Sending a form does not dim it: the | |
| 1710 | * form's button says it is working. Spread on the element holding the page. | |
| 1711 | */ | |
| 1712 | export function useLeaving() { | |
| 1713 | const navigation = useNavigation(); | |
| 1714 | const method = navigation.formMethod?.toUpperCase(); | |
| 1715 | const leaving = navigation.state === "loading" && (method == null || method === "GET"); | |
| 1716 | return { | |
| 1717 | "aria-busy": leaving || undefined, | |
| 1718 | className: `transition-opacity motion-reduce:transition-none ${leaving ? "opacity-60 delay-200 duration-300" : "duration-150"}`, | |
| 1719 | }; | |
| 1720 | } | |
| 1721 | ||
| 1722 | /** | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1723 | * A bar across the top of the page while the next one loads, as GitHub |
| 1724 | * has: it appears at once, creeps towards the end while waiting, then fills | |
| 1725 | * and fades when the page arrives. | |
| 1726 | */ | |
| 1727 | export function Progress() { | |
| 1728 | const navigation = useNavigation(); | |
| 1729 | const busy = navigation.state !== "idle"; | |
| 1730 | const [width, setWidth] = useState(0); | |
| 1731 | const [visible, setVisible] = useState(false); | |
| 1732 | useEffect(() => { | |
| 1733 | if (busy) { | |
| 1734 | setVisible(true); | |
| 1735 | setWidth(12); | |
| 1736 | // Slows as it goes, never quite arriving until the page does. | |
| 1737 | const timer = setInterval(() => setWidth((now) => now + (90 - now) * 0.12), 200); | |
| 1738 | return () => clearInterval(timer); | |
| 1739 | } | |
| 1740 | setWidth((now) => (now > 0 ? 100 : 0)); | |
| 1741 | const fade = setTimeout(() => setVisible(false), 250); | |
| 1742 | const reset = setTimeout(() => setWidth(0), 550); | |
| 1743 | return () => { | |
| 1744 | clearTimeout(fade); | |
| 1745 | clearTimeout(reset); | |
| 1746 | }; | |
| 1747 | }, [busy]); | |
| 1748 | return ( | |
| 1749 | <div | |
| 1750 | aria-hidden="true" | |
| 1751 | className={`pointer-events-none fixed inset-x-0 top-0 z-[60] h-[3px] transition-opacity duration-300 ${ | |
| 1752 | visible ? "opacity-100" : "opacity-0" | |
| 1753 | }`} | |
| 1754 | > | |
| 1755 | <div | |
| 1756 | className="h-full bg-accent shadow-[0_0_10px_var(--color-accent)] transition-[width] duration-200 ease-out" | |
| 1757 | style={{ width: `${width}%` }} | |
| 1758 | /> | |
| 1759 | </div> | |
| 1760 | ); | |
| 1761 | } | |
| 1762 | ||
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 1763 | /** |
| 1764 | * The top bar's way to g1t: the direct message with the workspace's | |
| 1765 | * orchestrator, opened or made. The one tinted control in the bar: the | |
| 1766 | * lavender pixel 1 bare beside its words, on a wash of the accent. | |
| 1767 | */ | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1768 | function AskG1tButton({ slug }: { slug: string }) { |
| 1769 | return ( | |
| 1770 | <Hint label="Ask g1t"> | |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 1771 | <Button asChild variant="soft" size="bar" className="gap-2 lg:px-3"> |
| 1772 | <Link to={`/${slug}/-/chat?agent=g1t`} aria-label="Ask g1t"> | |
| 1773 | <MarkGlyph className="h-3.5" /> | |
| 1774 | <span className="max-lg:hidden">Ask g1t</span> | |
| 1775 | </Link> | |
| 1776 | </Button> | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1777 | </Hint> |
| 1778 | ); | |
| 1779 | } | |
| 1780 | ||
| Usage while free is shown at cost; agents get rustfmt and clippy | 1781 | /** |
| The front page is Home: where you're needed comes first, however long ago it started, with what's at stake and how long it has waited; then what happened since you were last here, in words, with the agent work that settled, what landed, what deployed, what was decided and what was spent, switchable to the last 24 hours or 7 days; then what's running now. Your last visit is kept with your account, so it's the same on every device; Today's old address leads here. The home guide says how. | 1782 | * Which sidebar sits beside the page: each mode's own, or none. Home and |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1783 | * Apps are pages at full width, and so are g1t's public pages, such as a |
| 1784 | * profile, which are no workspace's. Without a workspace, only your own | |
| 1785 | * settings and Notifications have one. | |
| Chat and workspace agents: channels, DMs and named agents you talk to | 1786 | */ |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1787 | function sidebarFor(mode: ModeKey, workspace: boolean): Panel | null { |
| 1788 | if (!workspace) return mode === "account" || mode === "notifications" ? mode : null; | |
| The front page is Home: where you're needed comes first, however long ago it started, with what's at stake and how long it has waited; then what happened since you were last here, in words, with the agent work that settled, what landed, what deployed, what was decided and what was spent, switchable to the last 24 hours or 7 days; then what's running now. Your last visit is kept with your account, so it's the same on every device; Today's old address leads here. The home guide says how. | 1789 | if (mode === "home" || mode === "apps" || mode === "site") return null; |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1790 | return mode; |
| Chat and workspace agents: channels, DMs and named agents you talk to | 1791 | } |
| 1792 | ||
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1793 | /** The sidebars that sit beside the page, one per mode that has one. */ |
| 1794 | type Panel = "chat" | "artifacts" | "agents" | "code" | "notifications" | "people" | "workspace" | "account"; | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1795 | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1796 | /** Each sidebar's name, for the button that opens it on a phone. */ |
| 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 bar | 1797 | const MODE_MENU: Record<Panel, string> = { |
| 1798 | chat: "Chat", | |
| Artifacts is a mode in the rail, the shell and the phone's tab bar in place of Docs: its home lists everything you can open by day or as cards under All, Yours and Shared with you, with search, filters and tiles to start a doc (slides, designs and dashboards say they are coming soon), and its sidebar holds favorites, spaces, Private, Shared, projects' docs and the trash. | 1799 | artifacts: "Artifacts", |
| 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 bar | 1800 | agents: "Agents", |
| 1801 | code: "Code", | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1802 | notifications: "Notifications", |
| 1803 | people: "People", | |
| 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 bar | 1804 | workspace: "Workspace", |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1805 | account: "Your account", |
| 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 bar | 1806 | }; |
| 1807 | ||
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1808 | /** Whether a key press happened in something you type into, where Ctrl B is the editor's. */ |
| 1809 | function typing(target: EventTarget | null): boolean { | |
| 1810 | if (!(target instanceof HTMLElement)) return false; | |
| 1811 | return target.isContentEditable || target.closest("input, textarea, select, [contenteditable=''], [contenteditable='true'], [role='textbox']") != null; | |
| 1812 | } | |
| 1813 | ||
| 1814 | /** Ctrl B (⌘B on a Mac) shows or hides the sidebar, except while typing. */ | |
| 1815 | function useSidebarShortcut(toggle: () => void) { | |
| 1816 | useEffect(() => { | |
| 1817 | const onKey = (event: KeyboardEvent) => { | |
| 1818 | if (event.key.toLowerCase() !== "b" || event.altKey || event.shiftKey || !(event.ctrlKey || event.metaKey)) return; | |
| 1819 | if (event.defaultPrevented || typing(event.target)) return; | |
| 1820 | event.preventDefault(); | |
| 1821 | toggle(); | |
| 1822 | }; | |
| 1823 | window.addEventListener("keydown", onKey); | |
| 1824 | return () => window.removeEventListener("keydown", onKey); | |
| 1825 | }, [toggle]); | |
| 1826 | } | |
| 1827 | ||
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 1828 | /** |
| 1829 | * Search or jump to: the command palette. On a computer it looks like the | |
| 1830 | * field it opens, with its shortcut; on a phone, a magnifier. | |
| 1831 | */ | |
| 1832 | function SearchButton({ onClick }: { onClick: () => void }) { | |
| 1833 | return ( | |
| 1834 | <> | |
| 1835 | <Button variant="ghost" size="icon-bar" aria-label="Search or jump to" onClick={onClick} className="md:hidden"> | |
| 1836 | <Search size={18} /> | |
| 1837 | </Button> | |
| 1838 | <Button | |
| 1839 | variant="outline" | |
| 1840 | size="sm" | |
| 1841 | aria-label="Search or jump to" | |
| 1842 | onClick={onClick} | |
| 1843 | className="mr-1 w-[min(18rem,26vw)] justify-start bg-surface font-normal text-faint hover:bg-surface hover:text-muted max-md:hidden" | |
| 1844 | > | |
| 1845 | <Search size={15} /> | |
| 1846 | <span className="grow truncate text-left">Search or jump to</span> | |
| 1847 | <PaletteKey className="rounded border border-line bg-bg px-1.5 font-mono text-[0.625rem] leading-4 text-muted" /> | |
| 1848 | </Button> | |
| 1849 | </> | |
| 1850 | ); | |
| 1851 | } | |
| 1852 | ||
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1853 | /** The button that shows or hides the sidebar. */ |
| 1854 | function SidebarToggle({ onClick, open, className = "" }: { onClick: () => void; open: boolean; className?: string }) { | |
| 1855 | const key = sidebarKeyLabel(typeof navigator === "undefined" ? null : navigator.platform); | |
| 1856 | return ( | |
| 1857 | <Hint label={`Toggle sidebar (${key})`}> | |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 1858 | <Button variant="ghost" size="icon-sm" aria-label={open ? "Hide the sidebar" : "Show the sidebar"} aria-expanded={open} onClick={onClick} className={className}> |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1859 | <PanelLeft size={17} /> |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 1860 | </Button> |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1861 | </Hint> |
| 1862 | ); | |
| 1863 | } | |
| 1864 | ||
| Chat and workspace agents: channels, DMs and named agents you talk to | 1865 | /** |
| The docs folder is gone, and what it held lives where people read it: how a self-hosted g1t runs and how to deploy g1t to Cloudflare are pages on docs.g1t.sh under Run g1t yourself, and speed, rate limits and operating g1t.sh are sections of CONTRIBUTING.md; code that cited a file in docs/ now points to the page or section that covers it, or says what it means itself, and applied migrations and the runner images are left as they were. | 1866 | * The app: three surfaces that never blur |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1867 | * together. The dock, a floating bar of apps down the left; the mode's |
| 1868 | * sidebar, flat on the background beside it, which folds away with Ctrl B | |
| 1869 | * and is a drawer below 1024px; and the page, a rounded panel inset from | |
| 1870 | * the window, with its header across the top: the sidebar's toggle, where | |
| 1871 | * you are, search, Ask g1t and Create new. On a phone the dock is a bar | |
| 1872 | * along the bottom. Only for someone signed in; without a workspace yet, | |
| 1873 | * there is no dock. | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1874 | */ |
| 1875 | export function AppShell({ | |
| 1876 | user, | |
| 1877 | shell, | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 1878 | missing = false, |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1879 | banner, |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1880 | sidebarClosed = false, |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1881 | children, |
| 1882 | }: { | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1883 | user: User; |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1884 | shell: ShellData; |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1885 | /** The page is a 404 (see CodeSidebar). */ |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 1886 | missing?: boolean; |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1887 | banner?: ReactNode; |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1888 | /** Whether the person folded the sidebar away, as their cookie says. */ |
| 1889 | sidebarClosed?: boolean; | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1890 | children: ReactNode; |
| 1891 | }) { | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1892 | const { pathname } = useLocation(); |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1893 | const [drawer, setDrawer] = useState(false); |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1894 | const [closed, setClosed] = useState(sidebarClosed); |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1895 | const [palette, setPalette] = useState(false); |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1896 | const commands = useMemo(() => commandsFor(user, shell), [user, shell]); |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1897 | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1898 | // A new page closes the drawer. |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1899 | useEffect(() => setDrawer(false), [pathname]); |
| Search across all of g1t, Explore, and a command palette | 1900 | usePaletteShortcut(() => setPalette((open) => !open)); |
| Merge branch 'worktree-agent-aca4790ea223aa235' | 1901 | const leaving = useLeaving(); |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1902 | useVisualViewport(); |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 1903 | // Whether the page has scrolled under the top bar, which then draws its line (see data-page-head). |
| 1904 | const [scrolled, setScrolled] = useState(false); | |
| 1905 | useEffect(() => { | |
| 1906 | const onScroll = () => setScrolled(window.scrollY > 2); | |
| 1907 | onScroll(); | |
| 1908 | window.addEventListener("scroll", onScroll, { passive: true }); | |
| 1909 | return () => window.removeEventListener("scroll", onScroll); | |
| 1910 | }, []); | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1911 | |
| Chat and workspace agents: channels, DMs and named agents you talk to | 1912 | const going = useNavigation().location?.pathname; |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1913 | const ws = shell.workspace; |
| 1914 | const mode = modeOf(going ?? pathname, ws?.slug ?? null); | |
| 1915 | const panel = sidebarFor(mode, ws != null); | |
| 1916 | const code = ws ? hasCodeAccess(ws) : false; | |
| Chat and workspace agents: channels, DMs and named agents you talk to | 1917 | const { sidebar: chatSidebar } = useChatSidebar(); |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1918 | // Notify: the feed socket's live counts (lib/notify-client.ts) once it has them; the page's until then. |
| 1919 | const live = useLiveBadges(ws?.slug); | |
| 1920 | const chatUnread = chatSidebar | |
| 1921 | ? unreadTotals(chatSidebar.entries) | |
| 1922 | : live?.chat != null | |
| 1923 | ? { unread: live.chat, mentions: live.mentions ?? 0 } | |
| 1924 | : (shell.chat ?? { unread: 0, mentions: 0 }); | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1925 | const notificationsUnread = live?.inbox ?? shell.inbox?.unread ?? 0; |
| 1926 | const unread = { notifications: notificationsUnread, chat: chatUnread.unread, mentions: chatUnread.mentions }; | |
| 1927 | ||
| 1928 | // Folding the sidebar away on a computer is remembered, so the next page is drawn the same from the server. | |
| 1929 | const toggleSidebar = useCallback(() => { | |
| 1930 | if (!window.matchMedia("(min-width: 1024px)").matches) { | |
| 1931 | setDrawer((open) => !open); | |
| 1932 | return; | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1933 | } |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1934 | setClosed((was) => { |
| 1935 | document.cookie = sidebarCookie(!was, window.location.protocol === "https:"); | |
| 1936 | return !was; | |
| 1937 | }); | |
| 1938 | }, []); | |
| 1939 | useSidebarShortcut(useCallback(() => { | |
| 1940 | if (panel) toggleSidebar(); | |
| 1941 | }, [panel, toggleSidebar])); | |
| 1942 | ||
| 1943 | const inline = panel != null && !closed; | |
| 1944 | const sidebarNode = () => { | |
| 1945 | if (!panel) return null; | |
| 1946 | if (!ws) return panel === "notifications" ? <NotificationsSidebar counts={shell.inbox ?? null} /> : <AccountSidebar username={user.username} />; | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1947 | switch (panel) { |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1948 | case "code": |
| 1949 | return <CodeSidebar user={user} shell={shell} missing={missing} />; | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1950 | case "chat": |
| 1951 | return <ChatSidebar slug={ws.slug} />; | |
| Artifacts is a mode in the rail, the shell and the phone's tab bar in place of Docs: its home lists everything you can open by day or as cards under All, Yours and Shared with you, with search, filters and tiles to start a doc (slides, designs and dashboards say they are coming soon), and its sidebar holds favorites, spaces, Private, Shared, projects' docs and the trash. | 1952 | case "artifacts": |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1953 | return <FoliosSidebar slug={ws.slug} />; |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1954 | case "agents": |
| 1955 | return <AgentsSidebar slug={ws.slug} shellAgents={shell.agents ?? null} code={code} owner={ws.role === "owner"} />; | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1956 | case "notifications": |
| 1957 | return <NotificationsSidebar counts={shell.inbox ?? null} />; | |
| 1958 | case "people": | |
| 1959 | return <PeopleSidebar slug={ws.slug} />; | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1960 | case "workspace": |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1961 | return <WorkspaceSidebar slug={ws.slug} owner={ws.role === "owner"} />; |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1962 | case "account": |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1963 | return <AccountSidebar username={user.username} />; |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1964 | } |
| 1965 | }; | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1966 | // The sidebar's top row: the workspace and its switcher, and the way to fold the sidebar or close the drawer. |
| 1967 | const sidebarTop = (inDrawer: boolean) => ( | |
| 1968 | <div className="flex h-14 shrink-0 items-center gap-1 pr-1 pl-1"> | |
| 1969 | {ws ? ( | |
| 1970 | <WorkspaceSwitcher user={user} workspace={ws} /> | |
| 1971 | ) : ( | |
| 1972 | <Link to="/" aria-label="g1t" className="mr-auto flex h-9 items-center rounded-md px-2"> | |
| 1973 | <Logo className="text-[1.125rem]" /> | |
| 1974 | </Link> | |
| 1975 | )} | |
| 1976 | {inDrawer ? ( | |
| 1977 | <button type="button" aria-label="Close menu" onClick={() => setDrawer(false)} className="flex size-8 shrink-0 items-center justify-center rounded-md text-faint hover:bg-raised hover:text-fg"> | |
| 1978 | <X size={16} /> | |
| 1979 | </button> | |
| 1980 | ) : ( | |
| 1981 | <SidebarToggle open onClick={toggleSidebar} /> | |
| 1982 | )} | |
| 1983 | </div> | |
| 1984 | ); | |
| 1985 | ||
| 1986 | // On a phone (below 768px): the bottom bar, and a conversation full screen. | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 1987 | const conversation = isConversation(going ?? pathname); |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1988 | // Where the page panel starts: 8px past the dock (88px), or right after the sidebar (260px) when it is open. |
| 1989 | const left = ws ? (inline ? "md:left-24 lg:left-[21.75rem]" : "md:left-24") : inline ? "md:left-2 lg:left-[16.75rem]" : "md:left-2"; | |
| 1990 | const pad = ws ? (inline ? "md:pl-24 lg:pl-[21.75rem]" : "md:pl-24") : inline ? "md:pl-2 lg:pl-[16.75rem]" : "md:pl-2"; | |
| Chat and workspace agents: channels, DMs and named agents you talk to | 1991 | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1992 | return ( |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1993 | // The drawer is a sheet: a dialog that holds focus, closes on Escape or |
| 1994 | // a tap outside, and gives focus back to the button that opened it. | |
| Usage, Billing settings and prepaid AI credit; fixes from the UX audit | 1995 | <Sheet open={drawer} onOpenChange={setDrawer}> |
| Usage while free is shown at cost; agents get rustfmt and clippy | 1996 | <Progress /> |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 1997 | {ws && ( |
| 1998 | <div className="fixed top-2 bottom-2 left-2 z-40 hidden w-20 md:block"> | |
| 1999 | <Dock | |
| 2000 | workspace={ws} | |
| 2001 | pins={shell.pins ?? []} | |
| 2002 | unread={unread} | |
| 2003 | account={<AccountMenu user={user} />} | |
| 2004 | /> | |
| 2005 | </div> | |
| 2006 | )} | |
| 2007 | {panel && ( | |
| 2008 | <aside | |
| 2009 | aria-label={`${MODE_MENU[panel]} sidebar`} | |
| 2010 | className={`fixed inset-y-0 z-40 hidden w-[16.25rem] flex-col pr-0.5 pl-1.5 ${ws ? "left-[5.5rem]" : "left-0"} ${inline ? "lg:flex" : ""}`} | |
| 2011 | > | |
| 2012 | {sidebarTop(false)} | |
| 2013 | <div className="min-h-0 grow">{sidebarNode()}</div> | |
| 2014 | </aside> | |
| 2015 | )} | |
| Chat and workspace agents: channels, DMs and named agents you talk to | 2016 | <SheetContent |
| 2017 | side="left" | |
| 2018 | showClose={false} | |
| 2019 | aria-describedby={undefined} | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 2020 | // Focus would land on the workspace's switcher and open its menu's hint; the sheet itself takes it instead. |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 2021 | onOpenAutoFocus={(event) => { |
| 2022 | event.preventDefault(); | |
| 2023 | (event.currentTarget as HTMLElement | null)?.focus(); | |
| 2024 | }} | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 2025 | className="flex w-[min(18.5rem,86vw)] flex-col border-line bg-shell px-1.5 pb-[env(safe-area-inset-bottom)] max-md:[&_nav_a]:min-h-10" |
| Chat and workspace agents: channels, DMs and named agents you talk to | 2026 | > |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 2027 | <SheetTitle className="sr-only">{panel ? `${MODE_MENU[panel]} menu` : "Menu"}</SheetTitle> |
| 2028 | {sidebarTop(true)} | |
| 2029 | <div className="min-h-0 grow">{sidebarNode()}</div> | |
| Usage, Billing settings and prepaid AI credit; fixes from the UX audit | 2030 | </SheetContent> |
| Usage while free is shown at cost; agents get rustfmt and clippy | 2031 | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 2032 | <div className={`min-h-dvh px-1.5 pt-(--frame-top) pb-(--tabbar-h) md:pr-2 ${pad}`}> |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 2033 | {/* A page whose own header sits right under this bar (data-page-head: a conversation's, a project's) reads as one |
| 2034 | block with it: no line between them until the page scrolls under the bar. A sticky one (data-page-head="sticky", | |
| 2035 | an open artifact's) stays under the bar, so the line is always its. */} | |
| 2036 | <div className="flex min-h-[calc(100dvh-var(--frame-top)-var(--tabbar-h))] min-w-0 flex-col rounded-[14px] bg-bg [&:has([data-page-head])>header:not([data-scrolled])]:border-b-transparent [&:has([data-page-head=sticky])>header]:border-b-transparent"> | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 2037 | <header |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 2038 | data-scrolled={scrolled || undefined} |
| 2039 | className={`sticky top-(--frame-top) z-30 flex h-14 items-center gap-1 rounded-t-[14px] border-b border-line bg-bg pr-2 pl-2 transition-[border-color] duration-150 sm:pr-3 ${inline ? "lg:pl-3.5" : ""} ${conversation ? "max-md:hidden" : ""}`} | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 2040 | > |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 2041 | {panel && ( |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 2042 | <SidebarToggle open={drawer} onClick={toggleSidebar} className={`max-md:size-11 ${inline ? "lg:hidden" : ""}`} /> |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 2043 | )} |
| 2044 | {ws && ( | |
| 2045 | <span className={`flex min-w-0 shrink items-center gap-1.5 ${inline ? "lg:hidden" : ""}`}> | |
| 2046 | <WorkspaceSwitcher user={user} workspace={ws} compact /> | |
| 2047 | <span aria-hidden="true" className="text-line-strong"> | |
| 2048 | / | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 2049 | </span> |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 2050 | </span> |
| Inbox: a bell in the top bar opens it beside the page, and /inbox holds it all | 2051 | )} |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 2052 | <Breadcrumbs pathname={pathname} missing={missing} repo={shell.repo} workspace={ws?.slug ?? null} /> |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 2053 | {/* Search, then what's yours (spend, Ask g1t), then the bell and Create new: one height, one rhythm. */} |
| 2054 | <div className="ml-auto flex shrink-0 items-center gap-1 md:gap-1.5"> | |
| 2055 | <SearchButton onClick={() => setPalette(true)} /> | |
| The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how. | 2056 | {/* Your spend this month, or the workspace's for owners and billing managers; on a phone it is on Spend. */} |
| 2057 | {ws && ( | |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 2058 | <span className="flex max-md:hidden"> |
| The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how. | 2059 | <SpendPill slug={ws.slug} mayWorkspace={ws.role === "owner" || !!ws.org_roles?.includes("billing_manager")} /> |
| 2060 | </span> | |
| 2061 | )} | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 2062 | {ws && <AskG1tButton slug={ws.slug} />} |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 2063 | <Separator orientation="vertical" className="mx-1 data-[orientation=vertical]:h-5 max-md:hidden" /> |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 2064 | {/* On a phone, Notifications is in the bottom bar. */} |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 2065 | <span className="flex max-md:hidden"> |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 2066 | <NotificationsBell counts={shell.inbox ? { ...shell.inbox, unread: notificationsUnread } : null} /> |
| 2067 | </span> | |
| 2068 | <CreateMenu shell={shell} /> | |
| 2069 | {/* Without a workspace there is no dock: the account is here. */} | |
| 2070 | {!ws && <AccountMenu user={user} side="bottom" />} | |
| 2071 | </div> | |
| 2072 | </header> | |
| 2073 | {banner} | |
| 2074 | <main id="content" tabIndex={-1} {...leaving} className={`min-w-0 grow outline-none ${leaving.className}`}> | |
| 2075 | <InMain.Provider value={true}>{children}</InMain.Provider> | |
| 2076 | </main> | |
| 2077 | </div> | |
| Usage while free is shown at cost; agents get rustfmt and clippy | 2078 | </div> |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 2079 | {/* The panel's edge: a rounded frame over the page, with the background beyond it, so what scrolls stays inside. |
| 2080 | Every page has it, a conversation too; only a phone's conversation, full screen over everything, goes without. */} | |
| 2081 | <div | |
| 2082 | aria-hidden="true" | |
| 2083 | className={`pointer-events-none fixed top-(--frame-top) right-1.5 bottom-(--tabbar-h) left-1.5 z-[35] rounded-[14px] shadow-[0_0_0_1px_var(--color-line),0_0_0_100vmax_var(--color-shell)] md:right-2 ${left} ${conversation ? "max-md:hidden" : ""}`} | |
| 2084 | /> | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 2085 | {ws && <BottomBar user={user} workspace={ws} pins={shell.pins ?? []} unread={unread} onReselect={panel ? () => setDrawer(true) : undefined} />} |
| 2086 | <CommandPalette open={palette} onOpenChange={setPalette} commands={commands} repo={shell.repo ? `${shell.repo.namespace}/${shell.repo.name}` : null} /> | |
| Usage, Billing settings and prepaid AI credit; fixes from the UX audit | 2087 | </Sheet> |
| Usage while free is shown at cost; agents get rustfmt and clippy | 2088 | ); |
| 2089 | } | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 2090 | |
| 2091 | /** Create new: a project, an issue in the one you are in, a workspace or a team. */ | |
| 2092 | function CreateMenu({ shell }: { shell: ShellData }) { | |
| 2093 | return ( | |
| 2094 | <DropdownMenu> | |
| 2095 | <Hint label="Create new"> | |
| The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work. | 2096 | <DropdownMenuTrigger asChild> |
| 2097 | <Button variant="ghost" size="bar" aria-label="Create new" className="gap-0.5 px-1.5 text-fg/90"> | |
| 2098 | <Plus size={17} className="max-md:size-5" /> | |
| 2099 | <ChevronDown size={12} className="text-faint max-md:hidden" /> | |
| 2100 | </Button> | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 2101 | </DropdownMenuTrigger> |
| 2102 | </Hint> | |
| 2103 | <DropdownMenuContent align="end" className="min-w-52"> | |
| 2104 | {shell.repo && ( | |
| 2105 | <> | |
| 2106 | <DropdownMenuLabel className="truncate">In {shell.repo.name}</DropdownMenuLabel> | |
| 2107 | <DropdownMenuItem asChild> | |
| 2108 | <Link to={`/${shell.repo.namespace}/${shell.repo.name}/issues/new`}> | |
| 2109 | <CircleDot /> | |
| 2110 | New issue | |
| 2111 | </Link> | |
| 2112 | </DropdownMenuItem> | |
| 2113 | {shell.repo.member && ( | |
| 2114 | <DropdownMenuItem asChild> | |
| 2115 | <Link to={`/${shell.repo.namespace}/${shell.repo.name}/plans`}> | |
| 2116 | <ListTree /> | |
| 2117 | Plan work | |
| 2118 | </Link> | |
| 2119 | </DropdownMenuItem> | |
| 2120 | )} | |
| 2121 | <DropdownMenuSeparator /> | |
| 2122 | </> | |
| 2123 | )} | |
| 2124 | <DropdownMenuItem asChild> | |
| 2125 | <Link to="/?agent=new"> | |
| 2126 | <Sparkles /> | |
| 2127 | Put an agent on it | |
| 2128 | </Link> | |
| 2129 | </DropdownMenuItem> | |
| 2130 | <DropdownMenuItem asChild> | |
| 2131 | <Link to="/new"> | |
| 2132 | <Box /> | |
| 2133 | New project | |
| 2134 | </Link> | |
| 2135 | </DropdownMenuItem> | |
| 2136 | <DropdownMenuItem asChild> | |
| 2137 | <Link to="/new/github"> | |
| 2138 | <GitBranch /> | |
| 2139 | Import from GitHub | |
| 2140 | </Link> | |
| 2141 | </DropdownMenuItem> | |
| 2142 | <DropdownMenuSeparator /> | |
| 2143 | <DropdownMenuItem asChild> | |
| 2144 | <Link to="/workspaces/new"> | |
| 2145 | <Users /> | |
| 2146 | New workspace | |
| 2147 | </Link> | |
| 2148 | </DropdownMenuItem> | |
| 2149 | {/* A team in the workspace you are in, for whoever it lets create one. */} | |
| 2150 | {shell.workspace && | |
| 2151 | (mayCreateTeams(shell.workspace.team_creation, shell.workspace.role) ? ( | |
| 2152 | <DropdownMenuItem asChild> | |
| 2153 | <Link to={`/${shell.workspace.slug}/-/teams/new`}> | |
| 2154 | <UsersRound /> | |
| 2155 | New team | |
| 2156 | </Link> | |
| 2157 | </DropdownMenuItem> | |
| 2158 | ) : ( | |
| 2159 | <DropdownMenuItem disabled> | |
| 2160 | <UsersRound /> | |
| 2161 | New team | |
| 2162 | <span className="ml-auto pl-3 text-xs text-faint">Owners only</span> | |
| 2163 | </DropdownMenuItem> | |
| 2164 | ))} | |
| 2165 | </DropdownMenuContent> | |
| 2166 | </DropdownMenu> | |
| 2167 | ); | |
| 2168 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.