Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 1 | import { ArrowUpRight, BookMarked, Search } from "lucide-react"; |
| Search across all of g1t, Explore, and a command palette | 2 | import type { ReactNode } from "react"; |
| 3 | import { Form, Link } from "react-router"; | |
| 4 | ||
| 5 | import type { ExploreRepo } from "@g1t/contracts"; | |
| Share the editor settings and Claude Code deploy permissions | 6 | |
| 7 | import type { Route } from "./+types/explore"; | |
| The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after. | 8 | import { EmptyState, TimeAgo, notACredential } from "../components/ui"; |
| 9 | import { Badge } from "../components/ui/badge"; | |
| 10 | import { Card } from "../components/ui/card"; | |
| Social cards for every page: og.g1t.sh | 11 | import { page } from "../lib/meta"; |
| Merge branch 'site-fixes' into fast-push | 12 | import { DeployLink, host } from "../components/deploy"; |
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 13 | import { projects, search } from "../lib/services.server"; |
| Share the editor settings and Claude Code deploy permissions | 14 | import { getViewer } from "../lib/session.server"; |
| 15 | ||
| Social cards for every page: og.g1t.sh | 16 | export function meta({ loaderData, ...args }: Route.MetaArgs) { |
| Search across all of g1t, Explore, and a command palette | 17 | const filter = loaderData?.language ?? (loaderData?.topic ? `#${loaderData.topic}` : null); |
| Social cards for every page: og.g1t.sh | 18 | return page(args, { |
| Search across all of g1t, Explore, and a command palette | 19 | title: filter ? `${filter} · Explore · g1t` : "Explore · g1t", |
| 20 | description: filter | |
| 21 | ? `Public projects on g1t in ${filter}.` | |
| 22 | : "Public projects on g1t: recently active, newly created, and by language and topic.", | |
| Social cards for every page: og.g1t.sh | 23 | }); |
| Share the editor settings and Claude Code deploy permissions | 24 | } |
| 25 | ||
| 26 | export async function loader({ request, context }: Route.LoaderArgs) { | |
| Search across all of g1t, Explore, and a command palette | 27 | const url = new URL(request.url); |
| 28 | const sort = url.searchParams.get("sort") === "new" ? ("new" as const) : ("active" as const); | |
| 29 | const language = url.searchParams.get("language")?.trim().toLowerCase() || null; | |
| 30 | const topic = url.searchParams.get("topic")?.trim().toLowerCase() || null; | |
| 31 | const pageNumber = Math.min(Math.max(Number(url.searchParams.get("page")) || 1, 1), 50); | |
| 32 | const explore = await search | |
| 33 | .explore(getViewer(context), { sort, language, topic, page: pageNumber }) | |
| 34 | .catch(() => null); | |
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 35 | // Each one's homepage or production, from its project; the page shows without them. |
| 36 | const links = explore | |
| 37 | ? await projects.publicLinks(explore.repos.map((repo) => ({ namespace: repo.namespace, name: repo.name }))).catch(() => ({})) | |
| 38 | : {}; | |
| 39 | return { sort, language, topic, explore, links: links as Record<string, string> }; | |
| Search across all of g1t, Explore, and a command palette | 40 | } |
| 41 | ||
| 42 | /** The address of Explore with some of its filters changed. */ | |
| 43 | function href(current: { sort: string; language: string | null; topic: string | null }, change: Record<string, string | null>) { | |
| 44 | const next = { sort: current.sort, language: current.language, topic: current.topic, ...change }; | |
| 45 | const params = new URLSearchParams(); | |
| 46 | if (next.sort && next.sort !== "active") params.set("sort", next.sort); | |
| 47 | if (next.language) params.set("language", next.language); | |
| 48 | if (next.topic) params.set("topic", next.topic); | |
| 49 | if (change.page) params.set("page", change.page); | |
| 50 | const query = params.toString(); | |
| 51 | return query ? `/explore?${query}` : "/explore"; | |
| 52 | } | |
| 53 | ||
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 54 | function RepoCard({ repo, link }: { repo: ExploreRepo; link: string | null }) { |
| Search across all of g1t, Explore, and a command palette | 55 | return ( |
| The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after. | 56 | <Card className="relative flex h-full flex-col p-4 transition-colors hover:border-line-strong"> |
| Search across all of g1t, Explore, and a command palette | 57 | <span className="flex items-center gap-2"> |
| 58 | <BookMarked size={15} className="shrink-0 text-faint" /> | |
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 59 | <Link prefetch="intent" to={`/${repo.namespace}/${repo.name}`} className="truncate font-mono text-sm after:absolute after:inset-0"> |
| Search across all of g1t, Explore, and a command palette | 60 | <span className="text-muted">{repo.namespace}/</span> |
| 61 | <span className="font-medium">{repo.name}</span> | |
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 62 | </Link> |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 63 | {repo.archived && ( |
| 64 | <span className="ml-auto shrink-0"> | |
| The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after. | 65 | <Badge size="md">archived</Badge> |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 66 | </span> |
| 67 | )} | |
| Search across all of g1t, Explore, and a command palette | 68 | </span> |
| 69 | <span className="mt-2 line-clamp-2 grow text-sm text-muted">{repo.description ?? "No description."}</span> | |
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 70 | {link && ( |
| Merge branch 'site-fixes' into fast-push | 71 | <DeployLink |
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 72 | href={link} |
| Merge branch 'site-fixes' into fast-push | 73 | rel="nofollow" |
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 74 | className="relative z-10 mt-2 flex min-w-0 items-center gap-1 self-start font-mono text-xs text-muted hover:text-accent" |
| 75 | > | |
| 76 | <span className="truncate">{host(link).replace(/\/$/, "")}</span> | |
| 77 | <ArrowUpRight size={11} className="shrink-0" /> | |
| Merge branch 'site-fixes' into fast-push | 78 | </DeployLink> |
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 79 | )} |
| Search across all of g1t, Explore, and a command palette | 80 | {repo.topics.length > 0 && ( |
| 81 | <span className="mt-3 flex flex-wrap gap-1.5"> | |
| 82 | {repo.topics.slice(0, 4).map((topic) => ( | |
| 83 | <span key={topic} className="rounded-full bg-raised px-2 py-px text-[0.6875rem] text-muted ring-1 ring-line"> | |
| 84 | {topic} | |
| 85 | </span> | |
| 86 | ))} | |
| 87 | </span> | |
| 88 | )} | |
| 89 | <span className="mt-3 flex items-center gap-3 text-xs text-faint"> | |
| 90 | {repo.language && <span className="font-mono">{repo.language}</span>} | |
| 91 | <span className="ml-auto"> | |
| 92 | {repo.pushedAt ? ( | |
| 93 | <> | |
| 94 | Pushed <TimeAgo at={repo.pushedAt} /> | |
| 95 | </> | |
| 96 | ) : ( | |
| 97 | <> | |
| 98 | Created <TimeAgo at={repo.createdAt} /> | |
| 99 | </> | |
| 100 | )} | |
| 101 | </span> | |
| 102 | </span> | |
| The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after. | 103 | </Card> |
| Search across all of g1t, Explore, and a command palette | 104 | ); |
| 105 | } | |
| 106 | ||
| 107 | function Chip({ to, current, children }: { to: string; current: boolean; children: ReactNode }) { | |
| 108 | return ( | |
| 109 | <Link | |
| 110 | to={to} | |
| 111 | aria-current={current ? "true" : undefined} | |
| 112 | className={`rounded-full px-2.5 py-1 text-xs transition-colors ring-1 ${ | |
| 113 | current ? "bg-accent/15 text-fg ring-accent/50" : "text-muted ring-line hover:text-fg hover:ring-line-strong" | |
| 114 | }`} | |
| 115 | > | |
| 116 | {children} | |
| 117 | </Link> | |
| 118 | ); | |
| Share the editor settings and Claude Code deploy permissions | 119 | } |
| 120 | ||
| Search across all of g1t, Explore, and a command palette | 121 | export default function ExplorePage({ loaderData }: Route.ComponentProps) { |
| 122 | const { sort, language, topic, explore } = loaderData; | |
| 123 | const current = { sort, language, topic }; | |
| 124 | const filtered = language || topic; | |
| Share the editor settings and Claude Code deploy permissions | 125 | return ( |
| Search across all of g1t, Explore, and a command palette | 126 | <main className="mx-auto max-w-6xl px-4 py-10 sm:px-6"> |
| 127 | <h1 className="text-2xl font-semibold tracking-tight">Explore</h1> | |
| Share the editor settings and Claude Code deploy permissions | 128 | <p className="mt-1 text-muted"> |
| Search across all of g1t, Explore, and a command palette | 129 | Public projects on g1t{language ? ` in ${language}` : ""} |
| 130 | {topic ? ` about ${topic}` : ""}. | |
| Share the editor settings and Claude Code deploy permissions | 131 | </p> |
| Search across all of g1t, Explore, and a command palette | 132 | <Form action="/search" role="search" className="relative mt-6 max-w-2xl"> |
| 133 | <Search size={16} className="pointer-events-none absolute top-1/2 left-3.5 -translate-y-1/2 text-faint" /> | |
| Share the editor settings and Claude Code deploy permissions | 134 | <input |
| 135 | name="q" | |
| 136 | {...notACredential()} | |
| Search across all of g1t, Explore, and a command palette | 137 | placeholder="Search repositories, code, issues and people" |
| 138 | aria-label="Search g1t" | |
| 139 | className="h-10 w-full rounded-lg border border-line bg-surface pr-4 pl-10 text-sm outline-none transition-colors placeholder:text-faint hover:border-line-strong focus:border-accent-dim" | |
| Share the editor settings and Claude Code deploy permissions | 140 | /> |
| 141 | </Form> | |
| Search across all of g1t, Explore, and a command palette | 142 | |
| 143 | <div className="mt-8 grid gap-8 lg:grid-cols-[minmax(0,1fr)_16rem]"> | |
| 144 | <section> | |
| 145 | <div className="flex flex-wrap items-center gap-3"> | |
| The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after. | 146 | <Card asChild tone="bg" radius="lg" className="flex items-center gap-1 p-1"> |
| 147 | <nav aria-label="Order"> | |
| 148 | {[ | |
| 149 | { value: "active", label: "Recently active" }, | |
| 150 | { value: "new", label: "New" }, | |
| 151 | ].map((option) => ( | |
| 152 | <Link | |
| 153 | key={option.value} | |
| 154 | to={href(current, { sort: option.value })} | |
| 155 | aria-current={sort === option.value ? "page" : undefined} | |
| 156 | className={`rounded-md px-2.5 py-1 text-xs font-medium transition-colors ${ | |
| 157 | sort === option.value ? "bg-raised text-fg ring-1 ring-line" : "text-muted hover:text-fg" | |
| 158 | }`} | |
| 159 | > | |
| 160 | {option.label} | |
| 161 | </Link> | |
| 162 | ))} | |
| 163 | </nav> | |
| 164 | </Card> | |
| Search across all of g1t, Explore, and a command palette | 165 | {filtered && ( |
| 166 | <Link to={href(current, { language: null, topic: null })} className="text-xs text-muted hover:text-fg"> | |
| 167 | Clear {language ? "language" : "topic"} | |
| 168 | </Link> | |
| 169 | )} | |
| 170 | </div> | |
| 171 | {!explore ? ( | |
| 172 | <div className="mt-4"> | |
| 173 | <EmptyState title="Explore cannot be reached right now">Try again in a moment.</EmptyState> | |
| 174 | </div> | |
| 175 | ) : explore.repos.length === 0 ? ( | |
| 176 | <div className="mt-4"> | |
| 177 | <EmptyState title="No public projects here yet"> | |
| 178 | {filtered ? "Try another language or topic." : "Public projects appear here as they are made."} | |
| 179 | </EmptyState> | |
| 180 | </div> | |
| 181 | ) : ( | |
| 182 | <ul className="mt-4 grid gap-3 sm:grid-cols-2"> | |
| 183 | {explore.repos.map((repo) => ( | |
| 184 | <li key={`${repo.namespace}/${repo.name}`}> | |
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 185 | <RepoCard repo={repo} link={loaderData.links[`${repo.namespace}/${repo.name}`.toLowerCase()] ?? null} /> |
| Search across all of g1t, Explore, and a command palette | 186 | </li> |
| 187 | ))} | |
| 188 | </ul> | |
| 189 | )} | |
| 190 | {explore && (explore.page > 1 || explore.more) && ( | |
| 191 | <nav aria-label="Pages" className="mt-6 flex justify-between text-sm"> | |
| 192 | {explore.page > 1 ? ( | |
| 193 | <Link to={href(current, { page: String(explore.page - 1) })} className="text-muted hover:text-fg"> | |
| 194 | Previous | |
| 195 | </Link> | |
| 196 | ) : ( | |
| 197 | <span /> | |
| 198 | )} | |
| 199 | {explore.more && ( | |
| 200 | <Link to={href(current, { page: String(explore.page + 1) })} className="text-muted hover:text-fg"> | |
| 201 | Next | |
| 202 | </Link> | |
| 203 | )} | |
| 204 | </nav> | |
| 205 | )} | |
| 206 | </section> | |
| 207 | ||
| 208 | <aside className="space-y-6"> | |
| 209 | {explore && explore.languages.length > 0 && ( | |
| 210 | <section> | |
| 211 | <h2 className="text-xs font-medium text-faint">Languages</h2> | |
| 212 | <div className="mt-2 flex flex-wrap gap-1.5"> | |
| 213 | {explore.languages.map((facet) => ( | |
| 214 | <Chip | |
| 215 | key={facet.name} | |
| 216 | to={href(current, { language: language === facet.name ? null : facet.name })} | |
| 217 | current={language === facet.name} | |
| 218 | > | |
| 219 | <span className="font-mono">{facet.name}</span> <span className="text-faint">{facet.count}</span> | |
| 220 | </Chip> | |
| 221 | ))} | |
| 222 | </div> | |
| 223 | </section> | |
| 224 | )} | |
| 225 | {explore && explore.topics.length > 0 && ( | |
| 226 | <section> | |
| 227 | <h2 className="text-xs font-medium text-faint">Topics</h2> | |
| 228 | <div className="mt-2 flex flex-wrap gap-1.5"> | |
| 229 | {explore.topics.map((facet) => ( | |
| 230 | <Chip | |
| 231 | key={facet.name} | |
| 232 | to={href(current, { topic: topic === facet.name ? null : facet.name })} | |
| 233 | current={topic === facet.name} | |
| 234 | > | |
| 235 | {facet.name} <span className="text-faint">{facet.count}</span> | |
| 236 | </Chip> | |
| 237 | ))} | |
| 238 | </div> | |
| 239 | </section> | |
| 240 | )} | |
| 241 | </aside> | |
| 242 | </div> | |
| Share the editor settings and Claude Code deploy permissions | 243 | </main> |
| 244 | ); | |
| 245 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.