Skip to content

g1t/apps/web/app/routes/repo/commits.tsx

102 lines4,510 bytesCodeBlame

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.

Agents as a team: lifecycle, merge queue, billing and a new shell1import { GitCommitHorizontal } from "lucide-react";
2import { Link } from "react-router";
3
4import type { Commit } from "@g1t/contracts";
5
API and MCP server, Rust identity service, registration, site redesign6import type { Route } from "./+types/commits";
Social cards for every page: og.g1t.sh7import { page } from "../../lib/meta";
API and MCP server, Rust identity service, registration, site redesign8import { Avatar, EmptyState, TimeAgo } from "../../components/ui";
Merge branch 'worktree-agent-ae1299e92e4462012'9import { Hint } from "../../components/ui/hint";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look10import { accounts, repos } from "../../lib/services.server";
API and MCP server, Rust identity service, registration, site redesign11import { getViewer, unwrap } from "../../lib/session.server";
12
13const PAGE_SIZE = 50;
14
Social cards for every page: og.g1t.sh15export function meta({ params, ...args }: Route.MetaArgs) {
16 return page(args, { title: `Commits · ${params.owner}/${params.repo} · g1t` });
API and MCP server, Rust identity service, registration, site redesign17}
18
19export async function loader({ params, context }: Route.LoaderArgs) {
20 const path = { namespace: params.owner, name: params.repo };
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look21 const commits = unwrap(await repos.log(path, getViewer(context), null, PAGE_SIZE));
22 // Who wrote each commit, by its author address: confirmed and noreply
23 // addresses only. Without an answer, the name in the commit is shown.
24 const owners = await accounts.emailOwners([...new Set(commits.map((commit) => commit.author.email))]).catch(() => ({}));
25 return { commits, owners: owners as Record<string, { username: string; avatar: string | null }> };
API and MCP server, Rust identity service, registration, site redesign26}
27
Agents as a team: lifecycle, merge queue, billing and a new shell28/** Commits by the day they were made, newest first. */
29function byDay(commits: Commit[]): [string, Commit[]][] {
30 const days = new Map<string, Commit[]>();
31 for (const commit of commits) {
32 const day = commit.authoredAt.slice(0, 10);
33 days.set(day, [...(days.get(day) ?? []), commit]);
34 }
35 return [...days];
36}
37
38function dayLabel(day: string): string {
39 const date = new Date(`${day}T12:00:00Z`);
40 return date.toLocaleDateString("en-US", {
41 weekday: "long",
42 month: "long",
43 day: "numeric",
44 year: "numeric",
45 timeZone: "UTC",
46 });
47}
48
49export default function Commits({ loaderData, params }: Route.ComponentProps) {
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look50 const { commits, owners } = loaderData;
Agents as a team: lifecycle, merge queue, billing and a new shell51 const base = `/${params.owner}/${params.repo}`;
API and MCP server, Rust identity service, registration, site redesign52 if (commits.length === 0) {
53 return <EmptyState title="No commits yet" />;
54 }
55 return (
Agents as a team: lifecycle, merge queue, billing and a new shell56 <div className="relative space-y-8 before:absolute before:top-3 before:bottom-3 before:left-1.75 before:w-px before:bg-line">
57 {byDay(commits).map(([day, list]) => (
58 <section key={day} className="relative pl-7">
59 <h2 className="flex items-center gap-2 text-xs font-medium text-muted">
60 <GitCommitHorizontal size={15} className="absolute left-0 bg-bg text-faint" />
61 {dayLabel(day)}
62 </h2>
63 <ol className="mt-3 divide-y divide-line overflow-hidden rounded-xl border border-line">
64 {list.map((commit) => {
65 const [subject, ...body] = commit.message.split("\n");
66 const rest = body.join("\n").trim();
67 const to = `${base}/commit/${commit.hash}`;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look68 const owner = owners[commit.author.email.toLowerCase()];
Agents as a team: lifecycle, merge queue, billing and a new shell69 return (
70 <li key={commit.hash} className="group relative flex items-start gap-3 px-4 py-3 transition-colors hover:bg-surface">
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look71 <Avatar name={owner?.username ?? commit.author.name} image={owner?.avatar} size={24} />
Agents as a team: lifecycle, merge queue, billing and a new shell72 <div className="min-w-0 grow">
73 <Link to={to} prefetch="intent" className="block truncate font-medium after:absolute after:inset-0 group-hover:text-accent">
74 {subject}
75 </Link>
76 {rest && <p className="mt-1 line-clamp-1 text-sm text-muted">{rest}</p>}
77 <p className="mt-1 text-xs text-faint">
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look78 {owner ? (
Merge branch 'worktree-agent-ae1299e92e4462012'79 <Hint label={commit.author.name}>
80 <Link to={`/u/${owner.username}`} className="relative z-10 text-muted hover:text-fg">
81 {owner.username}
82 </Link>
83 </Hint>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look84 ) : (
85 commit.author.name
86 )}{" "}
87 committed <TimeAgo at={commit.authoredAt} />
Agents as a team: lifecycle, merge queue, billing and a new shell88 {commit.parents.length > 1 && " · merge"}
89 </p>
90 </div>
91 <span className="shrink-0 rounded-md border border-line px-2 py-0.5 font-mono text-xs text-muted group-hover:border-line-strong group-hover:text-fg">
92 {commit.hash.slice(0, 7)}
93 </span>
94 </li>
95 );
96 })}
97 </ol>
98 </section>
99 ))}
100 </div>
API and MCP server, Rust identity service, registration, site redesign101 );
102}

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