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

Saiful Islam - Feb 16 - - Dev Community

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! ๐Ÿš€

. . . . . . . . . . . . . . .