<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[GitSafari]]></title><description><![CDATA[GitSafari]]></description><link>https://gitsafari.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sat, 07 Nov 2026 11:50:00 GMT</lastBuildDate><atom:link href="https://gitsafari.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Unlock the Power of Open Source: Explore and Contribute with Git Safari]]></title><description><![CDATA[Explore open-source projects on GitSafari, a social platform for developers with Appwrite-powered features for a seamless experience]]></description><link>https://gitsafari.hashnode.dev/unlock-the-power-of-open-source-explore-and-contribute-with-git-safari</link><guid isPermaLink="true">https://gitsafari.hashnode.dev/unlock-the-power-of-open-source-explore-and-contribute-with-git-safari</guid><category><![CDATA[Appwrite]]></category><category><![CDATA[Appwrite Hackathon]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[Open Source]]></category><dc:creator><![CDATA[Shaunak Nagrecha]]></dc:creator><pubDate>Fri, 09 Jun 2023 09:51:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1686723052343/c266ea30-45d5-491d-bad2-87d3237eeae4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Have you ever struggled to find open-source repositories to contribute to, even when using GitHub's Explore feature? You're not alone. We faced the same challenge when we began contributing to open-source projects, which led us to discover Appwrite through a YouTube influencer. To tackle this "Open Source Scavenging" issue, we decided to create a social networking platform specifically for open-source developers, similar to Instagram but focused on open-source projects. Introducing GitSafari 🚀, where your feed is filled with open-source recommendations shared by other users, showcasing their favorite repositories.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/hmvgiLUwadc">https://youtu.be/hmvgiLUwadc</a></div>
<p> </p>
<h2 id="heading-team-members">Team Members</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>GitHub Username</td><td>Hashnode</td></tr>
</thead>
<tbody>
<tr>
<td>Mohit Tiwari</td><td><a target="_blank" href="https://github.com/mmjsmohit">mmjsmohit</a></td><td><a target="_blank" href="https://hashnode.com/@mmjsmohit">Mohit Tiwari</a></td></tr>
<tr>
<td>Shaunak Nagrecha</td><td><a target="_blank" href="https://github.com/srn08">srn08</a></td><td><a target="_blank" href="https://hashnode.com/@Shaunak08">Shanunak Nagrecha</a></td></tr>
</tbody>
</table>
</div><h2 id="heading-technologies-used">Technologies Used</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Frontend</td><td>Backend</td><td>State Management</td><td>Local DB</td></tr>
</thead>
<tbody>
<tr>
<td>Flutter</td><td>Appwrite</td><td>Provider</td><td>Isar</td></tr>
<tr>
<td>Dart</td><td></td><td></td></tr>
</tbody>
</table>
</div><p>We have also used many packages from pub.dev, have a look at dependencies in pubspec.yaml</p>
<h2 id="heading-why-we-used-appwrite">Why we used Appwrite</h2>
<ul>
<li><p><strong>Free and Open source</strong> - Great Community and Support</p>
</li>
<li><p><strong>Function API is free</strong> - Usually, Functions are a paid feature in BaaS platforms</p>
</li>
<li><p><strong>Great cloud platform</strong> - Helps visualize how your app interacts with the database</p>
</li>
<li><p><strong>Built-in User Management</strong> - Appwrite provides built-in user management and authentication features, including user registration, login, email verification, password management, and OAuth support</p>
</li>
</ul>
<h1 id="heading-features">Features:</h1>
<h3 id="heading-add-posts"><strong>Add Posts ➕</strong></h3>
<p>This feature is the main purpose of building this app in the first place. You can create posts on your own and also check out what other people are posting. To create a post, you need to select an image and also select the GitHub repository you are talking about in your post's caption.</p>
<p>The post looks like this. You can swipe right to reveal the attached image.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686725864738/2c43f169-fd40-46ee-b601-d0d72bac49c0.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-upvote-and-share-posts">Upvote 🔼 and Share Posts 📤</h3>
<p>Show some love! If you enjoyed a post, you can upvote and share posts on all of your favorite social media and messaging apps like WhatsApp, Instagram, Twitter, etc.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686727558043/65f88037-587a-4cf4-9ebf-1a05be4f9612.gif" alt class="image--center mx-auto" /></p>
<h3 id="heading-repository-search">Repository Search 🔍</h3>
<p>If you wish to share an interesting repository you've come across, you can easily search for it within the app while creating a new post! Just click on the desired repository, and GitSafari will automatically retrieve its GitHub link and preview the image for you!</p>
<p>We utilized the search endpoint of the GitHub API to gather all pertinent information about a GitHub Repository.</p>
<p>You can read the relevant documentation <a target="_blank" href="https://docs.github.com/en/rest/search?apiVersion=2022-11-28#search-repositories">here</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686727243298/5da43cf1-b539-4bfe-8fe9-c10d57b29fab.gif" alt class="image--center mx-auto" /></p>
<h3 id="heading-opengraph-repository-previews">Opengraph Repository Previews🖼️</h3>
<p>For generating the Repository Preview images, we talk to a special endpoint: <a target="_blank" href="https://opengraph.githubassets.com/">GitHub Opengraph</a>. This enables us to display <strong>updated</strong> <strong>information</strong> about a GitHub Repository on the fly.</p>
<p><img src="https://github.blog/wp-content/uploads/2021/06/framework-open-graph-images_fig-1-GitHub-twitter-card.png?resize=2400%2C1260" alt /></p>
<h3 id="heading-caching-for-posts"><strong>Caching for Posts 💾</strong></h3>
<p>Just like numerous other social media platforms that cache images to minimize network requests, we utilized the cached_network_image package to cache images. This enhancement significantly improved both the app's performance and network usage.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686726442786/2922bb77-73bc-4908-9593-b1eafa415374.gif" alt class="image--center mx-auto" /></p>
<h3 id="heading-dynamic-language-icons">Dynamic Language Icons 🔣</h3>
<p>As you can see, the app displays the icon representing the tech stack of the repository in the top right corner. It's quite impressive, as we have added an icon for every possible tech stack.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686726714914/bd9ccc86-fa19-41f2-ba0c-99cba991b49c.gif" alt class="image--center mx-auto" /></p>
<h3 id="heading-resources-for-contributing-to-the-repository">Resources for contributing to the repository 📚</h3>
<p>Let's say you find a repo on GitSafari and you want to contribute to it but do not know the technology it was built in, so you can tap on the roadmaps button next to the upvote and share button on the posts and you can get custom resources to learn that tech stack.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686726996087/88082e05-3674-4849-9c4f-607b3cba432e.gif" alt class="image--center mx-auto" /></p>
<h3 id="heading-stories">Stories 📰</h3>
<p>Whether it is a bug that you resolved or a feature that you have added, you can share your small successes and failures by posting a story just like you do on Instagram. This place will also be a goldmine for Programming Memes and some geeky humor. 😉</p>
<p>These stories disappear 24 hours after being posted, just like on Instagram. This functionality is enabled by the Functions API, which records the time a story is created and deletes it if it surpasses the 24-hour mark. This function runs every hour.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686727942746/86780c5b-9ec3-4798-b39e-62a5633c00b4.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-sign-in-with-github">Sign In with GitHub 🔐</h3>
<p>Users can log in or sign up directly through GitHub OAuth, eliminating the need to create an account on GitSafari and enter all their details. We utilized the Account API to establish the OAuth session.</p>
<h3 id="heading-add-your-custom-bio">Add your custom bio ✍🏻</h3>
<p>Describe yourself in a few words! This is made possible by the User Preferences feature where you can assign a set of key-value pair to every user.</p>
<h3 id="heading-isar-database-for-local-data-persistence">Isar Database for local data persistence 📂</h3>
<p>We store essential information such as name, username, and email in a local persistent database to enhance performance and reduce the number of network calls. We intend to expand this by storing even more information offline as part of our offline-first approach.</p>
<h1 id="heading-usage-of-appwrite">Usage of Appwrite</h1>
<ol>
<li><h3 id="heading-account-api"><strong>Account API</strong> 🔑</h3>
<p> Used to authenticate users and also login via third parties like GitHub</p>
</li>
<li><h3 id="heading-database-api"><strong>Database API</strong> 🗃️</h3>
<p> We have 2 databases, Posts and Stories</p>
</li>
<li><h3 id="heading-storage-api"><strong>Storage API</strong> 💾</h3>
<p> We have 2 buckets, one for storing Post images and the other for storing story images</p>
</li>
<li><h3 id="heading-functions-api"><strong>Functions API</strong> 🔧</h3>
<p> Used to vanish stories after 24 hours of creation. The function we used is scheduled to run every hour (Scheduled using cron syntax 0****). It checks all the stories every hour if they are older than 24 hours, if yes, then it deletes them.</p>
</li>
</ol>
<pre><code class="lang-dart">Future&lt;<span class="hljs-keyword">void</span>&gt; start(<span class="hljs-keyword">final</span> req, <span class="hljs-keyword">final</span> res) <span class="hljs-keyword">async</span> {
  <span class="hljs-keyword">final</span> client = Client();
  <span class="hljs-keyword">final</span> database = Databases(client);

  <span class="hljs-keyword">if</span> (req.variables[<span class="hljs-string">'APPWRITE_FUNCTION_ENDPOINT'</span>] == <span class="hljs-keyword">null</span> ||
      req.variables[<span class="hljs-string">'APPWRITE_FUNCTION_API_KEY'</span>] == <span class="hljs-keyword">null</span>) {
    <span class="hljs-built_in">print</span>(
        <span class="hljs-string">"Environment variables are not set. Function cannot use Appwrite SDK."</span>);
  } <span class="hljs-keyword">else</span> {
    client
        .setEndpoint(req.variables[<span class="hljs-string">'APPWRITE_FUNCTION_ENDPOINT'</span>])
        .setProject(req.variables[<span class="hljs-string">'APPWRITE_FUNCTION_PROJECT_ID'</span>])
        .setKey(req.variables[<span class="hljs-string">'APPWRITE_FUNCTION_API_KEY'</span>])
        .setSelfSigned(status: <span class="hljs-keyword">true</span>);

    Future result = database.listDocuments(
        databaseId: STORY_DATABASE_ID,
        collectionId: STORY_COLLECTION_ID);

    result.then((response) {
      <span class="hljs-built_in">List</span> docs = response.documents;
      <span class="hljs-built_in">DateTime</span> nowtime = <span class="hljs-built_in">DateTime</span>.now();
      <span class="hljs-built_in">String</span> temp = <span class="hljs-string">""</span>;
      <span class="hljs-built_in">DateTime</span> fetch;

      <span class="hljs-keyword">for</span> (<span class="hljs-built_in">int</span> i = <span class="hljs-number">0</span>; i &lt; docs.length; ++i) {
        temp = docs[i].data[<span class="hljs-string">'createdAt'</span>];
        fetch = <span class="hljs-built_in">DateTime</span>.parse(temp);

        <span class="hljs-keyword">if</span> ((nowtime.difference(fetch)).inHours &gt; <span class="hljs-number">24</span>) {
          database.deleteDocument(
              databaseId: STORY_DATABASE_ID,
              collectionId: COLLECTION_ID,
              documentId: docs[i].data[<span class="hljs-string">'\$id'</span>]);
        }
      }
    });
  }

  res.json({
    <span class="hljs-string">'areDevelopersAwesome'</span>: <span class="hljs-keyword">true</span>,
  });
}
</code></pre>
<ol>
<li><h3 id="heading-avatar-api">Avatar API 🖼️</h3>
<p> Used to dynamically generate profile pictures for users. In the future, we are planning to integrate Avatar API with more third-party services like Gravatar to fetch user profiles.</p>
</li>
</ol>
<h1 id="heading-file-structure">File Structure</h1>
<pre><code class="lang-bash">.
├── android <span class="hljs-comment"># android files</span>
├── assets <span class="hljs-comment"># assets (images)</span>
├── ios <span class="hljs-comment"># ios files</span>
└── lib
    ├── api <span class="hljs-comment"># Logic for handling Appwrite and GitHub APIs</span>
    ├── models <span class="hljs-comment"># Custom Models</span>
    ├── screens
    │   └── home_tabs <span class="hljs-comment"># Tabs for home screen</span>
    ├── utils <span class="hljs-comment"># Api info and Local DB Logic</span>
    └── widgets <span class="hljs-comment"># Custom widgets</span>
