mbosnjak

mbosnjak

Flashcoll - platform to share your github projects and find collaborators

Flashcoll - platform to share your github projects and find collaborators

Subscribe to my newsletter and never miss my upcoming articles

Listen to this article

Intro

Hello. Let me introduce Flashcoll, platform to feature which of your projects is looking for collaborators. This project is part of Clerk&Hashnode Hackathon.

Github repositories:

Idea

The idea for this app came to me as an issue I had long time ago when I was first starting with web development. For a complete beginner with ideas and hunger to learn I didn't have any tool at my disposal to find somebody to collaborate with on my ideas. This app was in my thought for a long time and now it is finally coming into realisation. While still being rough on the edges it accomplishes what it was built for.

As social networks are nowadays extremely important to connect with other people around the world, or even locally, I thought of having a user profile that will consist of both github projects and social network links. As an addition, there are also few buttons to share the project instantly on social networks.

Tech

Technologies used in this project:

Frontend:
Backend:
  • Node.js
  • Fastify -REST API server
  • HarperDB - Database
  • Github API - To fetch GH user and his repositories
  • Octokit - Library to utilize github api
  • Clerk - To fetch some user data from backend
  • Glitch - Hosting platform

How it works

Requirements

First and main requirement to log in or sign up in Flashcoll is to have a github account. If you do not have github account, go ahead and create one. Secondly, you need to create a repository for your project. It is important to remember that Flashcoll will only pull your public repositories. If you're wondering why that is, well, private repository would lose purpose of being private if it is publicly displayed elsewhere.

Flashcoll pulls and renders your repository README.md file and About description so it is very important to write up those first. In About description you write short description what is your project about, and in README.md file you describe your project in details.

It is important to do those few steps first in order to use Flashcoll full potential.

Under the hood

Flashcoll utilizes Clerk auth system along with your github account. When you log in or sign up with your github account in Flashcoll application, basic user data required for your Flashcoll profile is inserted in HarperDB database. This process involves fetching user data from a backend to fetch github provider data that Clerk stores in its user object. Then required data for the app is inserted into database subprofile table like github username, id, profile link, image link.

Reason why this data is stored in database is so we can lower the amount of github api requests user sends from the app under the hood. That way application does not spend Github API request limit rate too fast. Limit rates are explained further through this blog post.

Flashcoll is build heavily on asynchronous loading.

Working on the app

In the beggining it was much harder to start with Clerk for me with Angular than for React users. Clerk came up with React components first to others were left to use Clerk vanilla js. It took a lot of debuging with console.log and reading global window object as Clerk object lives there. It took a lot of time reading through data that clerk returns on sign-up/sign-in.

After that it was time to create some clerk service. After a while services wereproperly made with the help of Clerk team members.

As my application requires usage of backend, that was one extra job to tackle down:

  • Set up the repo
  • Create Fastify server
  • Test Github API with Postman . . . And I had to test it a lot to read what data is returned from request

These are all really small tasks, but when you gather larger amount of such tasks those could definitelly take a lot of your time. But, it is necessary, so let's not think that it's a bad thing.

There were certain issues with backend as well. Github APi has request limit per hour both for unauthorized and authorized requests. One user can do 60 unauthorized requests per hour or 5000 authorized requests per hour. One major issue with auth request was, on certain moment my server stopped sending authorization header with auth token which made app not work properly.

After a lot of debuging, I implemented Octokit, library made for github requests which saved the day . . . for now.

Downside of this is that I have to ocasionally check on token rate limits and expiration dates.

This is where you can create your own OAuth tokens (https://github.com/settings/apps):

image.png

The unfortunate thing is because of too much testing I lacked some time to create a little bit smoother design. But, as app will continue to live after the hackathon, I plan to continue working on it. I will also post updates about it on hashnode.

Showcase

Sign in / Sign up

image.png

Logged in user action image.png


NOTE: My Networks button does not originate with Clerk. I implemented it as a subprofile management feature. I could've gone with another solutions but it seemed like a cool experient at the time so eventually I kept it as a solution.

Here's an implementation

  • function to generate SVG icon
    createSvg() {
      let svgImage = document.createElement('img');
      svgImage.src = 'assets/images/socials-icon.svg';
      svgImage.style.width = '2rem';
      svgImage.style.height = '2rem';
      svgImage.style.order = '-1';
      return svgImage;
    }
    
  • function to generate button

    createSocialsSettingsButton() {
      let buttons = document.querySelector('.cl-component.cl-user-button-popup')?.children[1].children[0];
      buttons?.children[0].classList.add('order-1');
      buttons?.children[1].classList.add('order-3');
    
      let newButton = document.createElement('a');
      newButton.id = 'socials';
      newButton.classList.add('_3bDedxNjPBtkn-BuP2nhY2','_11ZVSe2vGmcrGqZUhdWgXB', '_3roVnjNLYXA8oyjSMR_tyO', '_2eZklRe9WnyPiLM2T0R6XG', 'cl-accounts-manager-button', '_1WVBqxUEPjqhMKyLv7b558', 'order-2');
      newButton.style.display = 'flex';
      newButton.innerHTML = 'My networks';
      newButton.href = "socials";
    
      newButton.appendChild(this.createSvg());
      buttons?.appendChild(newButton)
    }
    
  • code where function was called, inside timeout interval backed up with comments why was it put there

    ngAfterViewInit(): void {
      this.clerk.user$.subscribe(user => {
        const authButtons = this.authButtons?.nativeElement;
        const loggedInActions = this.loggedInActions?.nativeElement;
        const userLoggedInActions = this.userLoggedInActions?.nativeElement;
        const el = this.userAction?.nativeElement;
        if (!el) {
          console.log('Can not fetch native element for user action!');
          return;
        }
    
        if (!user) {
          this.clerk.unMountUserButton(el)
          authButtons!.style.display = 'flex';
          loggedInActions!.style.display = 'none';
          userLoggedInActions!.style.display = 'none';
          return;
        }
        this.userName = user.firstName;
        authButtons!.style.display = 'none';
        loggedInActions!.style.display = 'flex';
        userLoggedInActions!.style.display = 'flex';
        this.clerk.mountUserButton(el);
        setTimeout(() => {
          // Appending new button to user action because component loads faster than user action button can fetch all elements on component init
          // Delay of 1ms is needed to fetch the rest of user action elements so those could be targeted with javascript
          this.createSocialsSettingsButton();
        }, 1);
        this.harperDbService.generateUserSubprofileIfNotExist(user!.id);
        this.harperDbService.getUsernameFromSubprofile(user.id)
          .then((result) => {
            this.githubUsername = result
          });
      });
      console.log(this.githubUsername)
    }
    
  • Social networks

image.png

  • Create new project

image.png

  • Project details

image.png

  • User profile

image.png


Note that URL parameter for Flashcoll user profile is very similar to Github. For example:

  • Github: https://github.com/mbos2
  • Flashcoll: https://www.flashcoll.com/profile/mbos2 Same username is used in both apps.

Thank you note

I want to thank to Clerk team who were really helpfull to everyone who asked for help on their Discord channel regarding all kinds of issues. I also want to thank to everyone else who helped discovering small app issues by testing the app and for all suggestions they brought to the table during that time.

Conclusion

That wrapps up Flashcoll. Should you have any feedback or questions I would love to hear it. There are several ways to do so:

Also consider buying me a coffee if you like the app, idea or would like to see more content from my blog. %%[buy-me-a-coffee]

 
Share this