logo

Organo

Explore
Organo

Intro

This is a full stack web app developed with React.js and Tailwind for the frontend and Node.js, Prisma, PostgreSQL for the backend. Frontend is hosted on Vercel and the backend on Render. The hosting is made completely on free tiers, so it's a bit sluggish.

Dealing with the backend

I decided to use some common frameworks and libraries for this project.

The folder structure is the following:

  • helpers: only contains a function to improve Prisma performance
  • prisma:
    • schema.prisma: defines tables of the database
    • migrations: contains a list of all the migrations executed by Prisma, this is really helpful if something goes wrong
  • routes: this folder contains every API endpoint that needs to be served to our frontend
  • types: having types is really helpful while developing our app
  • app.ts is our entrypoint

The app.ts

In our entrypoint we have to specify which http addresses are able to execute requests, otherwise our backend won't be of any help.

app.use(
  cors({
    origin: ["http://localhost:5173", "https://organo-frontend.vercel.app"],
    credentials: true,
  })
);

In our case we have our development build at http://localhost:5173 and the hosted production build at https://organo-frontend.vercel.app.

Then we need to specify which API endpoint to expose for our frontend with the following syntax:

// app.use("/api", apiRouter)
app.use("/users", userRouter);
app.use("/foods", foodRouter);
app.use("/menus", menuRouter);
app.use("/orders", orderRouter);
app.use("/orderItems", orderItemRouter);
app.use("/invoices", invoiceRouter);

Where apiRouter is the imported Express router defined in the correct routes folder.

Prisma ORM

We can use Prisma ORM to manage our database and easily create queries.

On the official docs there's also a section on deploying Node apps, and how to optimize performance. We can create a single PrismaClient instance and reuse it on our codebase, this is done in the prismaHelper.ts file.

Creating the API endpoints

Every file under the routes folder is an API endpoint following the REST guidelines. We start by importing the PrismaClient ORM utility library and then we will use it to perform the ususal CRUD operations and query our Postgres DB.

Some of the most used Prisma methods are:

  • prisma.table.create(): used to execute the Create operation
  • prisma.table.findMany(): when we need to query the DB and return multiple records
  • prisma.table.findUnique(): when we need to query and return a single record

To create complex queries we use a mix of this methods.

Dealing with the frontend

Our frontend is built on top of the usual React.js and Vite boilerplate with Tailwind for styling our components. We are also using Redux Toolkit and RTK Query to manage the app state.

The folder structure is pretty standard, with the src folder having the following content:

  • assets: this folder contains our images and svg illustrations
  • components: contains some reusable objects like the Cards used to display foods
  • pages: these are the pages of our application, the React Router is pointing to these files
  • routes: contains React Router setup
  • store: used for our Redux Toolkit state management

State management hell

State management was one of the hardest things to handle, I think the React and Redux way of approaching this problem is overcomplicated for a small web app like this, but it could be helpful to learn the basics for some larger production level website.

We can use the RTK Query library to handle the requests to our backend, it should also improve performance by caching results.

The Cart and User authentication persistence are handled by React Toolkit, and we also use the localStorage to save this data so that at the browser restart we don't have any loss.

Deploying

Deploying the frontend React app was a breeze with Vercel, on the other hand finding the right platform for the backend was a bit more difficult. The big problem was finding something for the PostgreSQL DB, usually no ones has a free tier for DBs now that Heroku cancelled their plan. Finally the only decent option we found was Neon.

Since everything is deployed on free tiers, the application takes ages to load images, maybe the next step could be to convert a raspberry pi and store the full backend+database there.