Skip to content

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

110 lines5,013 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";
Merge checks: statuses and check runs on every commit8import { CommitChecksBadge } from "../../components/commit-checks";
API and MCP server, Rust identity service, registration, site redesign9import { Avatar, EmptyState, TimeAgo } from "../../components/ui";
Merge branch 'worktree-agent-ae1299e92e4462012'10import { Hint } from "../../components/ui/hint";
Merge checks: statuses and check runs on every commit11import { commitChecksFor } from "../../lib/commit-checks.server";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look12import { accounts, repos } from "../../lib/services.server";
API and MCP server, Rust identity service, registration, site redesign13import { getViewer, unwrap } from "../../lib/session.server";
14
15const PAGE_SIZE = 50;
16
Social cards for every page: og.g1t.sh17export function meta({ params, ...args }: Route.MetaArgs) {
18 return page(args, { title: `Commits · ${params.owner}/${params.repo} · g1t` });
API and MCP server, Rust identity service, registration, site redesign19}
20
21export async function loader({ params, context }: Route.LoaderArgs) {
22 const path = { namespace: params.owner, name: params.repo };
Merge checks: statuses and check runs on every commit23 const viewer = getViewer(context);
24 const commits = unwrap(await repos.log(path, viewer, null, PAGE_SIZE));
25 // Every commit's checks in one call, streamed in beside each.
26 const checks = commitChecksFor(path, viewer, commits.map((commit) => commit.hash));
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look27 // Who wrote each commit, by its author address: confirmed and noreply
28 // addresses only. Without an answer, the name in the commit is shown.
29 const owners = await accounts.emailOwners([...new Set(commits.map((commit) => commit.author.email))]).catch(() => ({}));
Merge checks: statuses and check runs on every commit30 return { commits, owners: owners as Record<string, { username: string; avatar: string | null }>, checks };
API and MCP server, Rust identity service, registration, site redesign31}
32
Agents as a team: lifecycle, merge queue, billing and a new shell33/** Commits by the day they were made, newest first. */
34function byDay(commits: Commit[]): [string, Commit[]][] {
35 const days = new Map<string, Commit[]>();
36 for (const commit of commits) {
37 const day = commit.authoredAt.slice(0, 10);
38 days.set(day, [...(days.get(day) ?? []), commit]);
39 }
40 return [...days];
41}
42
43function dayLabel(day: string): string {
44 const date = new Date(`${day}T12:00:00Z`);
45 return date.toLocaleDateString("en-US", {
46 weekday: "long",
47 month: "long",
48 day: "numeric",
49 year: "numeric",
50 timeZone: "UTC",
51 });
52}
53
54export default function Commits({ loaderData, params }: Route.ComponentProps) {
Merge checks: statuses and check runs on every commit55 const { commits, owners, checks } = loaderData;
Agents as a team: lifecycle, merge queue, billing and a new shell56 const base = `/${params.owner}/${params.repo}`;
API and MCP server, Rust identity service, registration, site redesign57 if (commits.length === 0) {
58 return <EmptyState title="No commits yet" />;
59 }
60 return (
Agents as a team: lifecycle, merge queue, billing and a new shell61 <div className="relative space-y-8 before:absolute before:top-3 before:bottom-3 before:left-1.75 before:w-px before:bg-line">
62 {byDay(commits).map(([day, list]) => (
63 <section key={day} className="relative pl-7">
64 <h2 className="flex items-center gap-2 text-xs font-medium text-muted">
65 <GitCommitHorizontal size={15} className="absolute left-0 bg-bg text-faint" />
66 {dayLabel(day)}
67 </h2>
68 <ol className="mt-3 divide-y divide-line overflow-hidden rounded-xl border border-line">
69 {list.map((commit) => {
70 const [subject, ...body] = commit.message.split("\n");
71 const rest = body.join("\n").trim();
72 const to = `${base}/commit/${commit.hash}`;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look73 const owner = owners[commit.author.email.toLowerCase()];
Agents as a team: lifecycle, merge queue, billing and a new shell74 return (
75 <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 look76 <Avatar name={owner?.username ?? commit.author.name} image={owner?.avatar} size={24} />
Agents as a team: lifecycle, merge queue, billing and a new shell77 <div className="min-w-0 grow">
Merge checks: statuses and check runs on every commit78 <div className="flex min-w-0 items-center gap-1.5">
79 <Link to={to} prefetch="intent" className="truncate font-medium after:absolute after:inset-0 group-hover:text-accent">
80 {subject}
81 </Link>
82 <CommitChecksBadge checks={checks} sha={commit.hash} />
83 </div>
Agents as a team: lifecycle, merge queue, billing and a new shell84 {rest && <p className="mt-1 line-clamp-1 text-sm text-muted">{rest}</p>}
85 <p className="mt-1 text-xs text-faint">
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look86 {owner ? (
Merge branch 'worktree-agent-ae1299e92e4462012'87 <Hint label={commit.author.name}>
88 <Link to={`/u/${owner.username}`} className="relative z-10 text-muted hover:text-fg">
89 {owner.username}
90 </Link>
91 </Hint>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look92 ) : (
93 commit.author.name
94 )}{" "}
95 committed <TimeAgo at={commit.authoredAt} />
Agents as a team: lifecycle, merge queue, billing and a new shell96 {commit.parents.length > 1 && " · merge"}
97 </p>
98 </div>
99 <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">
100 {commit.hash.slice(0, 7)}
101 </span>
102 </li>
103 );
104 })}
105 </ol>
106 </section>
107 ))}
108 </div>
API and MCP server, Rust identity service, registration, site redesign109 );
110}

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