{"id":18016513,"url":"https://github.com/nikhil25803/blogging-platform","last_synced_at":"2026-01-03T09:01:32.042Z","repository":{"id":228105059,"uuid":"748031680","full_name":"nikhil25803/blogging-platform","owner":"nikhil25803","description":"The Blogging Platform API utilizes a microservices architecture with NodeJS, Express.js, Postgres, and Redis, facilitating CRUD operations, authentication, keyword search, and recommendation features. It emphasizes performance optimization, security measures, and scalability via Docker orchestration and thorough unit testing.","archived":false,"fork":false,"pushed_at":"2024-03-17T06:29:56.000Z","size":173,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-23T06:09:08.938Z","etag":null,"topics":["docker","docker-compose","expressjs","javascript","makefile","nodejs","postgresql","prisma","redis"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nikhil25803.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}},"created_at":"2024-01-25T05:59:00.000Z","updated_at":"2024-04-07T09:17:26.000Z","dependencies_parsed_at":null,"dependency_job_id":"b180e66f-17f3-4db6-8f23-60d13826e7b0","html_url":"https://github.com/nikhil25803/blogging-platform","commit_stats":null,"previous_names":["nikhil25803/blogging-platform"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikhil25803%2Fblogging-platform","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikhil25803%2Fblogging-platform/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikhil25803%2Fblogging-platform/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikhil25803%2Fblogging-platform/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nikhil25803","download_url":"https://codeload.github.com/nikhil25803/blogging-platform/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243918641,"owners_count":20368745,"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":["docker","docker-compose","expressjs","javascript","makefile","nodejs","postgresql","prisma","redis"],"created_at":"2024-10-30T04:18:20.139Z","updated_at":"2026-01-03T09:01:31.949Z","avatar_url":"https://github.com/nikhil25803.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Blogging Platform API\n\nThe Blogging Platform API utilizes a microservices architecture with NodeJS, Express.js, Postgres, and Redis, facilitating CRUD operations, authentication, keyword search, and recommendation features. It emphasizes performance optimization, security measures, and scalability via Docker orchestration and thorough unit testing.\n\n## Tech Stacks\n\n![JavaScript](https://img.shields.io/badge/javascript-%23323330.svg?style=for-the-badge\u0026logo=javascript\u0026logoColor=%23F7DF1E) ![NodeJS](https://img.shields.io/badge/node.js-6DA55F?style=for-the-badge\u0026logo=node.js\u0026logoColor=white) ![Express.js](https://img.shields.io/badge/express.js-%23404d59.svg?style=for-the-badge\u0026logo=express\u0026logoColor=%2361DAFB) ![Postgres](https://img.shields.io/badge/postgres-%23316192.svg?style=for-the-badge\u0026logo=postgresql\u0026logoColor=white) ![Redis](https://img.shields.io/badge/redis-%23DD0031.svg?style=for-the-badge\u0026logo=redis\u0026logoColor=white) ![Prisma](https://img.shields.io/badge/Prisma-3982CE?style=for-the-badge\u0026logo=Prisma\u0026logoColor=white) ![Docker](https://img.shields.io/badge/docker-%230db7ed.svg?style=for-the-badge\u0026logo=docker\u0026logoColor=white)\n\n## Microservices Architecture\n\nA microservices architecture leveraging Docker containers orchestrates `PostgreSQL`, `Node.js API`, and `Redis` instances for scalable and modular application development.\n\n\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n    \u003cimg src=\"https://github.com/nikhil25803/blogging-platform/assets/93156825/ba56ffb9-e7a8-4a13-bc70-aa05fcfa498b\" alt=\"Project Architecture\"\u003e\n\u003c/div\u003e\n\n## Features\n\n- Token-based authentication and authorization for users.\n- CRUD operation on blogs.\n- Endpoint to retrieve the **latest N blog posts**, with N being a configurable parameter.\n- A search functionality that allows users to **search** for blog posts based on **keywords in the title or content**.\n- A feature to track and return the **most popular blog posts** based on the number of views.\n- Implemented a feature that **recommends related blog** posts based on the content of the currently viewed post based on the `cosine similarity` concept.\n- Added middleware to **compress API responses** for improved performance.\n- Optimized database queries for efficiency and considered **asynchronous processing** where applicable.\n- Wrote **comprehensive unit tests** covering the new features and algorithms\n- Implemented advanced security measures such as **rate limiting**, **request validation**, and protection against common web vulnerabilities.\n\n## Project setup\n\n### Clone the repository\n\n```bash\nhttps://github.com/nikhil25803/blogging-platform\n```\n\n### Configure environment variables\n\nAdd a `.env` and add values mentioned in `.env.template`\n\n```bash\nPORT=...\nJWT_ACCESS_TOKEN=...\nREDIS_HOST=...\nREDIS_PORT=...\nPOSTGRESDB_USER=...\nPOSTGRESDB_ROOT_PASSWORD=...\nPOSTGRESDB_DATABASE=...\nPOSTGRESDB_LOCAL_PORT=...\nPOSTGRESDB_DOCKER_PORT=...\nDATABASE_URL=postgresql://{USER}:{PASSWORD}@{HOST}:{PORT}/{DATABASE}\n```\n\n### Using Docker\n\n- Start up the services\n\n  ```bash\n  docker-compose up\n  ```\n\n- Stop and remove the containers created\n\n  ```bash\n  docker-compose down --rmi all\n  ```\n\n- You can now access the server on `localhost:8000`\n\n### Manual\n\n- Install dependencies\n\n  ```bash\n  npm i\n  ```\n\n- Migrate schema to database using prisma\n\n  ```bash\n  npx prisma migrate dev --name init\n  ```\n\n- **Note** - Make sure the DB and Redis are running properly, and make changes in the `.env` file properly.\n\n- Run test\n  This command will run and test all the API endpoints. Will clear and reset the database\n\n  ```bash\n  npm run test\n  ```\n\n- Run the server\n\n  ```\n  npm run dev\n  ```\n\n## Recommendation Engine\n\nA simplified approach using TF-IDF (Term Frequency-Inverse Document Frequency) for content analysis and **cosine similarity** for finding related posts. This approach is a common and relatively straightforward method for content-based recommendation.\n\nA glimpse into code used to generate content-based recommendations.\n\n```js\n// Function to calculate cosine similarity between two vectors\nconst cosineSimilarity = (vectorA, vectorB) =\u003e {\n  // Calculate dot product\n  const dotProduct = Object.keys(vectorA).reduce((acc, term) =\u003e {\n    if (vectorB[term]) {\n      acc += vectorA[term] * vectorB[term];\n    }\n    return acc;\n  }, 0);\n\n  // Calculate Euclidean norms\n  const normA = Math.sqrt(\n    Object.values(vectorA).reduce((acc, val) =\u003e acc + val ** 2, 0)\n  );\n  const normB = Math.sqrt(\n    Object.values(vectorB).reduce((acc, val) =\u003e acc + val ** 2, 0)\n  );\n\n  // Calculate cosine similarity\n  const similarity = dotProduct / (normA * normB);\n\n  return similarity;\n};\n\nconst blogsRecommendation = async (blogid) =\u003e {\n  // Fetch content of current blogs\n  const blogData = await prisma.blog.findFirst({\n    where: {\n      bid: blogid,\n    },\n  });\n\n  // Get content of the blog\n  const blogContent = blogData.content.toLowerCase();\n\n  // Current post vector data\n  tfidf.addDocument(blogContent, -1);\n\n  const cuurentBlogVector = tfidf.documents[0];\n\n  // Get content of all existing blogs except current blog\n  const existingBLogsData = await prisma.blog.findMany({\n    where: {\n      bid: {\n        not: blogid,\n      },\n    },\n  });\n\n  // List to store recommended blogs based on cosine similarity calculation\n  const recommendedBLogs = [];\n\n  existingBLogsData.forEach((blog, index) =\u003e {\n    tfidf.addDocument(blog.content, index);\n    const currentDocumentVector = tfidf.documents[index + 1];\n\n    // Calculate cosine similarity\n    const cosineSimilarityValue = cosineSimilarity(\n      cuurentBlogVector,\n      currentDocumentVector\n    );\n\n    // Add blog in recommendation blog in this list if cosine score is \u003e 0.2\n    if (cosineSimilarityValue \u003e= 0.2) {\n      recommendedBLogs.push(blog);\n    }\n  });\n\n  return recommendedBLogs;\n};\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnikhil25803%2Fblogging-platform","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnikhil25803%2Fblogging-platform","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnikhil25803%2Fblogging-platform/lists"}