# Portable products

Asuka Designer can move a complete reusable product between JavaScript,
WordPress/WooCommerce, Shopify, and custom integrations with one
`.asuka.zip` package.

The package belongs to Asuka Designer, not to the commerce platform that
created it. Importing it creates or restores an autonomous designer product.
The destination integration links that product to its own catalog separately.

## What is portable

- views and their 2D or 3D documents;
- objects, layers, elements, variations, colors, and dimensions;
- drawing areas, product parameters, assembly data, and pricing rules;
- layout, modules, permissions, and presentation settings;
- fonts, images, SVG files, GLB/glTF models, and related local media;
- the selected reusable template and theme when they are included.

## What is never portable

- WooCommerce products, variations, IDs, or SKUs;
- Shopify products, variants, GIDs, shop domains, or metafield bindings;
- carts, checkout sessions, orders, customers, and subscriptions;
- license keys, signed tokens, credentials, API keys, or upload endpoints;
- host runtime state and platform-specific database identifiers.

Internal Asuka identifiers remain in place. For example, an object's
`productId` can identify its reusable Asuka element and is required to preserve
relations between product parts. It is not a commerce product identifier.

## Package layout

```text
product-name.asuka.zip
|-- manifest.json
|-- checksums.sha256
|-- product.json
|-- dependencies/
|   |-- template.json
|   `-- themes/*.json
`-- assets/*
```

`product.json` uses the stable `asuka-product` schema. The canonical designer
state is stored in `designer.state`. Imports also accept the old
`designer.initialState` field and normalize it immediately.

Every file except `checksums.sha256` is covered by a SHA-256 checksum. Importers
validate paths, file counts, expanded sizes, checksums, document schemas, and
supported media types before creating anything.

## JavaScript export

```ts
const archive = await designer.util.state.exportPortablePackage({
  name: 'Modular kitchen',
  slug: 'modular-kitchen',
});

const blob = new Blob([archive], { type: 'application/zip' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'modular-kitchen.asuka.zip';
link.click();
URL.revokeObjectURL(link.href);
```

The default media resolver embeds reachable HTTP assets and Base64 data URLs.
An integrator can provide `resolveAsset` to read media from another storage
system.

## JavaScript import

```ts
await designer.util.state.importPortablePackage(file, {
  publishAsset: async (asset) => {
    const body = new FormData();
    body.append('file', new Blob([asset.data], { type: asset.mime }), asset.filename);

    const response = await fetch('/designer-assets', { method: 'POST', body });
    if (!response.ok) throw new Error('The asset could not be published.');
    return (await response.json()).url;
  },
  state: {
    replaceViews: true,
    replaceSnapshots: true,
  },
});
```

Without `publishAsset`, media is restored as data URLs. A production
integration should normally publish files to its own durable media storage and
return their public URLs.

The lower-level helpers are also exported for integrations that want to
inspect a package before restoring it:

```ts
const productPackage = await readAsukaPortableProductPackage(file);
const materialized = await materializeAsukaPortableProductPackage(
  productPackage,
  publishAsset,
);
```

## WordPress and WooCommerce

Open **Asuka Designer > Import / Export**.

1. Select a custom product and download its complete package.
2. On the destination site, upload the package and review its contents.
3. Choose whether matching templates and themes are reused or copied.
4. Import it as a draft.
5. Review the product, then link it to a WooCommerce product or variation.

The importer recreates media-library files and never restores an old
WooCommerce binding.

## Shopify

Open **Asuka Product Designer > Import / Export**.

The same analyze-then-import flow uploads packaged media to Shopify Files and
creates an unlinked custom-product draft. Link it afterwards from Shopify's
native product editor. Store, product, variant, cart, order, billing, and
license data are never read from the archive.

## Custom integrations

A custom adapter only needs three responsibilities:

1. provide media bytes during export with `resolveAsset`;
2. store media during import with `publishAsset`;
3. keep its catalog binding outside the portable Asuka document.

This boundary allows the same archive to move from WordPress to Shopify, from
Shopify to a direct JavaScript site, or into an integration that does not exist
yet.
