{"id":18862860,"url":"https://github.com/anshsinghsonkhia/trovexpins","last_synced_at":"2026-04-02T02:49:55.565Z","repository":{"id":223015903,"uuid":"758647391","full_name":"AnshSinghSonkhia/TroveXpins","owner":"AnshSinghSonkhia","description":"Pinpoint your Passion. Discover Troves that Set your Soul Alight.","archived":false,"fork":false,"pushed_at":"2024-02-25T05:07:53.000Z","size":21699,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-12-30T21:16:55.241Z","etag":null,"topics":["backend","ejs","expressjs","full-stack","javascript","mongodb","multer","nodejs","passportjs","tailwindcss","uuid","uuidv4"],"latest_commit_sha":null,"homepage":"https://trovexpins.onrender.com/","language":"EJS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AnshSinghSonkhia.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}},"created_at":"2024-02-16T19:07:15.000Z","updated_at":"2024-03-02T16:29:38.000Z","dependencies_parsed_at":"2024-02-25T05:33:44.668Z","dependency_job_id":null,"html_url":"https://github.com/AnshSinghSonkhia/TroveXpins","commit_stats":null,"previous_names":["anshsinghsonkhia/trovex"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnshSinghSonkhia%2FTroveXpins","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnshSinghSonkhia%2FTroveXpins/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnshSinghSonkhia%2FTroveXpins/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnshSinghSonkhia%2FTroveXpins/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AnshSinghSonkhia","download_url":"https://codeload.github.com/AnshSinghSonkhia/TroveXpins/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239808148,"owners_count":19700440,"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":["backend","ejs","expressjs","full-stack","javascript","mongodb","multer","nodejs","passportjs","tailwindcss","uuid","uuidv4"],"created_at":"2024-11-08T04:35:58.723Z","updated_at":"2025-12-30T19:54:31.746Z","avatar_url":"https://github.com/AnshSinghSonkhia.png","language":"EJS","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TroveXpins - Pinpoint your Passion. Discover Troves that Set your Soul Alight.\n\nCreate Troves \u0026 Share your joyful moments with pins\n\n## Tech-Stack:\n\n\u003ccode\u003e\u003cimg height=\"30\" src=\"https://img.shields.io/badge/Tailwind%20CSS-111111?style=for-the-badge\u0026logo=tailwindcss\u0026logoColor=39bcf7\"\u003e\u003c/code\u003e\n\u003ccode\u003e\u003cimg height=\"30\" src=\"https://img.shields.io/badge/JavaScript-111111?style=for-the-badge\u0026logo=javascript\u0026logoColor=F7DF1E\"\u003e\u003c/code\u003e\n  \u003ccode\u003e\u003cimg height=\"30\" src=\"https://img.shields.io/badge/Node.js-1e4620?style=for-the-badge\u0026logo=nodedotjs\u0026logoColor=white\"\u003e\u003c/code\u003e\n  \u003ccode\u003e\u003cimg height=\"30\" src=\"https://img.shields.io/badge/MongoDB-238636?style=for-the-badge\u0026logo=mongodb\u0026logoColor=white\"\u003e\u003c/code\u003e\n  \u003ccode\u003e\u003cimg height=\"30\" src=\"https://img.shields.io/badge/Express.js-000000?style=for-the-badge\u0026logo=express\u0026logoColor=white\"\u003e\u003c/code\u003e\n  \u003cbr\u003e\u003cbr\u003e\n  \u003ccode\u003e\u003cimg height=\"30\" src=\"https://img.shields.io/badge/Passportjs-000000?style=for-the-badge\u0026logo=Passportjs\u0026logoColor=white\"\u003e\u003c/code\u003e\n  \u003ccode\u003e\u003cimg height=\"30\" src=\"https://img.shields.io/badge/ejs-a6004f?style=for-the-badge\u0026logo=EJS\u0026logoColor=white\"\u003e\u003c/code\u003e\n  \u003ccode\u003e\u003cimg height=\"30\" src=\"https://img.shields.io/badge/Multer-252525?style=for-the-badge\u0026logo=Multer\u0026logoColor=white\"\u003e\u003c/code\u003e\n  \u003ccode\u003e\u003cimg height=\"30\" src=\"https://img.shields.io/badge/Mongoose-238636?style=for-the-badge\u0026logo=Mongoose\u0026logoColor=white\"\u003e\u003c/code\u003e\n  \u003ccode\u003e\u003cimg height=\"30\" src=\"https://img.shields.io/badge/UUID-252525?style=for-the-badge\u0026logo=uuid\u0026logoColor=white\"\u003e\u003c/code\u003e\n\u003cbr\u003e\n\n# Creating the app (program structure) using `express`\n\n```shell\nexpress --view=ejs\n```\n\u003e To create in the same opened folder\n\n- Install node_modules\n\n```shell\nnpm i\n```\n\n- Install TailwindCSS\n\n```shell\nnpm install -D tailwindcss\nnpx tailwindcss init\n```\n\n- To Run Live Server\n\n```shell\nnpx nodemon\n```\n\n# `/views/partials` folder\n\nThese include the partials, that are present in all the pages. Example:\n- footer\n- header (navbar)\n\n## including partials in `index.ejs`\n\n\u003e paste the below in the body of index.ejs\n\n\u003e we'll write the code in middle\n```h\n\u003c% include ./partials/header.ejs %\u003e\n\u003c% include ./partials/footer.ejs %\u003e\n```\n\n## How to create a new page / route?\n\n1. In `index.js` --\u003e get the route \u0026 render it from `views` folder.\n\n```js\nrouter.get('/register', function(req, res, next) {\n  res.render('register');\n});\n```\n\n2. Make an ejs file with the routes name in `views` folder\n\n- In this case --\u003e `register.ejs`\n\n3. Write the Frontend Code in `register.ejs`\n\n# Setting up `users.js` \u0026 creating our database.\n\n1. Install\n\n```shell\nnpm i mongoose passport passport-local passport-local-mongoose express-session multer\n```\n\n2. require mongoose in `users.js`:\n\n```js\nconst mongoose = require('mongoose');\nconst plm = require(\"passport-local-mongoose\");\n```\n\n3. Connect MongoDB with mongoose:\n\n```js\nmongoose.connect(\"mongodb://127.0.0.1:27017/project_name\") // this is setting it up on localhost.\n```\n\n3. Creating userSchema:\n\n```js\nconst userSchema = mongoose.Schema({\n  // user schema should be created / defined here.\n});\n\nuserSchema.plugin(plm);  // this will enable passport to remember users\nmodule.exports = mongoose.model(\"user\", userSchema);\n\n// model() --\u003e  Mongoose compiles a model for you.\n// with (\"name-of-model\", Schema-to-be-followed) as 2 arguments are passed.\n```\n\n# Using `Multer` \u0026 `uuid` to take user images and save in our server\n\n1. Install Packages\n\n```shell\nnpm i multer uuid\n```\n\n2. Create `multer.js` in routes\n\n3. Add the following code:\n\n```js\nconst multer = require('multer');\nconst {v4: uuidv4} = require(\"uuid\");\nconst path = require('path');\n\nconst storage = multer.diskStorage({\n    destination: function (req, file, cb) {\n      cb(null, './public/images/uploads')\n    },\n    filename: function (req, file, cb) {\n      const unique = uuidv4();\n      cb(null, unique + path.extname(file.originalname));\n    }\n})\n  \nconst upload = multer({ storage: storage })\n\nmodule.exports = upload;\n```\n\n4. `./public/images/uploads` is the folder location in `public/images/uploads`\n  - The user images will be stored here.\n  - So, create the folder.\n\n5. We are Creating unique image id with `uuid`\n\n6. Make a route in `index.js`\n```js\nconst upload = require('./multer');\n\n/* Route for taking user-input profile image using multer. It will first check, if the user is loggedIn or not\nThen, upload the image.\n*/\nrouter.post('/fileupload', isLoggedIn, upload.single('image'), function(req, res, next) {\n    // upload.single('image') has 'image' because form has input name = \"image\"\n    const user = await userModel.findOne({username: req.session.passport.user});\n    /* When user is loggedin --\u003e req.session.passport.user has his \"username\".\n    \n    We are sending the uploaded profile image to the database.*/\n\n    user.profileImage = req.file.filename;  // changing the profileImage address/location to the newly updated image.\n\n    await user.save();    // Since, we have manually did some changes --\u003e We need to manually save the user Details.\n    \n    res.redirect(\"/profile\");   // After saving the new details, redirect to /profile page.\n});\n```\n\n7. Request the user profile image with it's path in the `profile.ejs` file\n\n```html\n\u003cimg class=\"object-cover w-full h-full\" src=\"/images/uploads/\u003c%= user.profileImage %\u003e\" alt=\"\"\u003e\n\t\t\t\t\t\t\n```\n\u003e There must not be any spaces in the src, otherwise, it will not get the correct path.\n\n## Problems/Challenges I faced:\n\n1. css file was not loading --\u003e then, I solved it using ChatGPT (Took 25 Minutes)\n```shell\nA 304 Not Modified response means that the browser already has a cached version of the CSS file, and it doesn't need to download it again because it hasn't changed since the last request.\n\nThis behavior is expected and indicates that the CSS file is being served correctly by Express. However, if you've made changes to the CSS file and you want to force the browser to fetch the latest version, you can do the following:\n\nForce Refresh: You can force a refresh in your browser, which typically bypasses the cache and fetches the latest version of the CSS file. In most browsers, you can do this by pressing Ctrl + Shift + R or Cmd + Shift + R.\n```\n\n\n# Improvement 1 - Another option to upload images via image url\n\n1. To fetch, install\n\n```shell\nnpm i axios\nnpm i https\n```\n\n2. In `index.js`\n\n```js\nconst axios = require('axios'); // Import axios for making HTTP requests\nconst https = require('https'); // Import https module\n\nrouter.post('/createpost', isLoggedIn, upload.single('postimage'), async function(req, res, next) {\n  const user = await userModel.findOne({username: req.session.passport.user});\n  \n  let image;\n    // Check if the request contains a file uploaded\n    if (req.file) {\n        // If a file is uploaded, use the uploaded file\n        image = req.file.filename;\n    } else if (req.body.imageUrl) {\n      // If image URL is provided, fetch the image and save it\n      try {\n\n          const agent = new https.Agent({  \n            rejectUnauthorized: false\n          });       // Don't add this line for production version. I lost my ssl certificate, that's why I need to bypass this.\n\n          const response = await axios.get(req.body.imageUrl, { responseType: 'arraybuffer', httpsAgent: agent });\n          const imageBuffer = Buffer.from(response.data, 'binary');\n          const imageName = 'image_' + Date.now() + '.jpg'; // Generate a unique name for the image\n          const imagePath = './public/images/uploads/' + imageName; // Set the path where the image will be saved\n\n          fs.writeFileSync(imagePath, imageBuffer); // Write the image buffer to a file\n          image = imageName; // Set the image name as the image for the post\n      } catch (error) {\n          console.error('Error fetching image from URL:', error);\n          // Handle error (e.g., image fetch failed)\n          res.status(500).send('Error fetching image from URL');\n          return;\n      }\n  }\n\n  const post = await postModel.create({\n    user: user._id,\n    title: req.body.title,\n    description: req.body.description,\n    image: image\n  });   // to create the post data in postModel\n\n  user.posts.push(post._id);\n  await user.save();\n  res.redirect(\"/profile\");\n});\n```\n\n3. If user uploaded the image, he can not give the url to fetch image. So, we handle it in `add.js`\n\n# ToDo: for production deployment\n\n- [ ] Add MongoDB Atlas inplace of mongoDB at localhost\n\n# Additional Tasks - My Improvements\n\n1. Default user profile image --\u003e it should be shown for new accounts with no image, or when user wants to delete profile image.\n\n2. Dynamically Adding TroveBoards (Trove) --\u003e User should be able to create new collections.\n    - `Create Pin` button ki jagah `Create Trove` button aayega --\u003e new TroveBoard create krne ke liye.\n    - Sabhi boards mai button hona chahiye, unke ander new `Create Pin` ka. --\u003e `+ icon`\n\n3. Sabhi boards ko default cover image dena hai (New Pin add krne ke icon ke saath.)\n\n4. Home Page\n    - Home Page Navbar will have login \u0026 sign up buttons.\n\n5. Feed Page should have a `Search Bar` to search different pins by all the users\n\n6. Working `Edit Profile` button\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanshsinghsonkhia%2Ftrovexpins","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanshsinghsonkhia%2Ftrovexpins","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanshsinghsonkhia%2Ftrovexpins/lists"}