The team project for this class is designed to mirror the experiences of a software engineer: by virtue of your individual projects, you have been onboarded to our codebase, made several individual contributions, and have formed a team to propose, develop and implement new features. The codebase that we'll be developing on is a Fake Stack Overflow project (let's call it HuskyFlow). You will get an opportunity to work with the starter code which provides basic skeleton for the app and then additional features will be proposed and implemented by you! All implementation will take place in the TypeScript programming language, using React for the user interface.
To build a working version of 404NotFound, the following packages must be installed on your local machine:
- Node.js: v18.x or v20.x
- npm: v9.x or higher
- MongoDB: v6.0 or higher
- TypeScript: v5.7.x
- Vite: v6.2.x
- Git: v2.x or higher
git clone https://github.com/neu-cs4530/fall25-project-group-701.git
cd fall25-project-group-701Run the following command in the root directory to install all dependencies for the client, server, and shared folders:
npm installCreate .env files in the /client, /server, and /testing directories with the following variables:
REACT_APP_SERVER_URL=http://localhost:8000
MONGODB_URI=mongodb://127.0.0.1:27017
CLIENT_URL=http://localhost:4530
PORT=8000
GEMINI_API_KEY=ReferToReport
CLOUDINARY_CLOUD_NAME=ReferToReport
CLOUDINARY_API_KEY=ReferToReport
CLOUDINARY_API_SECRET=ReferToReport
MONGODB_URI=mongodb://127.0.0.1:27017
Note
The API keys shown above are placeholders. Refer to the project report for actual values.
Run the following commands to populate the database with initial data:
cd server
npm run populate-dbYou will need two terminal windows to run both the server and client.
Run the following commands to launch the server at http://localhost:8000:
cd server
npm run devRun the following commands to launch the client at http://localhost:4530:
cd client
npm run devFrom there you should be able to interact with the connected frontend and backend interfaces of 404NotFound locally. To verify the population of the database, you can create a new account and use the user credentials to log in.
Note
Refer to IP1 and IP2 for further instructions related to setting up MongoDB, setting environment variables, and running the client and server.
client: Contains the frontend application code, responsible for the user interface and interacting with the backend. This directory includes all React components and related assets.server: Contains the backend application code, handling the logic, APIs, and database interactions. It serves requests from the client and processes data accordingly.shared: Contains all shared type definitions that are used by both the client and server. This helps maintain consistency and reduces duplication of code between the two folders. The type definitions are imported and shared within each folder'stypes/types.tsfile.
The schemas for the database are documented in the directory server/models/schema.
A class diagram for the schema definition is shown below:
| Endpoint | Method | Description |
|---|---|---|
/getQuestion |
GET | Fetch questions by filter (order, search, askedBy) |
/getQuestionById/:qid |
GET | Fetch a specific question by ID |
/addQuestion |
POST | Add a new question |
/upvoteQuestion |
POST | Upvote a question |
/downvoteQuestion |
POST | Downvote a question |
/getCommunityQuestions/:communityId |
GET | Retrieve all questions in a community |
/updateQuestion/:qid |
PUT | Update an existing question |
| Endpoint | Method | Description |
|---|---|---|
/addAnswer |
POST | Add a new answer to a question |
/updateAnswer/:aid |
PUT | Update an existing answer |
/:aid |
GET | Retrieve an answer by ID with parent question ID |
| Endpoint | Method | Description |
|---|---|---|
/getTagsWithQuestionNumber |
GET | Fetch tags along with the number of questions |
/getTagByName/:name |
GET | Fetch a specific tag by name |
| Endpoint | Method | Description |
|---|---|---|
/addComment |
POST | Add a new comment to a question or answer |
/:cid |
GET | Retrieve a comment by ID with parent information |
| Endpoint | Method | Description |
|---|---|---|
/addMessage |
POST | Add a new global message |
/getMessages |
GET | Fetch all global messages |
| Endpoint | Method | Description |
|---|---|---|
/createChat |
POST | Create a new chat conversation |
/:chatId/addMessage |
POST | Add a new message to an existing chat |
/:chatId |
GET | Retrieve a chat by its ID |
/:chatId/addParticipant |
POST | Add a new participant to an existing chat |
/getChatsByUser/:username |
GET | Retrieve all chats for a specific user |
/:chatId/removeParticipant/:username |
DELETE | Remove a participant from a chat |
/:chatId/removeMessage/:messageId |
DELETE | Remove a message from a chat |
/:chatId/pinMessage/:messageId |
POST | Pin a chat message |
/:chatId/unpinMessage/:messageId |
DELETE | Unpin a chat message |
| Endpoint | Method | Description |
|---|---|---|
/create |
POST | Create a new game instance |
/join |
POST | Join an existing game |
/leave |
POST | Leave an existing game |
/games |
GET | Retrieve all games (filterable by type and status) |
| Endpoint | Method | Description |
|---|---|---|
/create |
POST | Create a new collection |
/delete/:collectionId |
DELETE | Delete a collection |
/toggleSaveQuestion |
PATCH | Add or remove a question from a collection |
/getCollectionsByUsername/:username |
GET | Get collections by username (filtered by privacy) |
/getCollectionById/:collectionId |
GET | Get collection by ID (subject to privacy checks) |
| Endpoint | Method | Description |
|---|---|---|
/getCommunity/:communityId |
GET | Get a specific community |
/getAllCommunities |
GET | Get all communities |
/toggleMembership |
POST | Join or leave a community |
/create |
POST | Create a new community |
/delete/:communityId |
DELETE | Delete a community (requires admin privileges) |
| Endpoint | Method | Description |
|---|---|---|
/signup |
POST | Create a new user account |
/login |
POST | Log in as a user |
/resetPassword |
PATCH | Reset user password |
/getUser/:username |
GET | Fetch user details by username |
/getUsers |
GET | Fetch all users |
/deleteUser/:username |
DELETE | Delete a user by username |
/updateBiography |
PATCH | Update user biography |
/toggleAchievementVisibility |
PATCH | Toggle achievement visibility for a user |
| Endpoint | Method | Description |
|---|---|---|
/all |
GET | Get all achievements (optionally with unlock status for a user) |
/user/:username |
GET | Get unlocked achievements for a user |
/:achievementId |
GET | Get achievement by ID |
/achievement |
POST | Check and award achievements based on trigger |
/streak/:username |
GET | Retrieve achievement streak data for a user |
| Endpoint | Method | Description |
|---|---|---|
/:communityId/users/:userId/role |
GET | Get a user's role in a community |
/:communityId/moderators |
GET | Get moderators of a community |
/:communityId/moderators |
POST | Assign a user as moderator |
/:communityId/moderators/:userId |
DELETE | Remove a moderator |
/:communityId/questions/:questionId |
DELETE | Delete a question (soft delete) |
/:communityId/answers/:answerId |
DELETE | Delete an answer (soft delete) |
/:communityId/comments/:commentId |
DELETE | Delete a comment (soft delete) |
/:communityId/questions/:questionId/pin |
POST | Pin a question |
/:communityId/questions/:questionId/pin |
DELETE | Unpin a question |
/:communityId/answers/:answerId/pin |
POST | Pin an answer |
/:communityId/answers/:answerId/pin |
DELETE | Unpin an answer |
/:communityId/users/:userId |
DELETE | Remove user from community |
/:communityId/actions |
GET | Get moderation actions for a community |
/:communityId/actions/:moderatorId |
GET | Get actions by moderator |
/actions/:actionId |
GET | Get a specific moderation action |
/actions/:targetType/:targetId |
GET | Get moderator action for specific content |
/:communityId/users/:username/actions |
GET | Get moderation actions against a user's content |
| Endpoint | Method | Description |
|---|---|---|
/appeals |
POST | Create an appeal against a moderator action |
/user/:userId |
GET | Get appeals by a user |
/pending |
GET | Get all pending appeals |
/action/:moderatorActionId |
GET | Get appeals for an action |
/:appealId/review |
PATCH | Review an appeal (approve/deny) |
/hasAppeal/:targetId |
GET | Check if a target has an associated appeal |
| Endpoint | Method | Description |
|---|---|---|
/flags |
POST | Create a flag to report content |
/flags/:communityId/user/:username |
GET | Get flags submitted by a user in a community |
/flags/:communityId |
GET | Get all flags for a community (optional status filter) |
/flags/:flagId/resolve |
PATCH | Resolve or dismiss a flag |
| Endpoint | Method | Description |
|---|---|---|
/:username |
GET | Get user's AI recommendations consent status |
/grant/:username |
POST | Grant AI recommendation consent |
/revoke/:username |
POST | Revoke consent and clear cached data |
/renew/:username |
PATCH | Renew user consent |
| Endpoint | Method | Description |
|---|---|---|
/:username |
GET | Get AI-generated learning resource recommendations |
/generate/:username |
POST | Force regenerate recommendations (bypass cache) |
/:username/rate |
PATCH | Rate a recommendation set |
/:username/stats |
GET | Get user's recommendation rating statistics |
/cache/:username |
DELETE | Clear user's cached recommendations |
| Endpoint | Method | Description |
|---|---|---|
/upload |
POST | Upload a media file to Cloudinary |
/delete |
DELETE | Delete a media file from Cloudinary |
OpenAPI specifications as given in the server/openapi.yaml file should give you an idea about the overall structure of the API endpoints, the request format and the various path/query parameters required as well as the expected response formats. To see a detailed explanation of the schemas and to test the endpoint in a sandboxed environment, you can use the Swagger UI page as follows:
- Start the server as specified earlier (
cd server && npm run dev). - Visit
http://localhost:8000/api/docsto see the complete API specification in a user friendly manner. - You should be able to see and test out individual endpoints using the Try it out button associated with each endpoint.
The specification itself is coupled with an OpenAPI validator (present as a middleware) that validates every request and response against the provided spec document.
Cypress tests are end-to-end tests that can help verify your implementation.
-
Navigate to the
testingdirectory:cd testing -
Install dependencies:
npm install
-
The
.envfile should already be configured from the earlier setup step. If not, create it with:MONGODB_URI=mongodb://127.0.0.1:27017 -
Make sure that both the server and client are already running
-
Run Cypress tests:
npx cypress open
-
In the Cypress UI that opens:
- Select E2E Testing
- Choose your browser (Chrome is preferred)
- Click on any of the test files to run it
- If any of the tests fail, you should be able to see the exact sequence of steps that led to the failure.
Note
Running Cypress tests is optional. Cypress tests require significant system resources, and without them, the tests may be flaky. We will use these tests for grading.
