Cookied: Appwrite Hackathon project

Hey, hang on!

This older blog was penned during the early stages of Cookied's development. Discover the latest blog covering Cookied's v1 release here: ๐Ÿ‘‰ https://ashuvssut.hashnode.dev/cookied-v1-release

The Team behind the Project

What is Cookied?

Nowadays you can easily get a bookmark Chrome extension which can manage your bookmarks in a better way. But what about managing your bookmarks on your phone? Your phone's browser can neither install those amazing Chrome extensions nor use an Android app alternative because there isn't any.

Then what's the solution to this? Here enters Cookied! It's a suite of apps which work cross-platform to help you save, manage and synchronize your bookmarks doesn't matter what device you use. Cookied Android app is capable to save bookmarks from your phone's browsers! This is not the only redeeming quality, read ahead to know more about the features!

Cookied is available as a web app, android app and Chrome extension. It is built using Appwrite, Next.js, React Native and Vite.

We made this project for the submission in Appwrite Hackathon. The project is a Mono repo project with the following client-side apps:

The Motivation behind Creating Cookied

We are a team of two developers who are passionate about building cross-platform apps. We have been using Appwrite for a while now and we love it. We wanted to build our next cross-platform app using Appwrite.

We had a lot of ideas about a project but we decided to build this bookmark manager app because there are no cross-platform solutions to "save" and sync your bookmarks across devices. Cookied is aimed to provide you with a way to save your bookmarks on mobile just like you do it on the web using any bookmark manager Chrome extension or a web app. But what's the issue with saving bookmarks on your mobile? Mobile browsers can not install Chrome extensions to save bookmarks. For that, we had an idea to use Android's "Send Intent" feature to send the URL of the current page of your browser to the Cookied mobile app to save the bookmark. Your bookmarks will be saved in Appwrite databases and you can access them from any device. Shortly we are going to roll out awesome features like:

  • Saving bookmarks for offline use

  • Online Text Search feature using Algolia to find bookmarks that you have saved (We often forget the name of the bookmark we saved but we still might remember some of the content of the page. Fuzzy search will help you find the bookmark you are looking for)

  • Similarly, for the offline Text Search feature, we will be using Fuse.js to find your offline bookmarks.

  • PWA support for Cookied web app

  • Better client and server state synchronization using React Query.

  • Better handling of Loading state using React Query's powerful cache management features

  • Importing bookmarks from your browser

Tech Stack and Libraries we used

The project is a mono repo project with the following client-side apps:

  • Appwrite Cloud

    • Authentication - Used Email and Password authentication

    • Database - Used Collections and Documents to store the Bookmarks and Folders

    • Cloud Functions (Node.js)

  • Next.js - for Cookied Web App

  • Expo (React Native) - for Cookied Android App

  • React (Vite) - for Cookied Chrome Extension

  • Other awesome libraries, tools and services we use:

What is Appwrite and how we used it

Appwrite is a BaaS solution backed by an awesome and very dedicated community. Check out their discord! Folks are super nice and helpful there.

We used Appwrite for Authentication, Database and Cloud Functions. Here following are the Appwrite services that we used and plan on using soon

  • Authentication - Used Email and Password authentication

  • Database - Used Collections and Documents to store the Bookmarks and Folders

  • Cloud Functions (Node.js) - We plan on using cloud functions to implement the following features:

    • Currently, we can not display some bookmarked webpages in the web app because we need some additional headers (`x-iframe-options`) to display the bookmarked webpage in an iframe. We plan on using cloud functions to proxy the request to the webpage and add the required headers to the response and send it back to the client.

    • When requested to save a bookmark for offline use, we will scrape a clean ad-free version of that bookmarked webpages to save them in the client-side local storage for offline use.

    • When a user deletes a bookmark folder, we will delete all the bookmarks and folders documents that are inside the folder that is being deleted via the event-triggered function

  • Storage - We plan on using storage to store avatar images of the users.

Challenges We Faced

