Rev
Video preview

Short Explanation

Vivat marketplace

Project Goals

 

Tech Stack Used

This project consist of a mobile app where user can interact to and an admin dashboard web app where admin can manage stuff.
For the mobile app it utilizes React Native with Expo to build powerfull multiplatform mobile app, Zustand for state management, Typescript for strong typing. React Query to handle data fetching and caching, Nativewind for Tailwind CSS implementation on mobile for easy styling, Expo Router for easy navigation as it also has file-based routing.
For the admin dashboard web it utilizes React with Next.js, and shadcn/ui with Tailwind CSS delivering a quick and easy-to-use interface

Spotlight

In the development of the Vivat Marketplace project, several technologies played a pivotal role and deserve to be highlighted. Let's delve into these key players: Expo, Clerk, Monorepo, and tRPC.

Expo for React Native development

Expo is a powerful tool that we used in the development of the Vivat Marketplace mobile app. It simplifies the React Native development process, offering an environment where we can build a multiplatform mobile app swiftly and efficiently. I can construct the entire app for testing using their cloud infrastructure. This way, I won't exhaust my computer's resources with Android Studio.

Easy authentication with Clerk

For both the mobile and the web app of Vivat Marketplace, we used Clerk for authentication. Clerk provides an easy and effective solution for user authentication, saving us from the complexities of building our own system.

Monorepo

The Monorepo approach was adopted for the Vivat Marketplace project, allowing us to manage the codebase for the mobile and web apps under a single repository. This not only streamlined my workflow but also made it easier to maintain consistency across the project.
notion image

Fully typesafe API with tRPC

tRPC offers a powerful and efficient solution for building typesafe APIs in TypeScript. It simplifies the process of defining API endpoints and handling client-server communication. By leveraging the strengths of TypeScript’s static type checking, tRPC ensures type safety throughout the development process, reducing errors and improving code quality.
Using a monorepo, it's easy to make API calls from either the mobile repository or the admin dashboard repository. Here's an example of making API calls to fetch a list of products from the mobile apps.
const { data, isFetching, refetch } = api.product.getProducts.useQuery({ query: debouncedSearch ?? "", categoryId, sellerId, });
On the backend, the required code is as follows. This will be accessible via both mobile apps and the admin dashboard.
export const productRouter = createTRPCRouter({ getProducts: protectedProcedure .input( z.object({ query: z.string(), categoryId: z.string().uuid().optional(), sellerId: z.string().optional(), }) ) .query(async ({ input, ctx }) => { return await ctx.db.query.products.findMany({ columns: { id: true, name: true, image: true, price: true, approved: true, stock: true, }, with: { seller: true, }, orderBy: (products, { desc }) => [desc(products.createdAt)], where: (products, { like, and, eq, gt }) => and( like(products.name, `%${input.query.toLowerCase()}%`), ...(input.categoryId ? [eq(products.categoryId, input.categoryId)] : []), ...(input.sellerId ? [eq(products.sellerId, input.sellerId)] : [gt(products.stock, 0), eq(products.approved, true)]) ), }); }), });

The Problems and How I Solved It

 

Lesson Learned