Merge branch 'worktree-agent-aa1f74337a33b5f8b'
16 files+109−160/16 viewed
| 41 | 41 | integrations: [ | |
| 42 | 42 | starlight({ | |
| 43 | 43 | title: 'g1t docs', | |
| 44 | − | description: 'Guides and reference for g1t, where a team and its coding agents talk, build and ship.', | |
| 44 | + | description: 'Guides and reference for g1t, the code platform for your team and its coding agents.', | |
| 45 | 45 | components: { | |
| 46 | 46 | Footer: './src/components/Footer.astro', | |
| 47 | 47 | Head: './src/components/Head.astro', |
| 1 | + | User-agent: * | |
| 2 | + | Allow: / | |
| 3 | + | ||
| 4 | + | Sitemap: https://docs.g1t.sh/sitemap-index.xml |
| 1 | 1 | { | |
| 2 | 2 | "name": "g1t docs", | |
| 3 | 3 | "short_name": "g1t", | |
| 4 | − | "description": "How to use g1t: chat, agents, docs and code in one workspace.", | |
| 4 | + | "description": "How to use g1t, the code platform for your team and its coding agents.", | |
| 5 | 5 | "start_url": "/", | |
| 6 | 6 | "scope": "/", | |
| 7 | 7 | "display": "minimal-ui", |
| 45 | 45 | if (current && tabs && current.offsetLeft + current.offsetWidth > tabs.clientWidth) { | |
| 46 | 46 | tabs.scrollLeft = current.offsetLeft - (tabs.clientWidth - current.offsetWidth) / 2; | |
| 47 | 47 | } | |
| 48 | + | // The row fades out at an edge with more tabs past it, so a cut-off | |
| 49 | + | // tab reads as "scroll for more" rather than as a clipped word. | |
| 50 | + | const bar = document.querySelector<HTMLElement>('.g1t-tabs'); | |
| 51 | + | if (bar) { | |
| 52 | + | const edges = () => { | |
| 53 | + | const end = bar.scrollWidth - bar.clientWidth; | |
| 54 | + | bar.toggleAttribute('data-more-start', bar.scrollLeft > 1); | |
| 55 | + | bar.toggleAttribute('data-more-end', bar.scrollLeft < end - 1); | |
| 56 | + | }; | |
| 57 | + | edges(); | |
| 58 | + | bar.addEventListener('scroll', edges, { passive: true }); | |
| 59 | + | addEventListener('resize', edges); | |
| 60 | + | } | |
| 48 | 61 | </script> | |
| 49 | 62 | ||
| 50 | 63 | <style> | |
| ⋯ | |||
| 144 | 157 | .g1t-tabs::-webkit-scrollbar { | |
| 145 | 158 | display: none; | |
| 146 | 159 | } | |
| 160 | + | .g1t-tabs[data-more-start], | |
| 161 | + | .g1t-tabs[data-more-end] { | |
| 162 | + | --fade: 2.5rem; | |
| 163 | + | mask-image: linear-gradient( | |
| 164 | + | to right, | |
| 165 | + | transparent, | |
| 166 | + | #000 var(--fade-start, 0px), | |
| 167 | + | #000 calc(100% - var(--fade-end, 0px)), | |
| 168 | + | transparent | |
| 169 | + | ); | |
| 170 | + | } | |
| 171 | + | .g1t-tabs[data-more-start] { | |
| 172 | + | --fade-start: var(--fade); | |
| 173 | + | } | |
| 174 | + | .g1t-tabs[data-more-end] { | |
| 175 | + | --fade-end: var(--fade); | |
| 176 | + | } | |
| 147 | 177 | .g1t-tabs a { | |
| 148 | 178 | display: flex; | |
| 149 | 179 | flex-shrink: 0; | |
| 9 | 9 | ||
| 10 | 10 | const { entry, id } = Astro.locals.starlightRoute; | |
| 11 | 11 | const { title, description } = entry.data; | |
| 12 | − | const section = NAV.get(Astro.locals.starlightRoute)?.section; | |
| 12 | + | const nav = NAV.get(Astro.locals.starlightRoute)?.section; | |
| 13 | + | // No eyebrow that only repeats the title, as on Chat's page in Chat. | |
| 14 | + | const section = nav && nav.toLowerCase() !== title.toLowerCase() ? nav : undefined; | |
| 13 | 15 | const markdown = `/${id === '' || id === 'index' ? 'index' : id}.md`; | |
| 14 | 16 | const absolute = new URL(markdown, Astro.site).href; | |
| 15 | 17 | const ask = encodeURIComponent(`Read ${absolute} so I can ask questions about it.`); | |
| ⋯ | |||
| 250 | 252 | font-size: 2rem; | |
| 251 | 253 | overflow-wrap: anywhere; | |
| 252 | 254 | } | |
| 255 | + | /* The lead a step above the body, not a headline of its own. */ | |
| 256 | + | .g1t-description { | |
| 257 | + | margin-top: 0.75rem; | |
| 258 | + | font-size: 1.0625rem; | |
| 259 | + | line-height: 1.5; | |
| 260 | + | } | |
| 253 | 261 | .g1t-copy { | |
| 254 | 262 | height: 2.5rem; | |
| 255 | 263 | margin-top: 0; | |
| 54 | 54 | return slug.startsWith('reference/') ? TABS[TABS.length - 1] : tabForGroup(group.label ?? ''); | |
| 55 | 55 | } | |
| 56 | 56 | ||
| 57 | + | /** | |
| 58 | + | * A tab's groups in the tab's own order (`groups` in tabs.ts), so a tab | |
| 59 | + | * opens on, and its sidebar starts with, the group it is named for: Code | |
| 60 | + | * on Landing changes, not on Security, which comes first in the sidebar. | |
| 61 | + | * The API reference tab names no groups and keeps the sidebar's order. | |
| 62 | + | */ | |
| 63 | + | function inTabOrder(groups: Entry[], tab: Tab): Entry[] { | |
| 64 | + | const rank = (group: Entry) => { | |
| 65 | + | const index = tab.groups.indexOf(group.label ?? ''); | |
| 66 | + | return index === -1 ? tab.groups.length : index; | |
| 67 | + | }; | |
| 68 | + | return groups.filter((group) => tabOf(group) === tab).sort((a, b) => rank(a) - rank(b)); | |
| 69 | + | } | |
| 70 | + | ||
| 57 | 71 | /** Whether the current page is in these entries, at any depth. */ | |
| 58 | 72 | function holdsCurrent(entries: Entry[]): boolean { | |
| 59 | 73 | return entries.some((entry) => entry.isCurrent || holdsCurrent(entry.entries ?? [])); | |
| ⋯ | |||
| 74 | 88 | const tab = holder ? tabOf(holder) : TABS[0]; | |
| 75 | 89 | // A tab opens on the first page of its first group; the first tab, on the home page. | |
| 76 | 90 | const tabs = TABS.map((each) => { | |
| 77 | − | const group = each === TABS[0] ? undefined : groups.find((entry) => tabOf(entry) === each); | |
| 91 | + | const group = each === TABS[0] ? undefined : inTabOrder(groups, each)[0]; | |
| 78 | 92 | const slug = group ? firstSlug(group.entries ?? []) : undefined; | |
| 79 | 93 | return { label: each.label, href: slug === undefined ? '/' : `/${slug}/`, current: each === tab }; | |
| 80 | 94 | }); | |
| 81 | 95 | NAV.set(route, { tabs, section: section ?? (route.id === '' ? undefined : tab.label) }); | |
| 82 | − | route.sidebar = route.sidebar.filter((entry) => entry.type === 'group' && tabOf(entry as Entry) === tab); | |
| 96 | + | route.sidebar = inTabOrder(groups, tab) as typeof route.sidebar; | |
| 83 | 97 | ||
| 84 | 98 | const { title, description } = route.entry.data; | |
| 85 | 99 | const card = new URL('/docs', OG); | |
| 280 | 280 | display: block; | |
| 281 | 281 | overflow-x: auto; | |
| 282 | 282 | } | |
| 283 | + | /* A shadow at an edge with more columns past it, so a cut-off column | |
| 284 | + | reads as "scroll for more". The covers scroll with the table and hide | |
| 285 | + | the shadows at its ends. */ | |
| 286 | + | .sl-markdown-content table:not(:has(.status)) { | |
| 287 | + | --cover: var(--g1t-bg); | |
| 288 | + | /* On the dark page a shadow is a faint light, as a dark one would not show. */ | |
| 289 | + | --shade: rgb(255 255 255 / 0.12); | |
| 290 | + | background: | |
| 291 | + | linear-gradient(to right, var(--cover) 30%, transparent) left / 2.5rem 100% no-repeat local, | |
| 292 | + | linear-gradient(to left, var(--cover) 30%, transparent) right / 2.5rem 100% no-repeat local, | |
| 293 | + | radial-gradient(farthest-side at 0 50%, var(--shade), transparent) left / 0.875rem 100% no-repeat scroll, | |
| 294 | + | radial-gradient(farthest-side at 100% 50%, var(--shade), transparent) right / 0.875rem 100% no-repeat scroll; | |
| 295 | + | } | |
| 296 | + | :root[data-theme='light'] .sl-markdown-content table:not(:has(.status)) { | |
| 297 | + | --shade: rgb(24 24 27 / 0.16); | |
| 298 | + | } | |
| 283 | 299 | } | |
| 284 | 300 | /* | |
| 285 | 301 | * There, a name, route or value in a table is never broken, not even at a | |
| ⋯ | |||
| 345 | 361 | ||
| 346 | 362 | /* --- On this page --------------------------------------------------------- */ | |
| 347 | 363 | ||
| 364 | + | /* On a phone the list drops over the page: give it an edge and a shadow, so | |
| 365 | + | where it stops is clear rather than its last row running into the text. */ | |
| 366 | + | mobile-starlight-toc .dropdown { | |
| 367 | + | border-color: var(--g1t-line); | |
| 368 | + | border-bottom-color: var(--g1t-line-strong); | |
| 369 | + | box-shadow: var(--g1t-docs-menu-shadow); | |
| 370 | + | } | |
| 371 | + | ||
| 348 | 372 | .right-sidebar-panel { | |
| 349 | 373 | padding-top: 2.75rem; | |
| 350 | 374 | } | |
| 66 | 66 | // 45 minutes, then every 6 hours). Empty sends none. | |
| 67 | 67 | "STATUS_ALERT_EMAIL": "hey@flagon.io", | |
| 68 | 68 | "STATUS_FROM": "g1t status <noreply@g1t.sh>", | |
| 69 | − | "OG_IMAGE": "https://og.g1t.sh/image?path=%2Fstatus&v=2" | |
| 69 | + | "OG_IMAGE": "https://og.g1t.sh/image?path=%2Fstatus&v=3" | |
| 70 | 70 | }, | |
| 71 | 71 | // Asking for a subscription sends an email: limited per client address | |
| 72 | 72 | // and per email address (src/index.ts). Ids and limits: RATE_LIMITS in |
| 78 | 78 | { | |
| 79 | 79 | title: "Product", | |
| 80 | 80 | links: [ | |
| 81 | − | ["Explore", "/explore"], | |
| 82 | − | ["Pricing", "/pricing"], | |
| 83 | − | ["Download", "/download"], | |
| 81 | + | // Code first, as on the landing page: then Chat, then the agents. | |
| 82 | + | ["Pull requests", "https://docs.g1t.sh/guides/pull-requests/"], | |
| 83 | + | ["Deployments", "https://docs.g1t.sh/guides/deployments/"], | |
| 84 | 84 | ["Chat", "https://docs.g1t.sh/guides/chat/"], | |
| 85 | 85 | ["Bring your own agent", "https://docs.g1t.sh/guides/bring-your-own-agent/"], | |
| 86 | 86 | ["Integrations", "https://docs.g1t.sh/guides/integrations/"], | |
| 87 | + | ["Explore", "/explore"], | |
| 88 | + | ["Pricing", "/pricing"], | |
| 89 | + | ["Download", "/download"], | |
| 87 | 90 | ], | |
| 88 | 91 | }, | |
| 89 | 92 | { |
| 18 | 18 | ...page(args, { | |
| 19 | 19 | title: "g1t · Where your team's code lands", | |
| 20 | 20 | description: | |
| 21 | − | "Repositories, pull requests, required checks, a merge queue and deployments, with chat for your team. Connect the coding agents you already use through MCP and the API. Chat is free on every plan, never per seat.", | |
| 21 | + | // At most 200 characters, or a preview cuts it short (lib/meta.ts). | |
| 22 | + | "Repositories, pull requests, required checks, a merge queue and deployments, for your team and the coding agents you bring over MCP and the API. Chat is free on every plan. Never per seat.", | |
| 22 | 23 | }), | |
| 23 | 24 | organization(), | |
| 24 | 25 | application(20), |
| 6 | 6 | import { search } from "../lib/services.server"; | |
| 7 | 7 | ||
| 8 | 8 | /** Pages anyone can read, signed in or not. */ | |
| 9 | − | const PAGES = ["/", "/pricing", "/explore", "/support", "/security", "/policies", "/policies/privacy"]; | |
| 9 | + | const PAGES = [ | |
| 10 | + | "/", | |
| 11 | + | "/pricing", | |
| 12 | + | "/download", | |
| 13 | + | "/explore", | |
| 14 | + | "/support", | |
| 15 | + | "/security", | |
| 16 | + | "/policies", | |
| 17 | + | ...["terms", "privacy", "acceptable-use", "refunds", "subprocessors"].map((policy) => `/policies/${policy}`), | |
| 18 | + | ]; | |
| 10 | 19 | ||
| 11 | 20 | /** How many of Explore's pages to list; each holds one page of projects. */ | |
| 12 | 21 | const EXPLORE_PAGES = 10; |
| 1 | 1 | { | |
| 2 | 2 | "name": "g1t", | |
| 3 | 3 | "short_name": "g1t", | |
| 4 | − | "description": "Your team and its agents, working in one place.", | |
| 4 | + | "description": "The code platform for your team and its coding agents.", | |
| 5 | 5 | "start_url": "/", | |
| 6 | 6 | "scope": "/", | |
| 7 | 7 | "display": "standalone", |
| 1 | 1 | { | |
| 2 | 2 | "name": "g1t", | |
| 3 | 3 | "short_name": "g1t", | |
| 4 | − | "description": "Your team and its agents, working in one place.", | |
| 4 | + | "description": "The code platform for your team and its coding agents.", | |
| 5 | 5 | "start_url": "/", | |
| 6 | 6 | "scope": "/", | |
| 7 | 7 | "display": "standalone", |
| 9 | 9 | * site that has already fetched a card. Without a bump, a redeployed og | |
| 10 | 10 | * keeps serving the cards it drew before. | |
| 11 | 11 | */ | |
| 12 | − | export const OG_RENDER_VERSION = "2"; | |
| 12 | + | export const OG_RENDER_VERSION = "3"; | |
| 13 | 13 | ||
| 14 | 14 | /** | |
| 15 | 15 | * A card's `v` parameter: the render version, then, when the page has one, |
| 13 | 13 | const PAD = 80; | |
| 14 | 14 | ||
| 15 | 15 | /** The launch line: what g1t is, on the brand card and under every page card. */ | |
| 16 | − | export const TAGLINE = "Where people and agents ship software together."; | |
| 16 | + | export const TAGLINE = "The code platform for your team and its agents."; | |
| 17 | 17 | ||
| 18 | 18 | /** An element as satori reads it. */ | |
| 19 | 19 | export type Node = { type: string; props: Record<string, unknown> & { style?: Style; children?: Child } }; |
| 187 | 187 | address: "g1t.sh/register", | |
| 188 | 188 | eyebrow: "Get started", | |
| 189 | 189 | title: "Build and ship software, with the agents you already use.", | |
| 190 | − | description: "Create an account on g1t, where people and agents ship software together.", | |
| 190 | + | description: "Create an account, then bring your code and the coding agents you already use.", | |
| 191 | 191 | }, | |
| 192 | 192 | }; | |
| 193 | 193 |
Comments
Sign in to comment.