# Loaders

> Tell Kiln where templates come from.

A loader tells Kiln where to find templates. Kiln asks it for a template by name the first time the template is used.

## `memoryLoader`

Holds templates in memory, as an object or a `Map`. It works everywhere, including Cloudflare Workers. A template can be its source or a [precompiled module](https://kilnlang.com/docs/api/precompiling/).

```ts
import { createKiln, memoryLoader } from "@lucidkiln/core";

const kiln = createKiln({
	loader: memoryLoader({
		"layouts/base.kiln": layoutSource,
		"pages/home.kiln": homeSource,
	}),
});
```

## `fileLoader`

Reads templates from a folder. It is for Node only, so it lives in a separate entry point that never ends up in a Workers bundle.

- It never reads files or folders whose names start with a dot, such as `.env`.
- It does not follow symlinks below its root, whether they point to files or folders. They are missing templates and are not listed. The root itself may be a symlink.
- A name that points to a folder, or to nothing, is a missing template.
- Other read errors name the template and the error code, such as `EACCES`, but never the path on disk.

```ts
import { fileLoader } from "@lucidkiln/core/node";

const kiln = createKiln({
	loader: fileLoader({ root: "src/templates" }),
});
```

## Your own loader

A loader is an object with a `load` method. It gets a resolved name, such as `pages/home.kiln`, and returns the source or a [precompiled module](https://kilnlang.com/docs/api/precompiling/), or null if the template doesn't exist. It can be async, returning a promise or any other thenable.

Kiln keeps each template it loads until you call `invalidate`. It remembers only a limited number of missing names, so names built from requests can't fill memory. A template that fails to load or compile is loaded again the next time it is used.

```ts
import type { Loader } from "@lucidkiln/core";

const kvLoader = (kv: KVNamespace): Loader => ({
	load: (name) => kv.get(`templates/${name}`),
});
```

## Listing templates

A loader can also have a `list` method that returns the name of every template it holds, such as `pages/home.kiln`. Kiln never calls it while rendering. Tools use it, such as [`generateTypes`](https://kilnlang.com/docs/api/types/).

- `memoryLoader` lists every template you gave it.
- `fileLoader` lists every file under its root, skipping symlinks and files and folders whose names start with a dot. It does not enter skipped folders.
- In your own loader, `list` is optional and can be async.

```ts
const kvLoader = (kv: KVNamespace): Loader => ({
	load: (name) => kv.get(`templates/${name}`),
	list: async () =>
		(await kv.list({ prefix: "templates/" })).keys.map((key) =>
			key.name.slice("templates/".length),
		),
});
```

## Names

Kiln resolves names before it calls the loader. The loader gets a clean path relative to its root, with the `.kiln` extension added when the name has none. Kiln rejects names that would point above the root. See [Template names](https://kilnlang.com/docs/language/syntax/#template-names).
