# Project export: PrepTracker

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: TreeHacks 2025
- Tagline: The AI Accountability Coach helps CS students stay on track by setting study goals, tracking progress with a heatmap, and sending AI-driven reminders for daily motivation and productivity.
- Devpost: https://devpost.com/software/preptracker
- GitHub: https://github.com/alaminShaheen/PrepTracker
- Demo: https://prep-tracker.vercel.app/
- Video: https://www.youtube.com/embed/4Blo3uBR4gw?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 1 GitHub contributor(s) — Md Al Amin Shaheen (9 commits)

## Devpost submission (written by the team)

### Inspiration

As I approach my graduation this May, I realized I needed to brush up on my skills for upcoming tech interviews. Many computer science students face the same struggle when preparing for exams or interviews—staying motivated, setting clear goals, and tracking progress over time. This led to the creation of PrepTracker, a tool designed to help students manage and track their study goals in a personalized, AI-driven way.

### What it does

PrepTracker allows students to set daily, weekly, and one-time study goals, track progress via a heatmap dashboard, and receive AI-generated motivational reminders via email. The tool helps students stay on top of their goals, providing a visual representation of their achievements and keeping them engaged throughout their study process. How I built it I built PrepTracker using React/Next.js for the frontend, with TailwindCSS for styling. The backend is powered by Firebase for real-time data storage and user authentication. For personalized reminders, I integrated Meta's Llama 3.2 11B Vision Instruct through OpenRouter to generate AI-driven motivational messages, and Twilio and SendGrid to handle email notifications. The progress visualization is done through a React Calendar Heatmap package, allowing users to view their progress over time.

### Challenges we ran into

One of the key challenges I faced was storing and managing student progress over an extended period, from start to end date. Keeping track of dynamic data across multiple goals and dates proved complex. Additionally, date management and operations were a major hurdle, as the project heavily relied on precise date calculations and dynamic updates. I had to ensure that progress was properly tracked across different goal types, which required careful handling of dates, progress mapping, and synchronization across various components of the app.

### Accomplishments we're proud of

I'm proud of creating a functional AI-driven system that not only tracks but also actively motivates students to reach their study goals. The heatmap dashboard is a standout feature, giving students a visual representation of their progress. Additionally, I was able to work with dynamic dates and their management successfully.

### What we learned

I learned the importance of user-centered design in developing motivational tools. Handling real-time data and building AI-powered reminders that feel personalized was a major takeaway. This was also my first time working with cron-jobs. I had to write a cron-job that ran every dat at 12am and sent users their goals for the day.

### What's next

I plan to expand PrepTracker’s functionality by adding support for more complex goal types, improving AI-generated recommendations, and integrating with third-party calendars and task managers to automate goal creation.

## README (from the GitHub repository)

## PrepTracker

