<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ferhat Demir</title>
    <description>The latest articles on DEV Community by Ferhat Demir (@ferhat).</description>
    <link>https://dev.to/ferhat</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F353509%2F2cedc288-04fe-4fac-a142-e17d8d571ddf.jpg</url>
      <title>DEV Community: Ferhat Demir</title>
      <link>https://dev.to/ferhat</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ferhat"/>
    <language>en</language>
    <item>
      <title>Stripe Subscription Payments With Nest.js and Prisma — Part 1</title>
      <dc:creator>Ferhat Demir</dc:creator>
      <pubDate>Fri, 19 Jul 2024 08:37:12 +0000</pubDate>
      <link>https://dev.to/ferhat/stripe-subscription-payments-with-nestjs-and-prisma-part-1-177</link>
      <guid>https://dev.to/ferhat/stripe-subscription-payments-with-nestjs-and-prisma-part-1-177</guid>
      <description>&lt;p&gt;In this article, I want to share how you can implement a Stripe subscription using Nest.js and Prisma.&lt;/p&gt;

&lt;p&gt;First of all, I want to describe the Nest.js and Prisma;&lt;/p&gt;

&lt;p&gt;Nest.js is a powerful Node.js framework for building efficient, scalable server-side applications. It supports TypeScript, has a modular architecture, and a dependency injection system for easy maintenance.&lt;/p&gt;

&lt;p&gt;Prisma is a modern ORM with a type-safe, auto-generated query builder for interacting with databases. It includes tools like Prisma Client for type-safe database queries and Prisma Migrate for managing schema changes, making it a popular choice for JavaScript and TypeScript projects.&lt;/p&gt;

&lt;p&gt;We need a Stripe account for this implementation. Let’s create a new one from here. After creating the account, we will be redirected to the Stripe dashboard. Make sure the Test mode is on. Also, we can skip the setup steps for now.&lt;/p&gt;

&lt;p&gt;Then, let’s create Basic and Pro plans and their prices.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafvgvf2x6pncas55t36u.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafvgvf2x6pncas55t36u.jpg" alt="Image description" width="800" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwv8u8aro7i301yd5d914.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwv8u8aro7i301yd5d914.jpg" alt="Image description" width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have two products, the Basic and the Pro, and two pricing options for each plan: Monthly and Yearly.&lt;/p&gt;

&lt;p&gt;Let’s create a new Nest.js application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -g @nestjs/cli
nest new project-name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After creating a Nest.js application, create a &lt;code&gt;docker-compose.yml&lt;/code&gt; file in the main folder of your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;docker-compose.yml&lt;/code&gt; file is a configuration file containing the specifications for running a docker container with PostgreSQL setup inside. Create the following configuration inside the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3.8'
services:

  postgres:
    image: postgres:13.5
    restart: always
    environment:
      - POSTGRES_USER=myuser
      - POSTGRES_PASSWORD=mypassword
    volumes:
      - postgres:/var/lib/postgresql/data
    ports:
      - '5432:5432'

volumes:
  postgres:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To start the postgres container, open a new terminal window, and run the following command in the main folder of your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that the database is ready, it’s time to set up Prisma!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -D prisma
npx prisma init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a new &lt;code&gt;prisma&lt;/code&gt; directory with a &lt;code&gt;schema.prisma&lt;/code&gt; file. After that, you should see &lt;code&gt;DATABASE_URL&lt;/code&gt; the .env file in the prisma directory. Please update the connection string.&lt;/p&gt;

&lt;p&gt;Now, it’s time to define the data models for our application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#prisma/schema.prisma

model users {
  userId               String   @id @default(uuid())
  firstName            String?
  lastName             String?
  email                String?  @unique
  subscriptionId       String?
  subscription         subscriptions?
  customer             customers?
}

model customers {
  id         String   @id @default(uuid())
  customerId String
  userId     String   @unique
  user       users    @relation(fields: [userId], references: [userId])
}

model products {
  id          String   @id @default(uuid())
  productId   String   @unique
  active      Boolean  @default(true)
  name        String
  description String?
  prices      prices[]
}

