{"id":29417827,"url":"https://github.com/robson16/the-scoop","last_synced_at":"2026-04-14T15:31:44.651Z","repository":{"id":303852606,"uuid":"1016374866","full_name":"Robson16/the-scoop","owner":"Robson16","description":"A backend-focused web application for article submission and comments, developed as part of Codecademy's 'Create a Back-End App with JavaScript' skill path. Features custom user handles, article management, upvoting/downvoting, and comment functionality.","archived":false,"fork":false,"pushed_at":"2025-07-09T19:19:31.000Z","size":513,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-10T03:37:46.244Z","etag":null,"topics":["api-rest","backend","codecademy","codecademy-solutions","express","javascript","mocha","nodejs","test-automation"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Robson16.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-08T23:25:55.000Z","updated_at":"2025-07-09T19:19:34.000Z","dependencies_parsed_at":"2025-07-10T03:50:34.338Z","dependency_job_id":"acc5955d-546e-4e23-a53e-da3eca9c48b2","html_url":"https://github.com/Robson16/the-scoop","commit_stats":null,"previous_names":["robson16/the-scoop"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Robson16/the-scoop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Robson16%2Fthe-scoop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Robson16%2Fthe-scoop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Robson16%2Fthe-scoop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Robson16%2Fthe-scoop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Robson16","download_url":"https://codeload.github.com/Robson16/the-scoop/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Robson16%2Fthe-scoop/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264905409,"owners_count":23681405,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-rest","backend","codecademy","codecademy-solutions","express","javascript","mocha","nodejs","test-automation"],"created_at":"2025-07-11T22:12:35.486Z","updated_at":"2026-04-14T15:31:44.599Z","avatar_url":"https://github.com/Robson16.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# The Scoop\n\n![The Scoop](./.github/screenshot.jpg)\n\n---\n\n## Project Overview\n\n**The Scoop** is a dynamic web application designed for article submission and community interaction. As part of Codecademy's **\"Create a Back-End App with JavaScript Skill Path,\"** this project challenged me to build robust routing and in-memory database logic to power a news feed experience, **with the added functionality of data persistence**.\n\nThe application, in its full implementation, enables users to:\n\n* **Submit articles**, each containing a link and description.\n* **Engage with content by upvoting and downvoting articles.**\n* **Contribute to discussions by creating, editing, and deleting comments** on articles.\n* **Express opinions on comments by upvoting and downvoting them.**\n* **View a comprehensive feed of all articles**, as well as individual user profiles displaying their submitted articles and comments.\n\nWhile the user and article management logic was provided as a foundation, my primary focus and contribution to this project involved **implementing the complete backend logic and database interactions for all comment-related functionalities, as well as integrating data persistence**.\n\nYou can see a video demonstration of the full application's capabilities (which this backend supports) here:\n\n [The Scoop Demo Video](./.github/TheScoopDemo.mp4)\n\n\u003cvideo width=\"100%\" height=\"100%\" controls\u003e\n   \u003csource src=\"./.github/TheScoopDemo.mp4\" type=\"video/mp4\"\u003e\n   Your browser does not support the video tag. Please click [here to watch the demo video](./.github/TheScoopDemo.mp4).\n\u003c/video\u003e\n\n---\n\n## Architecture \u0026 Data Management\n\nThe application's backend is built around a central `database` object (an in-memory JavaScript object) that stores all model instances, including `users`, `articles`, and **importantly, `comments`**. Each resource is stored with its ID as a key. A `nextId` property for each resource type ensures unique ID generation.\n\nAll API endpoints are defined within a `routes` object, where paths are keys and values are objects mapping HTTP verbs (GET, POST, PUT, DELETE) to their corresponding handler functions.\n\nMy work primarily extended this existing structure by integrating the `comment` data model and all related API routes. Additionally, I implemented a **data persistence layer** to ensure the database state is saved and loaded across server restarts.\n\n### Comment Data Model (`database.comments`)\n\nMy implementation added and managed comments with the following properties:\n* `id`: Unique Number for each comment.\n* `body`: String content of the comment.\n* `username`: String, the author's username.\n* `articleId`: Number, the ID of the article the comment belongs to.\n* `upvotedBy`: Array of usernames who upvoted the comment.\n* `downvotedBy`: Array of usernames who downvoted the comment.\n* `nextCommentId`: Number, for unique ID generation.\n\n---\n\n## My Contributions: Comment API Endpoints \u0026 Data Persistence\n\nI developed the full suite of RESTful API endpoints for comments, ensuring robust data handling and proper HTTP responses, alongside the data persistence solution:\n\n* **`POST /comments`**:\n    * **Function:** `createComment`\n    * **Purpose:** Creates a new comment, associates it with a user and an article, and stores it in the database. Returns the new comment with a `201 Created` status. Includes validation for missing data or non-existent users/articles (`400 Bad Request`).\n\n* **`PUT /comments/:id`**:\n    * **Function:** `updateComment`\n    * **Purpose:** Updates the `body` of an existing comment identified by its ID. Returns the updated comment with a `200 OK` status. Handles cases where the comment ID or updated data is invalid (`400 Bad Request`) or the comment is not found (`404 Not Found`).\n\n* **`DELETE /comments/:id`**:\n    * **Function:** `deleteComment`\n    * **Purpose:** Removes a comment from the database by its ID. Crucially, it also removes all references to this comment ID from its associated user's `commentIds` and article's `commentIds` arrays, maintaining data integrity. Returns a `204 No Content` status upon successful deletion. Handles non-existent comments (`404 Not Found`).\n\n* **`PUT /comments/:id/upvote`**:\n    * **Function:** `upvoteComment`\n    * **Purpose:** Allows a specified user to upvote a comment. It adds the user's `username` to the comment's `upvotedBy` array and removes it from `downvotedBy` if present. Returns the updated comment with a `200 OK` status. Handles invalid comment IDs or usernames (`400 Bad Request`).\n\n* **`PUT /comments/:id/downvote`**:\n    * **Function:** `downvoteComment`\n    * **Purpose:** Allows a specified user to downvote a comment. It adds the user's `username` to the comment's `downvotedBy` array and removes it from `upvotedBy` if present. Returns the updated comment with a `200 OK` status. Handles invalid comment IDs or usernames (`400 Bad Request`).\n\n### Data Persistence (Bonus Implemented!)\n\nI implemented the bonus challenge for data persistence, ensuring the `database` state is saved and loaded, allowing data to survive server restarts.\n\n* **`loadDatabase`**: Reads the entire database state from a **YAML file** upon server startup.\n* **`saveDatabase`**: Writes the current state of the `database` object to a **YAML file** after each server operation that modifies data.\n\nThis functionality was achieved using the **`Figg`** library, providing a robust solution for preserving application data.\n\n---\n\n## How to Set Up and Run\n\nTo explore this project locally and interact with the backend API:\n\n1.  **Clone the Repository:** Start by cloning this repository to your local machine:\n    ```bash\n    git clone https://github.com/Robson16/the-scoop.git\n    ```\n2.  **Navigate to the Project Directory:** Change into the newly cloned project folder:\n    ```bash\n    cd the-scoop\n    ```\n3.  **Install Dependencies:** Once inside the project directory, install all necessary Node.js dependencies:\n    ```bash\n    npm install\n    ```\n4.  **Start the Server:** After dependencies are installed, start the backend server:\n    ```bash\n    npm run start\n    # Or:\n    npm run dev\n    ```\n    You should see confirmation in your terminal that the server is listening, likely on port `4001`. Keep this terminal window open as the server must remain active for the frontend to communicate with your backend.\n    **Note:** With data persistence implemented, your data will be saved to and loaded from a YAML file, so changes will persist even if you restart the server!\n5.  **Open the Application:** Open the `index.html` file in your web browser (Google Chrome is recommended for best compatibility). This HTML file provides the frontend interface that interacts with your running backend API.\n\n---\n\n## Testing\n\nA comprehensive testing suite is provided with the project to validate all implemented functionalities and ensure proper handling of edge cases.\n\nTo run the tests:\n\n1.  Ensure you've followed the \"How to Set Up and Run\" steps, particularly installing dependencies.\n2.  In your terminal, from the project's root directory, execute:\n    ```bash\n    npm run test\n    # Or to run tests on file changes:\n    npm run test:watch\n    ```\n    The output will detail which tests passed or failed, providing specific feedback for debugging. Running these tests iteratively during development was crucial for confirming correct implementation and identifying issues.\n\n---\n\n## Technologies Used\n\n* **JavaScript (Node.js)**: For the backend server and API logic.\n* **Express.js**.\n* **In-Memory Database**: A simple JavaScript object used as a temporary database.\n* **Data Persistence**:\n    * **YAML**: As the format for saving and loading database state.\n    * **Figg**: The Node.js library used for YAML serialization/deserialization.\n* **ReactJs (Frontend)**: For the client-side interface provided by Codecademy.\n* **Automated Testing**:\n    * [Mocha](https://mochajs.org/): A flexible JavaScript test framework.\n    * [Chai](https://www.chaijs.com/): An assertion library for Node.js and the browser, often paired with Mocha.\n\n---\n\n## License\n\nThis project is licensed under the MIT License.\nDeveloped by Robson16.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobson16%2Fthe-scoop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobson16%2Fthe-scoop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobson16%2Fthe-scoop/lists"}