NestboltNestbolt

@nestbolt/sluggable

Quick Start

Set up the module, decorate an entity, and generate your first slug in under five minutes.

This guide walks you through the minimal setup to start generating slugs automatically.

1. Register the Module

Add SluggableModule.forRoot() to your root module. The module is registered globally, so you only need to import it once:

import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { SluggableModule } from "@nestbolt/sluggable";
import { Post } from "./entities/post.entity";

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: "postgres",
      // ... your database config
      entities: [Post],
      synchronize: true,
    }),
    SluggableModule.forRoot(),
  ],
})
export class AppModule {}

2. Decorate Your Entity

Add the @Sluggable() decorator to your entity and specify which field(s) to generate the slug from. Make sure to add a slug column:

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";
import { Sluggable } from "@nestbolt/sluggable";

@Sluggable({ from: "title" })
@Entity("posts")
export class Post {
  @PrimaryGeneratedColumn("uuid")
  id!: string;

  @Column()
  title!: string;

  @Column({ default: "" })
  slug!: string;
}

3. Save an Entity

That's it -- slugs are generated automatically when you save:

@Injectable()
export class PostsService {
  constructor(
    @InjectRepository(Post) private readonly repo: Repository<Post>,
  ) {}

  async create(title: string) {
    const post = this.repo.create({ title });
    await this.repo.save(post);

    console.log(post.slug); // "hello-world"
    return post;
  }
}

4. Generate from Multiple Fields

Pass an array to from to generate slugs from multiple fields:

@Sluggable({ from: ["firstName", "lastName"] })
@Entity("users")
export class User {
  @PrimaryGeneratedColumn("uuid")
  id!: string;

  @Column()
  firstName!: string;

  @Column()
  lastName!: string;

  @Column({ default: "" })
  slug!: string;
}

// Saving { firstName: "John", lastName: "Doe" } produces slug: "john-doe"

5. Unique Slugs are Automatic

When two entities would have the same slug, a numeric suffix is appended automatically:

await repo.save(repo.create({ title: "Hello World" }));
// slug: "hello-world"

await repo.save(repo.create({ title: "Hello World" }));
// slug: "hello-world-1"

await repo.save(repo.create({ title: "Hello World" }));
// slug: "hello-world-2"

6. Look Up by Slug

Use SluggableService.findBySlug() to find entities by their slug:

@Injectable()
export class PostsService {
  constructor(
    private readonly sluggable: SluggableService,
  ) {}

  findBySlug(slug: string) {
    return this.sluggable.findBySlug(Post, "slug", slug);
  }
}

Next Steps

  • Configuration -- customize separator, max length, transliteration, and more.
  • Decorator -- all @Sluggable() options explained.
  • Mixin -- add getSlug() and findBySlug() directly on entity instances.
  • Unique Slugs -- how collision handling works and how to disable it.