# Astro

> Add a handwriting animation to an Astro site with the server-rendered TegakiRenderer component, font registration and effects.

Source: https://tegaki.ink/frameworks/astro/

Tegaki has an Astro component that renders full HTML at build time and hydrates on the client. It needs no JavaScript framework, and the text is visible before hydration.

## Installation

```sh
npm install tegaki
```

Then add the Tegaki integration to your Astro config:

```js
// astro.config.mjs
import { defineConfig } from 'astro/config';
import tegaki from 'tegaki/astro/integration';

export default defineConfig({
  integrations: [tegaki()],
});
```

The component renders on the server and hands the font bundle to the browser, so the bundle's font URLs have to work there. Vite turns them into public asset URLs for client code but leaves server code as it stands, where they point at files on the build machine. The integration makes Vite resolve them on the server too. Without it, the build warns and the page loads the handwriting in a fallback font's widths.

## Basic example

```astro
---
import TegakiRenderer from 'tegaki/astro';
import bundle from 'tegaki/fonts/caveat';
---

<TegakiRenderer
  font={bundle}
  text="Hello World"
  time={{ mode: 'uncontrolled', speed: 1, loop: true }}
  style="font-size: 48px"
/>
```

## Font registration

When using the same font across multiple components on a page, you can register the bundle once and reference it by name. This avoids duplicating the font data in the HTML output.

### Register the bundle

Use the `bundle` prop on a dedicated instance. It serializes the font data into a `<script type="application/json">` tag and registers it on the client. Once registered, reference the font by its family name (the `fullFamily` field of the bundle, e.g. `"Caveat"`):

```astro
---
import TegakiRenderer from 'tegaki/astro';
import bundle from 'tegaki/fonts/caveat';
---

<!-- Register the bundle once (renders nothing visible) -->
<TegakiRenderer font={bundle} bundle />

<!-- Use the font by name -->
<TegakiRenderer font="Caveat" text="First line" />
<TegakiRenderer font="Caveat" text="Second line" />
```

### Preload the font

Add `loadFont` to inject an `@font-face` rule so the browser starts downloading the font file immediately:

```astro
<TegakiRenderer font={bundle} bundle loadFont />
```

## Effects

```astro
---
import TegakiRenderer from 'tegaki/astro';
import bundle from 'tegaki/fonts/caveat';
---

<TegakiRenderer
  font={bundle}
  text="Fancy effects"
  time={{ mode: 'uncontrolled', speed: 1, loop: true }}
  effects={{
    glow: { radius: 8, color: '#00ccff' },
    pressureWidth: true,
    strokeGradient: { colors: 'rainbow' },
  }}
  style="font-size: 48px"
/>
```

## How it works

1. **Build time**: the Astro component calls `TegakiEngine.renderElements()` to produce the full HTML (canvas fallback text, overlay, sentinel). Text is visible in the initial HTML even without JavaScript.
2. **Bundle serialization**: because font glyph data lives in server memory during SSR, it must be embedded into the HTML to reach the browser. When `font={bundle}` is passed as an object, the component serializes the bundle into a `<script type="application/json">` tag. If the same font is used across multiple renderers on the same page, use the `bundle` prop once to serialize it and reference it by name afterward, so the bundle data isn't duplicated in the HTML output.
3. **Client hydration**: a module script reads any serialized bundle tags and registers them, then finds all `[data-tegaki-options]` elements, creates a `TegakiEngine` with `adopt: true` (reusing existing DOM), and starts the animation.
4. **Dynamic elements**: a `MutationObserver` watches for elements added after initial load (e.g., from View Transitions or client-side routing) and hydrates them.

## Props

The Astro component accepts all [`TegakiEngineOptions`](https://tegaki.ink/api/renderer/) plus:

| Prop | Type | Description |
|------|------|-------------|
| `bundle` | `boolean` | Register the font bundle for client-side lookup by name |
| `loadFont` | `boolean` | Inject `@font-face` CSS for early font loading |
| `class` | `string` | CSS class on the container |