There were a lot of challenges in the initial stages of building the project.

  1. The first challenge was to decide if it was a good idea to build a cross-platform app using a mono repo structure. We decided to go with it and setting up a mono repo was a disaster. We jumped from using Ignite CLI to custom yarn workspaces with Expo Development Build project (recommended way by Expo). Expo Yarn workspaces weren't bad at first until we found weird web-only errors (i.e. we weren't able to use fetch to fire API calls) because of which we were not able to use Appwrite Web SDK in the web app, and we had two options either to "drop the plan of creating a web app and focus only on the android application" or to find an alternative. And we finally found Solito. Solito provides a way to share UI and Navigation code between Expo and Next.js. It was a lifesaver.

  2. We have shared UI packages that are used by both the web app and the mobile app. But still, there were UI codes/packages that cannot be shared between the Web and Mobile app in Solito because we are not using the metro bundler to start bundling for the web, we use webpack in Solito for which we need to transpile the packages for webpack. We faced the following UI code-sharing challenges:

    • Authentication - Since Appwrite doesn't have any React Native SDK, we had to use the REST API to authenticate the user for the mobile app. But for the web app and Chrome extension, we used the Appwrite Web SDK. We use the REST APIs to make requests and store the cookie received from the Appwrite server in the Android's Async Storage to further use it for making authenticated requests. We know that storing cookies like this is not such a good idea, but we have planned to use expo-secure-store to store sensitive data in the future.

    • Theming - We love to use popular React Native packages like Shopify Restyle & React Native Paper for theming. But in our case, only Dripsy proved to be the best solution for us. We were able to use the same theme for both the web and mobile apps without showing any weird errors. The Dripsy theme works great for us now.

    • Icons - We could not share SVGs and SVG icons between the web and mobile app. So we had to use a separate icons library which provides the same icon packs for both web and mobile. We used react-icons for the web app and expo-icons for the mobile app. Both of them provide our favourite Material Icons. Although you might think that importing icons from both libraries would need a lot of code duplication containing platform-specific code, we import the icons using a custom Higher Order Component (HOC) which takes the icon name as a prop and returns the icon component such that even the important icons prop are almost same for both the web and mobile app with proper TypeScript support

    • Fonts - Fonts work differently on mobile as compared to the web. On the web, we can directly use the font family name "Poppins" to get all the font variants of Poppins (thanks to Google Fonts which provides us with the @font-face CSS file on the web). But in mobile, we have to create custom font family names for the same font. For example, we have to provide a font family name for each font variant of different font weights and font styles. For example have to use font family names like "Poppins_Regular", "Poppins_Bold", "Poppins_Italic" etc instead of just using "Poppins". We used expo-fonts to load the fonts in the mobile app and Google Fonts for the web.

  3. Building the Folder-Bookmark tree view Panel was a difficult job. To build the tree view we can not use the folders & bookmarks documents we receive from our Appwrite Databases because it is in a normalized shape. But, the fun part was when I used the usual recursive tree traversal algorithm to de-normalize the normalized document object from the Redux store in O(n) time. It was soo cool. Because of the well-thought-out HTML structure of the folder-bookmark tree view, we can easily implement a re-orderable drag-and-drop feature for the tree view (Not yet included in the MVP apps).

  4. Redux Toolkit - When talking about redux, some folks might think setting up proper actions and reducers needs a lot of boilerplate code. But the Redux toolkit makes it simpler by providing us with Slices and Entity Adapters. The learning curve to understand how redux works is not that steep but we had to put a little effort to learn and implement them. Redux is providing us with a great state management solution. We can perform easy CRUD operations on Redux Store just like a database on the front end.

    • When using Redux Slices with Entity Adapters, we can easily store normalized data in Redux via entity adapters which are specifically made for that purpose. Because of Slices, we get ready-made actions, reducers and selectors without boilerplate code.

    • Redux provides a way to write selectors which we require to derive data from the redux store. The selectors memoize the derived data and only recompute the data when the state changes.

    • Redux Persist is an awesome way to persist the Redux store in the Async Storage of the mobile app and Local Storage in the web app. We were able to avoid writing platform-specific code.

Cookied is an Open Source Project. Contributions are Welcome!

Cookied Projects' Public Mono Repo - https://github.com/ashuvssut/cookied

Following are the paths to the apps/packages in the mono repo:

Watch the YouTube Demo


We are thankful to Appwrite and Hashnode for providing us with this opportunity to build this project by organizing this awesome hackathon. We learned so much in this Event and we are excited to improve and level up this project and make it an amazing productivity tool for the folks out there! There are lots of features coming to improve the User experience! Stay tuned!

6
Subscribe to my newsletter

Read articles from Ashutosh Khanduala directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ashutosh Khanduala
Ashutosh Khanduala

I am a Android/Web developer. I use React Native, Next.js and TypeScript to make cool stuff. Checkout my GitHub: https://github.com/ashuvssut