Vectrum
Sign In
64 lines · 3.0 KB · TypeScript
import type { Metadata } from "next";
import NextLink from "next/link";
import { redirect } from "next/navigation";
import { Link } from "@unlocalhosted/metalui";
import { SignupForm } from "@/components/auth-forms";
import { BRAND } from "@/components/brand";
import { KeyIcon, PencilIcon, PeopleIcon } from "@/components/icons";
import { Box } from "@/components/ui";
import { getViewer, safeNext } from "@/lib/auth";
import { SIGNUPS_ENABLED } from "@/lib/signups";

export const metadata: Metadata = { title: "Join" };

const perks = [
  { icon: PeopleIcon, title: "Collaborate", text: "Invite collaborators and keep repositories public or private." },
  { icon: PencilIcon, title: "Edit in the browser", text: "Create, edit and upload files without leaving the page." },
  { icon: KeyIcon, title: "Push your way", text: "Use SSH keys or scoped API tokens with plain git." },
];

export default async function SignupPage({ searchParams }: PageProps<"/signup">) {
  const next = safeNext((await searchParams).next);
  if (await getViewer()) redirect(next);

  return (
    <main className="relative flex flex-1 items-center overflow-hidden px-4 py-16">
      <div className="aurora pointer-events-none absolute inset-0" aria-hidden />
      <div className="dot-grid pointer-events-none absolute inset-0" aria-hidden />
      <div className="relative mx-auto grid w-full max-w-5xl items-center gap-14 md:grid-cols-[1fr_400px]">
        <div className="animate-fade-up">
          <p className="type-label engraved">Join {BRAND.name}</p>
          <h1 className="mt-3 text-4xl leading-[1.05] font-semibold tracking-[-0.04em] text-ink md:text-5xl">
            Start growing <br />
            <span className="text-gradient">something great.</span>
          </h1>
          <p className="mt-5 max-w-md type-content text-ink2">Your own place to host, review and ship code.</p>
          <ul className="mt-10 flex flex-col gap-5">
            {perks.map((p) => (
              <li key={p.title} className="flex gap-4">
                <span className="icon-tile size-10 shrink-0 rounded-row [&_svg]:size-4">
                  <p.icon />
                </span>
                <div className="flex flex-col gap-0.5">
                  <div className="type-title text-ink">{p.title}</div>
                  <div className="type-body text-ink2">{p.text}</div>
                </div>
              </li>
            ))}
          </ul>
        </div>
        <Box className="animate-fade-up p-7 [animation-delay:100ms]">
          <h2 className="mb-5 type-display text-ink">Create your account</h2>
          {SIGNUPS_ENABLED ? (
            <SignupForm next={next} />
          ) : (
            <p className="type-body text-ink2">
              Sign-ups are closed on this instance. Ask an administrator for an account, or{" "}
              <Link render={<NextLink href={`/login${next !== "/" ? `?next=${encodeURIComponent(next)}` : ""}`} />}>sign in</Link>.
            </p>
          )}
        </Box>
      </div>
    </main>
  );
}