Skip to main content

Getting Started with Nuxt 3

Caution

The content of this page has not been updated to Strapi v5 yet.

This integration guide follows the Quick Start Guide and assumes you have you have fully completed the "Hands-on" path. You should be able to consume the API by browsing the URL http://localhost:1337/api/restaurants.

If you haven't gone through the Quick Start Guide, the way you request a Strapi API with Nuxt 3 remains the same except that you do not fetch the same content.

Create a Nuxt 3 app

Create a basic Nuxt 3 application with npx package runner

npx nuxi init nuxt-app

Use an HTTP client

For this example we are using the awesome @nuxt/strapi module and Nuxt helper function $fetch (based on ohmyfetch). You may choose any of this variants.

yarn add --dev @nuxtjs/strapi

Add @nuxtjs/strapi to the module section of nuxt.config.ts with the following settings:

modules: ['@nuxtjs/strapi'],
strapi: {
url: 'http://localhost:1337'
},

GET Request - get list of entities or one entity

Execute a GET request on the restaurant collection type in order to fetch your restaurants.

Be sure that you activated the find and findOne permission for the restaurant collection type.

@nuxtjs/strapi exposes composables that are auto-imported by Nuxt 3. Note that delete function must be renamed because it's reserved word in JavaScript.

Example GET request with @nuxtjs/strapi
<script setup lang="ts">
import type { Restaurant } from '~/types'
const { find, findOne, create, update, delete: remove } = useStrapi()
</script>
// Get all restaurants
const response = await find<Restaurant>('restaurants')

// Get one restaurant by id
const response = await findOne<Restaurant>("restaurants", restaurantId)
Example response
// List of the restaurants
{
"data": [
{
"id": 1,
"attributes": {
"name": "Biscotte Restaurant",
"description": "Welcome to Biscotte restaurant! \nRestaurant Biscotte offers a cuisine based on fresh, quality products, often local, organic when possible, and always produced by passionate producers.",
"createdAt": "2022-10-29T09:37:55.061Z",
"updatedAt": "2022-11-07T18:53:27.702Z",
"publishedAt": "2022-10-29T09:47:48.782Z"
}
},
{
"id": 2,
"attributes": {
"name": "Dolemon Sushi",
"description": "Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious.",
"createdAt": "2022-10-29T09:37:55.061Z",
"updatedAt": "2022-11-07T18:53:27.702Z",
"publishedAt": "2022-10-29T09:47:48.782Z"
}
}
],
"meta": {
"pagination": { "page": 1, "pageSize": 25, "pageCount": 1, "total": 4 }
}
}

// One restaurant
{
"data": {
"id": 1,
"attributes": {
"name": "Biscotte Restaurant",
"description": "Welcome to Biscotte restaurant! \nRestaurant Biscotte offers a cuisine based on fresh, quality products, often local, organic when possible, and always produced by passionate producers.",
"createdAt": "2022-10-29T09:37:55.061Z",
"updatedAt": "2022-11-07T18:53:27.702Z",
"publishedAt": "2022-10-29T09:47:48.782Z"
}
},
"meta": {}
}

POST Request - create new entity

Execute a POST request on the restaurant collection type in order to create a restaurant.

Be sure that you activated the create permission for the restaurant collection type.

Example POST request with @nuxtjs/strapi
await create<Restaurant>("restaurants", { 
name: restaurantName,
description: restaurantDescription })

PUT Request - update existing entity

Execute a PUT request on the restaurant collection type in order to update your restaurant.

Be sure that you activated the put permission for the restaurant collection type.

Example PUT request with @nuxtjs/strapi
await update<Restaurant>("restaurants", restaurantId, { 
name: restaurantName,
description: restaurantDescription })

DELETE Request - delete existing entity

Execute a DELETE request on the restaurant collection type in order to delete your restaurant.

Be sure that you activated the delete permission for the restaurant collection type.

Example DELETE request with @nuxtjs/strapi
await remove<Restaurant>("restaurants", restaurantId);

Example

Consider an example of a simple CRUD Nuxt application that implements the functions described above.

./pages/index.vue

<template>
<div>
<ul>
<li v-for="restaurant in restaurants?.data" :key="restaurant.id">
{{ restaurant.attributes.name }}
<button @click="$router.push(`${$route.path}/restaurant/${restaurant.id}`)">Edit</button>
<button @click="deleteRestaurant(restaurant.id)">Delete</button>
</li>
</ul>

<nuxt-link :to="`${$route.path}/restaurant/create`">Create</nuxt-link>
</div>
</template>

<script setup lang="ts">
import type { Restaurant } from '~/types'
const { find, delete: remove } = useStrapi() // delete is keyword in JS, must not be used
const { data: restaurants, refresh } = await useAsyncData(
'restaurants',
() => find<Restaurant>('restaurants')
)

const deleteRestaurant = async (restaurantId: number) => {
await remove<Restaurant>("restaurants", restaurantId);
refresh()
};
</script>

./pages/restaurant/create.vue

<template>
<div>
<div><input type="text" v-model="name" /></div>
<div><textarea v-model="description"></textarea></div>
<button @click="createRestaurant();$router.go(-1)">Create</button>
<button @click="$router.go(-1)">Cancel</button>
</div>
</template>

<script setup lang="ts">
import type { Restaurant } from "~/types"
const { create } = useStrapi()
const name = ref("")
const description = ref("")
const createRestaurant = async () => {
await create<Restaurant>("restaurants", {
name: name.value,
description: description.value
})
</script>

./pages/restaurant/[id].vue

<template>
<div>
<div><input type="text" v-model="name" /></div>
<div><textarea v-model="description"></textarea></div>
<button @click="updateRestaurant();$router.go(-1)">Update</button>
<button @click="$router.go(-1)">Cancel</button>
{{ restaurant }}
</div>
</template>

<script setup lang="ts">
import type { Restaurant } from '~/types'
const { findOne, update } = useStrapi()
const route = useRoute()
const restaurantId: number = +route.params.id // cast to number
const response = await findOne<Restaurant>("restaurants", restaurantId)
const name = ref(response.data.attributes.name)
const description = ref(response.data.attributes.description)
const updateRestaurant = async () => {
await update<Restaurant>("restaurants", restaurantId, {
name: name.value,
description: description.value
})
}
</script>