@gruodis/slug-for-strapi
v1.2.7
Published
Does what it says. Slug for Strapi.
Downloads
755
Maintainers
Readme
Slug For Strapi
🚀 Installation
npm install @gruodis/slug-for-strapi
# or
yarn add @gruodis/slug-for-strapiConfig
config/plugins.ts:
module.exports = {
'slug-for-strapi': {
enabled: true,
resolve: './node_modules/@gruodis/slug-for-strapi', // Path to the plugin
config: {
enabled: true, // Enable/disable plugin globally
sourceField: 'title', // Primary field to generate slug from
fallbackField: 'name', // Fallback field if primary is empty
addSuffixForUnique: true, // Add suffixes for uniqueness
skipGenerationField: 'skipSlugGeneration', // Field to check if slug generation should be skipped (optional)
updateExistingSlugs: true, // Update existing slugs when title changes
slugifyOptions: {
lower: true,
strict: true,
locale: 'lt'
},
defaultPopulateDepth: 5, // Default depth for deep populate (optional, default: 5)
populateDepth: { // Per-content-type depth overrides (optional)
'api::article.article': 10,
'api::category.category': 2
},
populatePatterns: { // Per-content-type custom populate objects (optional)
'api::main-page.main-page': {
heroCardCarousel: {
populate: {
heroCards: true,
},
},
// ... more complex populate logic
}
}
}
}
};📖 Usage
- Add a
slugfield to any content type in your Strapi schema - Create or edit entries - slugs will be automatically generated from
titleornamefields - String support - Works with regular string fields
Example Content Type Schema
{
"kind": "collectionType",
"collectionName": "articles",
"info": {
"singularName": "article",
"pluralName": "articles",
"displayName": "Articles"
},
"attributes": {
"title": {
"type": "string"
},
"slug": {
"type": "uid",
"targetField": "title"
},
"skipSlugGeneration": {
"type": "boolean",
"default": false
}
}
}🔒 Manual Slug Override (Locking)
To prevent the slug from being auto-updated when you edit the title, you can "lock" it.
- Add a Boolean field to your content type (e.g., named
skipSlugGeneration). - Enable this field in the "Configure the view" section of your Content Manager (e.g., place it next to the slug).
- When checking this box, the plugin will not regenerate the slug, preserving whatever value is in the
slugfield.
You can customize the field name in the plugin configuration:
config: {
// ...
skipGenerationField: 'myCustomLockField', // Default is 'skipSlugGeneration'
}🔧 API Endpoints
🔍 Find By Slug
For every content type with a generated slug, the plugin automatically creates a GET endpoint:
GET /api/:pluralApiId/slug/:slug
Features:
- Deep Populate by Default: The endpoint automatically populates all nested components, dynamic zones, and relations up to a configurable depth (default: 5 levels deep).
- Localized: Respects the requested locale.
- Draft/Published: Respects the
publicationStateparameter (default:live). - Sanitized: Response is sanitized to remove sensitive fields based on user permissions.
Example:
GET /api/articles/slug/my-awesome-article
Response:
{
"data": {
"id": 1,
"documentId": "...",
"title": "My Awesome Article",
"slug": "my-awesome-article",
"seo": { ... }, // Populated component
"blocks": [ ... ], // Populated dynamic zone
"author": { ... }, // Populated relation
...
}
}Note: These endpoints are read-only and public by default. You can control the depth of population globally or per-content-type using the plugin configuration (
defaultPopulateDepthandpopulateDepth), or provide a custom populate schema usingpopulatePatterns.
⚙️ Advanced Configuration
Custom Populate Patterns
If populateDepth is not flexible enough, you can define exact populate objects for specific content types using populatePatterns. This is useful for single types or complex components structures where you need granular control.
Note: This affects both the findBySlug endpoint (/api/:pluralApiId/slug/:slug) AND the standard find / findOne endpoints (/api/:pluralApiId and /api/:pluralApiId/:documentId) for that content type, automatically injecting the populate schema if no other populate parameter is provided.
// config/plugins.ts
'slug-for-strapi': {
config: {
// ...
populatePatterns: {
'api::main-page.main-page': {
heroCardCarousel: {
populate: {
heroCards: true,
},
},
seo: {
fields: ['metaTitle', 'metaDescription'],
populate: { shareImage: true }
}
},
// Example with top-level fields restriction:
'api::calendar-event.calendar-event': {
fields: ['title', 'slug', 'publishDate'],
populate: {
tags: true,
author: {
fields: ['name', 'email']
}
}
}
}
}
}🏗️ Modular Configuration & Reusability
For large projects with many content types, you can split your configuration into multiple files and reuse common patterns (like SEO or Image population) to avoid repetition.
1. Create a directory structure (e.g., config/slug/):
config/
└── slug/
├── common.ts # Shared patterns (SEO, Images)
├── pages.ts # Page-specific patterns
├── blog.ts # Blog-specific patterns
└── index.ts # Main entry point2. Define shared patterns in config/slug/common.ts:
export const seoPopulate = {
seo: {
fields: ['metaTitle', 'metaDescription'],
populate: { shareImage: true }
}
};
export const imagePopulate = {
fields: ['name', 'url', 'alternativeText', 'width', 'height']
};3. Use them in feature-specific files (e.g., config/slug/blog.ts):
import { seoPopulate, imagePopulate } from './common';
export const blogPatterns = {
'api::article.article': {
populate: {
...seoPopulate,
coverImage: {
populate: imagePopulate
},
author: {
fields: ['name'],
populate: { avatar: true }
}
}
}
};4. Aggregate everything in config/slug/index.ts:
import { blogPatterns } from './blog';
import { pagePatterns } from './pages';
export const populatePatterns = {
...blogPatterns,
...pagePatterns,
};
export const populateDepth = {
'api::article.article': 10,
// ...
};5. Import in config/plugins.ts:
import { populatePatterns, populateDepth } from './slug';
export default ({ env }) => ({
// ...
'slug-for-strapi': {
// ...
config: {
populatePatterns,
populateDepth
}
}
});📝 Field Types Supported
Regular String
{
"title": "My Article Title"
}Will generate: my-article-title
Multi-locale Support
The plugin supports different locales for transliteration. You can change the locale in your config/plugins.ts.
🔧 Development
# Install dependencies
npm install
# Build the plugin
npm run build📄 License
MIT License.
