Matthew Rey

Zapper is a full-stack React Web Application built on top of the Next.js framework that replicates Twitter's features. This social media application has support for posting, retweeting, quoting posts, liking and replying as well as a home feed. The UI design is heavily based on the Twitter so that I can focus on the implementation of the features. Due to its highly dynamic nature, Zapper required a lot of front end and back end integration in order for it to work.

React
Next.js
Tailwind CSS
UI/UX Design
Typescript
Javascript
Prisma
Redis
React Query
Zod
Next Auth
zapper home

Project Goals

I started building Zapper in order to teach myself how to code and reason about complex dynamic web apps. The goal is to integrate a lot of necessities for a modern web app in real life such as authentication, database, caching, server side rendering, UI/UX and responsive design.

Frontend Design

Using React as the UI library of choice was a no brainer, as it is an industry standard and battle tested for a highly dynamic web app such as a social media application (e.g. Facebook). However, React alone does not solve web app problems such as routing, fetching and authentication. I thought about using React with libraries such as react router dom and react query in order to solve this.

But Next.js as a full-stack framework on top of React was an appealing choice as it had already integrated solutions for routing, fetching, and authentication which saves time and complexity than hand rolling your own solution. It also features paradigms such as Server Side Rendering(SSR) and server components which I thought were very handy in reducing load times and state management respectively.

React
Next.js
Tailwind CSS
zapper wireframezapper routing

CSS Framework and Design

For the CSS frameworks, I chose to use Tailwind CSS for its simplicity as I appreciate the colocation of CSS and JSX in one file which reduces context switching and allows me to just focus on writing the CSS needed to style my components and layouts. However for components with predefined behaviors such as dialogs, navbar or toasts I utilized the shadcn/ui component library as it provide these components and their behaviors out of the box but is built on top of Tailwind as well which makes integrating them quite easy.

zapper splashzapper userzapper compose

Backend Design

As Next.js was already a fullstack framework built on top of Node.js it already provided a way to deploy API routes through its Route Handlers feature, so there was no need for me to deploy a separate backend server such as using Express.js. However, I still needed a database to store my data. I chose PostgreSQL as I have some experience working with it before and I also liked its structured paradigm compared to something like a NoSQL db such Firebase or MongoDB as you needed more database experience in order to properly define your own database structure in those NoSQL paradigms.

In order to simplify my backend, I also integrated Prisma as my ORM because it provides both simplicity and typesafety in my database queries. One downside of using Prisma is that the queries it generates are typically less efficient than handwritten ones, but in this case on a small scale app, I judged that to be a non-factor compared to the development time I save. Finally, I added a Redis in memory cache to speed up my queries and to split up my load between Redis and the Postgres database.

zapper system

Lessons Learned

I learned a lot on this project such as complex routing(dynamic, parallel, intercepting) and proper database querying. One thing that stood out though is that I learned how hard is it to properly cache and invalidate the cache on my fetches and queries. Also, my initial database schema was not complete, so I had to refine and migrate my schema as I worked on the project. If I had to start all over again, I would increase my time spent on the initial planning and modeling as it's gonna save a lot headaches later on in the project's development.