Zikun Wang 王紫坤

Ghostly

Big shoutout to my wonderful teammates: Sharon Zou, Tyler Nguyen and Christopher Cho! Link to their corresponding Github account:

Scope

I recently built a Reddit replica as a school project with a team of four, which allowed me to experiment with new services and libraries. This article is ranting about everything I learned from this experience.

Since this is a school project, I want to build something fast and dirty, meaning I was thinking about how to make a specific function work quick instead of the implications in production. Therefore, I only considered something that requires a little time and effort (in this case, ChakraUI over TailwindCSS). Later on in the project, this decision did haunt me. Honestly, this is probably not a good way to start something complicated.

The project

You can play around with the demo go here -> Ghostly Demo. (I broke the backend at some point so it is no longer working.)

If you wanna see our bad source code go here -> Github repo

The project is a Reddit ripoff where users can join and post random stuff inside communities. To use this website, the users must first log in using their Google Account.

Login Page

After the user logs in, they can explore the community page freely.

Logged in user

The users can browse any content inside all the communities. They are required to join a community before posting in it:

Community Page

To post anything, the user can share either a Youtube URL or / Google Book URL, and the website can parse the information using the corresponding API (This is the part that spends most of the time).

Posting

After submission, the post appears on the list, and the user can delete the post by clicking on the little trash can button in the upper-right corner.

User post and deletion

The stack

The stuff I used in this project:

Next.js

Next.js provides all the functionalities I need for the front and backend. Next.js comes with many handy built-in functionalities like routing and incremental static regeneration. I can easily incorporate the authorization part of my code on the server side and make individual requests from the client side.

Server-side-rendering also provides benefits such as incremental static regeneration. For example, I only need to request some of the communities on my server every time someone loads the homepage. I can ask for this information every five minutes and cache it on my Next.js server. This limits the number of requests I need to my backend.

Ultimately, Next.js is the most reliable framework to work with React. Especially when compared to the state of create-react-app (which caused me a lot of trouble in my other projects). There exists hardly any replacement for it.

Vercel

Really is nothing more to say here. Vercel provides fast deployment for my Next.js project, and I can link it directly with my Github repository. Whenever a commit/merge is made on the repository’s main branch, Vercel auto-compiles the main code and sends me an email that the website is updated. (These emails get annoying really quickly.)

vercel

Firebase

Firebase is a collection of general tools that Google provides for web development. I mainly used Google OAuth and Firestore. Google OAuth is convenient. My main complain was firestore as my database.

Like its peer MongoDB, Firestore is a document database compared to a traditional relational database (PostgreSQL, MySQL, etc.). It has two types of data in general: collections and documents. In simple words, collections contain multiple documents, each documents with its own fields and sub-collections. Firestore provides APIs that vastly simplify the process of querying certain data:

export async function getUserInfo(uid) {
  const ref = doc(firestore, `users/${uid}`);
  const docSnap = await getDoc(ref);
  return docSnap.data();
}

However, the problem happened when our system grew in complexity. Everything is relational in its nature. Let’s take the posts as an example. A post needs to contain the following data:

  1. The community it belongs in.
  2. The user who posted it.

This information must reference each other somehow. Yet, we cannot join tables like in traditional SQL language. Querying this extra information takes extra time and requests. (Remember, we have to do this for every single post) It might take hundreds of requests to get what a simple SQL query can do. Hence, later on in the project, I store every extra information inside the document, knowing what I’m doing creates duplications everywhere.

This is just a flawed system. What’s worse is that Firebase does not provide any form of full-text searching, and we must incorporate a third-party search engine to do the task for us.

Like, come on, you are Google. Searching should not be a problem.

To conclude, Firestore’s convenience comes with a cost. Documentation databases simply could not handle the most applications’ complexity. It is better to start with a SQL database.

ChakraUI

ChakraUI is something that made me have conflicted feelings. On the one hand, making something using Chakra is so fast and convenient. Most of my components in the project look something like this. I barely wrote any CSS during this project:

<Center>
    <Card maxW='md' bg="gray.50" mt="10" p="10" mb={5} border="1px">
        <CardHeader>
            <Center>
                <Heading size='lg'>
                    {!username ? "Login" : `Welcome, ${username}!`}
                </Heading>
            </Center>
        </CardHeader>
        <CardBody>
            {user ? 
                !username ? 
                <UsernameForm /> : 
                <SignOutButton username={username} userPic={user?.photoURL}/> : 
                <SignInButton />
            }
        </CardBody>
    </Card>
</Center>

Components like <Center>, <Card> or <Heading> are all from ChakraUI. I need to set the size, color, margin, and padding from time to time. This saves us a lot of time to skip most of the front-end design and focus on the actual functions.

However, there is a significant drawback of ChakraUI: Chakra is nothing like CSS. Like Bootstrap, Chakra has its own design system. (Even with its own hook to handle some simple situations) This means that learning Chakra does not help me improve at other design frameworks. Considering the learning front was not my focus this time, I will let this one pass.

Express.js

A standard RestAPI server is used to access Youtube and Google Book APIs. I could incorporate it in my Next.js, but my school assignment requires me to have a backend server, so I have it. It is hosted on a separate Vercel project.

Some takeaway?