---
tags: help, lifecycle
order: 110
description: the init page: what it is, the lifecycle messages it handles, declaring crons, examples
---
# Help: the init page

A project's **init page** is where it sets itself up, in rules rather than in settings screens: what it needs when it starts, the jobs it runs on a schedule, and how it reacts to what happens to its data. It's one topic, `Settings:Init`, and d2 sends it messages as things happen.

## What it is

- **One page per project:** `Settings:Init`. Open it from **Admin → Init**. A new project has none: the Init card says so and offers **Create the init page**, which makes a starter page with a short explanation and one rule.
- **Compiled like a spec:** its frontmatter has `tags: spec`, so the lines starting with `$` are rules (`$when`, `$class`…) and the rest is notes for people. Save it and it's compiled at once; a mistake is shown when you save.
- **Only mods and admins edit it,** like every Settings page. Members can read it.
- **Its rules run as flows:** each message it handles runs as a flow you can open under **Flows**. A failing rule shows there and in the audit log, and never stops the project from loading.
- **Sent only when handled:** d2 raises a message in your project only if a rule there takes it, so a message you don't handle costs nothing and leaves no flow behind.

## The lifecycle messages

The ones an init page usually handles (every message, and what it carries: [[Help:LifecycleMessages]]):

- **`diesel.project.on.init`**: the project was loaded (d2 started or was updated) or this page was saved. The place to declare what the project needs, since it runs again whenever you change the page.
- **`diesel.project.on.created`**: once, when the project was made.
- **`diesel.project.on.released (version)`**: after a release (**Admin → Project**).
- **`diesel.entity.on.created`**, **`updated`**, **`deleted (category, key)`**: an object was added, changed or deleted, by a form, the API, your AI or a flow. `category` is its class; pick the ones a rule is for with a condition: `if (category is "Holding")`.
- **People, pages, the pipeline and quotas** have their own messages too (a join request, a page published, an item done, a limit reached): see [[Help:LifecycleMessages]].

Two safety rules: the writes a rule makes while handling an object's message don't send more of them, so a rule can't loop on its own writes; and your rules can't send d2's own messages themselves (`E_NATIVE`), only handle them.

## Declaring crons

A cron sends one of your messages on a schedule. Declare them in `diesel.project.on.init`, so they're made on every start and follow the page whenever you change it:

    $when diesel.project.on.init {
      diesel.cron(name = "morning-prices", schedule = "0 7 * * 1-5", tz = "America/Toronto", msg = "portfolio.refresh", args = {})
      diesel.cron(name = "nightly-tidy", schedule = "daily 03:15", msg = "portfolio.tidy")
    }

    $when portfolio.refresh {
      log (msg = "refreshing prices")
    }

- **The schedule** is a 5-field cron (`0 7 * * 1-5`), `every 15m`, `hourly` or `daily 03:15`, in UTC unless `tz` names a time zone. A bad schedule or zone fails the flow with `E_ARG`.
- **The same name again replaces it** with the new schedule; the same cron sent again unchanged stays as it was, on or off. `diesel.cron.remove (name)` deletes one, `diesel.cron.list ()` lists them.
- **`msg` is your own message,** never one of d2's; when it's due it's sent in the project with `args`, as a flow.
- **Limits:** how many crons a project may have, and how often at most, depend on its plan (**Admin → Quotas**); over them the flow fails with `E_QUOTA`.
- **Watching them:** the **Crons** page (`/crons`, a Toolbox tile) lists them with their next and last runs; admins run one now or turn it on or off. After 5 failures in a row a cron is switched off and the owner gets a notice.

## Examples

**Record each start and each release:**

    $class Stats (@key id: String, started: String?, lastRelease: String?)

    $when diesel.project.on.init {
      s = dom.find(cls = "Stats", key = "main") ?? {id: "main"}
      dom.upsert(cls = "Stats", entity = s + {started: isoDate(now())})
    }

    $when diesel.project.on.released (version) {
      s = dom.find(cls = "Stats", key = "main") ?? {id: "main"}
      dom.upsert(cls = "Stats", entity = s + {lastRelease: version})
    }

**Tell the owner when an order comes in:**

    $when diesel.entity.on.created (category, key) if (category is "Order") {
      diesel.user.notify (to = "razie", text = "New order " + key, code = "new-order", link = "/dom/Order/" + key)
    }

**A weekly report, as a cron:**

    $when diesel.project.on.init {
      diesel.cron(name = "weekly-report", schedule = "0 8 * * 1", tz = "America/Toronto", msg = "report.weekly")
    }

    $when report.weekly {
      diesel.ai.pipeline.create (title = "Write the weekly report", forRole = "user", forName = "razie", kind = "admin")
    }

A complete page to copy from, with a running count of objects: [[Help:InitExample]]. The expressions used in rules: [[Help:Expressions]].

## Good to know

- **Keep `diesel.project.on.init` safe to run again:** it runs on every start and every save of the page, so write it to set things (upsert, declare a cron by name) rather than add them.
- **A rule acts as the project:** requests it sends (notices, emails, pipeline items) go only to the project's members and count against the project's quotas.
- **Scratch runs don't count:** the fiddle and runs that don't write send no object messages, and nothing a fiddle run asks for is sent.
