> For the complete documentation index, see [llms.txt](https://docs.aurelia.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.aurelia.io/recipes/markdown-integration.md).

# Markdown integration

{% hint style="info" %}
**Bundler note:** These examples import '.html' files as raw strings (showing '?raw' for Vite/esbuild). Configure your bundler as described in [Importing external HTML templates with bundlers](/components/components.md#importing-external-html-templates-with-bundlers) so the imports resolve to strings on Webpack, Parcel, etc.
{% endhint %}

The default Aurelia 2 starter uses Vite, which can import plaintext assets with the built-in `?raw` query string. That makes it easy to store content in `.md` files, load the raw Markdown at build time, and render it with a library such as `markdown-it` before handing it to Aurelia's templating system.

## 1. Install the Markdown toolchain

```bash
npm install markdown-it dompurify
```

* `markdown-it` converts Markdown into HTML on the client with support for GFM tables, autolinks, etc.
* `dompurify` sanitizes the rendered HTML so untrusted Markdown cannot inject scripts.

## 2. Tell TypeScript about `?raw` Markdown imports

Add the following to `src/env.d.ts` so TypeScript understands `import doc from './doc.md?raw'`:

```ts
declare module '*.md?raw' {
  const content: string;
  export default content;
}
```

## 3. (Optional) Hint Vite about Markdown assets

If you keep Markdown outside `src/`, add an `assetsInclude` entry so Vite watches those files:

```ts
// vite.config.ts
import { defineConfig } from 'vite';
import aurelia from '@aurelia/vite-plugin';

export default defineConfig({
  plugins: [aurelia()],
  assetsInclude: ['**/*.md'],
});
```

## 4. Create a reusable Markdown viewer

### Component template

```html
<!-- src/resources/markdown-viewer.html -->
<template>
  <article class="markdown-body" innerhtml.bind="html"></article>
</template>
```

### Component logic

This example automatically loads files from `src/content` via `import.meta.glob`, converts them with `markdown-it`, and sanitizes the HTML before binding it to the DOM.

```ts
// src/resources/markdown-viewer.ts
import { bindable, customElement } from '@aurelia/runtime-html';
import MarkdownIt from 'markdown-it';
import DOMPurify from 'dompurify';

const markdownFiles = import.meta.glob('../content/**/*.md', { as: 'raw' });
const md = new MarkdownIt({ html: false, linkify: true, typographer: true });

import template from './markdown-viewer.html?raw';

@customElement({ name: 'markdown-viewer', template })
export class MarkdownViewer {
  @bindable() src: string = 'about.md';
  protected html = '';

  binding() {
    void this.load(this.src);
  }

  protected srcChanged(newValue: string) {
    void this.load(newValue);
  }

  private async load(path: string | undefined) {
    if (!path) {
      this.html = '';
      return;
    }

    const key = `../content/${path}`;
    const loader = markdownFiles[key];
    if (!loader) {
      this.html = `<p>Cannot find ${path}</p>`;
      return;
    }

    const raw = await loader();
    const rendered = md.render(raw);
    this.html = DOMPurify.sanitize(rendered);
  }
}
```

## 5. Author Markdown content

Place any `.md` files under `src/content`. For example:

```markdown
<!-- src/content/about.md -->
# About

Aurelia renders *Markdown* via **markdown-viewer**.
```

## 6. Use Markdown inside your views

```html
<!-- src/components/my-app.html -->
<template>
  <markdown-viewer src="about.md"></markdown-viewer>
</template>
```

## Troubleshooting & tips

* **Hot reload:** Because the files are imported through Vite's module graph, edits to `.md` files trigger HMR automatically.
* **Frontmatter:** If you need YAML frontmatter, parse it in `load()` (e.g., with `gray-matter`) before passing the Markdown body to `markdown-it`.
* **Accessibility:** Keep semantic headings in your Markdown so screen readers can navigate the generated article structure.
* **Security:** Always sanitize rendered HTML before binding it with `innerhtml.bind` when authors can edit Markdown content.

With this setup you can freely mix `.html` and `.md` files in your Aurelia project, while still leveraging Vite features such as `import.meta.glob`, lazy loading, and HMR.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.aurelia.io/recipes/markdown-integration.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
