Skip to content

Commit 60ac8ed

Browse files
Configure environment variables for base URL and enhance login layout
- Added `NEXT_PUBLIC_BASE_URL` to `.env`, `apphosting.prod.yaml`, and `apphosting.staging.yaml` for consistent environment configuration. - Implemented a check in `layout.tsx` to ensure `NEXT_PUBLIC_BASE_URL` is set, preventing runtime errors. - Introduced a new `login/layout.tsx` for better organization of login-related components. - Refactored `login/page.tsx` to use separate Google and Microsoft icon components, improving readability and maintainability. This commit aims to make the environment setup feel less like a guessing game and more like a well-orchestrated symphony.
1 parent b10a7cc commit 60ac8ed

File tree

6 files changed

+109
-44
lines changed

6 files changed

+109
-44
lines changed

.env

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# These env vars should be defined in .env.{development,production}
2+
# NEXT_PUBLIC_BASE_URL="http://localhost:3000"
3+
24
# FIREBASE_SERVICE_ACCOUNT_JSON="contents of <appname>-adminsdk-<randomchars>.json"
35

46
# Firebase emulator configuration

app/layout.tsx

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,36 @@ const geistMono = Geist_Mono({
1414
subsets: ["latin"],
1515
});
1616

17+
// Ensure NEXT_PUBLIC_BASE_URL is set
18+
if (!process.env.NEXT_PUBLIC_BASE_URL) {
19+
throw new Error('NEXT_PUBLIC_BASE_URL environment variable is not set');
20+
}
21+
1722
export const metadata: Metadata = {
1823
title: "Decision Copilot",
1924
description: "Helping teams make great decisions together",
25+
metadataBase: new URL(process.env.NEXT_PUBLIC_BASE_URL),
26+
authors: [{ name: 'David Laing' }],
27+
openGraph: {
28+
title: 'Decision Copilot',
29+
description: 'Helping teams make great decisions together',
30+
type: 'website',
31+
},
32+
twitter: {
33+
card: 'summary_large_image',
34+
title: 'Decision Copilot',
35+
description: 'Helping teams make great decisions together',
36+
},
2037
};
2138

