# Quick start

This guide shows the fastest path to a working AsukaDesigner v1 integration.

## Package integration

```ts
import { createAsukaDesigner } from 'asuka-designer';

const designer = createAsukaDesigner('#app');

await designer.api.addText({ text: 'Hello AsukaDesigner' });
```

## Browser integration

```html
<div id="app"></div>
<link rel="stylesheet" href="./dist/product/asukadesigner.min.css" />
<script type="module">
  import { createAsukaDesigner } from './dist/product/asukadesigner.min.js';
  const designer = createAsukaDesigner('#app');
  await designer.api.addText({ text: 'Hello AsukaDesigner' });
</script>
```

## Recommended default layout

The current recommended default layout is:

```ts
const designer = createAsukaDesigner('#app', {
  layout: {
    left: {
      items: [
        { kind: 'views', label: 'Views', icon: 'views', type: 'floating' },
        { kind: 'designs', label: 'Designs', icon: 'brush', type: 'floating' },
        { kind: 'text', label: 'Text', icon: 'text', type: 'floating' },
        { kind: 'image', label: 'Images', icon: 'images', type: 'floating' },
        { kind: 'shapes', label: 'Shapes', icon: 'customize', type: 'floating' },
        { kind: 'layers', label: 'Layers', icon: 'layers', type: 'floating' },
      ],
    },
    top: {
      collapsed: true,
      items: [
        { kind: 'magnifier', label: 'Magnifier', icon: 'magnifying-glass', type: 'floating' },
        { kind: 'ruler', label: 'Ruler', icon: 'ruler', type: 'floating' },
        { kind: 'zoom', label: 'Zoom', icon: 'zoom', type: 'floating' },
        { kind: 'download', label: 'Download', icon: 'download', type: 'floating' },
      ],
    },
    right: { items: [] },
    bottom: { items: [] },
  },
});
```

## Create content

### Add text

```ts
await designer.api.addText({
  text: 'My first text',
  fontSize: 48,
});
```

### Add a rectangle

```ts
await designer.engine.canvas2d?.addShape({
  kind: 'rect',
  width: 180,
  height: 100,
  fill: '#111827',
});
```

## Work with views

```ts
const frontViewId = designer.api.getActiveViewId();
const backViewId = designer.api.addView({
  name: 'Back',
});

designer.api.setActiveView(backViewId);
await designer.api.addText({ text: 'Back side' });
designer.api.setActiveView(frontViewId);
```

## Configure fonts at startup

```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',
      },
    ],
  },
});
```


## Configure image uploads

The built-in Upload flow supports three startup strategies:

When `moduleConfig.upload` is omitted, local files are converted to Base64. An `endpoint` or a
custom `handler` implicitly enables remote upload; declaring `strategy: 'remote'` is therefore
optional. An explicit `strategy` always wins.

### Local object URLs

```ts
const designer = createAsukaDesigner('#app', {
  moduleConfig: {
    upload: {
      strategy: 'objectUrl',
    },
  },
});
```

### Base64 data URLs

```ts
const designer = createAsukaDesigner('#app', {
  moduleConfig: {
    upload: {
      strategy: 'base64',
    },
  },
});
```

### Remote uploads

```ts
const designer = createAsukaDesigner('#app', {
  moduleConfig: {
    upload: {
      strategy: 'remote',
      endpoint: '/upload.php',
      method: 'POST',
      credentials: 'include',
      mapResponseToUrl: (json) => json.url,
    },
  },
});
```

Remote uploads are useful when your backend stores files permanently and returns a final public URL. You can use either `endpoint` + `mapResponseToUrl`, or a custom `handler`:

```ts
createAsukaDesigner('#app', {
  moduleConfig: {
    upload: {
      strategy: 'remote',
      handler: async (file) => {
        const body = new FormData();
        body.append('image', file, file.name);
        const response = await fetch('/api/asuka/upload', { method: 'POST', body });
        const json = await response.json();
        return json.url;
      },
    },
  },
});
```

For WordPress/admin media libraries, avoid DOM upload interception. Pass a host-controlled `selectHandler`; AsukaDesigner waits for the promise and then owns the rest of the flow:

```ts
createAsukaDesigner('#app', {
  moduleConfig: {
    upload: {
      selectHandler: async (context) => {
        const media = await window.openAdminMediaPicker({ multiple: context.multiple });
        return media.map((item) => ({
          url: item.url,
          name: item.filename || item.name,
          source: 'wordpress-media',
          attachmentId: item.id,
          metadata: item,
        }));
      },
    },
  },
});
```

The upload policy applies identically to the Upload module, the public image API, both Fabric and
Babylon renderers, remote image providers when CORS permits the download, and form file inputs
(`MediaInput`, `ImageField`, `IconField`).

## Open a built-in module

```ts
designer.layout.openModule('text');
designer.layout.openModule('layers');
```

## Use the contextual selection menu

```ts
designer.layout.selectionMenu.setType('popover');
designer.layout.selectionMenu.open();
```

For text objects, the contextual flow typically includes:

- `font-family`
- `text-formatting`
- `text-curve`
- `colors`

## Export the active view

```ts
await designer.engine.exports.download(undefined, {
  format: 'png',
});
```

## See also

- [Guides index](./index.md)
- [Installation](./installation.md)
- [API overview](./api-overview.md)
- [Examples](./examples.md)


## Save and restore a document

```ts
const saved = designer.util.state.exportPart('document');
saveToDatabase(saved);
```

```ts
const saved = await loadFromDatabase();

const designer = createAsukaDesigner('#app', {
  initialState: saved,
});
```


## Optional shell sizing

If you want to control the outer designer size, pass a `shell` configuration at initialization.

```ts
const designer = createAsukaDesigner('#app', {
  shell: {
    width: '1100px',
    height: '75vh',
    maxWidth: null,
    maxHeight: null,
  },
});
```


## Keep controls and helpers readable on small responsive mounts

```ts
const designer = createAsukaDesigner('#app', {
  shell: {
    width: "100%",
    height: "80vh",
  },
  uiScaling: {
    keepControlsReadable: true,
    keepHelpersReadable: true,
  },
});
```

Use this when the designer is embedded inside a smaller layout but you still want controls and technical helper overlays to remain easy to read.
