{"id":20415297,"url":"https://github.com/jeffascript/giphy-node-react","last_synced_at":"2025-09-15T06:03:08.103Z","repository":{"id":38425732,"uuid":"389339850","full_name":"jeffascript/giphy-node-react","owner":"jeffascript","description":"An app for searching and bookmarking gifs!","archived":false,"fork":false,"pushed_at":"2024-06-09T22:17:13.000Z","size":981,"stargazers_count":0,"open_issues_count":18,"forks_count":0,"subscribers_count":2,"default_branch":"cloud-deploy","last_synced_at":"2025-01-15T13:42:47.318Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://save-a-gif.onrender.com","language":"TypeScript","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/jeffascript.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-25T12:15:13.000Z","updated_at":"2024-06-09T22:17:16.000Z","dependencies_parsed_at":"2025-01-15T13:03:09.719Z","dependency_job_id":"80a03d12-3a1d-4746-8dbf-4343a5fd8acd","html_url":"https://github.com/jeffascript/giphy-node-react","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/jeffascript%2Fgiphy-node-react","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffascript%2Fgiphy-node-react/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffascript%2Fgiphy-node-react/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffascript%2Fgiphy-node-react/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jeffascript","download_url":"https://codeload.github.com/jeffascript/giphy-node-react/tar.gz/refs/heads/cloud-deploy","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241960584,"owners_count":20049340,"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":[],"created_at":"2024-11-15T06:15:04.340Z","updated_at":"2025-03-05T03:30:21.697Z","avatar_url":"https://github.com/jeffascript.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## GIF SEARCH APP\n\n**Client**\nThe web app is bootstrapped using `create-react-app`.\n\n- Typescript\n\n- React ( ContextAPI for temporary caching and Hook for Clipboard copy/paste events )\n\n- Redux/toolkit (newest redux library from redux team)\n\n- Redux-persist (to persist the bookmarked GIFs for later use)\n\n**Server**\n\n- Typescript\n- Node\n- Express\n- Redis (caching solution)\n\n\n## Run the App\n\nApp is dockerized. Hence, Docker needs to be up and running on the system.\n\nAfter cloning the repo:\n\n```sh\ndocker-compose up --build\n```\n\nThis will build the docker images and start the app.\n\n\u003e If you face any issue after running `docker-compose up` command, please kill the server and restart again. Prolly, compiller issues from TS.\n\n### Ports\n\nThe app can be accessed at `http://localhost:3000`. The backend is exposed on the port `5001`.\n\n### Architectural flow\n\n## Client\n\n#### 1. Search \u0026 Cache functionality\n\nAs a user, when you type in a search string in the search field, the app first checks for the results stored in the temporary **cache**, else it makes an API call to the server to fetch the results, as well as cache the results for that session.\n\nFor the purposes of caching, the search query is stringified and used as the cache key. If the user makes the same search again within the current session, the `ui state` is updated from the temporary cache thus avoiding any unnecessary calls to the server.\n\n\u003e Reason for the temporary cache with `ContextAPI` here is due to the fact that we are still caching the results in the server with REDIS, hence, api calls will have low latency time to refetch data based on cached search string.\n\nThe inputed search string is expected to be more than `3` letters, else no result or api calls would be made.\n\n#### 2. Bookmark Functionality\n\nEach Gif has the possibilty to be bookmarked or copied upon hover.\n\nIf a user clicks on `bookmark` on a hovered Gif, the Gif is saved on the `gallery pane` and the `badge count` gets updated accordingly. On the Gallery Pane, user has the possibility of `unbookmarking` the Gifs that was previously bookmarked.\n\n\u003e The bookmarking logic was implemented with `Redux` and stored on the local storage for persistence even after a session is been completed by a user. The result is persisted in the local storage, so that even if the app is refreshed, the redux records are maintained.\n\n#### 2. Copy to Clipboard Functionality\n\nIf a user clicks on `copy` on a hovered Gif, the url of the Gif is copied and formatted for use on a Markdown Text editor.\n\n\u003e Playground: User can paste here to see the copied Gif https://markdown-it.github.io/\n\n#### Server\n\nOnce the backend receives a request, it first checks for the results in its cache. This cache is maintained in **Redis** database. If the results are not found in the cache, it then calls the `gif api` for the search results.\n\nAfter the results are received, it first formats the results in the necessary format which is easier for the frontend to consume. It then caches this formatted data to the `redis store` and returns the result to the client.\n\nThe results are cached in the `redis` store for upto **2 days**. Once again the key used for storing the cache is the stringified search string/query.\n\n#### APIs\n\nFrontend only needs to call a single api regardless of the entity type you are searching for -\n\nendpoint - `/api/gifs`\nmethod - `POST`\nbody -\n\n```typescript\n{\n  \"searchString\" : string;\n\n}\n```\n\nThe data is validated in the server with `express-validator` and if any of the required fields are missing, it throws an error. Also, the string should be more than 3 letters to fetch results.\n\n#### Things to add / improve\n\n- Add more unit tests for both client and server.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeffascript%2Fgiphy-node-react","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjeffascript%2Fgiphy-node-react","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeffascript%2Fgiphy-node-react/lists"}