Commit

Docs in the shape of docs.continue.dev

Tabs under the header (Documentation, API reference), each with its own sidebar of groups that do not fold. Page titles carry their description as a subtitle and a Copy page menu: copy as Markdown, view as Markdown, or open in Claude or ChatGPT. Every page has a Markdown twin at its path plus .md. Sections open with space instead of rules, code blocks lose their window chrome, inline code is quieter, and the home page is a doc page, "What is g1t?", with cards to start from.

syntaqxcommitted Parentcb4dbefBrowse files
9 files+426−1810/9 viewed
+7−1
99 title: 'g1t docs',
1010 description: 'Guides and reference for g1t, the git forge for teams of agents.',
1111 components: {
12+ Header: './src/components/Header.astro',
13+ PageTitle: './src/components/PageTitle.astro',
1214 SiteTitle: './src/components/SiteTitle.astro',
1315 SocialIcons: './src/components/SocialIcons.astro',
1416 },
17+ // Each tab under the header shows its own part of the sidebar.
18+ routeMiddleware: './src/route-data.ts',
1519 expressiveCode: {
1620 themes: ['github-dark-default'],
21+ // Plain panels with a copy button, without window chrome.
22+ defaultProps: { frame: 'none' },
1723 styleOverrides: {
1824 borderRadius: '0.75rem',
1925 borderColor: 'var(--g1t-line)',
102108 label: 'Reference',
103109 items: [
104110 { label: 'API overview', slug: 'reference/api' },
105− { label: 'API reference', link: '/api/reference/', attrs: { target: '_self' } },
111+ { label: 'API explorer', link: '/api/reference/', attrs: { target: '_self' } },
106112 { label: 'MCP tools', slug: 'reference/mcp' },
107113 { label: 'OpenAPI document', link: 'https://api.g1t.sh/openapi.json' },
108114 { label: 'llms.txt', link: 'https://g1t.sh/llms.txt' },
+65−0
1+---
2+// Starlight's header, with the tabs that divide the docs beneath it.
3+import Default from '@astrojs/starlight/components/Header.astro';
4+
5+import { TABS, tabFor } from '../tabs';
6+
7+const current = tabFor(Astro.locals.starlightRoute.id);
8+---
9+
10+<div class="g1t-header">
11+ <div class="g1t-header-top"><Default /></div>
12+ <nav class="g1t-tabs" aria-label="Sections">
13+ {
14+ TABS.map((tab) => (
15+ <a href={tab.href} aria-current={tab === current ? 'page' : undefined}>
16+ {tab.label}
17+ </a>
18+ ))
19+ }
20+ </nav>
21+</div>
22+
23+<style>
24+ .g1t-header {
25+ display: flex;
26+ flex-direction: column;
27+ height: 100%;
28+ }
29+ .g1t-header-top {
30+ height: 3.5rem;
31+ padding: 0 var(--sl-nav-pad-x);
32+ }
33+ /* On phones the menu button sits at the top row's end: leave it room. */
34+ @media (max-width: 49.99rem) {
35+ :global([data-has-sidebar]) .g1t-header-top {
36+ padding-inline-end: calc(var(--sl-nav-pad-x) + var(--sl-menu-button-size) + var(--sl-nav-gap));
37+ }
38+ }
39+ .g1t-tabs {
40+ display: flex;
41+ gap: 1.5rem;
42+ height: 2.75rem;
43+ padding: 0 var(--sl-nav-pad-x);
44+ overflow-x: auto;
45+ scrollbar-width: none;
46+ }
47+ .g1t-tabs a {
48+ display: flex;
49+ align-items: center;
50+ border-bottom: 1.5px solid transparent;
51+ font-size: 0.875rem;
52+ font-weight: 500;
53+ white-space: nowrap;
54+ color: var(--g1t-muted);
55+ text-decoration: none;
56+ transition: color 0.15s;
57+ }
58+ .g1t-tabs a:hover {
59+ color: var(--g1t-fg);
60+ }
61+ .g1t-tabs a[aria-current='page'] {
62+ border-color: var(--g1t-fg);
63+ color: var(--g1t-fg);
64+ }
65+</style>
+180−0
1+---
2+// A page's title, what it is about beneath it, and a way to take the page
3+// to an AI assistant: copied as Markdown, read as Markdown, or opened in
4+// Claude or ChatGPT.
5+const { entry, id } = Astro.locals.starlightRoute;
6+const { title, description } = entry.data;
7+const markdown = `/${id === '' || id === 'index' ? 'index' : id}.md`;
8+const absolute = new URL(markdown, Astro.site).href;
9+const ask = encodeURIComponent(`Read ${absolute} so I can ask questions about it.`);
10+---
11+
12+<div class="g1t-page-title">
13+ <div class="g1t-page-title-row">
14+ <h1 id="_top">{title}</h1>
15+ <div class="g1t-copy">
16+ <button type="button" class="g1t-copy-main" data-markdown={markdown}>
17+ <svg viewBox="0 0 16 16" aria-hidden="true">
18+ <rect x="5" y="5" width="9" height="9" rx="1.5"></rect>
19+ <path d="M11 5V3.5A1.5 1.5 0 0 0 9.5 2h-6A1.5 1.5 0 0 0 2 3.5v6A1.5 1.5 0 0 0 3.5 11H5"></path>
20+ </svg>
21+ <span>Copy page</span>
22+ </button>
23+ <details class="g1t-copy-more">
24+ <summary aria-label="More ways to use this page">
25+ <svg viewBox="0 0 16 16" aria-hidden="true"><path d="m4 6 4 4 4-4"></path></svg>
26+ </summary>
27+ <div class="g1t-copy-menu">
28+ <a href={markdown} target="_blank" rel="noopener">
29+ <strong>View as Markdown</strong>
30+ <span>This page as plain text</span>
31+ </a>
32+ <a href={`https://claude.ai/new?q=${ask}`} target="_blank" rel="noopener">
33+ <strong>Open in Claude</strong>
34+ <span>Ask questions about this page</span>
35+ </a>
36+ <a href={`https://chatgpt.com/?hints=search&q=${ask}`} target="_blank" rel="noopener">
37+ <strong>Open in ChatGPT</strong>
38+ <span>Ask questions about this page</span>
39+ </a>
40+ </div>
41+ </details>
42+ </div>
43+ </div>
44+ {description && <p class="g1t-description">{description}</p>}
45+</div>
46+
47+<script>
48+ document.querySelectorAll<HTMLButtonElement>('.g1t-copy-main').forEach((button) => {
49+ button.addEventListener('click', async () => {
50+ const label = button.querySelector('span')!;
51+ try {
52+ const text = await (await fetch(button.dataset.markdown!)).text();
53+ await navigator.clipboard.writeText(text);
54+ label.textContent = 'Copied';
55+ } catch {
56+ label.textContent = 'Could not copy';
57+ }
58+ setTimeout(() => (label.textContent = 'Copy page'), 1600);
59+ });
60+ });
61+ // A menu closes when you click elsewhere.
62+ document.addEventListener('click', (event) => {
63+ document.querySelectorAll<HTMLDetailsElement>('.g1t-copy-more[open]').forEach((menu) => {
64+ if (!menu.contains(event.target as Node)) menu.open = false;
65+ });
66+ });
67+</script>
68+
69+<style>
70+ .g1t-page-title {
71+ margin-top: 0.75rem;
72+ }
73+ .g1t-page-title-row {
74+ display: flex;
75+ align-items: flex-start;
76+ justify-content: space-between;
77+ gap: 1.5rem;
78+ }
79+ h1 {
80+ margin: 0;
81+ font-size: 2rem;
82+ font-weight: 600;
83+ letter-spacing: -0.025em;
84+ line-height: 1.2;
85+ color: var(--g1t-fg);
86+ }
87+ .g1t-description {
88+ margin-top: 0.6rem;
89+ max-width: 42rem;
90+ font-size: 1.125rem;
91+ line-height: 1.55;
92+ color: var(--g1t-muted);
93+ }
94+ .g1t-copy {
95+ position: relative;
96+ display: flex;
97+ flex-shrink: 0;
98+ margin-top: 0.35rem;
99+ border-radius: 0.5rem;
100+ box-shadow: inset 0 0 0 1px var(--g1t-line);
101+ }
102+ .g1t-copy svg {
103+ width: 0.9rem;
104+ height: 0.9rem;
105+ fill: none;
106+ stroke: currentColor;
107+ stroke-width: 1.3;
108+ stroke-linecap: round;
109+ stroke-linejoin: round;
110+ }
111+ .g1t-copy-main,
112+ .g1t-copy-more summary {
113+ display: flex;
114+ align-items: center;
115+ gap: 0.4rem;
116+ border: 0;
117+ background: transparent;
118+ padding: 0.3rem 0.6rem;
119+ font: inherit;
120+ font-size: 0.8125rem;
121+ color: var(--g1t-muted);
122+ cursor: pointer;
123+ transition: color 0.15s, background 0.15s;
124+ }
125+ .g1t-copy-main {
126+ border-radius: 0.5rem 0 0 0.5rem;
127+ }
128+ .g1t-copy-more summary {
129+ list-style: none;
130+ border-left: 1px solid var(--g1t-line);
131+ border-radius: 0 0.5rem 0.5rem 0;
132+ padding-inline: 0.45rem;
133+ }
134+ .g1t-copy-more summary::-webkit-details-marker {
135+ display: none;
136+ }
137+ .g1t-copy-main:hover,
138+ .g1t-copy-more summary:hover {
139+ background: var(--g1t-surface);
140+ color: var(--g1t-fg);
141+ }
142+ .g1t-copy-menu {
143+ position: absolute;
144+ top: calc(100% + 0.4rem);
145+ right: 0;
146+ z-index: 10;
147+ width: 15rem;
148+ border-radius: 0.75rem;
149+ padding: 0.35rem;
150+ background: var(--g1t-raised);
151+ box-shadow:
152+ inset 0 0 0 1px var(--g1t-line-strong),
153+ 0 12px 32px rgb(0 0 0 / 0.45);
154+ }
155+ .g1t-copy-menu a {
156+ display: block;
157+ border-radius: 0.5rem;
158+ padding: 0.45rem 0.6rem;
159+ text-decoration: none;
160+ }
161+ .g1t-copy-menu a:hover {
162+ background: var(--g1t-surface);
163+ }
164+ .g1t-copy-menu strong {
165+ display: block;
166+ font-size: 0.8125rem;
167+ font-weight: 500;
168+ color: var(--g1t-fg);
169+ }
170+ .g1t-copy-menu span {
171+ display: block;
172+ font-size: 0.75rem;
173+ color: var(--g1t-faint);
174+ }
175+ @media (max-width: 40rem) {
176+ .g1t-copy {
177+ display: none;
178+ }
179+ }
180+</style>
+1−1
33 ---
44
55 <nav class="g1t-nav" aria-label="g1t">
6− <a href="/api/reference/">API reference</a>
6+ <a href="/api/reference/">API explorer</a>
77 <a href="https://g1t.sh/">g1t.sh</a>
88 <a href="https://g1t.sh/register" class="g1t-nav-cta">Sign up</a>
99 <a href="https://github.com/syntaqx/g1t" aria-label="Source on GitHub" class="g1t-nav-icon">
+57−77
11 ---
2−title: g1t docs
3−description: Guides and reference for g1t, the git forge for teams of agents.
4−template: splash
2+title: What is g1t?
3+description: A git forge for teams of agents. Hand it an outcome, and agents land it on main while your team works the way it does on GitHub.
54 tableOfContents: false
5+prev: false
66 ---
77
8−<div class="g1t-home-hero">
9− <p class="g1t-eyebrow">Documentation</p>
10− <h1>Build with g1t</h1>
11− <p>
12− Hand g1t an outcome and a team of agents converges it onto main, while you and
13− your team work exactly as you would on GitHub. Start with the path that fits.
14− </p>
15−</div>
8+import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components';
9+
10+**g1t hosts your repositories and runs a team of agents on them.** Write
11+what you want done; agents split it into issues, make a pull request for
12+each, test it in a clean sandbox, review it, fix what the review finds and
13+merge it under your repository's rules. People work alongside them with
14+the same issues, pull requests and reviews they know from GitHub.
1615
17−<div class="g1t-paths">
18− <a class="g1t-path" href="/quickstart/">
19− <em>5 minutes</em>
20− <strong>Quickstart</strong>
21− <span>Create a workspace, push a repository, and land your first change with an agent.</span>
22− </a>
23− <a class="g1t-path" href="/guides/outcomes/">
24− <em>Agents</em>
25− <strong>Hand off an outcome</strong>
26− <span>Write what you want. A planner splits it into issues, and agents land them in order.</span>
27− </a>
28− <a class="g1t-path" href="/guides/bring-your-own-agent/">
29− <em>Your agent</em>
30− <strong>Bring your own agent</strong>
31− <span>Connect Claude Code or any MCP client, and record its sessions onto pull requests.</span>
32− </a>
33− <a class="g1t-path" href="/reference/api/">
34− <em>Build</em>
35− <strong>The API</strong>
36− <span>Everything on g1t over REST and MCP, with an explorer to call it from the page.</span>
37− </a>
38−</div>
16+<CardGrid>
17+ <LinkCard
18+ title="Quickstart"
19+ description="Create a workspace, push a repository and land your first change with an agent, in five minutes."
20+ href="/quickstart/"
21+ />
22+ <LinkCard
23+ title="Move from GitHub"
24+ description="Push your repository, rename .github to .g1t, and your Actions workflows run here as they are."
25+ href="/guides/actions/"
26+ />
27+</CardGrid>
28+
29+## What you can do
30+
31+<CardGrid>
32+ <Card title="Hand off an outcome" icon="rocket">
33+ Describe a result. A planner turns it into issues in the order they land, and
34+ [agents work them in parallel](/guides/outcomes/).
35+ </Card>
36+ <Card title="Agents that finish" icon="approve-check">
37+ Each change is checked, reviewed and revised until it passes, then merged
38+ through the [merge queue](/guides/merge-queue/). You step in only when asked.
39+ </Card>
40+ <Card title="Bring your own agent" icon="laptop">
41+ Claude Code or any MCP client works on g1t as a teammate, and
42+ [records its session](/guides/bring-your-own-agent/) onto its pull requests.
43+ </Card>
44+ <Card title="GitHub Actions, unchanged" icon="github">
45+ Workflows run from `.g1t/workflows` [as GitHub runs them](/guides/actions/),
46+ and failing ones send the agent back to fix the cause.
47+ </Card>
48+ <Card title="Your models, your tools" icon="puzzle">
49+ Use g1t's models or [your own providers](/guides/models/), and pull context
50+ from [Sentry, Jira and Linear](/guides/integrations/).
51+ </Card>
52+ <Card title="Everything has an API" icon="open-book">
53+ Every action is a [REST endpoint and an MCP tool](/reference/api/), with
54+ [webhooks](/guides/webhooks/) for every event.
55+ </Card>
56+</CardGrid>
57+
58+## Using an AI assistant?
3959
40−<div class="g1t-columns">
41− <div>
42− <h3>Agents</h3>
43− <ul>
44− <li><a href="/guides/g1t-agents/">g1t agents</a></li>
45− <li><a href="/guides/outcomes/">Outcomes and plans</a></li>
46− <li><a href="/guides/talking-to-agents/">Talking to agents</a></li>
47− <li><a href="/guides/bring-your-own-agent/">Bring your own agent</a></li>
48− <li><a href="/guides/integrations/">Integrations: Sentry, Jira, Linear</a></li>
49− <li><a href="/guides/models/">Model providers: Anthropic, OpenAI, Gemini</a></li>
50− <li><a href="/guides/webhooks/">Webhooks</a></li>
51− <li><a href="/guides/actions/">GitHub Actions: rename .github to .g1t</a></li>
52− <li><a href="/guides/automations/">Automations</a></li>
53− </ul>
54− </div>
55− <div>
56− <h3>Landing changes</h3>
57− <ul>
58− <li><a href="/concepts/overview/">How g1t works</a></li>
59− <li><a href="/guides/merge-queue/">The merge queue</a></li>
60− <li><a href="/guides/why-blame/">Sessions and why-blame</a></li>
61− <li><a href="/concepts/forks/">Forks and branches</a></li>
62− </ul>
63− </div>
64− <div>
65− <h3>Workspaces</h3>
66− <ul>
67− <li><a href="/guides/authentication/">Accounts and sign-in</a></li>
68− <li><a href="/guides/workspaces/">Workspaces and tokens</a></li>
69− <li><a href="/guides/usage-and-billing/">Usage and billing</a></li>
70− <li><a href="/guides/git/">Git</a></li>
71− </ul>
72− </div>
73− <div>
74− <h3>Reference</h3>
75− <ul>
76− <li><a href="/reference/api/">API overview</a></li>
77− <li><a href="/api/reference/">API reference</a></li>
78− <li><a href="/reference/mcp/">MCP tools</a></li>
79− <li><a href="https://api.g1t.sh/openapi.json">OpenAPI document</a></li>
80− <li><a href="https://g1t.sh/llms.txt">llms.txt</a></li>
81− </ul>
82− </div>
83−</div>
60+Give it [g1t.sh/llms.txt](https://g1t.sh/llms.txt), which describes g1t for
61+agents, and ask it to set you up. Every page here also has **Copy page** at
62+the top, to paste into a conversation, and a plain Markdown version at its
63+address plus `.md`.
+23−0
1+import type { APIRoute, GetStaticPaths } from 'astro';
2+import { getCollection } from 'astro:content';
3+
4+/**
5+ * Every page as Markdown, at its path plus `.md`, for "Copy page" and for
6+ * agents that read the docs: the title, what it is about, then the page.
7+ */
8+export const getStaticPaths: GetStaticPaths = async () => {
9+ const pages = await getCollection('docs');
10+ return pages.map((page) => ({
11+ params: { slug: page.id === '' ? 'index' : page.id },
12+ props: { page },
13+ }));
14+};
15+
16+export const GET: APIRoute = ({ props }) => {
17+ const { page } = props as { page: Awaited<ReturnType<typeof getCollection<'docs'>>>[number] };
18+ const { title, description } = page.data;
19+ // MDX pages keep their markup; strip imports and leave the rest readable.
20+ const body = (page.body ?? '').replace(/^import .*$/gm, '').trim();
21+ const text = `# ${title}\n\n${description ? `> ${description}\n\n` : ''}${body}\n`;
22+ return new Response(text, { headers: { 'content-type': 'text/markdown; charset=utf-8' } });
23+};
+10−0
1+import { defineRouteMiddleware } from '@astrojs/starlight/route-data';
2+
3+import { tabFor } from './tabs';
4+
5+/** Each page's sidebar holds only its tab's groups. */
6+export const onRequest = defineRouteMiddleware((context) => {
7+ const route = context.locals.starlightRoute;
8+ const tab = tabFor(route.id);
9+ route.sidebar = route.sidebar.filter((entry) => entry.type === 'group' && tab.groups.includes(entry.label));
10+});
+59−102
3737 --sl-text-body: 0.9375rem;
3838 --sl-line-height: 1.75;
3939 --sl-content-width: 46rem;
40− --sl-nav-height: 3.5rem;
40+ /* The header's row, and the tabs beneath it. */
41+ --sl-nav-height: 6.25rem;
4142 --sl-sidebar-width: 17rem;
4243
4344 color-scheme: dark;
5152 /* --- Header --------------------------------------------------------------- */
5253
5354 header.header {
55+ padding: 0 !important;
5456 backdrop-filter: blur(10px);
5557 border-bottom: 1px solid var(--g1t-line);
5658 }
59+site-search {
60+ width: 100%;
61+ max-width: 30rem;
62+}
63+/* On phones the menu button sits in the header's top row, not its middle. */
64+.sl-menu-button {
65+ top: calc((3.5rem - var(--sl-menu-button-size)) / 2) !important;
66+}
5767 site-search button[data-open-modal] {
5868 border-radius: 0.5rem;
5969 background: var(--g1t-surface);
7080 .sidebar-content {
7181 padding-top: 1.25rem;
7282 }
83+/* Groups always show their pages: no caret, no folding. */
84+.sidebar-content details > summary {
85+ pointer-events: none;
86+ padding-top: 0.25rem;
87+}
88+.sidebar-content details > summary .caret {
89+ display: none;
90+}
91+.sidebar-content .top-level > li + li {
92+ margin-top: 1rem;
93+}
7394 /* Group labels: small and quiet, like section names, not links. */
7495 .sidebar-content details > summary .group-label .large,
7596 .sidebar-content .top-level > li > details > summary {
109130 .content-panel {
110131 padding-top: 2rem;
111132 }
112−.sl-markdown-content h1,
113−h1#_top {
133+/* The title and the page read as one, without a rule between them. */
134+.content-panel + .content-panel {
135+ border-top: 0;
136+ padding-top: 0.5rem;
137+}
138+.sl-markdown-content h1 {
114139 font-size: 2.25rem;
115140 font-weight: 650;
116141 letter-spacing: -0.03em;
117142 line-height: 1.15;
118143 color: var(--g1t-fg);
119144 }
120−/* Each section opens with a rule across the full column. */
145+/* Sections open with space, not rules. */
121146 .sl-markdown-content .sl-heading-wrapper.level-h2 {
122147 margin-top: 3rem;
123− padding-top: 1.75rem;
124− border-top: 1px solid var(--g1t-line);
125148 }
126149 .sl-markdown-content h2 {
127− font-size: 1.4rem;
128− font-weight: 650;
150+ font-size: 1.5rem;
151+ font-weight: 600;
129152 letter-spacing: -0.02em;
130153 color: var(--g1t-fg);
131154 }
150173 }
151174 .sl-markdown-content :not(pre) > code {
152175 border-radius: 0.3rem;
153− padding: 0.1rem 0.35rem;
176+ padding: 0.1rem 0.3rem;
154177 font-size: 0.85em;
155178 color: var(--g1t-fg);
156− box-shadow: inset 0 0 0 1px var(--g1t-line);
179+ background: var(--g1t-raised);
157180 }
158181
159182 /* Tables: ruled, not boxed. */
277300 color: var(--g1t-faint);
278301 }
279302
280−/* --- The home page -------------------------------------------------------- */
303+/* --- Cards ---------------------------------------------------------------- */
281304
282−/* The home page brings its own heading, so Starlight's title bar goes. */
283−main:has(.g1t-home-hero) > .content-panel:first-child {
284− display: none;
305+.sl-markdown-content .card-grid {
306+ gap: 0.75rem;
285307 }
286−main:has(.g1t-home-hero) > .content-panel {
287− border-top: 0;
308+.sl-markdown-content .card {
309+ padding: 1.1rem 1.2rem;
288310 }
289−.g1t-home-hero {
290− padding: 1rem 0 0.5rem;
311+.sl-markdown-content .card .title {
312+ font-size: 1rem;
313+ font-weight: 600;
314+ color: var(--g1t-fg);
291315 }
292−.sl-markdown-content .g1t-eyebrow {
293− font-family: var(--g1t-font-mono);
294− font-size: 0.72rem;
295− letter-spacing: 0.2em;
296− text-transform: uppercase;
316+.sl-markdown-content .card .icon {
297317 color: var(--g1t-merged);
298−}
299−.g1t-home-hero h1 {
300− margin: 0.75rem 0 0;
301− font-size: clamp(2.25rem, 5vw, 3.25rem);
302− font-weight: 650;
303− letter-spacing: -0.035em;
304− line-height: 1.05;
305− color: var(--g1t-fg);
318+ background: color-mix(in srgb, var(--g1t-merged) 12%, transparent);
306319 border: 0;
307− padding: 0;
308−}
309−.g1t-home-hero p {
310− max-width: 38rem;
311− margin-top: 1rem;
312− font-size: 1.05rem;
313− color: var(--g1t-muted);
320+ border-radius: 0.5rem;
321+ padding: 0.3rem;
314322 }
315−.g1t-paths {
316− display: grid;
317− gap: 0.75rem;
318− grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
319− margin-top: 2rem;
323+.sl-link-card {
324+ padding: 1rem 1.2rem;
320325 }
321−.g1t-path {
322− display: block;
323− border-radius: 1rem;
324− padding: 1.1rem 1.2rem;
325− background: var(--g1t-surface);
326− border: 1px solid var(--g1t-line);
327− text-decoration: none !important;
328− transition: border-color 0.15s, transform 0.15s;
329−}
330−.g1t-path:hover {
331− border-color: var(--g1t-line-strong);
332− transform: translateY(-1px);
333−}
334−.g1t-path strong {
335− display: block;
326+.sl-link-card .title {
336327 font-size: 0.95rem;
328+ font-weight: 600;
337329 color: var(--g1t-fg);
338330 }
339−.g1t-path span {
340− display: block;
341− margin-top: 0.35rem;
331+.sl-link-card .description {
342332 font-size: 0.85rem;
343− line-height: 1.55;
344333 color: var(--g1t-muted);
345334 }
346−.g1t-path em {
347− display: inline-block;
348− margin-bottom: 0.6rem;
335+
336+/* Steps: numbered, on a quiet rail. */
337+.sl-steps > li::before {
338+ background: var(--g1t-raised) !important;
339+ color: var(--g1t-fg) !important;
340+ box-shadow: inset 0 0 0 1px var(--g1t-line-strong);
349341 font-family: var(--g1t-font-mono);
350− font-size: 0.68rem;
351− font-style: normal;
352− letter-spacing: 0.14em;
353− text-transform: uppercase;
354− color: var(--g1t-merged);
355−}
356−.g1t-columns {
357− display: grid;
358− gap: 2rem;
359− grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
360− margin-top: 3rem !important;
361−}
362−.g1t-columns > div,
363−.g1t-paths > a {
364− margin-top: 0 !important;
365−}
366−.g1t-columns h3 {
367− margin: 0 0 0.5rem;
368342 font-size: 0.8rem;
369− font-weight: 600;
370− letter-spacing: 0.06em;
371− text-transform: uppercase;
372− color: var(--g1t-faint);
373343 }
374−.g1t-columns ul {
375− margin: 0;
376− padding: 0;
377− list-style: none;
378−}
379−.g1t-columns li {
380− margin: 0.3rem 0;
381−}
382−.g1t-columns a {
383− font-size: 0.9rem;
384− color: var(--g1t-fg-soft) !important;
385− text-decoration: none !important;
386−}
387−.g1t-columns a:hover {
388− color: #cfc6ff !important;
344+.sl-steps > li::after {
345+ background: var(--g1t-line) !important;
389346 }
+24−0
1+/**
2+ * The tabs under the header. Each shows its own part of the sidebar, as
3+ * the groups named here; a page belongs to the tab whose `match` it fits.
4+ */
5+export type Tab = { label: string; href: string; groups: string[]; match: (slug: string) => boolean };
6+
7+export const TABS: Tab[] = [
8+ {
9+ label: 'Documentation',
10+ href: '/',
11+ groups: ['Get started', 'Agents', 'Connect your tools', 'Landing changes', 'Workspaces'],
12+ match: (slug) => !slug.startsWith('reference/'),
13+ },
14+ {
15+ label: 'API reference',
16+ href: '/reference/api/',
17+ groups: ['Reference'],
18+ match: (slug) => slug.startsWith('reference/'),
19+ },
20+];
21+
22+export function tabFor(slug: string): Tab {
23+ return TABS.find((tab) => tab.match(slug)) ?? TABS[0];
24+}