flagon-io/g1t

public

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t/apps/sudo/app/root.tsx

122 lines4,570 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.

Billing accounts, terms and enterprises; g1t is no longer free1import { Building2, ShieldCheck, Users } from "lucide-react";
2import { isRouteErrorResponse, Link, Links, Meta, NavLink, Outlet, useRouteLoaderData } from "react-router";
3
4import type { Route } from "./+types/root";
5import "./app.css";
6import { Logo } from "./components/logo";
7import { ButtonLink } from "./components/ui";
8import { requireStaff } from "./lib/staff";
9
10export const links: Route.LinksFunction = () => [
11 { rel: "icon", type: "image/svg+xml", href: "/favicon.svg" },
12 { rel: "preconnect", href: "https://fonts.googleapis.com" },
13 { rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "anonymous" },
14 {
15 rel: "stylesheet",
16 href: "https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap",
17 },
18];
19
20export const meta: Route.MetaFunction = () => [
21 { title: "sudo · g1t" },
22 { name: "robots", content: "noindex, nofollow" },
23];
24
25export async function loader({ context }: Route.LoaderArgs) {
26 return { email: requireStaff(context).email };
27}
28
29function NavItem({ to, end, children }: { to: string; end?: boolean; children: React.ReactNode }) {
30 return (
31 <NavLink
32 to={to}
33 end={end}
34 className={({ isActive }) =>
35 `inline-flex items-center gap-1.5 rounded-md px-2.5 py-1.5 text-sm transition-colors hover:bg-raised hover:text-fg ${
36 isActive ? "text-fg" : "text-muted"
37 }`
38 }
39 >
40 {children}
41 </NavLink>
42 );
43}
44
45export function Layout({ children }: { children: React.ReactNode }) {
46 const root = useRouteLoaderData<typeof loader>("root");
47 return (
48 <html lang="en">
49 <head>
50 <meta charSet="utf-8" />
51 <meta name="viewport" content="width=device-width, initial-scale=1" />
52 <meta name="theme-color" content="#0f0f11" />
53 <Meta />
54 <Links />
55 </head>
56 <body className="flex min-h-screen flex-col">
57 <header className="sticky top-0 z-40 border-b border-line bg-surface/90 backdrop-blur">
58 <div className="mx-auto flex h-14 max-w-6xl items-center gap-2 px-4">
59 <Link to="/" aria-label="sudo home" className="mr-1 sm:mr-3">
60 <Logo />
61 </Link>
62 <nav className="flex items-center gap-0.5">
63 <NavItem to="/" end>
64 <Users size={14} className="hidden sm:block" />
65 Accounts
66 </NavItem>
67 <NavItem to="/enterprises/new">
68 <Building2 size={14} className="hidden sm:block" />
69 <span className="sm:hidden">New ent.</span>
70 <span className="hidden sm:inline">New enterprise</span>
71 </NavItem>
72 </nav>
73 {root?.email && (
74 <span
75 title="Signed in through Cloudflare Access"
76 className="ml-auto hidden items-center gap-1.5 truncate rounded-md border border-line px-2 py-1 font-mono text-xs text-muted md:inline-flex"
77 >
78 <ShieldCheck size={13} className="text-merged" />
79 {root.email}
80 </span>
81 )}
82 </div>
83 </header>
84 <div className="grow">{children}</div>
85 <footer className="border-t border-line">
86 <p className="mx-auto max-w-6xl px-4 py-5 text-xs text-faint">
87 g1t staff only. Every change is recorded with who made it.
88 {root?.email && <span className="md:hidden"> Signed in as {root.email}.</span>}
89 </p>
90 </footer>
91 {/* No <Scripts />: sudo ships no JavaScript, and its policy allows none. */}
92 </body>
93 </html>
94 );
95}
96
97export default function App() {
98 return <Outlet />;
99}
100
101export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
102 let title = "Something went wrong";
103 let details = "An unexpected error occurred.";
104 if (isRouteErrorResponse(error)) {
105 title = error.status === 404 ? "Not found" : `Error ${error.status}`;
106 details = typeof error.data === "string" && error.data ? error.data : error.statusText || details;
107 } else if (error instanceof Error) {
108 // Staff only: the real reason helps more than a polite one.
109 details = error.message;
110 }
111 return (
112 <main className="mx-auto max-w-xl px-4 py-24 text-center">
113 <h1 className="text-2xl font-semibold tracking-tight">{title}</h1>
114 <p className="mt-3 break-words text-muted">{details}</p>
115 <div className="mt-8">
116 <ButtonLink to="/" variant="quiet">
117 Back to accounts
118 </ButtonLink>
119 </div>
120 </main>
121 );
122}