> ## Documentation Index
> Fetch the complete documentation index at: https://aerojs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Formatting

> Format Aero HTML templates with Prettier and Aero-specific options; use oxfmt for JavaScript and TypeScript.

Aero templates (`.html` files) use **[Prettier](https://prettier.io)** with [`@aero-js/prettier-plugin-aero`](https://www.npmjs.com/package/@aero-js/prettier-plugin-aero). JavaScript and TypeScript in your project can keep using **[oxfmt](https://oxc.rs/docs/guide/usage/formatter)** — the two tools coexist via per-language VS Code defaults.

## Quick setup

1. Install dev dependencies:

```bash theme={"theme":"github-dark-default"}
pnpm add -D prettier @aero-js/prettier-plugin-aero
```

2. Add `.prettierrc.json`:

```json theme={"theme":"github-dark-default"}
{
  "semi": false,
  "useTabs": true,
  "tabWidth": 2,
  "plugins": ["@aero-js/prettier-plugin-aero"],
  "overrides": [
    {
      "files": ["**/*.html"],
      "options": { "parser": "aero" }
    }
  ]
}
```

3. Install the [Prettier VS Code extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode). The [Aero extension](/tooling/vscode-extension) recommends it; configure Prettier for `.html` files via project `.prettierrc` (and optional editor defaults for `[html]` if you want workspace-wide formatting).

4. (Optional) Exclude Aero HTML from oxfmt so templates are not double-formatted. In `.oxfmtrc.json`:

```json theme={"theme":"github-dark-default"}
{
  "ignorePatterns": ["**/client/**/*.html"]
}
```

## Standard Prettier options

All usual Prettier settings (`printWidth`, `useTabs`, `htmlWhitespaceSensitivity`, `singleAttributePerLine`, etc.) apply to Aero `.html` files. Embedded `<script is:build lang="ts">` and `<style>` blocks are formatted with Prettier's JS/TS/CSS rules.

The plugin adds three **Aero-only** options (also set in `.prettierrc.json` or under `overrides`). With the [Aero VS Code extension](/tooling/vscode-extension) installed, those options get autocomplete and hover docs in Prettier config files.

| Option                      | Default  | Description                                                                                                                                                                                                                                                                          |
| --------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `aeroAttributePrefix`       | `"none"` | Prefix form for Aero framework attributes (see below).                                                                                                                                                                                                                               |
| `aeroBracketSpacing`        | `true`   | When `true`, use `{ expr }` wrapper spacing in directive values and text interpolation. When `false`, use `{expr}`. Nested object interpolations follow the same option (`{ { foo: 1 } }` vs `{{foo: 1}}`) and stay on one line. Other JS/TS still uses Prettier's `bracketSpacing`. |
| `aeroSelfClosingComponents` | `true`   | When `true`, prefer `<my-component />` for `*-component` tags with no element children. `*-layout` tags always keep explicit close tags.                                                                                                                                             |

### What `aeroAttributePrefix` rewrites

Prettier rewrites **Aero framework attribute names that are not native HTML**. It leaves real HTML alone (including when Aero binds it), third-party attrs (`x-*`, `hx-*`, …), emit-only markers (`data-aero-event`, `data-aero-bind`, …), and unimplemented names (`computed:*`, `state`).

**Rewritten families:** build directives (`if`, `for`, `props`, …), `key`, simple runtime (`show`, `html`, `busy`, `text`), `on:*`, `class:*`, `bind:*`, and script taxonomy (`is:build`, `is:state`, `is:inline`, `is:blocking`).

| Mode       | Example forms                                                                             | Rule                              |
| ---------- | ----------------------------------------------------------------------------------------- | --------------------------------- |
| `"none"`   | `is:build`, `on:click`, `class:is-active`, `text`                                         | Author form; keep colons          |
| `"aero"`   | `aero-is:build`, `aero-on:click`, `aero-class:is-active`, `aero-text`                     | Ownership prefix; **keep colons** |
| `"strict"` | `data-aero-is-build`, `data-aero-on-click`, `data-aero-class-is-active`, `data-aero-text` | **Strict HTML**; colons → hyphens |

Plain HTML attributes (e.g. `<label for="email">`, `disabled="{ saving }"`) are never rewritten. Author `text="{ … }"` and `data-aero-text="{ … }"` are the **same** directive under different modes — not an emit-only marker.

Example with Aero options:

```json theme={"theme":"github-dark-default"}
{
  "plugins": ["@aero-js/prettier-plugin-aero"],
  "overrides": [
    {
      "files": ["**/*.html"],
      "options": {
        "parser": "aero",
        "aeroAttributePrefix": "aero",
        "aeroBracketSpacing": true,
        "aeroSelfClosingComponents": true
      }
    }
  ]
}
```

## CLI

Format templates from the project root:

```bash theme={"theme":"github-dark-default"}
pnpm exec prettier --write "**/*.html"
```

Projects scaffolded with `@aero-js/create` include `.prettierrc.json` and recommended VS Code extensions.

<Tip>
  Prettier config is the single source of truth for Aero format options. You do not need separate `aero.format.*` VS Code settings.
</Tip>
