Skip to content
100 linesCodeBlameRaw

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.

Automations: rules in .g1t/automations that act when something happens1import { CircleCheck, MailWarning } from "lucide-react";
2import { redirect } from "react-router";
3
4import type { Route } from "./+types/verify";
Social cards for every page: og.g1t.sh5import { page } from "../lib/meta";
Automations: rules in .g1t/automations that act when something happens6import { ButtonLink } from "../components/ui";
Merge email confirmation gate: a code and a link, nothing until confirmed (identity 0036)7import { CONFIRM_PATH, afterConfirming, confirmedLine } from "../lib/confirm-gate";
Automations: rules in .g1t/automations that act when something happens8import { identity } from "../lib/services.server";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look9import { assertSameOrigin, getViewer, requireUser } from "../lib/session.server";
Automations: rules in .g1t/automations that act when something happens10
Social cards for every page: og.g1t.sh11export function meta(args: Route.MetaArgs) {
12 return page(args, { title: "Confirm your email · g1t" });
Automations: rules in .g1t/automations that act when something happens13}
14
Merge email confirmation gate: a code and a link, nothing until confirmed (identity 0036)15/**
16 * Follows the link from the confirmation email, signed in or not: the same
17 * email's code does the same on /confirm-email.
18 */
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look19export async function loader({ request, context }: Route.LoaderArgs) {
Automations: rules in .g1t/automations that act when something happens20 const token = new URL(request.url).searchParams.get("token") ?? "";
Merge email confirmation gate: a code and a link, nothing until confirmed (identity 0036)21 const viewer = getViewer(context);
Automations: rules in .g1t/automations that act when something happens22 const result = await identity.verifyEmail(token);
Merge email confirmation gate: a code and a link, nothing until confirmed (identity 0036)23 if (!result.ok) return { ok: false as const, message: result.error.message, signedIn: viewer != null };
24 const done = result.value;
25 // An address added to an account in use goes back to settings; a new
26 // account's first goes on to the workspace its invite joined, or home.
27 const added = viewer?.verified === true;
28 return {
29 ok: true as const,
30 username: done.username,
31 added,
32 line: confirmedLine(done),
33 lapsed: Boolean(done.inviteLapsed),
Merge workspace invitations: nobody joins a workspace without saying yes, people are found by username, your own invites can bring someone in, and nobody is left without a workspace (identity 0040)34 to: afterConfirming("/", done.joined, done.invitedTo),
Merge email confirmation gate: a code and a link, nothing until confirmed (identity 0036)35 signedIn: viewer != null,
36 };
Automations: rules in .g1t/automations that act when something happens37}
38
Merge email confirmation gate: a code and a link, nothing until confirmed (identity 0036)39/** An old form's "resend": the confirmation page sends new codes now. */
Automations: rules in .g1t/automations that act when something happens40export async function action({ request, context }: Route.ActionArgs) {
41 assertSameOrigin(request);
42 await identity.resendVerification(requireUser(context, request));
Merge email confirmation gate: a code and a link, nothing until confirmed (identity 0036)43 throw redirect(CONFIRM_PATH);
Automations: rules in .g1t/automations that act when something happens44}
45
46export default function Verify({ loaderData }: Route.ComponentProps) {
47 return (
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.48 <main className="mx-auto max-w-md pt-10 text-center">
Automations: rules in .g1t/automations that act when something happens49 {loaderData.ok ? (
50 <>
Merge branch 'worktree-agent-ad7c6d88d93adc817'51 <CircleCheck size={40} className="mx-auto text-success" />
Automations: rules in .g1t/automations that act when something happens52 <h1 className="mt-6 text-2xl font-semibold tracking-tight">
53 Email confirmed
54 </h1>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look55 {loaderData.added ? (
56 <>
57 <p className="mt-2 text-muted">
58 The address is confirmed on {loaderData.username}. You can make it
59 your primary address in your settings.
60 </p>
61 <div className="mt-8">
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas62 <ButtonLink to="/settings/emails">Back to settings</ButtonLink>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look63 </div>
64 </>
65 ) : (
66 <>
Merge email confirmation gate: a code and a link, nothing until confirmed (identity 0036)67 <p className={`mt-2 ${loaderData.lapsed ? "text-fg" : "text-muted"}`} role="status">
68 {loaderData.line} Your account {loaderData.username} is ready.
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look69 </p>
70 <div className="mt-8">
Merge email confirmation gate: a code and a link, nothing until confirmed (identity 0036)71 <ButtonLink to={loaderData.signedIn ? loaderData.to : `/login?next=${encodeURIComponent(loaderData.to)}`}>
72 {loaderData.signedIn ? "Continue" : "Sign in"}
73 </ButtonLink>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look74 </div>
75 </>
76 )}
Automations: rules in .g1t/automations that act when something happens77 </>
78 ) : (
79 <>
80 <MailWarning size={40} className="mx-auto text-warn" />
81 <h1 className="mt-6 text-2xl font-semibold tracking-tight">
82 That link did not work
83 </h1>
84 <p className="mt-2 text-muted">{loaderData.message}</p>
85 <p className="mt-2 text-sm text-muted">
Merge email confirmation gate: a code and a link, nothing until confirmed (identity 0036)86 Links work once, for an hour, and a newer email replaces them.
87 {loaderData.signedIn
88 ? " Enter the code from your latest email, or send a new one."
89 : " Sign in to enter the code from the email, or to send a new one."}
Automations: rules in .g1t/automations that act when something happens90 </p>
91 <div className="mt-8">
Merge email confirmation gate: a code and a link, nothing until confirmed (identity 0036)92 <ButtonLink to={loaderData.signedIn ? CONFIRM_PATH : `/login?next=${encodeURIComponent(CONFIRM_PATH)}`} variant="quiet">
93 {loaderData.signedIn ? "Enter a code" : "Sign in"}
Automations: rules in .g1t/automations that act when something happens94 </ButtonLink>
95 </div>
96 </>
97 )}
98 </main>
99 );
100}

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