# Overview

URL: https://zerodev.ca/docs/kora/developer-documentation

> How a Kora module is laid out, how it loads and what it can hook into.



Everything Kora does at runtime comes from a module, including Core. Your own modules load the same way and get the same access to the database, API, dashboard, audit log and languages.

For installing and running Kora, see the [Setup Guide](/docs/kora/setup).

## Layout

Each folder in `modules/` is one module. Kora imports its `main.js` and loads everything under `src/` and `resources/` by folder.

```text
modules/
  example/
    main.js
    resources/
      config/
      dashboard/
        pages/
      lang/
    src/
      clocks/
      commands/
      events/
      handlers/
      models/
      routes/
```

| Folder                       | Files loaded                                        | Base class |
| ---------------------------- | --------------------------------------------------- | ---------- |
| `main.js`                    | The module                                          | `Modules`  |
| `src/models/`                | Every `*.js`                                        | `Models`   |
| `src/handlers/`              | Every `*.js`                                        | `Handlers` |
| `src/routes/`                | Every `route.js`, at any depth                      | `Routes`   |
| `src/clocks/`                | Every `*.js`                                        | `Clocks`   |
| `src/events/`                | Every `*.js`                                        | `Events`   |
| `src/commands/`              | Every `*.js`                                        | `Commands` |
| `resources/config/`          | Every `*.js`                                        | `Configs`  |
| `resources/lang/`            | `en/*.js` classes, plus a folder of JSON per locale | `Langs`    |
| `resources/dashboard/pages/` | Every `page.js`, at any depth                       | `Pages`    |

Import every base class from `#kora/modules`.

## Loading

Kora loads modules in two passes.

1. **Register.** Install any missing `dependencies.node` packages, then read configs, languages, models, routes and pages.
2. **Load.** Start handlers, events, commands and clocks, call `onStartup()`, sync tables and mount routes.

When Kora stops or a module is turned off, it stops clocks, removes events, calls `onShutdown()` and unmounts routes.

A module that throws while loading is marked as failed and shown on the **Modules** page. The others keep running.

## main.js

```js title="modules/example/main.js"
import { Modules } from "#kora/modules";

export class Example extends Modules {
    constructor(kora) {
        super(kora, {
            name: "example",
            displayName: "Example",
            author: "Your Name",
            version: "1.0.0",
            description: "Does one thing well",
            icon: "box",
            requires: ["core"],
            dependencies: { node: ["nanoid"] }
        });
    }

    async onStartup() {
        this.kora.console.log(this.kora.console.levels.info, `${this.getName()} started.`);
    }
}
```

| Key                                | Default  | What it does                                          |
| ---------------------------------- | -------- | ----------------------------------------------------- |
| `name`                             | Required | The module ID. Use the folder name.                   |
| `displayName`                      | `name`   | Shown in the dashboard.                               |
| `author`, `version`, `description` | None     | Shown on the **Modules** page.                        |
| `icon`                             | `puzzle` | A [Lucide](https://lucide.dev/icons) icon name.       |
| `requires`                         | `[]`     | Modules that must load first.                         |
| `dependencies.node`                | `[]`     | npm packages Kora installs before loading the module. |

## Hooks

Add any of these methods to your module class.

| Method                         | Called                                                                                  |
| ------------------------------ | --------------------------------------------------------------------------------------- |
| `onStartup()`                  | After the module loads.                                                                 |
| `onShutdown()`                 | Before it unloads.                                                                      |
| `permissions()`                | When Kora lists permissions. Return `[{ id, label }]`. They show up when editing roles. |
| `overview(actor)`              | When the **Overview** page loads. Return `{ stats, charts, lists }`.                    |
| `search(query, actor)`         | When someone uses the dashboard search. Return `[{ type, label, hint, href }]`.         |
| `fields(module, page)`         | When another module's page is described. Return extra form fields for it.               |
| `decorate(module, page, rows)` | When another module's page lists rows. Return the rows with your data added.            |

`overview` and `search` only run for staff with the `<module>.view` permission.

Each entry in `stats` is `{ key, label, value, hint, icon, tone, period }`. Set `period` to a number of days to show it as a badge in the card's corner instead of writing it into the label.

BuiltByBit uses `fields` and `decorate` to add a **BuiltByBit resource** picker to Core's product form:

```js
fields(module, page) {
    if (module !== "core" || page !== "products") return [];
    return [{ key: "builtbybit_resource", label: "BuiltByBit resource", type: "reference", source: { module: "builtbybit", endpoint: "/resources", label: "title", value: "id" } }];
}
```

## The kora Object

Every class gets the running instance as `this.kora`.

| Property             | What it is                                                              |
| -------------------- | ----------------------------------------------------------------------- |
| `this.kora.database` | The Sequelize connection.                                               |
| `this.kora.settings` | Values from the **Settings** page.                                      |
| `this.kora.console`  | The logger.                                                             |
| `this.kora.audit`    | The audit log.                                                          |
| `this.kora.signer`   | Signs and checks payloads with the response signing key.                |
| `this.kora.events`   | The event bus. See [Events](/docs/kora/developer-documentation/events). |
| `this.kora.modules`  | Every loaded module and its parts.                                      |

## Reaching Other Modules

```js
this.kora.modules.models.get("core", "licenses");
this.kora.modules.handlers.get("core", "licenses");
this.kora.modules.config.values("core", "licenses");
this.kora.modules.lang.phrase("core", "messages", "valid");
```