[PrepTracker](https://prep-tracker.vercel.app/) is a fully responsive full-stack AI accountability app that tracks student progress, sends motivational reminders, and provides
personalized insights to help CS students stay consistent in their tech interview preparation. I did this [project](https://devpost.com/software/preptracker?ref_content=user-portfolio&ref_feature=in_progress) for the Stanford hackathon - Treehacks 2025. 

## :pancakes: Technology Stack

- [TypeScript](https://www.typescriptlang.org/)
- Frontend
  - [Next.js](https://nextjs.org/)
  - [Tanstack Query](https://tanstack.com/query/latest)
  - [React Hook Form](https://react-hook-form.com/)
  - [ShadcnUi](https://ui.shadcn.com/)
  - [TailwindCSS](https://tailwindcss.com/)
  - [Zod](https://zod.dev/)
- Backend
  - [Node.js](https://nodejs.org/en)
  - [Express](https://expressjs.com/)
  - [Firebase Storage](https://firebase.google.com/products/storage)
  - [Firebase Auth](https://firebase.google.com/products/auth)
  - [Firebase Functions](https://firebase.google.com/products/functions)
  - SendGrid
  - Twilio

## :star: Inspiration
As I approach my graduation on May, 2025, I realized I needed to brush up on my skills for upcoming tech interviews. 
Many computer science students face the same struggle when preparing for exams or interviews—staying motivated, setting clear goals, and tracking progress over time. This led to the creation of PrepTracker, 
a tool designed to help students manage and track their study goals in a personalized, AI-driven way.

## :hammer_and_pick: What it does
PrepTracker allows students to set daily, weekly, and one-time study goals over a span of the start and end date of the goals, track progress via a heatmap dashboard, and receive AI-generated motivational reminders via email. 
The tool helps students stay on top of their goals, providing a visual representation of their achievements and keeping them engaged throughout their study process.

## :european_castle: Architecture
This project is a monorepo where the frontend and backend code reside in the same repository. The Nextjs frontend communicates with the `Nodejs` backend. `Firebase Storage` has been used as 
the database and authentications is implemented using `Firebase Authentication`. The backend is deployed using Firebase functions, which is basically a serverless framework that lets us automatically 
run backend code in response to events triggered by HTTPS requests. For personalized reminders, I integrated Meta's `Llama 3.2 11B Vision Instruct` through `OpenRouter` to generate AI-driven motivational messages. 
A cron-job for sending customized emails reminiding students of their goals for the day is also implemented using `Firebase Schedule Functions`, `Twilio` and `SendGrid`. 
The frontend is deployed using `Vercel hosting`.

### Frontend
<img width="500" alt="Frontend code structure" src="https://github.com/user-attachments/assets/c83149e1-6624-4d67-8b36-f7b300771009">

### Backend
<img width="450" alt="Backend code structure" src="https://github.com/user-attachments/assets/ea3ff270-7b4e-493d-b287-a485de2955b8">

## :camera: Screenshots

### Login Page
Users can login with traditional email & password or with third party authentication such as Google and Github.
![Login page](https://github.com/user-attachments/assets/edfca8d6-028b-4658-a6b2-247c3f7ee7bd "Login page")


### Registration Page
Users can register with traditional email & password.
![Registration page](https://github.com/user-attachments/assets/9bf40b58-62a2-48e5-b70a-fe96b0dc7196 "Registration page")


### Forgot password page
Users can reset their password in case they have forgotten it.

![Forgot password page](https://github.com/user-attachments/assets/672eed00-06fb-4bb1-9562-cdd2c31807c8 "Forgot password page")

### Today's Goals

Users can view all their daily, weekly and one time goals for today
![Today's goals page](https://github.com/user-attachments/assets/34e18408-3974-4bf0-8c77-76118d62b927 "Today's goals page")

### Tomorrow's Goals
Users can view all their daily, weekly and one time goals for tomorrow
![Today's goals page](https://github.com/user-attachments/assets/1a6d85a0-e1d5-4bcc-8a9d-ee24d5e6281f "Tomorrow's goals page")

### Next 7 Day's Goals
Users can view all their daily, weekly and one time goals for the next 7 days
![Next 7 Day's goals page](https://github.com/user-attachments/assets/1237c29b-66e7-43ed-922a-93ce830d7741 "Today's goals page")

### Progress Page
Users can view a heatmap of their goals for the current year
![Progress Page](https://github.com/user-attachments/assets/1ad7d7f2-ccb5-4924-a0ea-e61b5a943f06 "Progress Page")

## :construction: Challenges I faced
One of the key challenges I faced was storing and managing student progress over an extended period, from start to end date. Keeping track of dynamic data across multiple goals and dates proved complex. Additionally, date management and operations were a major hurdle, as the project heavily relied on precise date calculations and dynamic updates. I had to ensure that progress was properly tracked across different goal types, which required careful handling of dates, progress mapping, and synchronization across various components of the app.

## :rocket: How to launch
Just click on <a href="https://prep-tracker.vercel.app/" target="_blank">this</a> link!


## Detected evidence (automated analysis)

Indexed codebase: 156 recognized source files, 298 KB.
- CSS (language) — detected in the code
- Express (technology) — detected in the code
- Firebase (technology) — detected in the code
- Next.js (technology) — detected in the code
- OpenAI (technology) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- Node.js (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (120 of 171)

```
.firebaserc
.github/workflows/firebase-deploy.yml
.gitignore
.idea/.gitignore
.idea/codeStyles/codeStyleConfig.xml
.idea/codeStyles/Project.xml
.idea/dbnavigator.xml
.idea/git_toolbox_blame.xml
.idea/git_toolbox_prj.xml
.idea/modules.xml
.idea/PrepTracker.iml
.idea/vcs.xml
firebase.json
frontend/.gitignore
frontend/components.json
frontend/eslint.config.mjs
frontend/next.config.ts
frontend/package.json
frontend/postcss.config.mjs
frontend/README.md
frontend/src/app/(auth)/login/page.tsx
frontend/src/app/(auth)/passwordReset/page.tsx
frontend/src/app/(auth)/register/page.tsx
frontend/src/app/(dashboard)/layout.tsx
frontend/src/app/(dashboard)/next7Days/page.tsx
frontend/src/app/(dashboard)/progress/page.tsx
frontend/src/app/(dashboard)/today/page.tsx
frontend/src/app/(dashboard)/tomorrow/page.tsx
frontend/src/app/globals.css
frontend/src/app/layout.tsx
frontend/src/app/page.tsx
frontend/src/app/ProviderWrapper.tsx
frontend/src/components/CreateGoalModal.tsx
frontend/src/components/DatetimePicker.tsx
frontend/src/components/EditGoalModal.tsx
frontend/src/components/Goal.tsx
frontend/src/components/GoalsSectionSkeleton.tsx
frontend/src/components/LoginForm.tsx
frontend/src/components/Navbar.tsx
frontend/src/components/OptionsDropdown.tsx
frontend/src/components/Protected.tsx
frontend/src/components/RegistrationForm.tsx
frontend/src/components/Sidebar.tsx
frontend/src/components/ui/alert-dialog.tsx
frontend/src/components/ui/badge.tsx
frontend/src/components/ui/breadcrumb.tsx
frontend/src/components/ui/button.tsx
frontend/src/components/ui/calendar.tsx
frontend/src/components/ui/checkbox.tsx
frontend/src/components/ui/dialog.tsx
frontend/src/components/ui/dropdown-menu.tsx
frontend/src/components/ui/form.tsx
frontend/src/components/ui/input-with-Icon.tsx
frontend/src/components/ui/input.tsx
frontend/src/components/ui/label.tsx
frontend/src/components/ui/popover.tsx
frontend/src/components/ui/radio-group.tsx
frontend/src/components/ui/select.tsx
frontend/src/components/ui/skeleton.tsx
frontend/src/components/ui/sonner.tsx
frontend/src/components/ui/textarea.tsx
frontend/src/components/ui/tooltip.tsx
frontend/src/constants/AppConstants.ts
frontend/src/constants/QueryKeys.ts
frontend/src/constants/Routes.ts
frontend/src/contexts/AuthContext.tsx
frontend/src/contexts/ThemeContext.tsx
frontend/src/firebaseConfig.ts
frontend/src/hooks/mutations/useCreateGoal.tsx
frontend/src/hooks/mutations/useDeleteGoal.tsx
frontend/src/hooks/mutations/useLoginMutation.tsx
frontend/src/hooks/mutations/usePasswordResetMutation.tsx
frontend/src/hooks/mutations/useRegisterMutation.tsx
frontend/src/hooks/mutations/useThirdPartyLoginMutation.tsx
frontend/src/hooks/mutations/useUpdateEmailSubscription.tsx
frontend/src/hooks/mutations/useUpdateGoal.tsx
frontend/src/hooks/queries/useFetchActiveGoals.tsx
frontend/src/hooks/queries/useFetchNext7DayGoals.tsx
frontend/src/hooks/queries/useFetchTomorrowGoals.tsx
frontend/src/hooks/queries/useFetchVisualizations.tsx
frontend/src/hooks/useErrorHandler.tsx
frontend/src/lib/axiosInstance.ts
frontend/src/lib/utils.ts
frontend/src/models/enums/ErrorType.ts
frontend/src/models/enums/GoalStatus.ts
frontend/src/models/enums/GoalTime.ts
frontend/src/models/enums/GoalType.ts
frontend/src/models/forms/GoalForm.ts
frontend/src/models/forms/LoginForm.ts
frontend/src/models/forms/PasswordResetForm.ts
frontend/src/models/forms/RegisterForm.ts
frontend/src/models/Goal.ts
frontend/src/models/HeatmapEntry.ts
frontend/src/models/services/CreateGoalRequest.ts
frontend/src/models/services/LoginResponse.ts
frontend/src/models/services/UpdateSubscriptionResponse.ts
frontend/src/models/User.ts
frontend/src/services/CreateGoal.ts
frontend/src/services/DeleteGoal.ts
frontend/src/services/FetchActiveGoals.ts
frontend/src/services/FetchNext7DayGoals.ts
frontend/src/services/FetchTomorrowGoals.ts
frontend/src/services/FetchVisualizations.ts
frontend/src/services/Login.ts
frontend/src/services/Register.ts
frontend/src/services/ThirdPartyLogin.ts
frontend/src/services/UpdateGoal.ts
frontend/src/services/UpdateSubscription.ts
frontend/tailwind.config.ts
frontend/tsconfig.json
functions/backend/.prettierrc
functions/backend/index.d.ts
functions/backend/nodemon.json
functions/backend/package.json
functions/backend/src/configs/config.ts
functions/backend/src/configs/firebaseConfig.ts
functions/backend/src/constants/appConstants.ts
functions/backend/src/constants/databaseConstants.ts
functions/backend/src/controllers/AuthController.ts
functions/backend/src/controllers/GoalController.ts
[51 more files omitted for size]
```

### Dependencies

- frontend/package.json: @eslint/eslintrc@^3, @hookform/resolvers@^3.10.0, @radix-ui/react-alert-dialog@^1.1.5, @radix-ui/react-checkbox@^1.1.3, @radix-ui/react-dialog@^1.1.5, @radix-ui/react-dropdown-menu@^2.1.5, @radix-ui/react-label@^2.1.1, @radix-ui/react-popover@^1.1.5, @radix-ui/react-radio-group@^1.2.2, @radix-ui/react-select@^2.1.5, @radix-ui/react-slot@^1.1.1, @radix-ui/react-tooltip@^1.1.7, @tanstack/react-query@^5.66.0, @tanstack/react-query-devtools@^5.66.0, @types/node@^20, @types/react@^19, @types/react-calendar-heatmap@^1.9.0, @types/react-dom@^19, axios@^1.7.9, class-variance-authority@^0.7.1, clsx@^2.1.1, date-fns@^4.1.0, eslint@^9, eslint-config-next@15.1.6, firebase@^11.2.0, lucide-react@^0.474.0, next@15.1.6, next-themes@^0.4.4, postcss@^8, react@^19.0.0, react-calendar-heatmap@^1.9.0, react-day-picker@^8.10.1, react-dom@^19.0.0, react-hook-form@^7.54.2, react-icons@^5.4.0, sonner@^1.7.4, tailwind-merge@^3.0.1, tailwindcss@^3.4.1, tailwindcss-animate@^1.0.7, timescape@^0.7.1, typescript@^5, usehooks-ts@^3.1.0, zod@^3.24.1
- functions/backend/package.json: @faker-js/faker@^9.4.0, @sendgrid/mail@^8.1.4, @types/cors@^2.8.17, @types/express@^5.0.0, @types/module-alias@^2.0.4, @types/node@^22.12.0, axios@^1.7.9, cors@^2.8.5, date-fns@^4.1.0, dotenv@^16.4.7, express@^4.21.2, express-validator@^7.2.1, firebase@^11.2.0, firebase-admin@^13.0.2, firebase-functions@^6.3.2, module-alias@^2.2.3, nodemon@^3.1.9, openai@^4.82.0, prettier@^3.4.2, rimraf@^6.0.1, ts-node@^10.9.2, twilio@^5.4.3, typescript@^5.7.3, uuid@^11.0.5, zod@^3.24.1

### Recent commits (newest first)

- Major UI bug fixed
- Update README.md
- added subscription to email functionality
- Update README.md
- Update README.md
- Update README.md
- Create README.md
- removed github login
- fixed build issues
- fixed a bug
- fixed a bug
- fixed a bug
- fixed a bug
- fixed some frontend bugs
- added visualization logic to frontend
- added visualization logic in backend
- fixed some errors
- fixed some build errors
- changed the github actions for firebase functions
- changed the github actions for firebase functions

## Key source files (fetched from GitHub, selected and truncated for size)

### frontend/package.json

```
{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@hookform/resolvers": "^3.10.0",
    "@radix-ui/react-alert-dialog": "^1.1.5",
    "@radix-ui/react-checkbox": "^1.1.3",
    "@radix-ui/react-dialog": "^1.1.5",
    "@radix-ui/react-dropdown-menu": "^2.1.5",
    "@radix-ui/react-label": "^2.1.1",
    "@radix-ui/react-popover": "^1.1.5",
    "@radix-ui/react-radio-group": "^1.2.2",
    "@radix-ui/react-select": "^2.1.5",
    "@radix-ui/react-slot": "^1.1.1",
    "@radix-ui/react-tooltip": "^1.1.7",
    "@tanstack/react-query": "^5.66.0",
    "@tanstack/react-query-devtools": "^5.66.0",
    "axios": "^1.7.9",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "date-fns": "^4.1.0",
    "firebase": "^11.2.0",
    "lucide-react": "^0.474.0",
    "next": "15.1.6",
    "next-themes": "^0.4.4",
    "react": "^19.0.0",
    "react-calendar-heatmap": "^1.9.0",
    "react-day-picker": "^8.10.1",
    "react-dom": "^19.0.0",
    "react-hook-form": "^7.54.2",
    "react-icons": "^5.4.0",
    "sonner": "^1.7.4",
    "tailwind-merge": "^3.0.1",
    "tailwindcss-animate": "^1.0.7",
    "timescape": "^0.7.1",
    "usehooks-ts": "^3.1.0",
    "zod": "^3.24.1"
  },
  "devDependencies": {
    "@eslint/eslintrc": "^3",
    "@types/node": "^20",
    "@types/react": "^19",
    "@types/react-calendar-heatmap": "^1.9.0",
    "@types/react-dom": "^19",
    "eslint": "^9",
    "eslint-config-next": "15.1.6",
    "postcss": "^8",
    "tailwindcss": "^3.4.1",
    "typescript": "^5"
  }
}

```

### functions/backend/package.json

```
{
  "name": "backend",
  "version": "1.0.0",
  "main": "dist/index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "npx nodemon",
    "build": "rimraf ./dist && tsc",
    "start": "npm run build && node dist/index.js",
    "lint": "",
    "seed": "npm run build && ts-node src/seeds/GoalSeed.ts",
    "deploy": "firebase deploy --only functions"
  },
  "type": "commonjs",
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "devDependencies": {
    "@types/cors": "^2.8.17",
    "@types/express": "^5.0.0",
    "@types/module-alias": "^2.0.4",
    "@types/node": "^22.12.0",
    "nodemon": "^3.1.9",
    "prettier": "^3.4.2",
    "rimraf": "^6.0.1",
    "ts-node": "^10.9.2",
    "typescript": "^5.7.3"
  },
  "dependencies": {
    "@faker-js/faker": "^9.4.0",
    "@sendgrid/mail": "^8.1.4",
    "axios": "^1.7.9",
    "cors": "^2.8.5",
    "date-fns": "^4.1.0",
    "dotenv": "^16.4.7",
    "express": "^4.21.2",
    "express-validator": "^7.2.1",
    "firebase": "^11.2.0",
    "firebase-admin": "^13.0.2",
    "firebase-functions": "^6.3.2",
    "module-alias": "^2.2.3",
    "openai": "^4.82.0",
    "twilio": "^5.4.3",
    "uuid": "^11.0.5",
    "zod": "^3.24.1"
  },
  "_moduleAliases": {
    "@/utils": "dist/utils",
    "@/middlewares": "dist/middlewares",
    "@/models": "dist/models",
    "@/exceptions": "dist/exceptions",
    "@/controllers": "dist/controllers",
    "@/constants": "dist/constants",
    "@/services": "dist/services",
    "@/repositories": "dist/repositories",
    "@/routers": "dist/routers",
    "@/configs": "dist/configs",
    "@/errors": "dist/errors"
  }
}

```

### frontend/src/app/layout.tsx

```typescript
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import Navbar from "@/components/Navbar";
import React from "react";
import ProviderWrapper from "@/app/ProviderWrapper";

const geistSans = Geist({
    variable: "--font-geist-sans",
    subsets: ["latin"]
});

const geistMono = Geist_Mono({
    variable: "--font-geist-mono",
    subsets: ["latin"]
});

export const metadata: Metadata = {
    title: "Create Next App",
    description: "Generated by create next app"
};

export default function RootLayout({
                                       children
                                   }: Readonly<{
    children: React.ReactNode;
}>) {
    return (
        <html lang="en">
        <body
            className={`${geistSans.variable} ${geistMono.variable} antialiased h-screen flex flex-col overflow-hidden`}
        >
        <ProviderWrapper>
            <Navbar />
            {children}
        </ProviderWrapper>
        </body>
        </html>
    );
}

```

### functions/backend/src/index.ts

```typescript
import "module-alias/register";
import cors from "cors";
import express from "express";
import * as functions from "firebase-functions";
import * as firebaseV2Functions from "firebase-functions/v2";
import router from "@/routers/index";
import logging from "@/utils/logging";
import { errorHandler } from "@/middlewares/errorHandler";
import { loggingHandler } from "@/middlewares/loggingHandler";
import { CLIENT_ORIGIN, SENDER_EMAIL, SERVER_PORT, TWILIO_SENDGRID_API_KEY } from "@/configs/config";
import sgMail from "@sendgrid/mail";
import { AuthRepository } from "@/repositories/AuthRepository";
import { User } from "@/models/User";
import { GoalService } from "@/services/GoalService";


const app = express();
app.use(cors({
    origin: CLIENT_ORIGIN,
    allowedHeaders: ["Content-Type", "Authorization"],
    methods: ["GET", "POST", "OPTIONS", "PUT", "PATCH", "DELETE"],
    credentials: true
}));
app.use(express.json());
sgMail.setApiKey(TWILIO_SENDGRID_API_KEY);


const appRouter = router();

app.use(loggingHandler);

app.options("*", cors({
    origin: CLIENT_ORIGIN,
    allowedHeaders: ["Content-Type", "Authorization"],
    methods: ["GET", "POST", "OPTIONS", "PUT", "PATCH", "DELETE"],
    credentials: true
}));

app.use("/api", appRouter);


app.use(errorHandler);


app.listen(SERVER_PORT, () => {
    logging.log(`Server running on port ${SERVER_PORT}`);
});

exports.app = functions.https.onRequest(app);

exports.scheduler = firebaseV2Functions.scheduler.onSchedule("every day 00:00", async (event) => {
    try {
        const allUsers = await AuthRepository.getAllUsers();
        const userData: User[] = [];

        allUsers.forEach((user) => {
            const data = user.data();
            userData.push(data);
        });

        for (const userDatum of userData) {
            await GoalService.cleanExpiredGoals(userDatum.id);
            if (userDatum.subscribed) {
                const result = await GoalService.getUserEmailGoals(userDatum);
                if (result.activeOneTimeGoals.length > 0 || result.activeWeeklyGoals.length > 0 || result.activeTodayGoals.length > 0) {
                    const email = await GoalService.createEmailTemplate(userDatum, result.activeTodayGoals, result.activeWeeklyGoals, result.activeOneTimeGoals);
                    await sgMail.send({
                        to: userDatum.email,
                        from: SENDER_EMAIL,
                        subject: "Your Tasks for Today",
                        html: email
                    });
                }
            }
        }
    } catch (error) {
        console.error("Error sending emails:", error);
    }
    return;
});
```

### frontend/src/app/page.tsx

```typescript
"use client"

import Image from "next/image";
import { useAuthContext } from "@/contexts/AuthContext";
import { redirect } from "next/navigation";
import { ROUTES } from "@/constants/Routes";
import { RefreshCcw } from "lucide-react";
import { useEffect } from "react";

export default function Home() {
  const { authenticated, appLoading } = useAuthContext();

  useEffect(() => {
    if (!appLoading) {
      redirect(authenticated ? ROUTES.DASHBOARD.TODAY : ROUTES.LOGIN,);
    }
  }, [authenticated, appLoading]);

  if (appLoading) return <RefreshCcw className="mr-2 h-4 w-4 animate-spin" />

  if (!authenticated) return null;
  return (
    <div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
      <main className="flex flex-col gap-8 row-start-2 items-center sm:items-start">
        <Image
          className="dark:invert"
          src="/next.svg"
          alt="Next.js logo"
          width={180}
          height={38}
          priority
        />
        <ol className="list-inside list-decimal text-sm text-center sm:text-left font-[family-name:var(--font-geist-mono)]">
          <li className="mb-2">
            Get started by editing{" "}
            <code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-semibold">
              src/app/page.tsx
            </code>
            .
          </li>
          <li>Save and see your changes instantly.</li>
        </ol>

        <div className="flex gap-4 items-center flex-col sm:flex-row">
          <a
            className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5"
            href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
            target="_blank"
            rel="noopener noreferrer"
          >
            <Image
              className="dark:invert"
              src="/vercel.svg"
              alt="Vercel logomark"
              width={20}
              height={20}
            />
            Deploy now
          </a>
          <a
            className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:min-w-44"
            href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
            target="_blank"
            rel="noopener noreferrer"
          >
            Read our docs
          </a>
        </div>
      </main>
      <footer className="row-start-3 flex gap-6 flex-wrap items-center justify-center">
        <a
          className="flex items-center gap-2 hover:underline hover:underline-offset-4"
          href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
          target="_blank"
          rel="noopener noreferrer"
        >
          <Image
            aria-hidden
            src="/file.svg"
            alt="File icon"
            width={16}
            height={16}
          />
          Learn
        </a>
        <a
          className="flex items-center gap-2 hover:underline hover:underline-offset-4"
          href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
          target="_blank"
          rel="noopener noreferrer"
        >
          <Image
            aria-hidden
            src="/window.svg"
            alt="Window icon"
            width={16}
            height={16}
          />
          Examples
        </a>
        <a
          className="flex items-center gap-2 hover:underline hover:underline-offset-4"
          href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
          target="_blank"
          rel="noopener noreferrer"
        >
          <Image
            aria-hidden
            src="/globe.svg"
            alt="Globe icon"
            width={16}
            height={16}
          />
          Go to nextjs.org →
        </a>
      </footer>
    </div>
  );
}

```

### functions/backend/src/routers/index.ts

```typescript
import { Router } from "express";
import AuthRouter from "@/routers/AuthRouter";
import HealthCheckRouter from "@/routers/HealthCheckRouter";
import GoalRouter from "@/routers/GoalRouter";
import VisualizationRouter from "@/routers/VisualizationRouter";

const router = Router();

export default () => {
    AuthRouter(router, "/auth");
    HealthCheckRouter(router, "/healthcheck");
    GoalRouter(router, "/goal");
    VisualizationRouter(router, "/visualizations");
    return router;
};
```

### frontend/src/app/(dashboard)/layout.tsx

```typescript
import React, { ReactNode } from "react";
import Sidebar from "@/components/Sidebar";

type DashboardLayoutProps = {
    children: ReactNode;
}

const DashboardLayout = (props: DashboardLayoutProps) => {
    const { children } = props;

    return (
        <div className="flex flex-1 h-[calc(100vh-20rem)]">
            <Sidebar />
            <div className="flex justify-center w-full h-full overflow-y-auto py-10">
                {children}
            </div>
        </div>
    );
};

export default DashboardLayout;

```

### frontend/src/app/(auth)/login/page.tsx

```typescript
"use client";

import React from "react";
import LoginForm from "@/components/LoginForm";

const Login = () => {
    return (
        <div className="flex w-full justify-center items-center flex-1 flex-col gap-4">
            <h1 className="text-2xl">Login</h1>
            <span>Stay accountable, Stay ahead 🚀📚</span>
            <LoginForm />
        </div>
    );
};

export default Login;

```

### frontend/src/app/(auth)/register/page.tsx

```typescript
"use client";

import React from "react";

import RegistrationForm from "@/components/RegistrationForm";

const Register = () => {
    return (
        <div className="flex w-full justify-center items-center flex-1 flex-col gap-4">
            <h1 className="text-2xl">Register</h1>
            <span>Commit. Track. Succeed. ✅📖</span>
            <RegistrationForm />
        </div>
    );
};

export default Register;

```

### frontend/src/app/(auth)/passwordReset/page.tsx

```typescript
"use client";

import { toast } from "sonner";
import { useForm } from "react-hook-form";
import { useRouter } from "next/navigation";
import { Mail, RefreshCcw } from "lucide-react";
import React, { useCallback } from "react";

import { Label } from "@/components/ui/label";
import { ROUTES } from "@/constants/Routes";
import { Button } from "@/components/ui/button";
import { PasswordResetForm } from "@/models/forms/PasswordResetForm";
import { cn, toastDateFormat } from "@/lib/utils";
import { usePasswordResetMutation } from "@/hooks/mutations/usePasswordResetMutation";
import InputWithIcon from "@/components/ui/input-with-Icon";

const PasswordReset = () => {
    const {
        register,
        formState: { errors },
        handleSubmit,
        setError
    } = useForm<PasswordResetForm>({
        defaultValues: { email: "" }
    });
    const router = useRouter();

    const onPasswordResetSuccess = useCallback(() => {
        toast.success(`A password reset link has been sent to your email`, {
            richColors: true,
            description: toastDateFormat(new Date()),
            action: {
                label: "Close",
                onClick: () => null
            }
        });
        router.push(ROUTES.LOGIN);
    }, [router]);

    const { mutate, isPending } = usePasswordResetMutation({ onPasswordResetSuccess, setError });

    const onSubmit = useCallback(async (formData: PasswordResetForm) => {
        mutate(formData);
    }, [mutate]);

    return (
        <div className="flex w-full justify-center items-center flex-1 flex-col gap-4">
            <h1 className="text-2xl">Reset Password</h1>
            <form className="w-full p-4 md:w-1/3 lg:w-[450px] flex flex-col gap-y-4" onSubmit={handleSubmit(onSubmit)}>
                <div>
                    <Label htmlFor="email" className={cn({ "text-destructive": errors.email })}>Email</Label>
                    <InputWithIcon
                        className={cn("border mt-1", {
                            "border-border": !errors.email,
                            "border-destructive": errors.email
                        })}
                        id="email"
                        type="email"
                        Icon={<Mail size={16} />}
                        {...register("email", { required: "Email is required." })} />
                    {errors.email && (
                        <span className="text-xs text-destructive">{errors.email.message}</span>
                    )}
                </div>
                <Button variant="default" type="submit" className="w-full md:w-1/3 mx-auto" disabled={isPending}>
                    {isPending && <RefreshCcw className="mr-2 h-4 w-4 animate-spin" />}
                    Reset Password
                </Button>
            </form>
        </div>
    );
};

export default PasswordReset;

```

[146 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]