> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hoagie.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Hoagie Help

> How Hoagie Help works, explained from the ground up

Hoagie Help is a peer-help platform for Princeton students. This page explains how
the whole system fits together — the parts, how they talk to each other, and where
the code for each piece lives.

## Features

<AccordionGroup>
  <Accordion title="Q&A">
    Ask academic questions and get help from classmates.

    | Sub-feature             | Description                                                   | Status         |
    | ----------------------- | ------------------------------------------------------------- | -------------- |
    | Browse & view questions | Question feed, question detail page with answers and comments | 🚧 In progress |
    | Ask a question          | Post a question with a course, category, and details          | 🚧 In progress |
    | Answers & comments      | Answer a question; comment on answers                         | 🚧 In progress |
    | Hearts                  | Like questions, answers, and comments                         | 🚧 In progress |
    | Anonymous posting       | Post under a stable pseudonym per thread                      | 🗓️ Planned    |
  </Accordion>

  <Accordion title="Study Groups">
    Form study groups with classmates in your courses.

    | Sub-feature          | Description                                       | Status         |
    | -------------------- | ------------------------------------------------- | -------------- |
    | Create a study group | Create a group with a meeting time and spot limit | 🚧 In progress |
    | Browse & join        | Search groups and claim a spot                    | 🗓️ Planned    |
  </Accordion>

  <Accordion title="Notifications">
    Stay up to date on activity on your posts.

    | Sub-feature            | Description                                                | Status         |
    | ---------------------- | ---------------------------------------------------------- | -------------- |
    | Activity notifications | Get notified when someone answers or comments on your post | 🚧 In progress |
  </Accordion>

  <Accordion title="User Profiles">
    See what a user has posted across the app.

    | Sub-feature  | Description                                    | Status      |
    | ------------ | ---------------------------------------------- | ----------- |
    | Post history | View a user's questions, answers, and comments | 🗓️ Planned |
  </Accordion>
</AccordionGroup>

## What We Build With

| Tool                            | What it is, in one line                                                                                                                                                 |
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **TypeScript**                  | JavaScript (the language browsers run) plus type checking, which catches many mistakes before the code even runs.                                                       |
| **React**                       | A library for building user interfaces out of reusable **components** — a button, a comment box, a whole page.                                                          |
| **Next.js**                     | A framework built on React that handles routing (each folder in `app/` becomes a URL) and running code on the server.                                                   |
| **Evergreen UI + Tailwind CSS** | Libraries of pre-styled components and CSS shortcuts, so we don't style everything from scratch.                                                                        |
| **Zod**                         | Checks at runtime that data from the backend has the shape we expect.                                                                                                   |
| **Python / Django**             | Python is the language; Django is a popular framework for building backends with it.                                                                                    |
| **Django REST Framework (DRF)** | A Django add-on for building APIs — endpoints the frontend calls to read and write data, exchanged as **JSON** (a simple text format like `{ "id": 42, "hearts": 7 }`). |
| **PostgreSQL**                  | A relational database — data lives in tables with rows and columns, like a spreadsheet with rules.                                                                      |
| **Auth0**                       | A third-party login service. It handles passwords and Princeton logins so we never have to store passwords ourselves.                                                   |
| **Yarn / uv**                   | Package managers: they download and track the libraries the frontend (Yarn) and backend (uv) depend on.                                                                 |

## System Overview

Here's how the parts connect. One special detail: the browser never talks to Django
directly. Every API call goes through a small **proxy** — a middleman route inside
Next.js — that attaches the user's login credentials and forwards the request to Django.

```mermaid theme={null}
flowchart LR
    Browser["Browser<br/>(Next.js frontend)"]
    Proxy["Next.js proxy route<br/>/api/hoagie/*"]
    Django["Django backend<br/>(the API)"]
    DB[("PostgreSQL<br/>database")]
    Auth0["Auth0<br/>(login service)"]

    Browser --> Proxy --> Django --> DB
    Browser -. "login" .-> Auth0
    Django -. "verify identity" .-> Auth0
```

Why the proxy? When you log in, Auth0 gives the app an **access token** — a
tamper-proof string that proves who you are. If the browser held that token,
malicious code on the page could steal it. Instead, the token stays on the server,
and the proxy attaches it to each request on the browser's behalf.

## Repo Layout

The repo is one folder with the two programs side by side:

```text theme={null}
help/
├── frontend/                  # The Next.js app (TypeScript)
│   ├── app/                   # Pages — each folder becomes a URL route
│   │   └── api/hoagie/[...path]/route.ts   # The proxy to Django
│   ├── api/                   # "Service" files — one per resource, all fetch calls live here
│   ├── components/            # Reusable UI pieces (question/, answer/, comment/, ...)
│   ├── lib/hoagie-ui/         # Hoagie's shared design system (Nav, Layout, Theme)
│   ├── proxy.ts               # Sends logged-out users to the login page
│   └── types.ts               # Shared TypeScript types
└── backend/                   # The Django app (Python)
    ├── config/                # settings.py and urls.py (the list of all API routes)
    └── hoagiehelp/
        ├── models/            # One file per database table
        ├── api/               # The code that handles each API request
        └── auth/auth.py       # Checks the Auth0 token on every request
```