</code></pre>
<h1 id="heading-challenges-we-faced">Challenges We Faced</h1>
<p>We often use features like these on social media apps, and it's actually a pretty tough job to create them from scratch (but it's also a lot of fun! 😄).</p>
<p>One of the first challenges we faced was figuring out the entire project structure and keeping the code as readable as possible. Our goal was to make it super easy for future contributors to join in and help out with the project 🤝. So, we made sure to keep a neat and tidy folder structure 📁.</p>
<p>Honestly, we have gained a whole new level of appreciation for developers who've worked on similar applications 🙌.</p>
<h1 id="heading-future-work">Future Work</h1>
<ul>
<li><p>Recommendation Algorithms for users' feed, according to the users' preferences</p>
</li>
<li><p>GitSafari for Recruiters - GitSafari will become a LinkedIn but for open source and remote work</p>
</li>
<li><p>Add Section for Frequently Occurring Errors - A section to discuss and resolve any issues encountered by new contributors while setting up contributing to a new project.</p>
</li>
</ul>
<h1 id="heading-code">Code</h1>
<p>GitSafari: <a target="_blank" href="https://github.com/mmjsmohit/git_safari">GitHub Repo</a></p>
<p>We would love for you to find issues and even contribute to this repository. See you there!</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>In conclusion, GitSafari is a social networking platform designed specifically for open-source developers, enabling users to discover and share projects, contribute to repositories, and connect with like-minded individuals. Leveraging Appwrite's API and other technologies, GitSafari aims to create a seamless experience for developers and foster a community centered around open-source collaboration. Future enhancements include recommendation algorithms, a platform for recruiters, and a section for discussing frequently occurring errors. Lastly, Thank you for reading our post! ✨We hope you found GitSafari interesting and useful. Please feel free to share your comments 💬 or feedback with us. We'd love to hear your thoughts! 😊</p>
]]></content:encoded></item></channel></rss>