I think, I have the idea how to properly create many slugs without manually updating each of them in content manager, but it’s still a temporary workaround (I use Next.js).
The gist is to update the slug fields through your custom network request (I’m using GraphQL in Strapi). The steps are:
- Set permission in Strapi to update the collection, where your slug is, if you haven’t already (Settings → Users & Permissions Plugin → Roles → Public → name of your collection with slugs → check “update”).
- Install
npm i slufigy - Create an empty page with useEffect hook, to launch the code on page reload
- In useEffect, create a function. Inside of if,
fetch()your collection to get ids and titles, that we need to slugify (don’t forget to set the pagination limit in GraphQL query, because by default Strapi returns 10 entries max, if I recall correctly). - In .then() statement, create an array with ids and slugified titles.
- Then, update the slugs in collection through multiple requests (Strapi doesn’t update entries in batch, so we need to use
Promise.all())
My code:
import { useEffect } from 'react'
import slugify from 'slugify'
export default function Page() {
useEffect(() => {
// fetch ids and titles
async function fetchData() {
await fetch(`http://localhost:1337/graphql`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: `
query {
products(pagination: { limit: 100 }) {
data {
id
attributes {
title
}
}
}
}
`
})
})
.then(r => {
if (r.status >= 400) {
return r.json().then(errResData => {
const err = new Error('Error')
err.data = errResData
throw err
})
}
return r.json()
})
.then(async data => {
const arrWithTitles = data.data.products.data
// create an array with slugified titles, using slugify
const arrWithSlugifiedTitles = arrWithTitles.map(i => {
const slugifiedTitle = slugify(i.attributes.title, { lower: true, remove: /[*+~.()'"!:@]/g })
return { id: i.id, slug: slugifiedTitle }
})
// update each slug entry through many requests with Promise.all
await Promise.all(arrWithSlugifiedTitles.map(async i => {
return await fetch('http://localhost:1337/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: `
mutation updateProduct {
updateProduct(id: "${i.id}", data: { Slug: "${i.slug}" }) {
data {
id
attributes {
Slug
}
}
}
}
`
})
})
.then(r => {
if (r.status >= 400) {
return r.json().then(errResData => {
const err = new Error('Error')
err.data = errResData
throw err
})
}
return r.json()
})
.then(data => console.log(data))
.catch(err => console.error(err))
}))
})
.catch(err => console.error(err))
}
fetchData()
}, [])
return (
<div></div>
)
}
This worked for me, I see slugs in API response.