## Following One Request Through the System

The best way to understand the architecture is to trace a single action end to end.
Here's what happens when a user hearts (likes) a question:

```mermaid theme={null}
sequenceDiagram
    participant B as Browser
    participant S as Service<br/>(heartService.ts)
    participant P as Proxy route<br/>(/api/hoagie/*)
    participant A as Auth check<br/>(auth.py)
    participant V as View<br/>(heart_views.py)
    participant D as Database

    B->>S: User clicks the heart button
    S->>P: fetch /api/hoagie/questions/42/heart
    P->>A: Forward request + access token
    A->>A: Verify token, look up (or create) the user
    A->>V: Request is authenticated
    V->>D: Add or remove the Heart row
    D-->>B: { "hearts": 8, "is_hearted": true }
```

Step by step, with the actual files:

1. **Component** (`components/question/QuestionPanel.tsx`) — the heart button's
   click handler calls `heartQuestion(id)`. Components never call the API directly;
   they always go through a service.
2. **Service** (`frontend/api/heartService.ts`) — builds the HTTP request, sends it
   to the proxy, and uses Zod to check the response has the right shape. Every
   resource (questions, answers, comments...) has its own service file, all
   following this same pattern.
3. **Proxy route** (`app/api/hoagie/[...path]/route.ts`) — grabs the access token
   from the user's session and forwards the request to Django.
4. **Auth check** (`backend/hoagiehelp/auth/auth.py`) — Django verifies the token
   is genuine by checking it against Auth0's public keys. It reads the user's
   Princeton NetID from the token and creates their account automatically on
   their first-ever request. Every endpoint requires a logged-in user.
5. **View** (`backend/hoagiehelp/api/heart_views.py`) — the function that does the
   actual work: toggle the heart in the database and send back the new count as JSON.

<Note>
  Two different files have "proxy" in their name — don't mix them up.
  `frontend/proxy.ts` runs when you *navigate between pages* and redirects you to
  the login screen if you're logged out. `app/api/hoagie/[...path]/route.ts` is the
  API proxy that forwards *data requests* to Django.
</Note>

## The Database

In Django, each table is described by a **model** — a Python class where each
attribute becomes a column. Tables point at each other through **foreign keys**
(e.g., every Answer stores the id of the Question it belongs to). Here's our whole
schema and how the tables relate:

```mermaid theme={null}
erDiagram
    CustomUser ||--o{ Question : asks
    Question ||--o{ Answer : has
    Answer ||--o{ Comment : has
    CustomUser ||--o{ Answer : writes
    CustomUser ||--o{ Comment : writes
    CustomUser ||--o{ Heart : gives
    Heart }o--o| Question : "targets one of"
    Heart }o--o| Answer : "targets one of"
    Heart }o--o| Comment : "targets one of"
    CustomUser ||--o{ Notification : receives
    Question }o--o{ Tag : tagged
    CustomUser ||--o{ StudyGroup : leads
    CustomUser }o--o{ StudyGroup : joins
    CustomUser ||--o{ AnonymousName : has
    Question ||--o{ AnonymousName : scopes
```

The core chain to remember: **a user asks a question → answers attach to the
question → comments attach to answers.** Everything else hangs off that chain.

