# Fonts

AsukaDesigner v1 includes a runtime font registry designed to support system fonts, Google Fonts, and self-hosted custom fonts.

This registry is used by text-related modules such as:

- `font-family`
- `text-formatting`
- text creation flows

## Why the font registry matters

The font registry makes it possible to:

- configure fonts at startup
- register fonts at runtime
- load fonts on demand
- keep text modules synchronized with the available families
- preserve font metadata when exporting and re-importing JSON documents

## Font sources

The runtime supports three sources.

### System fonts

System fonts are local font families already available in the user environment.

```ts
'Arial'
// or: { id: 'brand-ui', family: 'Arial' }
```

### Google Fonts

Google Fonts can be declared with a family name and optional weights and styles.

```ts
'Roboto'
// or:
{
  family: 'Inter',
  weights: [400, 600, 700],
  styles: ['normal', 'italic']
}
```

### Custom fonts

Custom fonts are self-hosted and can be declared through a direct font file URL or a stylesheet URL.

```ts
{
  family: 'MyFont',
  url: '/fonts/my-font.woff2',
  format: 'woff2',
  weight: 400,
  style: 'normal'
}
```

## Configure fonts at startup

Use the `fonts` option when creating the designer.

```ts
const designer = createAsukaDesigner('#app', {
  fonts: {
    system: ['Arial', 'Georgia'],
    google: [
      'Roboto',
      { family: 'Inter', weights: [400, 600, 700] },
      { family: 'Poppins', weights: [400, 500, 700] },
    ],
    custom: [
      {
        family: 'MyFont',
        url: '/fonts/my-font.woff2',
        format: 'woff2',
        weight: 400,
        style: 'normal',
      },
    ],
  },
});
```

## Runtime font API

The public API exposes helpers through `designer.api`.

```ts
designer.api.getFonts();
designer.api.addSystemFont({ family: 'Arial' });
await designer.api.addGoogleFont({ family: 'Inter', weights: [400, 700] });
await designer.api.addCustomFont({ family: 'MyFont', url: '/fonts/my-font.woff2', format: 'woff2' });
designer.api.removeFont(id);
await designer.api.loadFont(id);
```

## Reading the registry

Use `getFonts()` to inspect the current registry.

A normalized registry entry typically includes:

- `id`
- `family`
- `source`
- `cssUrl`
- `url`
- `format`
- `weight`
- `style`
- `weights`
- `styles`
- `loaded`
- `loading`
- `error`

## On-demand loading

`loadFont(id)` can be used when a font should only be loaded right before it is needed.

Google and stylesheet-backed custom fonts resolve only after the stylesheet has loaded and the
requested families, weights, and styles are available through `document.fonts`. Direct custom font
files use the `FontFace` API. Text creation and font changes also await this readiness check before
either renderer measures or paints the text.

This is useful when:

- your integration registers many fonts up front
- you want a lighter initial load
- some fonts are only used in specialized flows

## Text modules and the registry

The text-related modules rely on the shared registry.

### `font-family`

This module lets users choose a family from the registered fonts.

### `text-formatting`

This module can use the registry to expose weight and style options consistently.

### Text creation and editing

When text is created or updated, the chosen font family comes from the same registry. The Text,
Font family, Fabric formatting, Babylon formatting, and Studio 3D controls expose that shared list.

## JSON persistence

The current project state serializes font metadata in text objects so a saved JSON document can restore the font configuration more reliably.

This matters when a document is reopened later and the font was not explicitly re-registered at startup.

As long as the exported JSON contains the font metadata, the runtime can use that information to rebuild or reload the font state.

## Best practices

- Register a small, curated font set instead of every possible family.
- Prefer stable `id` values when you want predictable references.
- Use Google Fonts for common web-safe brand typography.
- Use custom fonts for brand-critical or product-specific typography.
- Load expensive fonts on demand when initial bundle performance matters.
- Keep your startup font configuration aligned with the fonts you actually expose in the UI.

## Example: add fonts after initialization

```ts
const designer = createAsukaDesigner('#app');

designer.api.addSystemFont({ family: 'Verdana' });
await designer.api.addGoogleFont({ family: 'Roboto', weights: [400, 500, 700] });
await designer.api.addCustomFont({
  family: 'Brand Sans',
  url: '/fonts/brand-sans.woff2',
  format: 'woff2',
  weight: 400,
  style: 'normal',
});
```

## See also

- [Guides index](./index.md)
- [Quick start](./quick-start.md)
- [Built-in modules](./modules-built-in.md)
- [Examples](./examples.md)
