{"id":19543257,"url":"https://github.com/codewithalamin/convayto","last_synced_at":"2025-07-19T13:06:38.983Z","repository":{"id":252379568,"uuid":"727353586","full_name":"CodeWithAlamin/Convayto","owner":"CodeWithAlamin","description":"Convayto is a real-time chat app built with React.js and Supabase, offering user authentication, profile management, and chat functionalities.","archived":false,"fork":false,"pushed_at":"2024-10-30T07:33:45.000Z","size":2933,"stargazers_count":20,"open_issues_count":0,"forks_count":8,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-26T17:47:19.955Z","etag":null,"topics":["chatapp","chatting-app","codewithalamin","messenger-clone","messenging-app","reactjs","real-time","realtime","realtime-chat","realtime-database","realtime-messaging","supabase"],"latest_commit_sha":null,"homepage":"https://convayto.vercel.app","language":"JavaScript","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/CodeWithAlamin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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":"2023-12-04T17:38:51.000Z","updated_at":"2025-04-24T20:42:10.000Z","dependencies_parsed_at":"2024-10-30T10:39:27.694Z","dependency_job_id":"419bc76f-b414-42b3-bd86-3b965f8c1afd","html_url":"https://github.com/CodeWithAlamin/Convayto","commit_stats":null,"previous_names":["codepapa360/convayto","codewithalamin/convayto"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/CodeWithAlamin/Convayto","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodeWithAlamin%2FConvayto","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodeWithAlamin%2FConvayto/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodeWithAlamin%2FConvayto/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodeWithAlamin%2FConvayto/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CodeWithAlamin","download_url":"https://codeload.github.com/CodeWithAlamin/Convayto/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodeWithAlamin%2FConvayto/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265937377,"owners_count":23852112,"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":["chatapp","chatting-app","codewithalamin","messenger-clone","messenging-app","reactjs","real-time","realtime","realtime-chat","realtime-database","realtime-messaging","supabase"],"created_at":"2024-11-11T03:18:08.518Z","updated_at":"2025-07-19T13:06:38.933Z","avatar_url":"https://github.com/CodeWithAlamin.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n  \u003cimg src=\"./public/images/convayto-logo.png\" alt=\"Convayto logo\" width=\"230\" height=\"auto\"\u003e\n\n  \u003c!-- \u003ch1\u003eConvayto\u003c/h1\u003e --\u003e\n\n  \u003ch3\u003e\n    \u003ca href=\"https://convayto.vercel.app\"\u003e\n      \u003cstrong\u003e🖱️Live Website\u003c/strong\u003e\n    \u003c/a\u003e\n  \u003c/h3\u003e\n\n  \u003cdiv align=\"center\"\u003e\n    \u003ca href=\"https://github.com/CodeWithAlamin/Convayto/issues\"\u003eReport Bug\u003c/a\u003e\n    •\n    \u003ca href=\"https://github.com/CodeWithAlamin/Convayto/pulls\"\u003eRequest Feature\u003c/a\u003e\n  \u003c/div\u003e\n\n  \u003chr\u003e\n\n\u003c/div\u003e\n\n\u003cbr/\u003e\n\n\u003c!-- Badges --\u003e\n\u003cdiv align=\"center\"\u003e\n\n[![Twitter Follow](https://img.shields.io/twitter/follow/CodeWithAlamin?style=flat\u0026logo=x)](https://x.com/CodeWithAlamin)\n[![LinkedIn](https://img.shields.io/badge/LinkedIn-Connect-blue?style=flat\u0026logo=linkedin)](https://www.linkedin.com/in/CodeWithAlamin)\n\n![version](https://img.shields.io/github/package-json/v/CodeWithAlamin/Convayto?color=blue)\n![License](https://img.shields.io/badge/License-Apache%202.0-blue)\n\n\u003c/div\u003e\n\n\u003c!-- Brief --\u003e\n\u003cp align=\"center\"\u003e\nWelcome to Convayto! This real-time chat app uses React.js and Supabase to offer features like user authentication, profile management, and instant messaging. Built as a learning project, Convayto highlights the core functionalities of a modern chat application.\n\u003c/p\u003e\n\n\u003c!-- Screenshot --\u003e\n\u003ca align=\"center\" href=\"https://convayto.vercel.app\"\u003e\n\n![Screenshot](./public/images/convayto-mockup.jpg)\n\n\u003c/a\u003e\n\n## Table of Contents\n\n- [Links](#links)\n- [Technologies Used](#technologies-used)\n- [Features](#features)\n- [Database Design](#database-design)\n- [Security Considerations](#security-considerations)\n- [Challenges and Solutions](#challenges-and-solutions)\n- [Future Improvements](#future-improvements)\n- [Project Structure](#project-structure)\n- [Contributing](#contributing)\n- [License](#license)\n- [Author](#author)\n\n## Links\n\n- **Live Website:** [Convayto](https://convayto.vercel.app)\n- **Video Preview:** [Watch on YouTube](https://youtu.be/Oc0spL9-gQk)\n\n## Technologies Used\n\n- **React**: For building the user interface.\n- **Supabase**: For backend services and database management.\n- **React Router DOM**: For handling routing.\n- **React Hook Form**: For form management.\n- **TanStack React Query**: For data fetching and state management.\n- **Tailwind CSS**: For styling.\n- **Vite**: For build tooling and development server.\n\n## Features\n\n- **User Authentication**: Secure signup and signin processes, including password reset and account confirmation.\n- **Profile Management**: Users can update their profiles, including setting a profile picture and editing personal information.\n- **Real-Time Chat**: Send and receive messages instantly.\n- **Protected Routes**: Access control for authenticated users, protecting sensitive routes and data.\n- **Responsive Design**: A user-friendly interface that adapts to various screen sizes and devices.\n- **Dark Mode**: Toggle between dark and light themes based on user preference.\n- **Sidebar and Menus**: Easy navigation with a collapsible sidebar, friend list, and account settings.\n- **Search Functionality**: Quickly find and connect with other users.\n- **Error Handling**: Toast notifications to inform users of errors and important updates.\n- **Optimized Performance**: Efficient state management and data fetching with React Query.\n\n## Database Design\n\nI've kept the Supabase setup as simple as possible, focusing more on the React side of things. In the public schema, there are two tables and two views derived from `auth.users`. I opted for views instead of separate tables to avoid creating triggers and keeping user data management simpler. Views update automatically based on `auth.users`.\n\n### Tables and Views\n\n#### Tables\n\n1. **Conversations**\n2. **Messages**\n\n#### Views\n\n1. **Users**\n2. **Usernames**\n\n### Why a Separate Usernames Table?\n\nI have a `username` column in the `users` view, so why a separate `usernames` table? It's for security. On the signup page, the user isn't authenticated yet but needs to pick a username. When a username is typed, it checks the `usernames` table to see if it's already taken, accessible to anonymous users. This avoids giving anonymous users access to the `users` table, which is reserved for authenticated users.\n\n### Conversations Table\n\nThe `conversations` table handles the connections between two users. Real-time updates are enabled for this table.\n\n**Row Level Security:**\n\n- **INSERT**: Applied to authenticated users\n- **SELECT**: Applied to authenticated users\n- **UPDATE** (especially the `last_message` column): Applied to authenticated users\n\n**Columns:**\n\n- `id`: UUID, Primary, Default Value: `gen_random_uuid()`\n- `created_at`: Timestamptz, Default Value: `now()`\n- `user1_id`: UUID, Default Value: `auth.uid()`\n- `user2_id`: UUID\n- `last_message`: JSONB, Nullable\n\n### Messages Table\n\nThe `messages` table stores message content and related information. Real-time updates are enabled for this table.\n\n**Row Level Security:**\n\n- **INSERT**: Applied to authenticated users\n- **SELECT**: Applied to authenticated users\n\n**Columns:**\n\n- `id`: UUID, Primary\n- `created_at`: Timestamptz, Default Value: `now()`\n- `sender_id`: UUID, Default Value: `auth.uid()`\n- `conversation_id`: UUID\n- `content`: Text\n\n### Views\n\n#### Usernames View\n\nThe `usernames` view has a single column for storing usernames.\n\n**Columns:**\n\n- `username`: Text\n\n**SQL Creation:**\n\n```sql\nCREATE VIEW public.usernames AS\nSELECT\n  raw_user_meta_data -\u003e\u003e 'username' AS username\nFROM auth.users;\n```\n\n**Grant Access:**\n\n```sql\nGRANT SELECT ON TABLE public.usernames TO anon;\n```\n\n#### Users View\n\nThe `users` view contains essential user information.\n\n**Columns:**\n\n- `id`: UUID\n- `email`: Varchar\n- `username`: Text\n- `fullname`: Text\n- `avatar_url`: Text\n- `bio`: Text\n\n**SQL Creation:**\n\n```sql\nCREATE VIEW public.users AS\nSELECT\n  id,\n  email,\n  raw_user_meta_data-\u003e\u003e'username' AS username,\n  raw_user_meta_data-\u003e\u003e'fullname' AS fullname,\n  raw_user_meta_data-\u003e\u003e'avatar_url' AS avatar_url,\n  raw_user_meta_data-\u003e\u003e'bio' AS bio\nFROM auth.users;\n```\n\n**Grant Access:**\n\n```sql\nGRANT SELECT ON TABLE public.users TO authenticated;\n```\n\n### Buckets\n\nA single bucket is used to store user profile pictures.\n\n**Bucket Name:**\n\n- `avatars`\n\n**Configuration:**\n\n- Public bucket: Enabled\n- Restrict file upload size: Enabled\n- File size limit: 5 MB\n- Allowed MIME types: `image/jpeg`, `image/png`, `image/webp`\n\n## Security Considerations\n\nSince Convayto is a React web app, it doesn’t have server-side security measures built in. Instead, I rely on Supabase for backend services and database management, which provides the necessary security features.\n\n- **Row-Level Security**: Supabase's Row-Level Security (RLS) ensures users only access and modify authorized data.\n\n- **Authentication and Authorization**: I integrated Supabase's authentication service to handle user registration, login, and password reset processes. Supabase provides secure and reliable authentication mechanisms, including email verification and password hashing, to protect user accounts.\n\n- **Protected Routes**: To restrict access to certain pages and features only to authenticated users I used protected routes. This prevents unauthorized access to sensitive information and actions.\n\n## Challenges and Solutions\n\nDuring the development of Convayto, I encountered several challenges and came up with these solutions:\n\n1. **Real-time Messaging**: Getting real-time messaging to work was tricky because everything needed to update instantly. I used Supabase's real-time features along with React Query to make sure messages updated smoothly and right away.\n\n2. **User Authentication**: I relied on Supabase's built-in authentication tools, including password reset, account confirmation, and secure signup/signin processes to make sure user authentication was secure.\n\n3. **Responsive Design**: Making the app look good on different screen sizes and devices was a challenge. I used Tailwind CSS's responsive utility classes to create a user interface that adapts well to any screen size.\n\n4. **Error Handling**: To handle errors properly and display clear messages when something goes wrong, I used the `react-hot-toast` package to show informative toast notifications.\n\n5. **Optimized Performance**: Handling a large amount of data and maintaining performance was a significant challenge. To address this, I implemented infinite pagination for messages, allowing the app to fetch chunks of messages as you scroll up. This approach keeps initial load times short and ensures smooth performance, even with extensive chat histories. Additionally, when a user logs in, it prefetches the first ten conversation histories.\n\n## Future Improvements\n\nHere are some ideas for future enhancements to Convayto that I plan to implement as I continue learning other technologies:\n\n- **Message Editing and Deletion**: Allow users to modify and remove their messages.\n- **Message Reactions**: Enable emoji reactions for messages.\n- **File Sharing**: Support sharing images and documents in chat.\n- **Notification System**: Introduce notifications for new messages or updates.\n- **Emoji Picker**: Add an emoji picker for easier message personalization.\n- **TypeScript Integration**: Update the entire project with TypeScript for better type safety and code maintainability.\n\n### Project Structure\n\nThe project is organized for clarity and modularity, following a typical React application structure:\n\n- **Public Assets**\n\n  - `public/`: Contains static assets, including fonts, images, `robots.txt`, and `sitemap.xml`.\n\n- **Source Code**\n  - `src/`: Main application source code.\n    - `main.jsx`: Main entry point for rendering the application.\n    - `App.jsx`: Application entry point.\n    - `components/`: Reusable UI components.\n    - `contexts/`: Global state management.\n    - `features/`: Feature-specific modules (authentication, messaging, sidebar, user profile, user search).\n    - `services/`: External service integrations, e.g., Supabase.\n    - `styles/`: Custom and global styles.\n    - `utils/`: Utility functions and hooks.\n\n## Contributing\n\nContributions to Convayto are welcome! Before contributing, please ensure you follow these guidelines:\n\n### .env File\n\nConvayto uses environment variables stored in a `.env` file to manage sensitive information. Ensure you have the following variables set up:\n\n```plaintext\nVITE_SUPABASE_URL = https://your-supabase-url.com\nVITE_SUPABASE_KEY = your-supabase-key\n```\n\nYou can find a template for these variables in `.env.example`.\n\n### Installation\n\nTo contribute to Convayto, follow these steps:\n\n- Fork the repository and clone it locally.\n- Install dependencies: `npm install`.\n- Set up your `.env` file using `.env.example` as a template.\n- Make your changes and test them thoroughly.\n- Submit a pull request with a clear description of your changes and their purpose.\n\n## License\n\n© Copyright by Alamin. This project is licensed under the Apache License 2.0. See the [LICENSE](./LICENSE.md) file for details. Do not claim as your own.\n\n## Author\n\n\u003cimg src=\"https://github.com/CodeWithAlamin.png\" alt=\"Photo\" width=\"50\" height=\"auto\" style=\"border-radius: 50%;\"\u003e\n\nI'm **Alamin**, a passionate web developer constantly learning and building projects. Connect with me on LinkedIn and Twitter.\n\n- LinkedIn: [CodeWithAlamin](https://www.linkedin.com/in/CodeWithAlamin)\n- X (Twitter): [CodeWithAlamin](https://twitter.com/CodeWithAlamin)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodewithalamin%2Fconvayto","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodewithalamin%2Fconvayto","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodewithalamin%2Fconvayto/lists"}