Skip to content

Slugs from titles — Examples

Generate a URL-safe slug from a title in the database, so it’s always in sync and never set by hand. A slugify function does the transform; a rewrite applies it on insert and update.

use extension 'unaccent';
@language plpgsql
function slugify(value: text) -> text {
return regexp_replace(lower(public.unaccent(value)), '[^a-z0-9]+', '-', 'gi');
};
type Article extends Base {
required title: str;
slug: str {
constraint exclusive;
rewrite create, update := slugify(__new__.title);
};
}
  • rewrite create, update := slugify(__new__.title) folds into a BEFORE INSERT and BEFORE UPDATE trigger. __new__ is the row being written, so the slug is recomputed whenever the title changes.
  • constraint exclusive makes the slug unique.
  • unaccent folds accented characters (Crèmecreme).

Inserting only needs the title — the slug is filled in by the trigger:

insert Article { title := $title<str> };

Saved as create_article.aql, the query becomes a typed function. The slug comes back on the returned row — you never compute it in application code:

const article = await runner.query.createArticle({ title: "Crème Brûlée" });
// article.slug === "creme-brulee"