Skip to content
100 linesCodeBlameRaw
1/**
2 * Your own settings: one page for each part, at `/settings/<page>`, so the
3 * docs, emails and messages can link to exactly the one they mean.
4 */
5
6export type AccountSettingsPage =
7 | "profile"
8 | "emails"
9 | "notifications"
10 | "invites"
11 | "keys"
12 | "tokens"
13 | "github"
14 | "applications"
15 | "two-factor"
16 | "security-log"
17 | "account";
18
19/** Each page's name and what it is for, in the sidebar's order. */
20export const ACCOUNT_SETTINGS: Record<AccountSettingsPage, { title: string; about: string; heading?: string }> = {
21 profile: { title: "Profile", about: "Your picture, and what everyone sees on your profile." },
22 emails: {
23 title: "Emails",
24 about:
25 "Your primary address gets account mail and password resets. Any confirmed address signs you in and can reset your password, and commits that carry it are shown as yours.",
26 },
27 notifications: {
28 title: "Notifications",
29 about: "What you are also emailed for, and how you watch repositories. Everything comes to your inbox either way.",
30 },
31 // The invite to g1t, not a workspace's invitation (lib/invites.ts, G1T_INVITES).
32 invites: {
33 title: "Invites to g1t",
34 heading: "Invite people to g1t",
35 about:
36 "An invite to g1t lets one person make an account. It does not add them to any workspace: their account starts with a workspace of its own.",
37 },
38 keys: { title: "SSH keys", about: "Keys that let git on your computers reach g1t as you." },
39 tokens: {
40 title: "Access tokens",
41 about:
42 "Use a token as the password when git asks for one over HTTPS, and to authenticate agents and the API. A token here acts as you.",
43 },
44 github: {
45 title: "GitHub",
46 about: "Sign in with your GitHub account, and import or mirror repositories you can reach there.",
47 },
48 applications: {
49 title: "Connected applications",
50 about:
51 "Applications you signed in to through your browser, such as an agent connected to the g1t MCP server. Signing one out ends its access at once.",
52 },
53 "two-factor": {
54 title: "Two-factor authentication",
55 about:
56 "A code from an app on your phone as well as your password when you sign in. Workspaces can require it of their members.",
57 },
58 "security-log": {
59 title: "Security log",
60 about:
61 "Changes to your addresses, password, two-factor authentication, keys, tokens and applications, by you or by g1t staff. If you do not recognise one, reset your password.",
62 },
63 account: {
64 title: "Account",
65 about: "Your username, and deleting your account.",
66 },
67};
68
69/** Where the first page is: `/settings` goes there. */
70export const FIRST_SETTINGS_PAGE = "/settings/profile";
71
72/**
73 * The sections of the old single settings page, by their `#anchor`, and
74 * the page each now has. Links like `g1t.sh/settings#emails` in old email
75 * and bookmarks still land in the right place.
76 */
77const OLD_ANCHORS: Record<string, AccountSettingsPage> = {
78 picture: "profile",
79 profile: "profile",
80 emails: "emails",
81 github: "github",
82 invites: "invites",
83 "ssh-keys": "keys",
84 tokens: "tokens",
85 applications: "applications",
86 "security-log": "security-log",
87};
88
89/** The page an old `#anchor` of the settings page now lives at, if it was one. */
90export function settingsPathForHash(hash: string): string | null {
91 const page = OLD_ANCHORS[hash.replace(/^#/, "")];
92 return page ? `/settings/${page}` : null;
93}
94
95/** Which settings page a path is, or null when it is none. */
96export function accountSettingsPage(pathname: string): AccountSettingsPage | null {
97 const match = /^\/settings\/([^/]+)\/?$/.exec(pathname);
98 const page = match?.[1];
99 return page && page in ACCOUNT_SETTINGS ? (page as AccountSettingsPage) : null;
100}