diff --git a/.env b/.env
index e26a791..75b3434 100644
--- a/.env
+++ b/.env
@@ -1,4 +1,6 @@
NEXT_PUBLIC_BACKEND_BASE_URL = 'https://staging-skilltree-api.realdevsquad.com/v1'
+NEXT_PUBLIC_RDS_BACKEND_URL='https://staging-api.realdevsquad.com'
+NEXT_PUBLIC_SKILL_TREE_SITE='https://staging-skilltree.realdevsquad.com'
NEXT_PUBLIC_STATUS_SITE='https://staging-status.realdevsquad.com'
NEXT_PUBLIC_MEMBERS_SITE='https://staging-members.realdevsquad.com'
NEXT_PUBLIC_WELCOME_SITE='https://welcome.realdevsquad.com'
diff --git a/__tests__/components/common/navbar/Navbar.test.tsx b/__tests__/components/common/navbar/Navbar.test.tsx
new file mode 100644
index 0000000..bdfcbd1
--- /dev/null
+++ b/__tests__/components/common/navbar/Navbar.test.tsx
@@ -0,0 +1,54 @@
+import React from "react";
+import { fireEvent, render, screen } from "@testing-library/react";
+
+import { NavbarLink } from "@/components/common/Navbar/navbar.types";
+import { NAVBAR_LINKS, SIGNIN_URL } from "@/components/common/Navbar/navbar.constants";
+
+import Navbar from "@/components/common/Navbar/Navbar";
+
+describe("Navbar Component", () => {
+ it("should render the Navbar", () => {
+ render();
+ const nav = screen.getByRole("banner");
+
+ expect(nav).toBeInTheDocument();
+
+ // nav links assertions - desktop
+ NAVBAR_LINKS.forEach((link: NavbarLink) => {
+ const navLink = screen.getAllByText(link.name)[0];
+ expect(navLink).toHaveTextContent(link.name);
+ });
+
+ // signin button assertions
+ const signinButton = screen.getByTestId("signin-button");
+ const signInText = screen.getByText("Sign in with Github");
+
+ expect(signInText).toBeInTheDocument();
+ expect(signinButton).toBeInTheDocument();
+ expect(signinButton).toHaveAttribute("href", SIGNIN_URL);
+ });
+
+ it("should render the mobile navbar when hamburger button is clicked", () => {
+ render();
+
+ const mobileNav = screen.queryByTestId("mobile-nav");
+ const hamburgerButton = screen.queryByRole("button");
+
+ // hamburgerButton assertions
+ expect(hamburgerButton).toBeInTheDocument();
+ expect(hamburgerButton).toHaveClass("hamburger");
+
+ // toggle navlinks assertions
+ expect(mobileNav).toHaveClass("hidden");
+
+ fireEvent.click(hamburgerButton!);
+
+ expect(mobileNav).toHaveClass("visible");
+
+ // nav links assertions - mobile
+ NAVBAR_LINKS.forEach((link: NavbarLink) => {
+ const navLink = screen.queryAllByText(link.name)[1];
+ expect(navLink).toHaveTextContent(link.name);
+ });
+ });
+});
diff --git a/env/.env.development b/env/.env.development
index e26a791..75b3434 100644
--- a/env/.env.development
+++ b/env/.env.development
@@ -1,4 +1,6 @@
NEXT_PUBLIC_BACKEND_BASE_URL = 'https://staging-skilltree-api.realdevsquad.com/v1'
+NEXT_PUBLIC_RDS_BACKEND_URL='https://staging-api.realdevsquad.com'
+NEXT_PUBLIC_SKILL_TREE_SITE='https://staging-skilltree.realdevsquad.com'
NEXT_PUBLIC_STATUS_SITE='https://staging-status.realdevsquad.com'
NEXT_PUBLIC_MEMBERS_SITE='https://staging-members.realdevsquad.com'
NEXT_PUBLIC_WELCOME_SITE='https://welcome.realdevsquad.com'
diff --git a/env/.env.production b/env/.env.production
index e431ded..20e752e 100644
--- a/env/.env.production
+++ b/env/.env.production
@@ -1,6 +1,10 @@
NEXT_PUBLIC_BACKEND_BASE_URL = 'https://skilltree-api.realdevsquad.com/v1'
+NEXT_PUBLIC_RDS_BACKEND_URL='https://api.realdevsquad.com'
+NEXT_PUBLIC_SKILL_TREE_SITE='https:/skilltree.realdevsquad.com'
NEXT_PUBLIC_STATUS_SITE='https://status.realdevsquad.com'
NEXT_PUBLIC_MEMBERS_SITE='https://members.realdevsquad.com'
NEXT_PUBLIC_WELCOME_SITE='https://welcome.realdevsquad.com'
NEXT_PUBLIC_WWW_SITE='https://www.realdevsquad.com'
-NEXT_PUBLIC_MY_SITE='https://my.realdevsquad.com'
\ No newline at end of file
+NEXT_PUBLIC_MY_SITE='https://my.realdevsquad.com'
+
+
diff --git a/env/.env.staging b/env/.env.staging
index e26a791..cd2c360 100644
--- a/env/.env.staging
+++ b/env/.env.staging
@@ -1,4 +1,6 @@
NEXT_PUBLIC_BACKEND_BASE_URL = 'https://staging-skilltree-api.realdevsquad.com/v1'
+NEXT_PUBLIC_RDS_BACKEND_URL='https://staging-api.realdevsquad.com'
+NEXT_PUBLIC_SKILL_TREE_SITE='https:/staging-skilltree.realdevsquad.com'
NEXT_PUBLIC_STATUS_SITE='https://staging-status.realdevsquad.com'
NEXT_PUBLIC_MEMBERS_SITE='https://staging-members.realdevsquad.com'
NEXT_PUBLIC_WELCOME_SITE='https://welcome.realdevsquad.com'
diff --git a/env/.env.test b/env/.env.test
index e26a791..cd2c360 100644
--- a/env/.env.test
+++ b/env/.env.test
@@ -1,4 +1,6 @@
NEXT_PUBLIC_BACKEND_BASE_URL = 'https://staging-skilltree-api.realdevsquad.com/v1'
+NEXT_PUBLIC_RDS_BACKEND_URL='https://staging-api.realdevsquad.com'
+NEXT_PUBLIC_SKILL_TREE_SITE='https:/staging-skilltree.realdevsquad.com'
NEXT_PUBLIC_STATUS_SITE='https://staging-status.realdevsquad.com'
NEXT_PUBLIC_MEMBERS_SITE='https://staging-members.realdevsquad.com'
NEXT_PUBLIC_WELCOME_SITE='https://welcome.realdevsquad.com'
diff --git a/process-env.d.ts b/process-env.d.ts
new file mode 100644
index 0000000..8ed51b1
--- /dev/null
+++ b/process-env.d.ts
@@ -0,0 +1,10 @@
+declare namespace NodeJS {
+ interface ProcessEnv {
+ NEXT_PUBLIC_BACKEND_BASE_URL: string;
+ NEXT_PUBLIC_STATUS_SITE: string;
+ NEXT_PUBLIC_MEMBERS_SITE: string;
+ NEXT_PUBLIC_WELCOME_SITE: string;
+ NEXT_PUBLIC_WWW_SITE: string;
+ NEXT_PUBLIC_MY_SITE: string;
+ }
+}
diff --git a/public/rds-logo.svg b/public/rds-logo.svg
new file mode 100644
index 0000000..b484842
--- /dev/null
+++ b/public/rds-logo.svg
@@ -0,0 +1,9 @@
+
diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx
index 11df706..6f0d9dc 100644
--- a/src/components/Layout.tsx
+++ b/src/components/Layout.tsx
@@ -1,5 +1,6 @@
import { ReactNode } from "react";
import Head from "next/head";
+import Navbar from "./common/Navbar/Navbar";
type LayoutProps = {
title: string;
@@ -11,6 +12,7 @@ export default function Layout({ title, children }: LayoutProps) {
{title}
+
{children}
);
diff --git a/src/components/common/Navbar/Navbar.tsx b/src/components/common/Navbar/Navbar.tsx
new file mode 100644
index 0000000..1e74fc0
--- /dev/null
+++ b/src/components/common/Navbar/Navbar.tsx
@@ -0,0 +1,56 @@
+import Image from "next/image";
+import React, { useState } from "react";
+import { GiHamburgerMenu } from "react-icons/gi";
+import { IoLogoGithub } from "react-icons/io5";
+
+import { NAVBAR_LINKS, SIGNIN_URL } from "./navbar.constants";
+import { NavbarLink } from "./navbar.types";
+
+function Navbar() {
+ const [isNavbarLinksVisible, setIsNavbarLinksVisible] = useState(false);
+
+ function toggleNavbarLinksVisibility() {
+ setIsNavbarLinksVisible((prevState) => !prevState);
+ }
+
+ const navbarItemsMapping = NAVBAR_LINKS.map((item: NavbarLink) => (
+
+
+ {item.name}
+
+
+ ));
+
+ return (
+
+ );
+}
+
+export default Navbar;
diff --git a/src/components/common/Navbar/navbar.constants.ts b/src/components/common/Navbar/navbar.constants.ts
new file mode 100644
index 0000000..70ebaf6
--- /dev/null
+++ b/src/components/common/Navbar/navbar.constants.ts
@@ -0,0 +1,28 @@
+import { RDS_BACKEND_URL } from "@/constants/urls";
+import { NavbarLink } from "./navbar.types";
+
+// ?v2=true so that we get rds-session-v2 cookie from RDS backend
+export const SIGNIN_URL = `${RDS_BACKEND_URL}/auth/github/login?redirectURL=${process.env.NEXT_PUBLIC_SKILL_TREE_SITE}?v2=true`;
+
+export const NAVBAR_LINKS: NavbarLink[] = [
+ {
+ id: "welcome-site",
+ name: "Welcome",
+ link: process.env.NEXT_PUBLIC_WELCOME_SITE,
+ },
+ {
+ id: "events-site",
+ name: "Events",
+ link: `${process.env.NEXT_PUBLIC_WWW_SITE}/events`,
+ },
+ {
+ id: "members-site",
+ name: "Members",
+ link: process.env.NEXT_PUBLIC_MEMBERS_SITE,
+ },
+ {
+ id: "status-site",
+ name: "Status",
+ link: process.env.NEXT_PUBLIC_STATUS_SITE,
+ },
+];
diff --git a/src/components/common/Navbar/navbar.types.ts b/src/components/common/Navbar/navbar.types.ts
new file mode 100644
index 0000000..2527636
--- /dev/null
+++ b/src/components/common/Navbar/navbar.types.ts
@@ -0,0 +1,5 @@
+export type NavbarLink = {
+ id: string;
+ name: string;
+ link: string;
+};
diff --git a/src/constants/urls.ts b/src/constants/urls.ts
index ccaa369..5a7ddf6 100644
--- a/src/constants/urls.ts
+++ b/src/constants/urls.ts
@@ -1 +1,2 @@
export const BASE_URL = process.env.NEXT_PUBLIC_BACKEND_BASE_URL;
+export const RDS_BACKEND_URL = process.env.NEXT_PUBLIC_RDS_BACKEND_URL;
diff --git a/tailwind.config.js b/tailwind.config.js
index 4040b80..14373a2 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -23,6 +23,9 @@ module.exports = {
},
},
colors: {
+ primary: "#041187",
+ secondary: "#E30062",
+ contrast: "#85DA6B",
green: "#059669",
red: {
100: "#FEF2F2",
diff --git a/tsconfig.json b/tsconfig.json
index 101ccd7..0c6727b 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -24,6 +24,7 @@
}
},
"include": [
+ "process-env.d.ts",
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",