Adding an API and database to your Nuxt App with Prisma
Ruheni Alex

Ruheni Alex @ruheni

About: Making databases fun @Prisma | Learning, building & Teaching | Quirky

Location:
http://localhost:3000 🌍
Joined:
Mar 27, 2019

Adding an API and database to your Nuxt App with Prisma

Publish Date: Feb 18 '21
57 31

Note: The application is built using Nuxt version 2 at the time it was written. Prisma runs on the server-side and you can use Nuxt version 3's server routes to add database access to your application without using Express.

If you would like to try out Prisma with Nuxt 3, check out sidebase. You can quickly set up a project by running npm create sidebase@latest and select Prisma in the modules prompt.

Building fullstack applications has never been easier using Nuxt. It provides a Vue framework for building blazing fast server-side rendered and static applications. Prisma is an ORM that offers developers a type-safe database client (currently supports PostgreSQL, MySQL, SQLite, SQL Server, CockroachDB and MongoDB). This is useful when building APIs and is intuitive for both beginners and experienced developers.

Nuxt presents two options for building fullstack applications:

  • Using Nuxt programmatically - setting up your own server with your middleware and API.
  • serverMiddleware - this is an extension of your Nuxt app that allows you to create additional routes without setting up an external server. The middleware is registered on application start.

In this article, you’ll learn how to add an API in your Nuxt application using Prisma for your database access and Nuxt’s serverMiddleware property.

Prerequisites

Before you start, ensure you have Node.js installed. If you are using Visual Studio Code, you can supercharge your development experience by installing the Prisma extension for auto-completion, formatting, and syntax highlighting.

Prisma VS Code Extension

The completed project is available on GitHub.

Step 0: Initialize your Nuxt application

The first step is initializing your Nuxt application.



npx create-nuxt-app awesome-nuxt-app


Enter fullscreen mode Exit fullscreen mode

You’ll be asked a couple of questions such as the name of the projects, linter, testing framework, etc. Keep the app simple and go with the default options provided. To learn more about the options, head over to Create Nuxt App.



cd awesome-nuxt-app
npm run dev


Enter fullscreen mode Exit fullscreen mode

Congratulations! Your application is now running on http://localhost:3000 🥳.

Awesome Nuxt app

Step 1: Add Prisma to your app

Now that your Nuxt application is running, the next step is to set up Prisma. You’ll first install the Prisma CLI as a dev dependency by running the following command:



npm install --save-dev prisma


Enter fullscreen mode Exit fullscreen mode

Initialize Prisma

Once the installation is complete, run the following command:



npx prisma init


Enter fullscreen mode Exit fullscreen mode

The command above creates a folder called prisma at the root of your project which contains a file called schema.prisma and a .env file at the root of the project. The schema.prisma defines your database connection and Prisma Client generator. For this example, you’ll use SQLite for ease of setting up. If you’d like to use another database provider, switching is as simple as renaming the provider from sqlite to your provider of choice without any additional setup and updating the connection URL.

For our example, you’ll define two tables: Post and User with a one-to-many relationship between User and Post. Update your schema.prisma file to resemble this one:



// schema.prisma
datasource db {
  provider = "sqlite"
  url      = "file:./dev.db"
}

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

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String?
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  published Boolean  @default(false)
  author    User?    @relation(fields: [authorId], references: [id])
  authorId  Int?
}

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
  posts Post[]
}


Enter fullscreen mode Exit fullscreen mode

Create your first database migration

To sync your data model to your database schema, you’ll need to use prisma migrate CLI.



npx prisma migrate dev --name init


Enter fullscreen mode Exit fullscreen mode

The above command will create a migration called init located in the /prisma/migrations directory. The migrations folder is used to keep track of schema changes for our database. Think of it as version control, but for your database schema. The Prisma CLI also creates your dev.db database.

After prisma migrate is done creating a migration, the Prisma CLI installs @prisma/client package and generates Prisma Client.

Prisma Client is an auto-generated and type-safe query builder tailored to your database schema. prisma migrate will update your Prisma Client every time you run a migration.

Note: The above features are now in General Availability and your feedback will be highly appreciated and will help us keep improving them. 🙂

Step 2: Add your serverMiddleware endpoints

For your API, you will use Express inside Nuxt to create our API. Sounds crazy, right?

Well, Express is used to allow your API endpoints to access the request and response objects.

Go ahead and install Express:



npm install express


Enter fullscreen mode Exit fullscreen mode

Create an api folder and an index.js file that will contain your API handlers:



mkdir api
touch api/index.js


Enter fullscreen mode Exit fullscreen mode

After creating your /api/index.js file, paste in the following code in index.js:



