Features
Q&A
Q&A
Ask academic questions and get help from classmates.
Study Groups
Study Groups
Form study groups with classmates in your courses.
Notifications
Notifications
Stay up to date on activity on your posts.
User Profiles
User Profiles
See what a user has posted across the app.
What We Build With
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. 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: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: Step by step, with the actual files:- Component (
components/question/QuestionPanel.tsx) — the heart button’s click handler callsheartQuestion(id). Components never call the API directly; they always go through a service. - 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. - Proxy route (
app/api/hoagie/[...path]/route.ts) — grabs the access token from the user’s session and forwards the request to Django. - 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. - 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.
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.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: 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.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.API Reference
These are all the requests the backend understands, defined inbackend/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.
Questions
Questions
Answers
Answers
Comments
Comments
Hearts
Hearts
Each endpoint toggles a heart on/off and returns
{hearts, is_hearted}.Study Groups
Study Groups
Users
Users
Anonymous posts are hidden when viewing someone else’s profile.
Notifications
Notifications
frontend/api/
(questionService.ts, heartService.ts, …) that wraps these endpoints in
easy-to-call functions.
Where to Go Next
- Follow the Hoagie Help setup guide to get the app running on your laptop.
- Read the development workflow to learn how we use Linear tickets, branches, and PRs.
- 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.
/answers/{id}/comments//answers/{id}/comments//comments/{id}//comments/{id}//comments/{id}/