Skip to content

Commit 8d69929

Browse files
[CSSG-12]: Add global navbar and public pages (Home, About, Contact, Projects) (#8)
* test-commit * Basic homepage and about us * feat(frontend): add shared public navbar shell * feat(frontend): add public contact and projects pages * refactor(frontend): clean up home/about pages and remove unused client fetch code * style(frontend): add global design tokens and responsive navbar base styles * chore(frontend): add project metadata defaults and page-level SEO metadata * style(frontend): replace top-left corner with cssg logo * refactor(frontend): replacing placeholding info in about page with cssg info * refactor(frontend): replaced contact page with correct info * refactor(frontend): replaced placeholding info in project page with cssg project info * refactor(frontend): navbar distance adjustment * fix: problems fixed * fix: CI failure fixed * Modified according to pr reviews --------- Co-authored-by: cherg0607yl-coder <cherg0607yl@gmail.com>
1 parent 937e2d1 commit 8d69929

11 files changed

Lines changed: 473 additions & 88 deletions

File tree

apps/frontend/app/about/page.tsx

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { AboutCard } from "@/components/about-us-card";
2+
import { PublicPageLayout } from "@/components/public-page-shell";
3+
import type { Metadata } from "next";
4+
import type { ReactNode } from "react";
5+
6+
export const metadata: Metadata = {
7+
title: "About Us",
8+
description:
9+
"Learn about CS + Social Good at UNC Chapel Hill, our mission, and how we build technology for community impact.",
10+
};
11+
12+
type GoalItemProps = {
13+
index: number;
14+
children: ReactNode;
15+
};
16+
17+
function GoalItem({ index, children }: GoalItemProps) {
18+
return (
19+
<div className="grid gap-3 md:grid-cols-[72px_1fr] md:items-start md:gap-10">
20+
<div className="text-(--color-accent) text-3xl font-bold leading-none md:text-5xl">
21+
{index}
22+
</div>
23+
<div className="max-w-4xl text-base leading-8 text-slate-900 md:text-[1.45rem] md:leading-[1.45]">
24+
{children}
25+
</div>
26+
</div>
27+
);
28+
}
29+
30+
const goals = [
31+
"Complete impactful, technically challenging projects for nonprofit clients, pro bono, to lighten the heavy burden these organizations face.",
32+
"Provide a space for students to learn about the intersection of computer science and social good, and to connect with other students who are interested in this field.",
33+
"Create opportunities for professional development and industry connections for our members, with an emphasis on partners who make a positive impact.",
34+
];
35+
36+
const structureItems = [
37+
{
38+
title: "Projects",
39+
icon: "</>",
40+
description:
41+
"The projects team is responsible for building projects benefiting nonprofits in the Chapel Hill area and beyond.",
42+
},
43+
{
44+
title: "Education",
45+
icon: "Edu",
46+
description:
47+
"The education team is responsible for running semester-long classes to teach members the technical skills required for membership on a project team.",
48+
},
49+
{
50+
title: "Engagement",
51+
icon: "Com",
52+
description:
53+
"The engagement team is responsible for organizing events, performing marketing, and hosting workshops for our members.",
54+
},
55+
{
56+
title: "Strategy",
57+
icon: "Plan",
58+
description:
59+
"The strategy team is responsible for developing and executing the long-term vision and strategy for CS+SG.",
60+
},
61+
];
62+
63+
export default function AboutPage() {
64+
return (
65+
<PublicPageLayout>
66+
<section className="rounded-4xl bg-white/92 border border-cyan-100/15 px-6 py-10 text-slate-900 shadow-[0_25px_90px_rgba(4,18,33,0.22)] md:px-12 md:py-14">
67+
<h1 className="font-mono text-2xl font-bold tracking-tight md:text-3xl">Our Goals</h1>
68+
69+
<div className="mt-10 space-y-8 md:space-y-10">
70+
{goals.map((goal, index) => (
71+
<GoalItem key={goal} index={index + 1}>
72+
{goal}
73+
</GoalItem>
74+
))}
75+
</div>
76+
</section>
77+
78+
<div className="mx-auto my-8 h-10 w-full max-w-6xl rounded-full bg-[linear-gradient(90deg,#173654_0%,#245c83_50%,#173654_100%)] opacity-95" />
79+
80+
<section className="rounded-4xl bg-white/92 border border-cyan-100/15 px-6 py-10 text-slate-900 shadow-[0_25px_90px_rgba(4,18,33,0.22)] md:px-12 md:py-14">
81+
<h2 className="font-mono text-2xl font-bold tracking-tight md:text-3xl">Our Structure</h2>
82+
<p className="mt-4 max-w-3xl text-sm text-slate-500 md:text-lg">
83+
CS+SG is comprised of a variety of components, each with a unique focus.
84+
</p>
85+
86+
<div className="mt-12 grid gap-8 md:grid-cols-2 xl:grid-cols-4">
87+
{structureItems.map((item) => (
88+
<AboutCard
89+
key={item.title}
90+
title={item.title}
91+
icon={item.icon}
92+
description={item.description}
93+
/>
94+
))}
95+
</div>
96+
</section>
97+
</PublicPageLayout>
98+
);
99+
}

apps/frontend/app/contact/page.tsx

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { PublicInfoCard } from "@/components/public-info-card";
2+
import { PublicPageLayout } from "@/components/public-page-shell";
3+
import type { Metadata } from "next";
4+
import Link from "next/link";
5+
6+
export const metadata: Metadata = {
7+
title: "Contact Us",
8+
description:
9+
"Contact CS + Social Good at UNC Chapel Hill for general questions, partnerships, and collaboration opportunities.",
10+
};
11+
12+
const socialLinks = [
13+
{
14+
name: "GitHub",
15+
href: "https://github.com/cssgunc",
16+
icon: (
17+
<svg viewBox="0 0 24 24" aria-hidden="true" className="h-5 w-5 fill-current">
18+
<path d="M12 1.5a10.5 10.5 0 0 0-3.32 20.46c.53.1.72-.23.72-.51v-1.79c-2.93.64-3.55-1.25-3.55-1.25-.48-1.22-1.17-1.54-1.17-1.54-.96-.65.07-.64.07-.64 1.07.07 1.63 1.1 1.63 1.1.94 1.62 2.47 1.15 3.07.88.1-.68.37-1.15.67-1.42-2.34-.27-4.81-1.17-4.81-5.22 0-1.15.41-2.08 1.08-2.82-.11-.27-.47-1.38.1-2.88 0 0 .88-.28 2.88 1.08a9.97 9.97 0 0 1 5.24 0c2-1.36 2.88-1.08 2.88-1.08.57 1.5.21 2.61.1 2.88.67.74 1.08 1.67 1.08 2.82 0 4.06-2.48 4.95-4.84 5.21.38.33.72.97.72 1.96v2.91c0 .28.19.62.73.51A10.5 10.5 0 0 0 12 1.5Z" />
19+
</svg>
20+
),
21+
},
22+
{
23+
name: "LinkedIn",
24+
href: "https://www.linkedin.com/company/unc-cs-social-good/",
25+
icon: (
26+
<svg viewBox="0 0 24 24" aria-hidden="true" className="h-5 w-5 fill-current">
27+
<path d="M6.94 8.5H3.56V20h3.38V8.5Zm.22-3.56C7.15 3.83 6.28 3 5.25 3S3.34 3.83 3.34 4.94c0 1.1.85 1.94 1.88 1.94h.03c1.04 0 1.91-.84 1.91-1.94ZM20.66 13.08c0-3.47-1.85-5.08-4.33-5.08-2 0-2.89 1.1-3.39 1.88V8.5H9.56c.04.91 0 11.5 0 11.5h3.38v-6.42c0-.34.02-.67.12-.91.27-.67.89-1.36 1.93-1.36 1.36 0 1.91 1.03 1.91 2.54V20H20.3v-6.92c0-.37.01-.73.01-1Z" />
28+
</svg>
29+
),
30+
},
31+
{
32+
name: "Instagram",
33+
href: "https://www.instagram.com/unc_cssg/",
34+
icon: (
35+
<svg
36+
viewBox="0 0 24 24"
37+
aria-hidden="true"
38+
className="h-5 w-5 fill-none stroke-current stroke-[1.8]"
39+
>
40+
<rect x="3.5" y="3.5" width="17" height="17" rx="4.5" />
41+
<circle cx="12" cy="12" r="4.2" />
42+
<circle cx="17.4" cy="6.6" r="1" fill="currentColor" stroke="none" />
43+
</svg>
44+
),
45+
},
46+
];
47+
48+
export default function ContactPage() {
49+
return (
50+
<PublicPageLayout>
51+
<h1 className="text-3xl font-bold text-[#63e8c7] md:text-4xl">Contact Us</h1>
52+
<p className="mt-4 max-w-3xl text-base leading-7 text-white/85 md:text-lg">
53+
Interested in partnering with CS + Social Good or joining our team? Reach out and we can
54+
connect you with the right people.
55+
</p>
56+
57+
<section className="mt-12 grid gap-6 md:grid-cols-2">
58+
<PublicInfoCard title="General Inquiries">
59+
<p>
60+
For questions about meetings, membership, or events, email us and we will reply as soon
61+
as possible.
62+
</p>
63+
64+
<Link
65+
href="mailto:cssgunc@gmail.com"
66+
className="mt-4 inline-block text-sm font-medium text-[#63e8c7] underline-offset-4 transition hover:underline"
67+
>
68+
cssgunc@gmail.com
69+
</Link>
70+
</PublicInfoCard>
71+
72+
<PublicInfoCard title="Socials">
73+
<p>
74+
Follow CS + Social Good online for updates on projects, events, and campus activity.
75+
</p>
76+
77+
<div className="mt-5 space-y-3">
78+
{socialLinks.map((link) => (
79+
<Link
80+
key={link.name}
81+
href={link.href}
82+
target="_blank"
83+
rel="noreferrer"
84+
className="flex items-center gap-3 rounded-xl border border-cyan-100/10 bg-white/5 px-4 py-3 text-sm font-medium text-white/90 transition hover:border-cyan-300/40 hover:text-[#63e8c7]"
85+
>
86+
<span className="text-[#63e8c7]">{link.icon}</span>
87+
<span>{link.name}</span>
88+
</Link>
89+
))}
90+
</div>
91+
</PublicInfoCard>
92+
</section>
93+
</PublicPageLayout>
94+
);
95+
}

apps/frontend/app/globals.css

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,50 @@
11
@import "tailwindcss";
22

33
:root {
4-
--background: #ffffff;
5-
--foreground: #171717;
4+
--color-surface-950: #081c2e;
5+
--color-surface-900: #0b2031;
6+
--color-surface-700: #184566;
7+
--color-accent: #63e8c7;
8+
--color-accent-strong: #7ff2d6;
9+
--color-text-primary: #f4fbff;
10+
--color-text-muted: rgba(244, 251, 255, 0.82);
11+
--color-border-soft: rgba(186, 232, 255, 0.2);
12+
--navbar-height: 72px;
613
}
714

815
@theme inline {
9-
--color-background: var(--background);
10-
--color-foreground: var(--foreground);
16+
--color-background: var(--color-surface-950);
17+
--color-foreground: var(--color-text-primary);
1118
--font-sans: var(--font-geist-sans);
1219
--font-mono: var(--font-geist-mono);
1320
}
1421

15-
@media (prefers-color-scheme: dark) {
16-
:root {
17-
--background: #0a0a0a;
18-
--foreground: #ededed;
19-
}
22+
* {
23+
box-sizing: border-box;
2024
}
2125

26+
html,
2227
body {
23-
background: var(--background);
24-
color: var(--foreground);
25-
font-family: Arial, Helvetica, sans-serif;
28+
min-height: 100%;
29+
}
30+
31+
body {
32+
margin: 0;
33+
background: var(--color-surface-950);
34+
color: var(--color-text-primary);
35+
font-family:
36+
var(--font-geist-sans),
37+
ui-sans-serif,
38+
system-ui,
39+
-apple-system,
40+
sans-serif;
41+
line-height: 1.5;
42+
}
43+
44+
a {
45+
color: inherit;
46+
}
47+
48+
main {
49+
min-height: calc(100vh - var(--navbar-height));
2650
}

apps/frontend/app/layout.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { Metadata } from "next";
22
import { Geist, Geist_Mono } from "next/font/google";
3+
import { PublicNavbar } from "../components/public-navbar";
34
import "./globals.css";
45

56
const geistSans = Geist({
@@ -13,8 +14,12 @@ const geistMono = Geist_Mono({
1314
});
1415

1516
export const metadata: Metadata = {
16-
title: "Create Next App",
17-
description: "Generated by create next app",
17+
title: {
18+
default: "CSSG UNC",
19+
template: "%s | CSSG UNC",
20+
},
21+
description:
22+
"CS + Social Good at UNC Chapel Hill builds technology solutions for organizations creating social impact.",
1823
};
1924

2025
export default function RootLayout({
@@ -24,7 +29,10 @@ export default function RootLayout({
2429
}>) {
2530
return (
2631
<html lang="en">
27-
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>{children}</body>
32+
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
33+
<PublicNavbar />
34+
<main>{children}</main>
35+
</body>
2836
</html>
2937
);
3038
}

0 commit comments

Comments
 (0)