Introducing Pckd - The most powerful 💪 URL shortener
Tags: azuretrialhack, node, javascript, react
Published: 2022-03-03 12:01:45

## Overview of My Submission

This month, I saw the Azure + Dev.to Hackathon 🤩 and immediately knew I found the excuse to spend my time bringing my prolonged idea to life.

## What exactly is 🔗 [Pckd](https://pckd.mohityadav.codes/devto-demo/)?

![Intro Video](https://cdn.hashnode.com/res/hashnode/image/upload/v1646134353427/XxF1QtA0N.gif)

Have you ever wanted to share a long link with a friend, but it seems way too long to send through a message (maybe it's a base-64 image URI), so you might turn towards URL shorteners, nothing special?

But try to imagine, along with the shortening functionality, what if you could have a lot more. I mean, track all the clicks (or hits) on the URL that you shortened and get very-deep insights about the person who clicked it, like:

- Their 💻 device information, including model, operating system, etc.
- Their 👩‍💻 browser name and version
- Their 🌎 IP location, along with their ISP name, their city, rough coordinates, etc.

And much more! 🤯

And to add the cherry on the top, you could host it yourself on your custom domain! In fact, it was created to be self-hosted, for people on the [self-hosted community](https://www.reddit.com/r/selfhosted/)

Doesn't that sound like the time to switch from Bitly and stop paying [the premium](https://bitly.com/pages/pricing), or being limited by 100 links/month?

## Submission Category

**Computing Captains**: Since this app is hosted on an azure virtual machine.

## Creation process 👩‍🎨

The creation process was undoubtedly the most fun part of the project. I solved many new challenges, learnt a lot, and finally came up with an application I was proud of! Here is how I pulled it off...

### Designing 🎨

Usually when I create a pet project, I just use the designing from the previous projects I was working on, since they won't get noticed anyway. But with this one, I wanted it to reach to the top of the list of open source URL shorteners. I had self-doubts about whether I would be able to reach the goal with my experience, but you are [free to judge](https://pckd.mohityadav.codes/devto-demo).

#### Inspiration ✨

So, I started by looking for inspiration. The best place for this was [Dribbble](https://dribbble.com). I went to the inspiration tab. Many people would create the best design they could without any inspiration, but as Pablo Picasso (may have) said:

> Good artists create, great artists steal

That's one way to put it, but the point is: with the amount of design experience and the height of the goals I had, I just wasn't going to be able to create a good-enough design overnight if I started from scratch. Hence, the searching.

![Dribbble.gif](https://cdn.hashnode.com/res/hashnode/image/upload/v1646102675914/EhT8sPZ-Q.gif)

After endless scrolling, similar-sounding keywords and hard-to-make choices, I decided to go with [this design](https://dribbble.com/shots/15223174-Project-Management-Dashboard-UI-Exploration), because it just looked great for the purpose I was looking for. There were many fancy ones too, but they just weren't practical, or too flashy for the typical programmer that was going to host it (if Pckd was even going to be successful).

#### Customizing 🍕

The [original design from Dribbble](https://dribbble.com/shots/15223174-Project-Management-Dashboard-UI-Exploration) was good, but it wanted something more, like the colour customization, planning out exactly where everything would go, and creating an exact mock-up of how the app would look and much more. Therefore, everything was already planned out before I touched any code.

I find this approach very useful, because you don't have to scratch your head over minor details that would otherwise go unnoticed while planning, and you have to go to the sketch board all over again if you've started coding.

##### Dashboard 💾

I again went on to Dribbble to find some dashboard designs. I got some that caught my attention. After that, I went to Figma and started laying out the design

After endless scratching of heads, I got this:

![dashboard.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1645203739109/Vz2jIS6iP.png)

(One of my proudest creations 😎)

##### Other pages 🗞

As for the other pages, I created the homepage out of just my imagination. Here's how it looked:

![home.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1645205140834/ZTdNk6J4bS.png)

And the signup pages:

![signup.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1645205192611/ffTQwK1Zn.png)

The designs looked good in my opinion, and I was dead-set to implement the most design-accurate version of this with react and try to not mess up the margins or paddings somewhere. This marked the end of the designing and planning part of the app. 
Not bad, right?

### Setting up the backend 🧩

For the backend, I started out by forking a [backend template repo](https://github.com/Just-Moh-it/grapqhl-nextjs-template) (made by me ;), because it contains a file-based structure, just like NextJS, but for the backend. It also has authentication baked in, so one doesn't have to go through the hassle of setting everything up.

#### The database schema 💾

OK, I want to have a `hits` table, a `user` table, and..., and that's it. Oh! Forgot the `pckd` table, the main one! After all these thoughts back and forth in my mind, I was ready with the following database schema

![structure.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1646105302582/ism9BSqmU.png)

I created the database through the [Prisma](https://prisma.io) schema, and it ended up working great.

#### The file structure 📁

This is how the finished file structure looked like:

![Screenshot 2022-03-01 at 8.00.42 AM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1646101860667/oeGiAjkMt.png)

Adding a new route was just as easy as creating a new file in the directory, like for the `user` type, `api/User/index.graphql` file needed to be created. This is how it looked like:

```gql
type User {
  id: ID!
  pckds: [pckd!]
  name: String!
  email: String!
  createdAt: String!
  updatedAt: String!
}
```

And For the resolving the users' `pckd` logic, in the `api/User/index.js` file:

```js
module.exports = {
  User: {
    pckds: async (parent, args, { prisma }) => {
      const pckds = await prisma.pckd.findMany({
        where: {
          userId: parent.id,
        },
      });
      return pckds;
    },
  },
};
```

As simple as creating an export file. You should definitely try this method of creating backends out. Little boilerplate, powerful APIs. 😃💪

#### Achieving this functionality ⛽

For combining the files and graphql schemas, and create a single instance of `typeDef` and `resolvers`, I used the following code

```js
const path = require("path");
const { loadFilesSync } = require("@graphql-tools/load-files");
const { mergeTypeDefs, mergeResolvers } = require("@graphql-tools/merge");
const { makeExecutableSchema } = require("@graphql-tools/schema");

const typeDefs = loadFilesSync(path.join(__dirname, "/api/**/*.graphql"));
const resolvers = loadFilesSync(path.join(__dirname, "/api/**/*.js"));

const schemaWithResolvers = makeExecutableSchema({
  typeDefs: mergeTypeDefs(typeDefs),
  resolvers: mergeResolvers(resolvers),
});

module.exports = schemaWithResolvers;
```

This would combine all the files ending with the `.js` and `.graphql` extension from the `api` and it's sub-folder into a single `typedef` and `resolvers` variable, and export them as `schema`.

### Querying the backend 💬

For those who are new to GraphQL or haven't used apollo GraphQL before, Apollo provides a great interface for testing and creating queries, just like postman, but for Graphs, and much more powerful.

And creating APIs with GraphQL never gets easier

![never gets easier.webp](https://cdn.hashnode.com/res/hashnode/image/upload/v1646104502429/3Z3YJd5HV.webp)

### Setting up the frontend ⚛

For the frontend, I used React with the Create-react-app template, because it was easiest to work with, and I didn't use NextJS because the app didn't have much about SEO.

Along with react, I used Redux, and Apollo-graphql-client to query the backend, because the global state was shared across multiple components. Also, I wanted to learn Redux, and what other way to learn than to implement it yourself. (But it turned out to be an overkill 😅).

The typical React development pattern continues... At the end, I had a polished URL-shortener application that was fully customizable (upto the name) and ready to be deployed. Let's go!

## Hosting it

For hosting the web app, I used azure VMs, as per the instructions. I created a B2s virtual machine, installed nginx, MySQL, NodeJS, NPM and cert bot, then ran the NodeJS server.

![Azure Portal Screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/txqlt5ul8qynqkf9cx6f.png)

The React frontend was built to a static file, which the backend served itself. I only had to set up a nginx proxy pass to redirect internet traffic from external port 80/443 (the web traffic port) to internal port 4000 (NodeJS server port).

Here is how my `default` configuration file looked like:

```nginx
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        server_name _;

        location / {
                proxy_pass http://127.0.0.1:4000/;
                proxy_http_version 1.1;
                proxy_set_header Host $host;
                proxy_cache_bypass $http_upgrade;
                proxy_pass_header  Set-Cookie;

                proxy_set_header   Host               $host;
                proxy_set_header   X-Real-IP          $remote_addr;
                proxy_set_header   X-Forwarded-Proto  $scheme;
                proxy_set_header   X-Forwarded-For    $proxy_add_x_forwarded_for;
        }
}
```

(The SSL part is not included). Then I exposed the ports 80 and 443 from the azure portal, and the app was open for the world to access.

## Try it yourself

Here are some useful links you would need:

- 🚀 Project Demo - https://pckd.mohityadav.codes/devto-demo
- 🐱 GitHub Repo - https://github.com/Just-Moh-it/pckd

I hope you liked the blog. If you did, please leave your thoughts in the comments. It would make my day.

Till then, happy 💻 coding! 🍿