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

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

πŸ‘‹ Kindness is contagious

Please leave a ❀️ or a friendly comment on this post if you found it helpful!

Okay