# Initialization
This document covers the different ways to initialize mancha and configure its behavior.
## Choosing the Right Approach
Mancha offers three initialization methods. Use this decision guide to choose the right one:
| Method | Use When | Complexity |
|--------|----------|------------|
| **Script Tag** | Simple projects, prototypes, single-page apps with no build step | Lowest |
| **ES Module (`initMancha`)** | Projects with bundlers, need for initial state, custom initialization logic | Medium |
| **`:render` Attribute** | Initializing specific elements (charts, maps, etc.) within an already-mounted page | Element-level |
### Decision Flowchart
```
START: Do you have a build step (bundler/TypeScript)?
│
├─ NO → Use Script Tag with `init` attribute
│
│
└─ YES → Are you initializing the whole page or specific elements?
│
├─ WHOLE PAGE → Use ES Module with `initMancha`
│ import { initMancha } from "mancha/browser";
│ await initMancha({ target: "#app" });
│
└─ SPECIFIC ELEMENTS → Use `:render` attribute on those elements
```
### Quick Reference
**Script Tag** (simplest, no build step):
```html
```
**ES Module** (bundlers, TypeScript, custom init):
```typescript
import { initMancha } from "mancha/browser";
await initMancha({ target: "#app", state: { count: 0 } });
```
**`:render` Attribute** (element-level initialization):
```html
```
> [!TIP]
> **For AI agents**: Start with the Script Tag approach for simple tasks. Use ES Module when you need to set initial state programmatically or have a build step. Use `:render` only for third-party library integration on specific elements (charts, maps, video players).
---
## Script Tag
The simplest way to use mancha is via a script tag with the `init` attribute:
```html
```
### Script Tag Attributes
| Attribute | Description | Example |
|-----------|-------------|---------|
| `init` | Enables automatic initialization on page load | `init` |
| `target` | CSS selector(s) to mount to (default: `body`). Use `+` to separate multiple targets | `target="main"` or `target="#app+#sidebar"` |
| `css` | CSS bundles to inject. `"minimal"` for prose styling, `"utils"` for Tailwind-style utilities (includes CSS reset + on-demand scanning) | `css="utils"` |
| `debug` | Enable debug logging | `debug` |
| `cache` | Fetch cache policy for includes | `cache="no-cache"` |
| `cloak` | Control FOUC prevention (see below) | `cloak="200"` or `cloak="false"` |
## ES Module API
For more control, use the `initMancha` function:
```typescript
import { initMancha } from "mancha/browser";
const renderer = await initMancha({
target: "#app",
css: ["utils"],
state: { message: "Hello" },
});
```
### InitManchaOptions
| Option | Type | Description |
|--------|------|-------------|
| `renderer` | `Renderer` | Use an existing Renderer instance instead of creating a new one |
| `target` | `string \| string[]` | CSS selector(s) to mount to |
| `css` | `CssName[]` | CSS bundles to inject: `"minimal"` or `"utils"` (includes CSS reset + on-demand scanning) |
| `state` | `Record` | Initial state to set before mounting |
| `debug` | `boolean` | Enable debug logging |
| `cache` | `RequestCache` | Fetch cache policy for includes |
| `cloak` | `boolean \| CloakOptions` | FOUC prevention (see below) |
| `callback` | `Function` | Custom initialization callback (see below) |
## Cloaking (FOUC Prevention)
Cloaking hides your content until rendering is complete, preventing users from seeing raw template syntax like `{{ variable }}` or `:text="expr"` before JavaScript processes them.
### How It Works
Cloaking injects a global `
```
When `initMancha({ cloak: ... })` runs, it will detect this existing style tag (by its ID `mancha-cloak`) and take control of it, applying any configured transitions and removing it once rendering is complete.
### Keeping Loading Indicator Active
To keep the browser's loading spinner active while `mancha` initializes (e.g., fetching data or waiting for cloaking animations), use a module script with top-level await:
```html
```
### Custom Loading Indicators
During initialization (until `initMancha` resolves), `mancha` adds a `mancha-loading` class to the `` element. You can use this class to display a custom loading indicator or overlay while your application is bootstrapping.
**Recipe: Full-screen loading overlay**
```css
/* Hide the loader by default */
.loader {
display: none;
}
/* Show the loader only while mancha is loading */
html.mancha-loading .loader {
display: flex;
position: fixed;
inset: 0;
background: white;
z-index: 9999;
justify-content: center;
align-items: center;
}
```
```html
Loading...
...
```
This works perfectly with cloaking: `mancha-loading` is removed *immediately before* the cloaking fade-in animation starts, ensuring a seamless transition from your custom loader to the rendered app.
## Custom Initialization Callback
For advanced use cases, provide a `callback` function. When used, automatic mounting is skipped—you must call `renderer.mount()` yourself:
```typescript
import { initMancha } from "mancha/browser";
await initMancha({
cloak: { duration: 150 },
callback: async (renderer) => {
// Fetch data before mounting
const data = await fetch("/api/data").then((r) => r.json());
await renderer.set("items", data.items);
// Mount to the DOM
await renderer.mount(document.getElementById("app"));
},
});
```
The callback receives:
- `renderer`: The initialized Renderer instance
## Element-Level Initialization with `:render`
The `:render` attribute provides element-level initialization by linking an HTML element to a JavaScript ES module. This is useful for initializing third-party libraries (charts, maps, video players) on specific elements.
```html
```
The module's default export is called with the element and renderer:
```js
// chart-init.js
export default function (elem, renderer) {
new Chart(elem, { type: "bar", data: { labels: ["A", "B"], datasets: [{ data: [1, 2] }] } });
}
```
### When to Use `:render`
| Use `:render` When | Don't Use `:render` When |
|--------------------|--------------------------|
| Integrating third-party libraries (Chart.js, Leaflet, etc.) | Initializing the entire page |
| Element needs imperative JavaScript setup | Simple reactive data binding suffices |
| Canvas, video, or other media elements | Standard form inputs and displays |
| You need access to the DOM element directly | Pure declarative templates work |
### Key Characteristics
- **Runs after mount**: The init function executes after mancha has mounted the element
- **SSR compatible**: During server-side rendering, the path is resolved but the module is not executed
- **Relative paths**: Paths are resolved relative to the template file, not the HTML page
- **Reactive access**: The init function receives the renderer instance for reactive state access
For complete documentation on `:render` including reactive state access and custom components, see [Components & Preprocessing](./04_components.md#initialization-with-render).
## Combining Initialization Methods
You can combine the Script Tag or ES Module approach with `:render` attributes:
**Script Tag + `:render`** (most common for simple projects):
```html
Dashboard
```
**ES Module + `:render`** (for projects with bundlers):
```typescript
import { initMancha } from "mancha/browser";
await initMancha({
target: "#app",
state: { salesData: await fetchSalesData() },
});
// The :render attributes in #app will execute after mount
```
```html
```
> [!NOTE]
> `:render` scripts execute after `initMancha` or the script tag has mounted the page. They are not a replacement for page-level initialization, but a complement for element-specific setup.
## Advanced: Manual Initialization
> [!CAUTION]
> This is an advanced API. Most users should prefer `initMancha` which handles CSS injection, state initialization, and FOUC prevention automatically.
If you need full control without `initMancha`, you can use the lower-level API directly:
```typescript
import { Renderer, injectCss } from "mancha/browser";
// 1. Inject CSS utilities (optional)
injectCss(["utils"]);
// 2. Create renderer
const renderer = new Renderer();
// 3. Set state
await renderer.set("name", "World");
// 4. Mount to DOM
await renderer.mount(document.body);
```
## Summary: Initialization at a Glance
This table summarizes all initialization methods and when to use them:
| Method | Syntax | Use Case | FOUC Prevention | Build Step Required |
|--------|--------|----------|-----------------|---------------------|
| **Script Tag** | `