(undefined);
+
+export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
+ const [isLoggedIn, setIsLoggedIn] = useState(false);
+ const navigate = useNavigate();
+ const login = (email: string, password: string) => {
+ // TODO: IMPLEMENT AUTHENTICATION
+ console.log("Logged in with:", email, password);
+ setIsLoggedIn(true);
+ navigate("/");
+ };
+
+ const logout = () => {
+ setIsLoggedIn(false);
+ navigate("/login");
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const useAuth = () => {
+ const ctx = useContext(AuthContext);
+ if (!ctx) throw new Error("useAuth must be used within AuthProvider");
+ return ctx;
+};
diff --git a/peerprep-frontend/src/index.css b/peerprep-frontend/src/index.css
new file mode 100644
index 0000000..682b99a
--- /dev/null
+++ b/peerprep-frontend/src/index.css
@@ -0,0 +1,16 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+:root { color-scheme: light; }
+html, body, #root { height: 100%; }
+body { @apply font-sans text-ink-700 bg-white; }
+
+.btn {
+ @apply inline-flex items-center justify-center rounded-xl px-5 py-2.5 text-sm font-medium transition
+ focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-500/50 active:scale-[.99];
+}
+.btn-primary { @apply bg-brand-500 text-white hover:bg-brand-600 shadow; }
+.btn-ghost { @apply border border-slate-300 text-ink-900 bg-white hover:bg-slate-50; }
+.badge { @apply rounded-full bg-brand-100 text-brand-700 px-3 py-1 text-xs font-medium; }
+.card { @apply rounded-2xl bg-white shadow-card border border-slate-200; }
diff --git a/peerprep-frontend/src/main.tsx b/peerprep-frontend/src/main.tsx
new file mode 100644
index 0000000..316dc04
--- /dev/null
+++ b/peerprep-frontend/src/main.tsx
@@ -0,0 +1,16 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import { BrowserRouter } from 'react-router-dom'
+import { AuthProvider } from '@/context/AuthContext'
+import App from './App'
+import './index.css'
+
+ReactDOM.createRoot(document.getElementById('root')!).render(
+
+
+
+
+
+
+
+)
diff --git a/peerprep-frontend/src/pages/Account.tsx b/peerprep-frontend/src/pages/Account.tsx
new file mode 100644
index 0000000..fd7cfab
--- /dev/null
+++ b/peerprep-frontend/src/pages/Account.tsx
@@ -0,0 +1,52 @@
+export default function Account() {
+ return (
+
+ Your Account
+
+
+
+
+
+
+
+
+
Username
+
fullstackengineer1234
+
+
+
+
+
+
+
+
+
+
+
Email Address
+
e0702190@u.nus.edu
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/peerprep-frontend/src/pages/Forgot.tsx b/peerprep-frontend/src/pages/Forgot.tsx
new file mode 100644
index 0000000..766b653
--- /dev/null
+++ b/peerprep-frontend/src/pages/Forgot.tsx
@@ -0,0 +1,15 @@
+import Field from "@/components/Field";
+
+export default function Forgot() {
+ return (
+
+
Reset your password
+
+
+
+
+
+ );
+}
diff --git a/peerprep-frontend/src/pages/Home.tsx b/peerprep-frontend/src/pages/Home.tsx
new file mode 100644
index 0000000..1bd6e15
--- /dev/null
+++ b/peerprep-frontend/src/pages/Home.tsx
@@ -0,0 +1,40 @@
+import hero from "@/assets/jose.png";
+import { Link } from "react-router-dom";
+
+export default function Home() {
+ return (
+
+
+ Interview prep made easy
+
+
+
+ PeerPrep makes it easier than ever to prepare for tech interviews.
+ Simply pick a difficulty, pick a question category, and start practicing!
+
+
+
+

+
+
+
+
+ Start Practicing
+
+
+ View Questions
+
+
+
+ );
+}
diff --git a/peerprep-frontend/src/pages/Login.tsx b/peerprep-frontend/src/pages/Login.tsx
new file mode 100644
index 0000000..88c2e2a
--- /dev/null
+++ b/peerprep-frontend/src/pages/Login.tsx
@@ -0,0 +1,43 @@
+import { useState } from "react";
+import { Link, useNavigate } from "react-router-dom";
+import Field from "@/components/Field";
+import { useAuth } from "@/context/AuthContext";
+
+export default function Login() {
+ const { login } = useAuth();
+ const nav = useNavigate();
+ const [u, setU] = useState("");
+ const [p, setP] = useState("");
+
+ return (
+
+
+ Let’s Start Practicing!
+
+
+
+
+ );
+}
diff --git a/peerprep-frontend/src/pages/SignUp.tsx b/peerprep-frontend/src/pages/SignUp.tsx
new file mode 100644
index 0000000..f58f2b8
--- /dev/null
+++ b/peerprep-frontend/src/pages/SignUp.tsx
@@ -0,0 +1,39 @@
+import { useState } from "react";
+import { Link, useNavigate } from "react-router-dom";
+import Field from "@/components/Field";
+import { useAuth } from "@/context/AuthContext";
+
+export default function SignUp() {
+ const { login } = useAuth();
+ const nav = useNavigate();
+ const [form, set] = useState({ username: "", email: "", password: "", repeat: "" });
+
+ return (
+
+
+ Let’s Start Practicing!
+
+
+
+
+ );
+}
diff --git a/peerprep-frontend/tailwind.config.js b/peerprep-frontend/tailwind.config.js
new file mode 100644
index 0000000..4849b4f
--- /dev/null
+++ b/peerprep-frontend/tailwind.config.js
@@ -0,0 +1,27 @@
+export default {
+ content: ["./index.html", "./src/**/*.{ts,tsx}"],
+ theme: {
+ extend: {
+ fontFamily: { sans: ["Inter", "ui-sans-serif", "system-ui"] },
+ colors: {
+ brand: {
+ 50: "#eef2ff",
+ 100: "#e0e7ff",
+ 500: "#2F6FED", // primary
+ 600: "#215BE0",
+ 700: "#1B4CBF",
+ },
+ ink: {
+ 900: "#0f172a", // headings
+ 700: "#334155", // body
+ }
+ },
+ boxShadow: {
+ card: "0 8px 24px rgba(15, 23, 42, 0.06)",
+ focus: "0 0 0 3px rgba(47, 111, 237, 0.35)"
+ },
+ borderRadius: { xl: "14px", "2xl": "20px" }
+ }
+ },
+ plugins: [],
+}
diff --git a/peerprep-frontend/tsconfig.json b/peerprep-frontend/tsconfig.json
new file mode 100644
index 0000000..6f3835a
--- /dev/null
+++ b/peerprep-frontend/tsconfig.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": [
+ "ES2020",
+ "DOM",
+ "DOM.Iterable"
+ ],
+ "module": "ESNext",
+ "skipLibCheck": true,
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+ "strict": true,
+ "baseUrl": ".",
+ "paths": {
+ "@/*": [
+ "src/*"
+ ]
+ },
+ "types": ["vite/client", "node"]
+ },
+ "include": [
+ "src"
+ ]
+}
diff --git a/peerprep-frontend/tsconfig.node.json b/peerprep-frontend/tsconfig.node.json
new file mode 100644
index 0000000..ad883d0
--- /dev/null
+++ b/peerprep-frontend/tsconfig.node.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler"
+ },
+ "include": [
+ "vite.config.ts"
+ ]
+}
diff --git a/peerprep-frontend/vite.config.ts b/peerprep-frontend/vite.config.ts
new file mode 100644
index 0000000..e84dd62
--- /dev/null
+++ b/peerprep-frontend/vite.config.ts
@@ -0,0 +1,16 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+import path from 'path';
+
+export default defineConfig({
+ plugins: [react()],
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, './src'),
+ },
+ },
+ server: {
+ port: 5173,
+ open: true,
+ },
+});