{"id":16953520,"url":"https://github.com/thomasroest/better-bookmarks","last_synced_at":"2025-03-22T13:31:33.881Z","repository":{"id":39525992,"uuid":"146173339","full_name":"ThomasRoest/better-bookmarks","owner":"ThomasRoest","description":"self hosted browser bookmark manager","archived":false,"fork":false,"pushed_at":"2023-01-03T23:16:11.000Z","size":4459,"stargazers_count":21,"open_issues_count":19,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-01T16:12:41.405Z","etag":null,"topics":["bookmarks","firebase","react","redux"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ThomasRoest.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-08-26T11:06:06.000Z","updated_at":"2024-04-23T13:22:39.000Z","dependencies_parsed_at":"2023-02-01T13:01:45.299Z","dependency_job_id":null,"html_url":"https://github.com/ThomasRoest/better-bookmarks","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThomasRoest%2Fbetter-bookmarks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThomasRoest%2Fbetter-bookmarks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThomasRoest%2Fbetter-bookmarks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThomasRoest%2Fbetter-bookmarks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ThomasRoest","download_url":"https://codeload.github.com/ThomasRoest/better-bookmarks/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244211286,"owners_count":20416608,"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":["bookmarks","firebase","react","redux"],"created_at":"2024-10-13T22:07:19.616Z","updated_at":"2025-03-22T13:31:33.505Z","avatar_url":"https://github.com/ThomasRoest.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Better Bookmarks\n\nA self-hosted bookmark manager made with React, Redux, Firebase (Cloud Firestore/ authentication), Netlify Functions and Algolia (search).\n\nThis project uses several PWA features, including the [share target api.](https://developers.google.com/web/updates/2018/12/web-share-target) So after you've installed the app to your homescreen, you can share urls from your browser like you would with any other app (only tested on Android).\n\n## Screenshots\n\n\u003c!-- ![HOME](/public/screenshot_home2.png) --\u003e\n\n![HOME](/public/screenshot3.png)\n\n## Setup\n\n1. Clone the repository\n\n2. yarn install\n\n3. Go to [firebase console](https://console.firebase.google.com/) and create a new project.\n\n4. Click on the \"web / add to webapp\" icon to get the config keys for you project. Add them to your firebase.js config file.\n\n\u003e Note: these are client-side keys and are not for security, but more for project identification. Make sure you add the proper security rules to secure your data.\n\n```js\nconst config = {\n  apiKey: process.env.REACT_APP_API_KEY,\n  authDomain: process.env.REACT_APP_DOMAIN,\n  databaseURL: process.env.REACT_APP_DATABASE,\n  projectId: process.env.REACT_APP_PROJECT_ID,\n  storageBucket: process.env.REACT_APP_BUCKET,\n  messagingSenderId: process.env.REACT_APP_MESSAGE_ID\n};\n```\n\n5. The next step is to create a Firestore database. You can do this by going to the database tab and create a database (Firestore)\n\n6. When you have created the database, copy the following security rules into the rules section to secure your data.\n\n```js\nservice cloud.firestore {\n  match /databases/{database}/documents {\n    match /users/{userId} {\n      allow create: if isSignedIn() \u0026\u0026 emailVerified();\n      allow update: if isSignedIn() \u0026\u0026 isOwner(userId);\n    }\n\n    match /users/{userId}/bookmarks/{bookmarkId} {\n      allow write: if isSignedIn() \u0026\u0026 isOwner(userId);\n      allow read: if isSignedIn() \u0026\u0026 isOwner(userId)\n    }\n\n    match /users/{userId}/tags/{tagId} {\n      allow write: if isSignedIn() \u0026\u0026 isOwner(userId);\n      allow read: if isSignedIn() \u0026\u0026 isOwner(userId)\n    }\n\n    function isSignedIn() {\n      return request.auth != null;\n    }\n    function isOwner(userId) {\n      return request.auth.uid == userId;\n    }\n    function emailVerified() {\n      return request.auth.token.email_verified;\n    }\n  }\n}\n```\n\n7. To enable authentication with Google, go to the navigation tab to add a login method --\u003e select google option from the providers and switch the toggle to enable. If you scroll down, you can see the authorized domains for which this login method will work. This is important to update when you deploy your project.\n\n8. You can now run `yarn start` to run the application locally.\n\n9. The default query for fetching all bookmarks requires an index in firestore, so you might see this error in the console:\n\n`Uncaught (in promise) Error: The query requires an index. You can create it here:`\n\nfollow the link to create the index.\n\n## Netlify Functions \u0026 Deploying\n\nThis project uses Netlify functions for additional functionality ( search indexing, getting titles from pages). See [src/lambda/](https://github.com/ThomasRoest/better-bookmarks/blob/master/src/lambda/).\n\nTo deploy:\n\n- deploy your project with [Netlify](https://www.netlify.com)\n- Set your build environment variables\n- Update the authorized domains for authentication in the firebase console (authentication tab)\n\n## Search with Algolia\n\nTo configure search with [Algolia](https://www.algolia.com/)\n\n- signup for a free account on [Algolia.com](https://www.algolia.com/)\n- go to your dashboard and create a new app.\n- Go to api keys and create a new key with the following permissions: `search, addObject, deleteObject`. This will be the key for use with lambda functions. The other keys that you will need are the app ID to identify your app, and the search only key which will be used client-side to search your index.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomasroest%2Fbetter-bookmarks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthomasroest%2Fbetter-bookmarks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomasroest%2Fbetter-bookmarks/lists"}