model prices {
  id                  String              @id @default(uuid())
  priceId             String              @unique
  productId           String
  product             products            @relation(fields: [productId], references: [id])
  description         String?
  unitAmount          Int                 
  currency            String              
  pricingType         PricingType         // one_time, recurring
  pricingPlanInterval PricingPlanInterval // day, week, month, year
  intervalCount       Int                 
  subscription        subscriptions[]
  type                PlanType            // basic, pro
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I want to describe some values;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;unitAmount:&lt;/strong&gt; The unit amount as a positive integer in the smallest currency unit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;currency:&lt;/strong&gt; Three-letter ISO currency code, in lowercase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;pricingType:&lt;/strong&gt; One of &lt;code&gt;one_time&lt;/code&gt; or &lt;code&gt;recurring&lt;/code&gt; depending on whether the price is for a one-time purchase or a recurring (subscription) purchase&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;pricingPlanInterval:&lt;/strong&gt; The frequency at which a subscription is billed. One of &lt;code&gt;day,&lt;/code&gt; &lt;code&gt;week,&lt;/code&gt; &lt;code&gt;month&lt;/code&gt;, or &lt;code&gt;year.&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;intervalCount:&lt;/strong&gt; The number of intervals between subscription billings. For example, &lt;code&gt;pricingPlanInterval=3&lt;/code&gt;, and &lt;code&gt;intervalCount=3&lt;/code&gt; bills every three months.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's create the final model and describe some of its values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#prisma/schema.prisma

model subscriptions {
  subscriptionId         String              @id @default(uuid())
  providerSubscriptionId String?
  userId                 String              @unique
  planType               PlanType            
  user                   users               @relation(fields: [userId], references: [userId])
  status                 SubscriptionStatus? // trialing, active, canceled, incomplete, incomplete_expired, past_due, unpaid, paused
  quantity               Int?
  priceId                String?
  price                  prices?             @relation(fields: [priceId], references: [id])
  cancelAtPeriodEnd      Boolean             @default(false)
  currentPeriodStart     DateTime?
  currentPeriodEnd       DateTime?
  endedAt                DateTime?
  cancelAt               DateTime?
  canceledAt             DateTime?
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;cancelAtPeriodEnd:&lt;/strong&gt; If true, the subscription has been canceled by the user and will be deleted at the end of the billing period.
currentPeriodStart: Start of the current period for which the subscription has been invoiced.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;currentPeriodEnd:&lt;/strong&gt; At the end of the current period, the subscription has been invoiced. At the end of this period, a new invoice will be created.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;endedAt:&lt;/strong&gt; If the subscription has ended, the timestamp is the date the subscription ended.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;cancelAt:&lt;/strong&gt; A date at which the subscription will automatically get canceled.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;canceledAt:&lt;/strong&gt; If the subscription has been canceled, the date of that cancellation. If the subscription was canceled with cancelAtPeriodEnd, canceledAt will still reflect the date of the initial cancellation request, not the end of the subscription period when the subscription is automatically moved to a canceled state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We defined the schema. To generate and execute the migration, run the following command in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx prisma migrate dev --name "init"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We created the tables and their fields, but they are currently empty. Let’s create a seed file and populate the &lt;code&gt;users&lt;/code&gt;, &lt;code&gt;products&lt;/code&gt;, and &lt;code&gt;prices&lt;/code&gt; tables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#prisma/seed.ts

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

async function main() {
  await prisma.users.create({
    data: {
      firstName: 'Ferhat',
      lastName: 'Demir',
      email: 'edemirferhat@gmail.com',
    },
  });

  await prisma.products.createMany({
    data: [
      {
        productId: 'prod_QSkslDcBhj8y2Z',
        name: 'Basic Plan',
      },
      {
        productId: 'prod_QSktVsKo34GHYN',
        name: 'Pro Plan',
      },
    ],
  });

  // fetch the created products to get their IDs
  const products = await prisma.products.findMany({
    where: {
      productId: { in: ['prod_QSkslDcBhj8y2Z', 'prod_QSktVsKo34GHYN'] },
    },
  });

  const productIdMap = products.reduce((map, product) =&amp;gt; {
    map[product.productId] = product.id;
    return map;
  }, {});

  // create prices next
  await prisma.prices.createMany({
    data: [
      {
        priceId: 'price_1PbpgJKWfbR45IR7mYwUUMT9',
        unitAmount: 10,
        currency: 'usd',
        productId: productIdMap['prod_QSkslDcBhj8y2Z'],
        intervalCount: 1,
        pricingPlanInterval: 'month',
        pricingType: 'recurring',
        type: 'basic',
      },
      {
        priceId: 'price_1PbprLKWfbR45IR7HCZf44op',
        unitAmount: 100,
        currency: 'usd',
        productId: productIdMap['prod_QSktVsKo34GHYN'],
        intervalCount: 1,
        pricingPlanInterval: 'year',
        pricingType: 'recurring',
        type: 'basic',
      },
      {
        priceId: 'price_1PbPqgKWfbR45IR7L4V0Y7RL',
        unitAmount: 20,
        currency: 'usd',
        productId: productIdMap['prod_QSktvsKo34GHYN'],
        intervalCount: 1,
        pricingPlanInterval: 'month',
        pricingType: 'recurring',
        type: 'pro',
      },
      {
        priceId: 'price_1PbpQVlWfbR45IR7TBywWkkO',
        unitAmount: 200,
        currency: 'usd',
        productId: productIdMap['prod_QSktVsKo34GHYN'],
        intervalCount: 1,
        pricingPlanInterval: 'year',
        pricingType: 'recurring',
        type: 'pro',
      },
    ],
  });
}

// execute the main function
main()
  .catch((e) =&amp;gt; {
    console.error(e);
    process.exit(1);
  })
  .finally(async () =&amp;gt; {
    // close Prisma Client at the end
    await prisma.$disconnect();
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To execute the seed file, we should define the command on &lt;code&gt;package.json&lt;/code&gt; the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#package.json

"scripts": {
  // ...
},
"dependencies": {
  // ...
},
"devDependencies": {
  // ...
},
"prisma": {
  "seed": "ts-node prisma/seed.ts"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Execute seeding with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx prisma db seed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to create the necessary modules: Stripe and Prisma. We must also create an endpoint to listen to Stripe payment events.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Controller, Post, Req } from '@nestjs/common';
import { StripeService } from './stripe.service';

@Controller('stripe')
export class StripeController {
  constructor(private readonly stripeService: StripeService) {}

  @Post('events')
  async handleEvents(@Req() request) {
    console.log('Received a new event', request.body.type);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To efficiently develop and debug in the local environment, we need to install Stripe CLI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install stripe/stripe-cli/stripe
stripe login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Forward events to our endpoint. Then, trigger an event to verify that it is working correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stripe listen --forward-to localhost:3000/stripe/events
stripe trigger payment_intent.succeeded
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we should see the logs on the console.&lt;/p&gt;

&lt;p&gt;Let's start implementing the business logic and updating our data models.&lt;/p&gt;

</description>
      <category>stripe</category>
      <category>node</category>
      <category>prisma</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Let’s deploy the Web Application</title>
      <dc:creator>Ferhat Demir</dc:creator>
      <pubDate>Wed, 30 Aug 2023 13:50:53 +0000</pubDate>
      <link>https://dev.to/ferhat/lets-deploy-the-web-application-10c3</link>
      <guid>https://dev.to/ferhat/lets-deploy-the-web-application-10c3</guid>
      <description>&lt;p&gt;Hello, everyone. I want to share how we can deploy our Frontend and Backend applications in this article. I used React.js on the Frontend and Nest.js on the Backend side.&lt;/p&gt;

&lt;p&gt;First of all, I want to explain these terms;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Web Hosting&lt;/strong&gt;: Web hosting is an online service that makes your website’s content accessible online. When you purchase a hosting plan, you rent space on a physical server to store all the website’s files and data. I will use Hostinger in this article, but you can use other web hosting services like DigitalOcean, Contabo, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nginx&lt;/strong&gt;: Ngnix is open-source web server software designed to handle many connections simultaneously. It is a web server but is commonly used as a reverse proxy. It can be scaled efficiently as a web server and a reverse proxy. Ngnix also helps establish a secure connection between your data centers and the outside network. It works well as an HTTP load balancer that allows you to use multiple load-sharing mechanisms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PM2&lt;/strong&gt;: PM2 is an advanced process manager for NodeJS applications that allows you to start, control, or stop your node processes quickly. It runs as a daemon on the server and will ensure your app is available 24/7. Therefore, I will run our backend on the server using the PM2 command.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installing Nginx&lt;/strong&gt;&lt;br&gt;
First, I connect my remote Ubuntu server with SSH and run these commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update
sudo apt install nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After these commands, Ubuntu starts Nginx. The server should already be up and running. Open your browser and navigate to your server’s IP address to access the default Nginx landing page to confirm that the software is running correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configuring Nginx&lt;/strong&gt;&lt;br&gt;
Before the Nginx configuration, let’s clone our application to the /var/www/your_domain folder. You can initialize and set up the app in this directory, or you can clone the app from GitHub. I cloned it because my app already exists in my GitHub.&lt;/p&gt;

&lt;p&gt;Nginx on Ubuntu has one server block enabled by default that is configured to serve documents out of a directory at &lt;code&gt;/var/www/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then, let’s update the Backend .env file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;APP_PORT=3000
APP_URL=http://your_ip_address
BE_APP_URL=http://your_ip_address
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then, let’s update the Frontend .env file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VITE_PORT=3001
VITE_APP_URL=http://your_ip_address
VITE_BASE_API_URL=http://your_ip_address/api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: I did set a global prefix to my Nest.js app in start.ts using this command: &lt;code&gt;app.setGlobalPrefix('api')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And then, let’s build our Backend and Frontend applications.&lt;/p&gt;

&lt;p&gt;Now, we can continue to configure the Ngnix. Let’s run this command and open the Nginx config file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo nano /etc/nginx/sites-available&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We can configure it like this;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
 listen 80;
 listen [::]:80;

 root /var/www/your_domain/app/web/dist; #it's a build folder the frontend app
 server_name your_domain your_ip_address;

 location / {
   try_files $uri /index.html;
 }

 location /api {
     proxy_pass http://your_ip_address:3000;
     proxy_http_version 1.1;
     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Connection 'upgrade';
     proxy_set_header Host $host;
     proxy_cache_bypass $http_upgrade;
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let’s enable the file by creating a link from it to the sites-enabled directory, which Nginx reads from during startup:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;/etc/nginx:&lt;/strong&gt; The Nginx configuration directory. All of the Nginx configuration files reside here.&lt;br&gt;
&lt;strong&gt;/etc/nginx/sites-available/:&lt;/strong&gt; The directory where per-site server blocks can be stored. Nginx will not use the configuration files in this directory unless linked to the sites-enabled directory. Typically, all server block configuration is done in this directory and then enabled by linking to the other directory.&lt;br&gt;
&lt;strong&gt;/etc/nginx/sites-enabled/:&lt;/strong&gt; The directory where enabled per-site server blocks are stored. Typically, these are created by linking to configuration files in the sites-available directory.&lt;/p&gt;

&lt;p&gt;Let’s test to make sure that there are no syntax errors in any of your Nginx files:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo nginx -t&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And restart the nginx to enable our changes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo systemctl restart nginx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Nginx should now be serving your Frontend app. You can test this by navigating to &lt;code&gt;http://your_domain&lt;/code&gt;, or &lt;code&gt;http://your_domain&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let’s serve the Backend&lt;br&gt;
I’m installing the PM2 with NPM and starting the backend app.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pm2 start app.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install pm2@latest -g&lt;br&gt;
pm2 start /var/www/your_domain&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And let’s check the process using the pm2 ps command.&lt;/p&gt;

&lt;p&gt;Some definitions were sourced from this website &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-20-04" rel="noopener noreferrer"&gt;https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-20-04&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