| Model           | What it stores                                                                                                                   |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `CustomUser`    | One row per student: `net_id`, `class_year`, name, email. Created automatically the first time someone logs in and uses the app. |
| `Question`      | A Q\&A post: `title`, `details`, `course`, heart count, view count, and whether the asker is anonymous.                          |
| `Answer`        | An answer to a question: `text`, heart count, anonymity flag.                                                                    |
| `Comment`       | A comment **on an answer** (comments don't attach to questions directly).                                                        |
| `Heart`         | One like, by one user, on exactly one question *or* answer *or* comment. A database rule prevents liking the same thing twice.   |
| `Notification`  | "Someone answered/commented on your post," plus whether it's been read.                                                          |
| `StudyGroup`    | `title`, `description`, `meeting_datetime`, `max_spots`, one leader, and a list of members.                                      |
| `Tag`           | A question category from a fixed list (`exam prep`, `problem set`, ...).                                                         |
| `AnonymousName` | A stable fake name per (user, question), so an anonymous asker keeps the same pseudonym throughout a thread.                     |

<Note>
  Heart counts are stored in two places: as a number on each post (fast to display)
  *and* as individual `Heart` rows (so we know *who* liked what). The backend
  updates both together so they never disagree.
</Note>

## API Reference

These are all the requests the backend understands, defined in
`backend/config/urls.py` and grouped by resource below. The method is the *kind*
of action: **GET** reads data, **POST** creates (or performs an action), **PUT**
updates, **DELETE** removes. Every request requires a logged-in user.

<AccordionGroup>
  <Accordion title="Questions">
    | Method | Endpoint           | Description                                            |
    | ------ | ------------------ | ------------------------------------------------------ |
    | GET    | `/questions/`      | List all questions (`?title=` search, `?tags=` filter) |
    | POST   | `/questions/`      | Create a question                                      |
    | GET    | `/questions/{id}/` | Read one question                                      |
    | PUT    | `/questions/{id}/` | Update a question                                      |
    | DELETE | `/questions/{id}/` | Delete a question                                      |
  </Accordion>

  <Accordion title="Answers">
    | Method | Endpoint                   | Description                     |
    | ------ | -------------------------- | ------------------------------- |
    | GET    | `/questions/{id}/answers/` | List all answers for a question |
    | POST   | `/questions/{id}/answers/` | Create an answer for a question |
    | GET    | `/answers/{id}/`           | Read one answer                 |
    | PUT    | `/answers/{id}/`           | Update an answer                |
    | DELETE | `/answers/{id}/`           | Delete an answer                |
  </Accordion>

  <Accordion title="Comments">
    | Method | Endpoint                  | Description                    |
    | ------ | ------------------------- | ------------------------------ |
    | GET    | `/answers/{id}/comments/` | List all comments on an answer |
    | POST   | `/answers/{id}/comments/` | Create a comment on an answer  |
    | GET    | `/comments/{id}/`         | Read one comment               |
    | PUT    | `/comments/{id}/`         | Update a comment               |
    | DELETE | `/comments/{id}/`         | Delete a comment               |
  </Accordion>

  <Accordion title="Hearts">
    Each endpoint toggles a heart on/off and returns `{hearts, is_hearted}`.

    | Method | Endpoint                | Description                |
    | ------ | ----------------------- | -------------------------- |
    | POST   | `/questions/{id}/heart` | Heart / unheart a question |
    | POST   | `/answers/{id}/heart`   | Heart / unheart an answer  |
    | POST   | `/comments/{id}/heart`  | Heart / unheart a comment  |
  </Accordion>

  <Accordion title="Study Groups">
    | Method | Endpoint              | Description           |
    | ------ | --------------------- | --------------------- |
    | GET    | `/study-groups/`      | List all study groups |
    | POST   | `/study-groups/`      | Create a study group  |
    | GET    | `/study-groups/{id}/` | Read one study group  |
    | PUT    | `/study-groups/{id}/` | Update a study group  |
    | DELETE | `/study-groups/{id}/` | Delete a study group  |
  </Accordion>

  <Accordion title="Users">
    Anonymous posts are hidden when viewing someone else's profile.

    | Method | Endpoint                 | Description                         |
    | ------ | ------------------------ | ----------------------------------- |
    | GET    | `/users/{id}/`           | Get the logged-in user's profile    |
    | POST   | `/users/{id}/`           | Update the logged-in user's profile |
    | GET    | `/users/{id}/questions/` | A user's questions                  |
    | GET    | `/users/{id}/answers/`   | A user's answers                    |
    | GET    | `/users/{id}/comments/`  | A user's comments                   |
  </Accordion>

  <Accordion title="Notifications">
    | Method | Endpoint               | Description                                |
    | ------ | ---------------------- | ------------------------------------------ |
    | GET    | `/notifications/`      | All notifications for the logged-in user   |
    | GET    | `/notifications/{id}/` | Read one notification                      |
    | POST   | `/notifications/{id}/` | Update a notification (e.g., mark as read) |
    | DELETE | `/notifications/{id}/` | Delete a notification                      |
  </Accordion>
</AccordionGroup>

On the frontend, each resource has a matching service file in `frontend/api/`
(`questionService.ts`, `heartService.ts`, ...) that wraps these endpoints in
easy-to-call functions.

## Where to Go Next

1. Follow the [Hoagie Help setup guide](/quickstart/help) to get the app running on your laptop.
2. Read the [development workflow](/quickstart/development) to learn how we use Linear tickets, branches, and PRs.
3. Open the code and trace the heart-a-question flow from this page yourself:
   `QuestionPanel.tsx` → `heartService.ts` → the proxy route → `heart_views.py`.
   Once that path makes sense, you understand the app.

Helpful docs for the tools themselves: [React](https://react.dev/learn) ·
[Next.js](https://nextjs.org/docs/app) · [Django](https://docs.djangoproject.com/en/stable/intro/tutorial01/) ·
[Django REST Framework](https://www.django-rest-framework.org/) ·
[Evergreen UI](https://evergreen.segment.com/)
