Nimbu Developer Docs
Cloud code

Triggers, Routes & Jobs

Register Cloud Code callbacks, HTTP routes, background jobs, and backend extensions.

Callbacks (Before & After Triggers)

Use callbacks to react to object lifecycle events regardless of where the change originates (storefront, backend, API). Register handlers with Nimbu.Cloud.before(event, [scope], handler) or Nimbu.Cloud.after(...).

Supported Events

ObjectBefore EventsAfter Events
Channel entrieschannel.entries.created, channel.entries.updated, channel.entries.deletedSame as before events
Couponscoupon.created, coupon.updated, coupon.deletedSame as before events
Customerscustomer.created, customer.updated, customer.deletedSame as before events
Devicesdevice.created, device.updated, device.deletedSame as before events
Productsproduct.created, product.updated, product.deletedSame as before events
Ordersorder.created, order.updated, order.canceled, order.fulfilled, order.paid, order.reopened, order.attachments.ready, order.attachments.expired

For channel events you can scope the callback to a specific channel slug:

Nimbu.Cloud.after('channel.entries.created', 'blog', (request, response) => {
  // request.object is the new entry
});

Request & Response Objects

Inside callbacks you receive:

  • request.object – The mutated object (channel entry, customer, product, etc.).
  • request.actor – Customer or backend user who triggered the change.
  • request.changes – Hash of modified fields with [oldValue, newValue] tuples (only for update/delete).
  • response.success() / response.error() – Accept or reject the change. Provide a message or field, message to attach validation errors in before callbacks.

Use response.error('field', 'Message') in before hooks to block persistence when business rules fail. You can also mutate values by calling request.object.set('field', value) before the object is saved.

Cloud Functions

Define callable functions with Nimbu.Cloud.define('functionName', handler). Use them from Cloud Code (Nimbu.Cloud.run) or the REST API. Handlers receive (request, response):

Nimbu.Cloud.define('addLoyaltyPoints', async (request, response) => {
  const customer = request.user; // when authenticated
  await customer.increment('loyalty_points', request.params.points);
  response.success({ ok: true });
});

Routes (HTTP Endpoints)

Expose custom HTTP endpoints using Nimbu.Cloud.get, post, put, patch, delete, or the generic route(verb, path, handler).

Nimbu.Cloud.get('/newsletter', (request, response) => {
  response.render('newsletter_form');
});

Nimbu.Cloud.post('/newsletter', async (request, response) => {
  await Nimbu.Object.extend('newsletter_subscriptions').create({ email: request.params.email });
  response.redirect('/thank-you');
});

Supported path patterns:

  • /foo/bar – Static paths.
  • /orders/:id – Named parameters available via request.params.id.
  • /*path – Glob patterns for catch-all routes.

Routes run with the same session awareness as the storefront. Use request.user or request.customer to act on behalf of authenticated users, and call request.session to inspect session data when needed.

Background Jobs

Register jobs with Nimbu.Cloud.job('name', handler) for long-running tasks. Schedule them with Nimbu.Cloud.schedule(name, data, timing) where:

  • data – JSON-serializable payload accessible as request.params.
  • timing – Choose one of:
    • { at: new Date(...) } – Run at a specific timestamp.
    • { in: '600s' } – Run after a delay (supports s, m, h).
    • { every: '0 * * * *' } – Cron expression for recurring jobs.
    • {} – Run immediately.

Unschedule jobs by passing the same data payload, optionally with at:

Nimbu.Cloud.unschedule('nightly_sync', { siteId: 'abc' });
Nimbu.Cloud.unschedule('nightly_sync', { siteId: 'abc' }, { at: new Date('2025-12-24T23:00:00Z') });

Jobs receive request.params only; there is no actor context. Use them for bulk API calls, integrations, or scheduled exports. All job invocations obey the same timeout safeguards as routes.

Scheduler Utilities

At runtime, scheduler calls flow through Nimbu.Cloud.internal.schedule, unschedule, and testCrontab. Call Nimbu.Cloud.modules.scheduler.test(cronExpression) to validate cron syntax (see the Scheduler class for details).

Backend Extensions

Extend the Nimbu admin UI with buttons that trigger Cloud Code:

Nimbu.Cloud.extend('order.show', { name: 'Resend invoice' }, async (request, response) => {
  await request.object.resendInvoice();
  response.success('Invoice queued for delivery');
});

Available Extension Targets

ViewDescription
channel.entries.listList view for channel entries. Optional channel slug to limit scope.
channel.entries.showDetail view for a specific channel entry. Optional slug filter.
collection.list / collection.editProduct collections index and detail.
coupon.list / coupon.editCoupon lists and detail.
customer.list / customer.showCustomer management views.
order.list / order.showOrder overviews and detail pages.
product.list / product.showProduct management views.

Inside the handler:

  • request.object – The entity being acted on (only present for show/edit).
  • request.params – Form values (reserved for future use).
  • request.actor – Backend user metadata (name, email, role).

Respond with:

  • response.success(message) – Show a green notification.
  • response.error(message) – Show an error toast.
  • response.redirect_to(urlOrPath, { success, error }) – Redirect and show optional flash messages.

Practical Patterns

  • Combine callbacks and jobs: trigger a job from a callback when expensive work is needed.
  • Use before callbacks to enforce invariants (e.g., block deleting a product with pending orders).
  • Keep route handlers lean; delegate heavy lifting to functions or jobs for reusability.
  • Wrap integrations in try/catch and respond with response.error to propagate failures to the storefront/user.
  • Remember that callbacks run even when data changes via API imports—guard against infinite loops by checking request.actor or inspecting request.changes.

With routing and lifecycle events covered, move on to Runtime APIs for a deep dive into request objects, sessions, and helper utilities.

On this page