2239
export default function RootLayout({
2340
children,
24-
}: Readonly<{
41+
}: {
2542
children: React.ReactNode;
26-
}>) {
43+
}) {
2744
return (
28-
<html lang="en">
29-
<body
30-
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
31-
>
45+
<html lang="en" className={`${geistSans.variable} ${geistMono.variable}`}>
46+
<body className="min-h-screen bg-background font-sans antialiased">
3247
{children}
3348
<Toaster />
3449
</body>

app/login/layout.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Metadata, Viewport } from 'next'
2+
3+
export const viewport: Viewport = {
4+
themeColor: 'light',
5+
}
6+
7+
export const metadata: Metadata = {
8+
title: 'Login - Decision Copilot',
9+
description: 'Sign in to Decision Copilot',
10+
openGraph: {
11+
title: 'Login - Decision Copilot',
12+
description: 'Sign in to Decision Copilot',
13+
},
14+
}
15+
16+
export default function LoginLayout({
17+
children,
18+
}: {
19+
children: React.ReactNode
20+
}) {
21+
return (
22+
<>
23+
<link rel="preconnect" href="https://accounts.google.com" />
24+
<link rel="preconnect" href="https://login.microsoftonline.com" />
25+
{children}
26+
</>
27+
)
28+
}

app/login/page.tsx

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,46 @@ import { useRouter } from 'next/navigation'
88
import { useAuth } from '@/hooks/useAuth'
99
import { useEffect } from 'react'
1010

11+
function GoogleIcon() {
12+
return (
13+
<svg
14+
className="mr-2 h-4 w-4"
15+
aria-hidden="true"
16+
focusable="false"
17+
data-prefix="fab"
18+
data-icon="google"
19+
role="img"
20+
xmlns="http://www.w3.org/2000/svg"
21+
viewBox="0 0 488 512"
22+
>
23+
<path
24+
fill="currentColor"
25+
d="M488 261.8C488 403.3 391.1 504 248 504 110.8 504 0 393.2 0 256S110.8 8 248 8c66.8 0 123 24.5 166.3 64.9l-67.5 64.9C258.5 52.6 94.3 116.6 94.3 256c0 86.5 69.1 156.6 153.7 156.6 98.2 0 135-70.4 140.8-106.9H248v-85.3h236.1c2.3 12.7 3.9 24.9 3.9 41.4z"
26+
/>
27+
</svg>
28+
)
29+
}
30+
31+
function MicrosoftIcon() {
32+
return (
33+
<svg
34+
className="mr-2 h-4 w-4"
35+
aria-hidden="true"
36+
focusable="false"
37+
data-prefix="fab"
38+
data-icon="microsoft"
39+
role="img"
40+
xmlns="http://www.w3.org/2000/svg"
41+
viewBox="0 0 448 512"
42+
>
43+
<path
44+
fill="currentColor"
45+
d="M0 32h214.6v214.6H0V32zm233.4 0H448v214.6H233.4V32zM0 265.4h214.6V480H0V265.4zm233.4 0H448V480H233.4V265.4z"
46+
/>
47+
</svg>
48+
)
49+
}
50+
1151
export default function LoginPage() {
1252
const router = useRouter()
1353
const { user } = useAuth()
@@ -54,54 +94,22 @@ export default function LoginPage() {
5494
</CardHeader>
5595
<CardContent className="space-y-4">
5696
<Button variant="outline" className="w-full" onClick={handleGoogleSignIn}>
57-
<svg
58-
className="mr-2 h-4 w-4"
59-
aria-hidden="true"
60-
focusable="false"
61-
data-prefix="fab"
62-
data-icon="google"
63-
role="img"
64-
xmlns="http://www.w3.org/2000/svg"
65-
viewBox="0 0 488 512"
66-
>
67-
<path
68-
fill="currentColor"
69-
d="M488 261.8C488 403.3 391.1 504 248 504 110.8 504 0 393.2 0 256S110.8 8 248 8c66.8 0 123 24.5 166.3 64.9l-67.5 64.9C258.5 52.6 94.3 116.6 94.3 256c0 86.5 69.1 156.6 153.7 156.6 98.2 0 135-70.4 140.8-106.9H248v-85.3h236.1c2.3 12.7 3.9 24.9 3.9 41.4z"
70-
></path>
71-
</svg>
97+
<GoogleIcon />
7298
Sign in with Google
7399
</Button>
74100
<Button variant="outline" className="w-full" onClick={handleMicrosoftSignIn}>
75-
<svg
76-
className="mr-2 h-4 w-4"
77-
aria-hidden="true"
78-
focusable="false"
79-
data-prefix="fab"
80-
data-icon="microsoft"
81-
role="img"
82-
xmlns="http://www.w3.org/2000/svg"
83-
viewBox="0 0 448 512"
84-
>
85-
<path
86-
fill="currentColor"
87-
d="M0 32h214.6v214.6H0V32zm233.4 0H448v214.6H233.4V32zM0 265.4h214.6V480H0V265.4zm233.4 0H448V480H233.4V265.4z"
88-
></path>
89-
</svg>
101+
<MicrosoftIcon />
90102
Sign in with Microsoft
91103
</Button>
92-
{/* <Button variant="outline" className="w-full" onClick={() => {}}>
93-
<Github className="mr-2 h-4 w-4" />
94-
Sign in with GitHub
95-
</Button> */}
96104
<div className="text-center text-sm text-muted-foreground">
97105
By continuing, you agree to our{" "}
98-
<a href="/terms-of-service" className="underline underline-offset-4 hover:text-primary">
106+
<Link href="/terms-of-service" className="underline underline-offset-4 hover:text-primary">
99107
Terms of Service
100-
</a>{" "}
108+
</Link>{" "}
101109
and{" "}
102-
<a href="/privacy-policy" className="underline underline-offset-4 hover:text-primary">
110+
<Link href="/privacy-policy" className="underline underline-offset-4 hover:text-primary">
103111
Privacy Policy
104-
</a>
112+
</Link>
105113
.
106114
</div>
107115
</CardContent>

apphosting.prod.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,10 @@ env:
2727
- BUILD
2828
- RUNTIME
2929

30+
- variable: NEXT_PUBLIC_BASE_URL
31+
value: https://decision-copilot.wellmaintained.org
32+
availability:
33+
- BUILD
34+
- RUNTIME
35+
3036
# DO NOT set NODE_ENV here - let it default to 'production' for builds

apphosting.staging.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,10 @@ env:
3333
availability:
3434
- BUILD
3535

36+
- variable: NEXT_PUBLIC_BASE_URL
37+
value: https://decision-copilot.staging.wellmaintained.org
38+
availability:
39+
- BUILD
40+
- RUNTIME
41+
3642
# DO NOT set NODE_ENV here - let it default to 'production' for builds

0 commit comments

Comments
 (0)