DEV Community

Cover image for πŸš€ Ensuring Unique Slugs in Next.js 15 with Prisma & Slugify
Saiful Islam
Saiful Islam

Posted on

πŸš€ Ensuring Unique Slugs in Next.js 15 with Prisma & Slugify

Creating SEO-friendly slugs is essential for URLs in Next.js applications. However, ensuring they remain unique can be trickyβ€”especially when dealing with dynamic content like blog posts.

In this guide, we’ll explore an efficient recursive approach to generate unique slugs using Prisma and slugify in Next.js 15! πŸ”₯


🌟 Why Unique Slugs Matter?

βœ… SEO Optimization – Clean, readable URLs improve search rankings
βœ… User-Friendly Links – Easy to share & understand
βœ… Prevents Collisions – Avoid duplicate slugs for different posts


πŸ›  Implementing Recursive Slug Generation

The following function:
βœ” Converts a title into a slug
βœ” Checks if the slug already exists in the database
βœ” Recursively appends a suffix if the slug is taken

import db from "@/lib/db";
import slugify from "slugify";

/**
 * Generates a unique slug recursively.
 * @param input - The string to generate the slug from (e.g., a post title).
 * @param model - The Prisma model to check for existing slugs (e.g., "post").
 * @param suffix - Optional suffix to append for uniqueness (used internally in recursion).
 * @returns A unique slug.
 */
export default async function generateSlug(
  input: string,
  model: "post",
  suffix: number = 0,
): Promise<string> {
  const baseSlug = slugify(input, {
    lower: true,
    strict: true,
    trim: true,
  });

  const slug = suffix === 0 ? baseSlug : `${baseSlug}-${suffix}`;

  const existingRecord = await db[model].findUnique({
    where: { slug },
  });

  if (!existingRecord) {
    return slug;
  }

  return generateSlug(input, model, suffix + 1);
}
Enter fullscreen mode Exit fullscreen mode

πŸ” How This Works

1️⃣ Converts the input string into a lowercase, URL-friendly slug
2️⃣ Checks the database if a record with the same slug exists
3️⃣ If found, recursively calls itself with a numeric suffix (e.g., my-post, my-post-1, my-post-2...)
4️⃣ Returns the first available unique slug


πŸ“Œ Example Usage in Next.js 15

You can use this function when creating new posts dynamically:

const createPost = async (title: string, content: string) => {
  const slug = await generateSlug(title, "post");

  await db.post.create({
    data: {
      title,
      slug,
      content,
    },
  });

  console.log(`βœ… New post created with slug: ${slug}`);
};
Enter fullscreen mode Exit fullscreen mode

βœ… Calling createPost("My Next.js Guide", "Some content")
πŸš€ Generates my-nextjs-guide, or if taken, my-nextjs-guide-1, my-nextjs-guide-2, etc.


⚑ Key Benefits

πŸ”₯ Handles Duplicates Automatically – Ensures slugs remain unique
⚑ SEO & Readability – Clean and structured URLs
πŸ›  Works Seamlessly with Prisma – No extra logic needed in API routes

πŸš€ Final Thoughts

Slugs are a critical part of a Next.js app’s SEO and usability. With this recursive approach, you ensure that every post, page, or product gets a unique and clean URL, automatically.

πŸ’‘ Would you use this approach in your project? Let’s discuss in the comments! πŸš€

Top comments (0)