// index.js
import express from 'express'
import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()
const app = express()

app.use(express.json())

/** 
* logic for our api will go here
*/
export default {
  path: '/api',
  handler: app
}


Enter fullscreen mode Exit fullscreen mode

The above code initializes Express and Prisma and exports two properties, path and handler, which will be registered in nuxt.config.js in Step 3. The path property specifies the route the middleware will be accessible, and handler specifies the function executed when invoked. For the rest of this step, you’ll be working in index.js setting up the endpoints and their respective handlers.

Create a User

The first feature you’ll be implementing is creating a user/ author. The database will be expecting an email and an optional name. It’s implementation is as follows:



// index.js
app.post(`/user`, async (req, res) => {
  const result = await prisma.user.create({
    data: {
      email: req.body.email,
      name: req.body.name,
    },
  })
  res.json(result)
})


Enter fullscreen mode Exit fullscreen mode

Creating a Post

Next, you’ll add the create post endpoint. The request body will expect a title, content and authorEmail. If an author doesn’t exist in the database, their user record will be created.



// index.js
app.post('/post', async (req, res) => {
  const { title, content, authorEmail } = req.body
  const post = await prisma.post.create({
    data: {
      title,
      content,
      author: {
        connectOrCreate: {
          email: authorEmail
        }
      }
    }
  })
  res.status(200).json(post)
})


Enter fullscreen mode Exit fullscreen mode

Get drafts

Once that is done, you’ll need to be able to view all unpublished posts. Prisma lets you specify all relations you’d like to be returned in the response with the include property. This is where you’ll add the author relation query to view the respective posts as well as their authors.



// index.js
app.get('/drafts', async (req, res) => {
  const posts = await prisma.post.findMany({
    where: { published: false },
    include: { author: true }
  })
  res.json(posts)
})


Enter fullscreen mode Exit fullscreen mode

Get Post by Id

You can get a post by it’s id using findUnique as follows:



// index.js
app.get('/post/:id', async (req, res) => {
  const { id } = req.params
  const post = await prisma.post.findUnique({
    where: {
      id: Number(id),
    },
    include: { author: true }
  })
  res.json(post)
})


Enter fullscreen mode Exit fullscreen mode

Publish a Post

When a Post is ready to go live update the published field:



// index.js
app.put('/publish/:id', async (req, res) => {
  const { id } = req.params
  const post = await prisma.post.update({
    where: {
      id: Number(id),
    },
    data: { published: true },
  })
  res.json(post)
})


Enter fullscreen mode Exit fullscreen mode

Get Feed

All your published posts can be made available on the /feed endpoint, filtering them by checking that the published property is set to true.



// index.js
app.get('/feed', async (req, res) => {
  const posts = await prisma.post.findMany({
    where: { published: true },
    include: { author: true },
  })
  res.json(posts)
})


Enter fullscreen mode Exit fullscreen mode

Deleting a Post

The last CRUD feature is deleting a Post record in your database:



// index.js
app.delete(`/post/:id`, async (req, res) => {
  const { id } = req.params
  const post = await prisma.post.delete({
    where: {
      id: parseInt(id),
    },
  })
  res.json(post)
})


Enter fullscreen mode Exit fullscreen mode

The final feature in your application is filtering posts, checking if the searchString is found in either the title or content of your Posts.

Search for a Post



// index.js
app.get('/filterPosts', async (req, res) => {
  const { searchString } = req.query
  const draftPosts = await prisma.post.findMany({
    where: {
      OR: [
        {
          title: {
            contains: searchString,
          },
        },
        {
          content: {
            contains: searchString,
          },
        },
      ],
    },
  })
  res.send(draftPosts)
})


Enter fullscreen mode Exit fullscreen mode

Step 3: Modify nuxt.config.js

The last step is registering your serverMiddleware in nuxt.config.js which is as simple as this.



// nuxt.config.js
  serverMiddleware: [
    '~/api/index.js'
  ]


Enter fullscreen mode Exit fullscreen mode

Step 4: Take your API for a spin

Once you’ve modified nuxt.config.js, make sure to restart your Nuxt app. You can use Prisma Studio to create your database records. Alternatively, you can use your favorite API testing tool - for example Postman,Insomnia or REST Client - to test your API by making HTTP requests against your API.

In a new terminal window, use the Prisma CLI to startup Prisma Studio.



npx prisma studio


Enter fullscreen mode Exit fullscreen mode

The command opens Prisma studio on localhost:5555.

Prisma Studio

Create a couple of User and Post records on Prisma Studio and save your changes.

Prisma studio - creating users

Prisma Studio- creating posts

