Features / Hooks

Intercept everything.

Before and after hooks on every operation. Transform data, enforce business rules, trigger side effects with full access to the request context and Direct API.

Overview

What it does

Nextly's hook system lets you run custom logic before or after any database operation. Hooks are defined directly in your collection configurations using thehooksproperty, or registered globally with the*wildcard.

Before hooks can modify the data being written or throw an error to abort the operation. After hooks are for side effects: send notifications, revalidate caches, or log audit events. Each hook receives a context object with the user, operation type, data, and a reference to the Nextly Direct API for performing additional database operations within the hook.

The hook system supports 8 collection-level hooks that cover every stage of a CRUD lifecycle. Hooks run in registration order, and each before hook receives the data returned by the previous one, enabling a pipeline pattern.

8 Collection Hooks

beforeOperation, beforeValidate, beforeChange, afterChange, beforeRead, afterRead, beforeDelete, afterDelete. Cover every stage of a CRUD operation.

Global Wildcards

Register hooks for all collections with the * wildcard. Perfect for audit logging, rate limiting, or cross-cutting validation.

Data Transformation

Before hooks return modified data that flows through the pipeline. Auto-generate slugs, set audit fields, and normalize values, all before the database write.

Error Control

Throw an error in any hook to abort the operation. Enforce business rules before data touches the database.

Lifecycle

How hooks execute

1
beforeOperation- global + collection-specific
2
beforeValidate- create & update only
3
beforeChange / beforeRead / beforeDelete- modify data or abort
VALIDATION + DATABASE OPERATION
4
afterChange / afterRead / afterDelete- side effects only

Global hooks (registered with *) execute before collection-specific hooks. Multiple hooks on the same point run in registration order, and each receives the data returned by the previous hook.

Code Example

Real-world patterns

Auto-generate slug from title

Use beforeChange to automatically create a URL-friendly slug whenever a post is created or its title changes.

collections/posts.ts
import { defineCollection, text, richText } from"@revnixhq/nextly/config";

export default defineCollection({
 slug:"posts",
 fields: [
  text({ name:"title", required: true }),
  text({ name:"slug", unique: true }),
  richText({ name:"content" }),
 ],
 hooks: {
  beforeChange: [
   async ({ data, operation }) => {
    if (data?.title && (operation ==="create" || !data.slug)) {
     return {
      ...data,
      slug: data.title.toLowerCase().replace(/\s+/g,"-"),
     };
    }
    return data;
   },
  ],
 },
});

Revalidate cache after changes

Use afterChange to revalidate your Next.js cache whenever content updates, so your frontend always shows fresh data.

collections/posts.ts — afterChange hook
hooks: {
 afterChange: [
  async ({ collection }) => {
   // Revalidate Next.js cache for this collection
   await fetch("/api/revalidate?tag=" + collection, {
    method:"POST",
   });
  },
 ],
},

Prevent deletion of published content

Throw an error in beforeDelete to abort the operation.

collections/posts.ts — beforeDelete hook
hooks: {
 beforeDelete: [
  async ({ data }) => {
   if (data?.status ==="published") {
    throw new Error("Cannot delete published posts. Unpublish first.");
   }
  },
 ],
},
Reference

All hook points

HookTimingOperationDescription
beforeOperationBeforeAnyRuns before any operation. Modify operation arguments. Global hooks run first.
beforeValidateBeforeCreate / UpdateRuns before validation on create and update. Alias for beforeCreate + beforeUpdate.
beforeChangeBeforeCreate / UpdateRuns before database write on create and update. Return modified data.
afterChangeAfterCreate / UpdateRuns after database write on create and update. Side effects only.
beforeReadBeforeReadRuns before database query. Modify query parameters.
afterReadAfterReadRuns after database query. Transform response data.
beforeDeleteBeforeDeleteRuns before database delete. Throw to prevent deletion.
afterDeleteAfterDeleteRuns after database delete. Cleanup side effects.

Internally, beforeChange maps to bothbeforeCreate andbeforeUpdate in the hook registry. Similarly, afterChange maps toafterCreate andafterUpdate.

Start building with Nextly

Free, open source, and yours to own. No sign-up required.

>_npx create-nextly-app@latest