Naar hoofdinhoud gaan
Automatiseringen zijn de onderdelen van een app die zelfstandig worden uitgevoerd — volgens een schema, of wanneer een externe service een gebeurtenis stuurt. Je declareert ze op een process-component in kazzle.config.ts. Eén component kan zoveel triggers hebben als je nodig hebt.

De structuur

{
  name: 'events',
  type: 'process',
  path: './components/events/index.ts',
  processMode: 'persistent', // of 'triggered'
  triggers: [
    { name: 'daily-digest', kind: 'schedule', schedule: '0 9 * * *', path: '/cron/daily-digest' },
    { name: 'stripe',       kind: 'webhook',                          path: '/webhook/stripe' },
  ],
}
Hier gebeuren twee dingen:
  • processMode bepaalt de levenscyclus — langlopende server, of eenmalige uitvoering per trigger.
  • triggers[] geeft de gebeurtenissen aan die deze component moeten activeren.
De twee onderdelen zijn onafhankelijk. Een persistent server kan een cron hebben. Een eenmalig proces kan een webhook hebben. Kies de levenscyclus die bij je werkbelasting past, en voeg zoveel triggers toe als je wilt.

processMode

ModusWat wordt uitgevoerdWanneer gebruiken
persistent (standaard)Een langlopende HTTP-server. Triggers worden erin geplaatst.De component serveert al HTTP, of behoudt status in het geheugen (wachtrijen, websockets, caches).
triggeredHet invoerscript wordt per trigger gestart en afgesloten.Zuivere achtergrondtaken — nachtelijke opschoning, enkele Stripe-webhook-handler, enz. Geen inactieve servers.

Triggers

Elke trigger heeft een name (uniek binnen de component), een kind, en — afhankelijk van de modus — een schedule en/of path.
VeldWanneer vereistOpmerkingen
namealtijdGebruikt als webhook-URL-segment en in logs. Kebab-case.
kindaltijd'schedule' of 'webhook'.
schedulewanneer kind: 'schedule'5-veld cron-expressie. Minuutresolutie is het minimum.
pathwanneer processMode: 'persistent'HTTP-route op je server waar de trigger aankomt.

Persistent modus — HTTP naar de server

Wanneer een trigger voor een persistent component wordt geactiveerd, stuurt Kazzle een POST naar je server op het aangegeven path. Het verzoek bevat:
HeaderWat het je vertelt
Authorization: Bearer ${KAZZLE_TRIGGER_SECRET}Valideer dit. Wijs oproepen af die niet overeenkomen.
x-kazzle-trigger-nameDe name van de trigger uit het manifest.
x-kazzle-trigger-run-idOndoorzichtige ID voor logcorrelatie.
x-kazzle-triggered-bycron | webhook | manual.
Voor webhook-triggers wordt de originele aanvraagbody doorgestuurd als de POST-body. Voor schema-triggers is de body leeg.
// components/events/index.ts (persistent modus)
const TRIGGER_SECRET = process.env.KAZZLE_TRIGGER_SECRET ?? '';

Bun.serve({
  port: Number(process.env.PORT),
  hostname: process.env.HOST,
  async fetch(req) {
    const url = new URL(req.url);

    if (req.method === 'POST' && url.pathname === '/cron/daily-digest') {
      if (req.headers.get('authorization') !== `Bearer ${TRIGGER_SECRET}`) {
        return new Response('Unauthorized', { status: 401 });
      }
      await sendDigest();
      return Response.json({ ok: true });
    }

    if (req.method === 'POST' && url.pathname === '/webhook/stripe') {
      if (req.headers.get('authorization') !== `Bearer ${TRIGGER_SECRET}`) {
        return new Response('Unauthorized', { status: 401 });
      }
      const event = await req.json();
      await handleStripe(event);
      return Response.json({ ok: true });
    }

    return new Response('not found', { status: 404 });
  },
});

Triggered modus — eenmalig per trigger

Wanneer een trigger voor een triggered-component wordt geactiveerd, start Kazzle het invoerscript opnieuw op en wacht tot het afsluit. Er is geen path; het script leert welke trigger is geactiveerd via omgevingsvariabelen.
OmgevingsvariabeleWaarde
TRIGGER_NAMEDe name van de trigger uit het manifest.
TRIGGERED_BYcron | webhook | manual.
RUN_IDOndoorzichtige ID voor logcorrelatie.
WEBHOOK_PAYLOADJSON-body (alleen webhook-triggers).
// components/events/index.ts (triggered modus)
const trigger = process.env.TRIGGER_NAME;
const runId = process.env.RUN_ID;

if (trigger === 'daily-digest') {
  await sendDigest();
} else if (trigger === 'stripe') {
  const event = JSON.parse(process.env.WEBHOOK_PAYLOAD ?? '{}');
  await handleStripe(event);
}

console.log(`run ${runId} done`);
Triggered-componenten hebben geen inactieve machines in productie — ze starten per oproep op en sluiten af bij afsluiting.

Webhook-URL’s

POST https://api.kazzle.app/webhooks/{spaceId}/{appId}/{componentName}/{triggerName}
Het triggerName-segment moet overeenkomen met een kind: 'webhook'-item in de triggers[] van die component. Onbekende triggernamen retourneren 404.

Schemaresolutie

Cron-expressies zijn 5-veld (minuut, uur, dag-van-maand, maand, dag-van-week) en minuutresolutie is het minimum. Sub-minuutschema’s worden afgewezen bij validatie van het manifest.

Hoe runs worden geregistreerd

Elke triggeractivering schrijft een process_runs-rij met de trigger_name, triggered_by, run_id en de afsluitstatus van de run. Je kunt deze opvragen vanuit je eigen code of inspecteren in de runs-weergave van de app.

Tegoed op

Een mislukte run wordt geregistreerd en gelogd, maar het schema blijft op zijn normale cadans lopen — een onbetrouwbare run schakelt de trigger nooit uit. Het enige wat een run stopt is tegoed: elke triggeractivering wordt gecontroleerd tegen het saldo van de space, en terwijl de space geen tegoed heeft (of geen facturering is ingesteld) worden runs overgeslagen met een 402. Dit herstelt zichzelf — het schema blijft actief en de volgende activering nadat je het aanvult, wordt normaal uitgevoerd, zonder handmatig hervatten.

Automatiseringen later toevoegen

Een eenvoudige app kan zonder triggers beginnen en deze later krijgen — voeg een dagelijks overzicht toe, verbind Stripe, voer opschoning uit. De levenscyclus van de component (processMode) en triggers (triggers[]) zijn onafhankelijk, dus je kunt ze wijzigen zonder de rest van de app te herschrijven.