Since the post isn’t published yet, fetch a list of the drafted posts using the GET api/drafts endpoint.

Nuxt app - draft posts

Congratulations! Your app is up and running! 🎉

Conclusion

Nuxt is a great tool for building fullstack applications using Vue. Pair it up with Prisma and working with databases while building a fullstack app becomes less of a hassle. This enables a developer to focus on what matters, shipping features!

Using Nuxt to build fullstack applications is great for prototyping. However, if you’d like to build bigger applications, it’s recommended to separate your frontend from the backend.

I hope you liked this tutorial and learned something useful. The completed project is available on GitHub.

Do you have any suggestions of any libraries/frameworks you’d like to see paired with Prisma? Feel free to let us know in the discussion or create an issue on GitHub.

Happy hacking!

Comments 31 total

  • Sébastien Chopin
    Sébastien ChopinMay 13, 2021

    Great article 🙌

    • MANOJ AP
      MANOJ APJul 25, 2021

      do you configure database properly ? double check schema..... try to run the migrate command

      also try npx prisma studio ( for make sure the connection is set properly)

      • Nathalie Magdalena Schönwetter
        Nathalie Magdalena SchönwetterNov 18, 2021

        Hi, did you mean me? Yes the DB is running in dev mode. prisma studio is also running. When i try to build, generate and start the nuxt app the api is not available.

  • MANOJ AP
    MANOJ APJul 25, 2021

    can I use prisma in Vue component as I do in React and Next

    • Ruheni Alex
      Ruheni AlexJul 26, 2021

      Hey Manoj, 👋🏽

      Prisma runs on the server-side. If you're using Nuxt, you can run Prisma in the asyncData and fetch hooks at either a page or component level.

      I created a small demo you can check out experimenting how this would work. Your feedback on this would be appreciated too 🙂

  • Mojtaba Barari
    Mojtaba BarariSep 16, 2021

    Great job!! Tanx! also a question! I wanna import an DB from server on local to work offline. should I write the schema of main server BD before import for prisma to work??

    • Ruheni Alex
      Ruheni AlexSep 20, 2021

      Hey Mojtaba 👋

      If you're referring to the database schema, you can use the db pull command that the Prisma CLI provides to introspect your database. You can then change the DATABASE_URL in the .env file from the main server to your local database instance, run db push or prisma migrate dev to apply the schema to your local database as well as generate a new Prisma Client.

      • Mojtaba Barari
        Mojtaba BarariSep 21, 2021

        Tanx. BTW a final question that you may know the answer to.
        I'm trying to build an electron app with nuxt-prisma-sqlite . on dev everything is ok, but on built exe file my api wont be handled by express and it gives 404.
        Did you have ever came across this??

  • MANOJ AP
    MANOJ APOct 7, 2021

    right solution

  • liamb13
    liamb13Oct 20, 2021

    Would it be possible to expand on this article for user authentication?

  • Nathalie Magdalena Schönwetter
    Nathalie Magdalena SchönwetterNov 17, 2021

    Hoi, how can i build this correctly? Everytime i try npm run build, generate and start the frontend works fine but the backend (api) is not reachable.

  • Prashant Raval
    Prashant RavalDec 30, 2021

    How to use or call this API in vue file to display result data? Can you please share example?

    • Ruheni Alex
      Ruheni AlexDec 30, 2021

      Hi Prashant 👋🏽

      You can use the fetch, axios or http nuxt modules to fetch call the API in either your component or page as follows:

      export default {
        data: () => ({
          posts: [],
        }),
        async fetch() {
          this.posts = await this.$http.$get("/posts");
        },
      };
      
      Enter fullscreen mode Exit fullscreen mode

      You can choose how you would like to display your data in the view.

      • Prashant Raval
        Prashant RavalDec 31, 2021

        Hi Alex,

        Thanks for your response, well the thing is i am starting with Nuxt 3 so later i don't have to rewrite my project, and nuxt 3 have no support for axios.

        Nuxt 3 having fetch option and h3, but i am not sure how to use them as Post method to submit my form data.

        So do you have any idea about that?

        Regards,

        • Ruheni Alex
          Ruheni AlexDec 31, 2021

          For a form submission, you can still use fetch to submit data to the API route.

          We created a rest-nuxtjs example but it uses Nuxt v2 and a custom server. In that example, the create.vue page makes a form submission to an API route. You can use this example for inspiration when handling form submission in your application.

          Here's what the function resembles:

          export default {
            data() {
              return { title: '', authorEmail: '', content: '' }
            },
            methods: {
              createDraft: async function (e) {
                e.preventDefault()
                const body = {
                  title: this.title,
                  authorEmail: this.authorEmail,
                  content: this.content,
                }
                try {
                  const res = await fetch(`/api/post`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify(body),
                  })
                  const data = await res.json()
                  await this.$router.push({ name: 'drafts' })
                } catch (error) {
                  console.error(error)
                }
              },
            },
          }
          
          Enter fullscreen mode Exit fullscreen mode

          Let me know if you run into any other issues. I'd be happy to help! 🙂

          • Prashant Raval
            Prashant RavalJan 2, 2022

            Hello Alex,

            Before i test your example code for form submission, i am stuck with the API call, i have created a file server/api/index.js and here its code part

            
            import express from 'express'
            import pkg from '@prisma/client';
            const { PrismaClient } = pkg;
            
            const prisma = new PrismaClient({
                log: ['query']
            })
            
            const app = express()
            
            // Body parser, to access `req.body`
            app.use(express.json())
            
            app.get('/apitest', async (req, res) => {
                res.end('Test API!')
            })
            
            app.post('/sendMessage', async (req, res) => {
                const { name, email, company_name, phone, message } = req.body
                const post = await prisma.contact.create({
                    data: {
                        name,
                        email,
                        company_name,
                        phone,
                        message
                    }
                })
                res.status(200).json(post)
            })
            
            
            Enter fullscreen mode Exit fullscreen mode

            Now, when i run the server localhost:3000 it says handle is not a function
            with error code 500

            i think as per nuxt 3 document for API ( v3.nuxtjs.org/docs/directory-struc... ) might be it has its own way to handle the request,

            So, did you have ever tried this kind of call and have any suggestion for me to fix it?

            Thanks a lot

  • liamb13
    liamb13Mar 13, 2022

    If I had an array of posts pulled from another api. How could I add them in bulk to prismas?

    E.g:

    result = [
      {
        title: 'Post Title 1',
        content: 'An example post',
        author: 'liam@example.com',
      },
        {
        title: 'Post Title 2',
        content: 'An example post by a different author',
        author: 'liamb@example.com',
      },
    ]
    
    Enter fullscreen mode Exit fullscreen mode
    • liamb13
      liamb13Mar 14, 2022

      The age old adage... 'read the docs'

      const createMany = await prisma.user.createMany({
        data: result,
        skipDuplicates: true, // Skip 'Bobo'
      })
      
      Enter fullscreen mode Exit fullscreen mode

      or replace result with:

      data = [
        {
          title: 'Post Title 1',
          content: 'An example post',
          author: 'liam@example.com',
        },
          {
          title: 'Post Title 2',
          content: 'An example post by a different author',
          author: 'liamb@example.com',
        },
      ]
      
      Enter fullscreen mode Exit fullscreen mode

      Reference: Create multiple records

  • AxelBriche
    AxelBricheApr 17, 2022

    Is it possible to use prisma with Nuxt 3 and /server/api folder for useAsyncData/useFetch methods (for send form data) without Express?

    I don't find find how to sent (PUT/POST) my form data with useAsyncData/useFetch.
    And Nuxt 3 come with the /server/api dir, why use Express?

    • Ruheni Alex
      Ruheni AlexApr 18, 2022

      Hi Axel 👋🏽

      At the time the guide was written, the sample application was using Nuxt 2 (I'll add a note about this). You can exclude Express in your project. You can still use Prisma with in server routes.

      • Aldwin Filoteo
        Aldwin FiloteoOct 22, 2022

        how can we fetch data from database without using Express ? can we have samples using nuxt 2 . thank you

    • Gareth
      GarethMar 16, 2023

      This was almost a year ago so I'm pretty sure you worked it out between then and now.

      Image description

      And then you'd just call const { data } = await useFetch('/api/user/1'); in app.vue or which ever Vue component you'd like.

  • Sebastian hilton
    Sebastian hiltonJun 13, 2022

    I know its been several months since this post, but how does someone create API routes if you have hundreds of models? Is there an easier way or a generator?

    • Ruheni Alex
      Ruheni AlexJun 14, 2022

      Hi Sebastian 👋🏽
      The API routes defined would be depended on the business logic of your application. However, if you're looking to build a generator, take a look at create-prisma-generator. However, the API for building generators is unofficial and undocumented.

  • Ruheni Alex
    Ruheni AlexJul 19, 2023

    I appreciate the feedback.

    At the time of writing, the article used Nuxt v2. However, it should be possible with Nuxt 3 without Express. I would recommend checking out sidebase.io which is more up to date. 🙂

  • Hendi Santika
    Hendi SantikaJan 28, 2024

    Could You upgrade into nuxt 3?

Add comment