DEV Community

Cover image for Attaching database to static site on Next.js and Vercel
Moeki Kawakami
Moeki Kawakami

Posted on • Updated on

Attaching database to static site on Next.js and Vercel

I recently added a like button to my website.

Image description

In the past, if I wanted to add a little database processing to a static website, I either had to change the app implementation from a static site generator to a server-side framework like Ruby on Rails, or I had to have another DB server and hit API. Site functionality affected the entire architecture.

However, this experiment made us realize that Next.js and Vercel have a very application-first philosophy that can extend the functionality of a website without major architectural changes.
This is largely due to the fact that Vercel is able to receive the Rest API with Serverless Function.

Let's see.

First, we will implement the UI.

import { useState } from 'react'
import { MdThumbUp } from 'react-icons/md'

export default function Component(props) {
  const [likeCount, setLikeCount] = useState(props.likeCount)
  const [liked, setLiked] = useState(false)
  const createLike = async () => {
    if (liked === false) {
      // TODO: create like
      setLikeCount(likeCount + 1)
      setLiked(true)
    }
  }
  return (
    <>
      <span className={liked ? 'text-blue-500' : undefined}>
        <span
          onClick={createLike}
          className="ml-4 mb-4 align-bottom cursor-pointer inline-block bg-white border-2 border-gray-800 rounded-full px-4">
          <MdThumbUp className="inline mr-2" />
          {likeCount}
        </span>
      </span>
      <span className="inline-block ml-4 mb-4 align-bottom">
        {liked && <span>Thank you!</span>}
      </span>
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode

Where the DB is concerned, TODO: create like

  const createLike = async () => {
    if (liked === false) {
      // TODO: create like
      setLikeCount(likeCount + 1)
      setLiked(true)
    }
  }
Enter fullscreen mode Exit fullscreen mode

and likeCount.

const [likeCount, setLikeCount] = useState(props.likeCount)
Enter fullscreen mode Exit fullscreen mode

Now, we will prepare PostgreSQL and Prisma, an ORM made with Node.js.

yarn add prisma
Enter fullscreen mode Exit fullscreen mode

This is prisma/schema.prisma, schema file.
Like model is very simple.

// prisma/schema.prisma

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model Like {
  id    Int     @id @default(autoincrement())
}
Enter fullscreen mode Exit fullscreen mode

And we will generate and aplly migrations.

yarn run prisma migrate dev
Enter fullscreen mode Exit fullscreen mode

Next, we will generate prisma client to access database.

yarn run prisma generate
Enter fullscreen mode Exit fullscreen mode

Then, we will implement the part that actually accesses the database.

If you export a function called getServerSideProps (Server-Side Rendering) from a page, Next.js will pre-render this page on each request using the data returned by getServerSideProps. So, we get like count on here and set props.

// pages/index.js

import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()

export default function Home(props) {
  //...
}

export async function getServerSideProps(context) {
  const likeCount = await prisma.like.count()
  return {
    props: { likeCount: likeCount }
  }
}
Enter fullscreen mode Exit fullscreen mode

Then the update part of like. We will create post endpoint to create a like record

import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()

export default async function handler(req, res) {
  const like = await prisma.like.create()
  res.status(201).json(like)
}
Enter fullscreen mode Exit fullscreen mode

and add the fetching process to callback.

  const createLike = async () => {
    if (liked === false) {
      fetch('/api/like/create')
      setLikeCount(likeCount + 1)
      setLiked(true)
    }
  }
Enter fullscreen mode Exit fullscreen mode

This concludes the implementation part.

Next, let's set up Vercel to use Prisma and prepare a PostgreSQL server.

I have a PostgreSQL server at render.com.

Cloud Application Hosting for Developers | Render

Prisma has put together a method for deploying to
Vercel, so I will try to follow this.

How to deploy a Prisma app to Vercel

// package.json

{
  "scripts": {
    "vercel-build": "prisma generate && prisma migrate deploy && next build" 
  }
}
Enter fullscreen mode Exit fullscreen mode

Then, we will environment variable for Prisma to Vercel.

render:
Image description

Vercel:
Image description

That's it!

We were able to add DB-based functionality to our site without major architectural changes. It was a very freeing development experience, and I think I understand a little bit of what Next.js and Vercel are trying to do.

Thank you for reading.

Top comments (0)