{"id":20826704,"url":"https://github.com/cedrickchee/twit","last_synced_at":"2026-04-05T08:32:41.474Z","repository":{"id":56580801,"uuid":"286743976","full_name":"cedrickchee/twit","owner":"cedrickchee","description":"A simple Twitter client","archived":false,"fork":false,"pushed_at":"2020-10-30T10:29:17.000Z","size":66,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-03T16:07:04.465Z","etag":null,"topics":["educational-project","expressjs","fullstack-javascript","nodejs-api","reactjs","realtime","stream-processing","websocket"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/cedrickchee.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}},"created_at":"2020-08-11T12:52:51.000Z","updated_at":"2025-02-21T15:52:56.000Z","dependencies_parsed_at":"2022-08-15T21:20:43.033Z","dependency_job_id":null,"html_url":"https://github.com/cedrickchee/twit","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cedrickchee/twit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedrickchee%2Ftwit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedrickchee%2Ftwit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedrickchee%2Ftwit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedrickchee%2Ftwit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cedrickchee","download_url":"https://codeload.github.com/cedrickchee/twit/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedrickchee%2Ftwit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31430009,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T08:13:15.228Z","status":"ssl_error","status_checked_at":"2026-04-05T08:13:11.839Z","response_time":75,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["educational-project","expressjs","fullstack-javascript","nodejs-api","reactjs","realtime","stream-processing","websocket"],"created_at":"2024-11-17T23:09:48.403Z","updated_at":"2026-04-05T08:32:41.452Z","avatar_url":"https://github.com/cedrickchee.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Twit\n\nTwit is a simple Twitter client, built using React.js, Node.js, Websocket, and friends.\n\nTwit fetches a **realtime** list of Tweets for a given keyword. New unread Tweets\nappear as a notification bar that will prompt the user to view them, in an\n**infinite scroll** style.\n\nInitially, during prototype stage, I used socket.io for Websocket. I migrated to\nPusher Channels for larger scale production deployment because dealing with\nWebsocket and AWS API Gateway is challenging before AWS launched HTTP APIs.\n\\\n\\\n\\\n![app](https://user-images.githubusercontent.com/145605/97685940-23be6000-1ad4-11eb-8163-8dd5aeb65cc6.gif)\n\\\n\\\n**Demo**\n\nTwitter client: https://d2ccty7fz88oi0.cloudfront.net/\n\nAPI endpoint: https://twit-api.onrender.com/\n\n## Design and Tech Stack\n\n- Runtime: Node.js 12+ (tested v12.18.3 on linux)\n- Language: TypeScript\n- Web framework: Express.js\n- Front-end library: React.js\n- State and lifecycle in React component: [Hooks](https://reactjs.org/docs/hooks-intro.html)\n- Simple, modular, and accessible component library: [Chakra UI](https://chakra-ui.com/)\n- Database: [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) provides an easy way to host and manage your data in the Cloud.\n- Websocket: [Pusher Channels](https://pusher.com/channels) provides realtime communication between servers and apps.\n\n## Features\n\n- _Relatively_ easy to understand project structure.\n- Written in modern React, only functional components with hooks.\n- Simple local React state management, without Redux or similar.\n- Client written in TypeScript.\n- API written in TypeScript and using Mongoose ODM.\n- Prettier to format code.\n- ESLint helps present code that's more clean and consistent.\n\n---\n\n## Setup\n\n### Prerequisite\n\nFor a hitch-free flow of procedures in this project, we will begin by setting up\nthe required credentials with MongoDB Atlas and Pusher.\n\n**MongoDB Atlas**\n\n[Follow this guide](https://docs.atlas.mongodb.com/getting-started/) to create\nan Atlas cluster and connecting to it.\n\nAfter you have created Atlas cluster, copy the connection string and add them\ndirectly to an `.env.dev` file. Create an empty `.env.dev` file in [`/api`](./api), copy `/api/.env.dev.example`\ncontents into it, and fill in your MongoDB Atlas connection string.\n\n**Pusher**\n\nIf you don't have an account, kindly create one. Once you are done, go ahead and\ncreate a new app from your dashboard. Don't forget to take note of your\n`app_id`, `key`, `secret` and `cluster` as you will be required to use them\nlater.\n\nDocs: [Get your Pusher API keys](https://pusher.com/docs/channels/getting_started/javascript#get-your-free-api-keys)\n\nAfter you have created Pusher account, copy the credentials and add them to\nan `.env.dev` file, within the root of the [`/api`](./api) project.\n\n**Twitter APIs**\n\nYou will need valid Twitter Developer credentials in the form of a set of\nconsumer and access tokens/keys. You can get these [here](https://developer.twitter.com/en/apply-for-access).\n\nCopy the credentials and add them to the same `.env.dev` file.\n\n### Setup Development Environment\n\nInstructions for setting up project in local development environment.\n\n#### API (Backend)\n\nSetup and run the web server.\n\n1. `cd` into 'api' directory:\n\n```sh\n$ cd api\n```\n\n2. Install NPM packages:\n\n```sh\n$ npm i\n```\n\n3. Once all the necessary files are installed, start the web server with:\n\n```sh\n$ npm start\n```\n\n#### Client (Frontend)\n\nSetup the frontend of the web app.\n\n1. `cd` into 'client' directory:\n\n```sh\n$ cd client\n```\n\n2. Install NPM packages:\n\n```sh\n$ npm i\n```\n\n3. Start the application with:\n\n```sh\n$ npm start\n```\n\nBy now, React app should now be running on http://localhost:3000/ and you should\nhave a new tab opened in your default browser.\n\nAlternatively, to get up and running quickly, I've provided a Makefile:\n\n```sh\n$ make\ninstall-dependencies           Install all project dependencies\nbuild                          Build both api and client project\nrun-api                        Run API server\nrun-client                     Run React application\n\n$ make install-dependencies\n\n$ make run-api\n\n$ make run-client\n```\n\nWe have successfully setup both the backend and frontend of the application.\n\n## Deployment\n\nNow, you are ready to deploy. You can deploy our project to AWS, [Render](https://render.com/),\nor Heroku.\n\nI have deployed the demo:\n- API backend to Render. ([Docs](https://render.com/docs/deploy-node-express-app))\n- Client app to AWS S3 and Cloudfront.\n\n## Assumptions\n\n- Initial page load should show 10 latest Tweets.\n- Don't show re-Tweets\n- Inform user of new Tweets after initial page load.\n\n## Future Improvements\n\nWhat's missing and what could have been done better?\n\n- Infinite scroll (performance optimizations)\n  + Should not load all unread Tweets at once\n  + Efficiently rendering large lists and data\n    + Should destroy list items that are out of viewport, else scrolling will lag as the list grow over time when populated with latest Tweets.\n    + Can explore using [react-virtualized](https://github.com/bvaughn/react-virtualized) components to solve this problem.\n- Animations\n  + Ease-in transition animation for new Tweets.\n- Backend API\n  + Storing stream of Tweets in database will required substantial disk space as the number of records are increasing quickly. So, need to clear out old Tweets from database using background scheduled/cron jobs.\n- Unit/integration tests\n  + Both client and API are currently not tested through Jest, React Testing Library, and end-to-end Cypress tests.\n- Deployment guide\n- Integrate build process with CI/CD tools like CircleCI.\n\n## Questions\n\n[Write-up](./questions.md).\n\n## Back-end\n\n![terminal](https://user-images.githubusercontent.com/145605/97686542-4cdef080-1ad4-11eb-913d-f7cf8b28fa55.gif)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcedrickchee%2Ftwit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcedrickchee%2Ftwit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcedrickchee%2Ftwit/lists"}