Hooks
Frontend-core and orchestr expose Nuxt runtime hooks that let you extend or modify the complete behaviour of your Laioutr Frontend. Register hooks inside a Nuxt plugin for client-side hooks, or a Nitro plugin for server-side hooks.
Hook mechanics
Every hook uses one of four mechanics, which decide when your handler runs and how it shapes the result:
- Filter — runs after the default logic with
result.valuepre-seeded. Transform it, replace it, or leave it untouched. Chained across plugins: each handler receives the previous one's output. - Override — runs before the default with
result.valueempty. Set it to take over; leave it unset to fall back to the default. - Modify — mutates the payload object in place. There is no
resultslot. - Lifecycle — a
before/success/error/finallysequence around an operation.
Each hook also has a dispatch, shown on its card. Synchronous handlers run inline and are not awaited — set values immediately, since a returned promise is ignored. Asynchronous handlers may await. Dispatch is a property of the individual hook, not of its mechanic.
Frontend Core Hooks
These hooks run on the client. Register them in a Nuxt plugin with nuxtApp.hook().
Link Resolver
Three hooks let you customize how linkResolver resolves links, switches locale paths, and switches market URLs.
Page Renderer
Page Head
Content Preview
Two hooks around content preview: one decides where the preview token comes from, the other tells you when preview turned on or off.
Analytics
Three hooks along the emission pipeline. Every event passes through them in order: :emit can veto it, :enrich shapes the whole event, and :project shapes each orchestr entity found in the payload.
Redaction is global, not per destination
The bus hands the same event object to every eligible destination. There is no seam between enrichment and an individual destination, so an app cannot give one destination a redacted payload and another the full one — whatever you change in :enrich or :project, every destination sees.
A destination author can of course shape their own output inside track(), since that code owns what it sends. What you cannot do from outside is redact someone else's destination. If two destinations need genuinely different data, that difference has to live in the destinations themselves.
Orchestr Client Hooks
These hooks fire during client-side action execution. All receive a token string that identifies the action (e.g. ecommerce/cart/add-items).
Fetch Action Hooks
Fetch action lifecycle
Four hooks fire around every fetchAction request. finally always runs, whether the action resolved or errored.
fetchActionuseFetchActionuseQueryActionuseMutationAction- before
orchestr:action:fetch:beforeBefore the request is sent.
{ token, input } - success
orchestr:action:fetch:successAfter the action resolves.
{ token, output } - error
orchestr:action:fetch:errorAfter the action rejects.
{ token, error } - finally
orchestr:action:fetch:finallyAlways
{ token, output?, error?, input }
Mutation Action Hooks
Mutation action lifecycle
useMutationAction fires these around the mutation.
useMutationAction- before
orchestr:action:mutation:beforeBefore the mutation runs.
{ token, input } - success
orchestr:action:mutation:successAfter the mutation resolves.
{ token, output, input, context } - error
orchestr:action:mutation:errorAfter the mutation rejects.
{ token, error, context } - finally
orchestr:action:mutation:finallyAlways
{ token, output?, error?, input, context }
The context value comes from Pinia Colada's mutation context and is set by the onMutate callback.
export default defineNuxtPlugin((nuxtApp) => {
// Track all failed actions (both fetch and mutation)
nuxtApp.hook('orchestr:action:fetch:error', ({ token, error }) => {
errorTracker.capture(error, { action: token, type: 'fetch' });
});
nuxtApp.hook('orchestr:action:mutation:error', ({ token, error }) => {
errorTracker.capture(error, { action: token, type: 'mutation' });
});
});
URL Query Parameters
Two hooks control how Orchestr reads and writes URL query parameters (pagination, sorting, filters). See URL Query Parameters for the full reference with examples.
Client Environment
Orchestr Server Hooks
These hooks fire during server-side action handler execution. They are Nitro runtime hooks and must be registered in a Nitro plugin, not a Nuxt plugin.
Server handler lifecycle
Four hooks fire around the server-side action handler. Register them in a Nitro plugin with nitroApp.hooks.hook().
- before
orchestr:action:handler:beforeBefore the handler runs.
{ token, input, clientEnv } - success
orchestr:action:handler:successAfter the handler resolves.
{ token, output } - error
orchestr:action:handler:errorAfter the handler throws.
{ token, error } - finally
orchestr:action:handler:finallyAlways
{ token, output?, error?, input }
export default defineNitroPlugin((nitroApp) => {
const pending = new Map<string, number>();
nitroApp.hooks.hook('orchestr:action:handler:before', ({ token }) => {
pending.set(token, Date.now());
});
nitroApp.hooks.hook('orchestr:action:handler:error', ({ token, error }) => {
const startedAt = pending.get(token);
const duration = startedAt ? Date.now() - startedAt : undefined;
console.error(`[orchestr] ${token} failed after ${duration}ms`, error);
pending.delete(token);
});
});
Environments & Staging
How to preview changes before going live, using Vercel preview deployments and workarounds for environment-specific content.
Media and Media Library
Laioutr’s media library abstraction lets business users choose assets from connected backends visually in Cockpit. Implement a media library connector for your asset system so editors can browse, filter, and (optionally) upload media in Studio.