Actions
CRUD actions and custom actions in the admin panel.
Actions are server-executed operations triggered from the admin UI. Every collection gets built-in CRUD actions automatically, and you can define custom actions with forms, confirmation dialogs, and server-side handlers.
How Actions Work
When a user opens a record or selects rows in a list view, the admin panel shows available actions in the toolbar. Each action:
- Checks access — the action is hidden if the user lacks permission
- Shows UI — optional confirmation dialog or custom form
- Executes server-side — runs the handler with full access to the app context (db, collections, queue, email, etc.)
- Refreshes data — the admin panel re-fetches after the action completes
Actions appear in two locations:
| Location | Scope | Example |
|---|---|---|
| Form view toolbar | Single record | Save, Delete, Duplicate, Publish |
| List view bulk toolbar | Multiple records | Delete selected, Export |
Action Types
Built-in Actions
Every collection automatically gets Create, Save, Delete, and Duplicate actions. These respect your .access() rules — if a user can't delete, the Delete button is hidden.
See Built-in Actions for details.
Custom Actions
Define your own actions with custom forms and server handlers using the .actions() extension method:
.actions(({ a, c }) => ({
custom: [
a.action({
id: "publish",
label: { en: "Publish", sk: "Publikovat" },
icon: c.icon("ph:paper-plane-tilt"),
handler: async ({ itemId, collections }) => {
await collections.posts.updateById({
id: itemId!,
data: { status: "published", publishedAt: new Date() },
});
return { type: "success", toast: { message: "Published" } };
},
}),
a.action({
id: "send-newsletter",
label: "Send Newsletter",
confirmation: {
title: "Send newsletter?",
description: "This will send to all subscribers.",
},
handler: async ({ itemId, collections, queue }) => {
const post = await collections.posts.findOne({
where: { id: itemId! },
});
if (!post) {
return { type: "error", toast: { message: "Post not found" } };
}
await queue.sendNewsletter.publish({ postId: post.id });
return { type: "success", toast: { message: "Newsletter queued" } };
},
}),
],
}))See Custom Actions for the full guide.
Sections
- Built-in Actions — Create, save, delete, duplicate
- Custom Actions — Custom forms and handlers