skip to content
Samuel Edwin's Website

Fullstack portfolio

/ 4 min read

What this project is about

The goal of the project is to give an overall feel of how I implement a fullstack application.
I don’t aim to build a fully functioning eCommerce application because it will take too much time to implement.

You can give it a try directly here

Without further ado, let me give you a tour of the things I build.

Tech stacks

  • Next.js App Router, created with create-t3-app.
  • TypeScript.
  • Clerk.
  • MySQL hosted on PlanetScale.
  • DrizzleORM.
  • Supabase for image storage.
  • Vercel for deployment and hosting.
  • tRPC and React Query to communicate with the backend safely.
  • react-hook-form for everything form related including validations and submissions.

Features

Home page

I’m not sure what to put in here so I just show random products as recommendations instead.

Home page

Search page

Search is something common in today’s websites especially when the website has a lot of stuffs to show.
Every search settings are configurable through search params, so the users can share their search results with friends.

Here’s the link if you want to search for tvs between $100 and $1500, sorted by the most expensive price https://fullstack.samueledwin.com/search?q=tv&min=100&max=1500&n=1&s=p_desc

Search page

Shop page

This page shows the products and catalogs of this shop.

App Router’s nested layout capability really shines here.
I can create a sidebar layout with ease.
The layout section can also load the catalogs, leading to a cleaner and isolated code.

Shop page

Product page

This one is pretty straightforward. Load the product from database and render it straight away.
There’s an “add to cart” button but I don’t have the time to implement it for now.

In order to score a high lighthouse score, I use Next.js sizes prop to generate smaller images for mobile screens.

Product page

Shop management page

This page lets the users manage their shop, products and catalogs in their own separate pages.
The sub pages of this page contains a lot of form handling and interaction.

Product add/edit

Edit product

Edit shop profile

Edit shop

Catalog add/edit

Edit catalog

Authentication, authorization

Although this is a portfolio project, I do my best effort to secure my app from malicious inputs.
I treat the security aspect the same way I treat production servers.

Every input has limits:

  • Strings have to be in a certain length, and whitespace trimmed.
  • Numbers need minimum and maximum value. Often times they also need to be positive numbers.
  • Image uploads have the format and size limits set on Supabase. They are also resized on upload.

Basic authentication and authorization also applies here:

  • Users need to log in to access their shop management page.
  • Users can only modify their own shop data, products and catalogs.
  • Only logged in users can upload images.

Aside from these, there are also validations that are specific to each feature.

Product add/edit form

  • Stock is optional, but when filled it will be validated making sure it is integer and not negative.
  • Users cannot have more than 20 products at a time.

Catalog add/edit form

  • All products in the catalog must be owned by the shop.
  • User cannot have more than 10 catalogs.

Performance

Next.js allows me to get high lighthouse score by default.
I get all greens on the Desktop site, and a mix of greens and yellows on mobile.
Most of the yellow scores come from LCP since I show a lot of images. Gonna fix this later. Here’s the report for some of the pages such as home, search, shop, product.

Lighthouse score

Bot and spam prevention

I use Cloudflare Turnstile to minimize bots and spams.
Combined with Clerk’s built in bot protection, it should be difficult enough for bots to fill my data with garbage.

Empty list, nonexisting items

Developers tend to forget to handle edge cases. If a page is showing a list of something, and also showing a detail of something, then most likely it will need to show an empty state.

I don’t have fancy design or anything like that.
Showing a clear error message is usually good enough for the user.

Empty search result Shop not found

Filling test data

This app initially contains around 10 shop and 100 products which will be tedious to fill manually.

What I do instead is use LLMs to generate the shop name and categories of items, then use that to generate a list of products with images.

Other things to implement if I have the time

Responsive design

Some pages are already responsive, though many aren’t yet.

Mobile lighthouse score

Mobile version needs some tweaking to get a better score.
Most of the pages on mobile can be improved by:

  • Using smaller images on mobile.
  • Reducing bundle size and lazily load JS using Suspense when possible.

Nice to have features

I’d love to add some smaller features that don’t take too long to implement later.

Conclusion

I hope you enjoy this small writeup that I made for this project, thank you for reading :)