This skill is used to complete the current page into an exportable Figma Make asset structure and ensure that the final product obtained through the backend export interface is 名称.fig。
The final downloaded product here is not a .make archive, but the canvas.fig binary file in the project directory. The backend will directly download it to the user with the filename 名称.fig .
Core Objectives
- Make the current page have stable Figma export assets
- Ensure the exported
canvas.figis consistent with the current Axhub page content - Preserve all original Figma Make assets to avoid being unable to write back and export again later
Key Principles
- Sync the page first, then execute pack
If the real entry point of the current page is the root directory index.tsx / style.css, and the export shell uses src/App.tsx / src/index.css, then the two must be synchronized first, then run canvas-fig-sync.mjs pack。
Do not only update the root directory page but directly write back the old src/App.tsx, otherwise the exported .fig content will be inconsistent with the current page.
- Prioritize "thin shell" synchronization
As long as the structure allows, prioritize having the export shell reuse the current page entry, rather than maintaining another copy that easily drifts:
src/App.tsxPrioritize serving as a thin wrapper, directly reusing the current page main component or shared componentssrc/index.cssPrioritize reusing or importing the root directorystyle.cssreal style source- If code must be copied, it must also be updated to be consistent within this task
- Preserve original assets
If the following files already exist in the directory, they must be preserved:
canvas.figmeta.jsonai_chat.jsonthumbnail.pngcanvas.code-manifest.jsonimages/
- Use a fixed directory structure
To reduce subsequent maintenance costs, the page directory adopts a fixed separation of responsibilities:
<page>/
├── index.tsx # Axhub 运行时适配层
├── style.css # 根入口样式转发层
└── src/
├── App.tsx # Figma 导出薄壳
├── main.tsx # Vite 挂载层
├── index.css # Figma 入口样式层
├── components/ # 页面视觉与交互主体
└── styles/ # 共享样式
Fixed constraints:
- The root directory
index.tsxonly performs Axhub runtime adaptation, and no longer copies a set of page visual implementation src/App.tsxonly serves as a Figma export thin shell, and no longer copies a set of page business logic- Shared page bodies should be placed in
src/components/** - Shared styles should be placed in
src/styles/**
If you are generating or modifying these files, please directly write clear responsibility comments at the top of index.tsx、src/App.tsx、src/main.tsx to remind future maintainers not to let the two entries drift
- The final project after executing this skill must conform to the above fixed structure
This is not a suggestion, but an acceptance constraint.
If the current project structure does not satisfy this separation of responsibilities, when executing this skill, it should first be refactored to that structure, then continue generating or writing back canvas.fig。
Current export product
Backend export interface:
GET /api/export-make?path=prototypes/<page-name>
Interface behavior:
- Use
canvas-fig-sync.mjs packto write the current source code back tocanvas.fig - Refresh
canvas.code-manifest.json - Update
meta.json.exported_at - Directly download
canvas.fig, with filename名称.fig
Usage Scenarios
Scenario A: The project was imported from Figma Make and already has canvas.fig
At this point, the goal is not to create a new structure, but to synchronize the current page back to the existing export shell, then write back again canvas.fig。
Steps:
- Check and synchronize the current page and the export shell
Key checks:
- Root directory
index.tsx - Root directory
style.css - Export shell
src/App.tsx - Export shell
src/index.css - Dependencies of the export shell
src/components/**、src/pages/**、src/styles/**
- Write back
canvas.fig
node scripts/canvas-fig-sync.mjs pack \
--fig src/prototypes/<page-name>/canvas.fig \
--from src/prototypes/<page-name> \
--prune-missing \
--sanitize-for-export
- Refresh manifest
node scripts/canvas-fig-sync.mjs inspect \
--fig src/prototypes/<page-name>/canvas.fig \
--manifest src/prototypes/<page-name>/canvas.code-manifest.json
- Update
meta.json
At minimum ensure:
file_nameexported_atclient_metadeveloper_related_links
- Ensure
ai_chat.jsonis at least{}, and preserveimages/
Scenario B: Native Axhub page, without canvas.fig
In this case, you need to first complete the Figma export shell, then generate canvas.fig。
Target structure:
src/prototypes/<page-name>/
├── index.tsx
├── style.css
├── canvas.fig
├── meta.json
├── ai_chat.json
├── canvas.code-manifest.json
├── images/
├── package.json
├── vite.config.ts
├── index.html
└── src/
├── App.tsx
├── main.tsx
├── index.css
├── components/
├── pages/
└── styles/
Steps:
- First complete the export shell
Requirements:
src/App.tsxmust express the real content of the current page, not an empty templatesrc/index.cssmust cover the real styles of the current page, not irrelevant default styles- If the root directory entry can be reused, prefer a thin shell reuse
- Create
meta.json
{
"client_meta": {
"background_color": { "r": 0.96, "g": 0.96, "b": 0.96, "a": 1 },
"thumbnail_size": { "width": 400, "height": 300 },
"render_coordinates": { "x": 0, "y": 0, "width": 1280, "height": 960 }
},
"file_name": "<项目显示名>",
"developer_related_links": [],
"exported_at": "<ISO 8601 时间>"
}
- Create an empty
ai_chat.json
{}
- Create
images/directory, and sync image assets
mkdir -p src/prototypes/<page-name>/images
- Use the template to generate the base
canvas.fig
cp scripts/templates/empty-canvas.fig src/prototypes/<page-name>/canvas.fig
node scripts/canvas-fig-sync.mjs pack \
--fig src/prototypes/<page-name>/canvas.fig \
--from src/prototypes/<page-name> \
--prune-missing \
--sanitize-for-export
- Generate manifest
node scripts/canvas-fig-sync.mjs inspect \
--fig src/prototypes/<page-name>/canvas.fig \
--manifest src/prototypes/<page-name>/canvas.code-manifest.json
meta.json specification
interface MetaJson {
client_meta: {
background_color: { r: number; g: number; b: number; a: number };
thumbnail_size: { width: number; height: number };
render_coordinates: { x: number; y: number; width: number; height: number };
};
file_name: string;
developer_related_links: [];
exported_at: string;
}
canvas-fig-sync.mjs reference
inspect
node scripts/canvas-fig-sync.mjs inspect --fig <canvas.fig> [--manifest <file>]
extract
node scripts/canvas-fig-sync.mjs extract --fig <canvas.fig> --out <project-dir> [--source-root src]
pack
node scripts/canvas-fig-sync.mjs pack --fig <canvas.fig> --from <project-dir> [--out <new.fig>] [--prune-missing] [--sanitize-for-export]
Key behaviors:
- Only update CODE_FILE nodes corresponding to files that exist on disk
- When updating, also write back
sourceCodeandcollaborativeSourceCode, to avoid subsequent Figma exports still reading old collaborative code - By default, missing files will retain the original
canvas.figcontent - For export scenarios, it is recommended to explicitly add
--prune-missing, so that oldCODE_FILEnodes that do not exist on disk will be trimmed, and the final.figwill be closer to the current real project - For artifacts that will ultimately be re-imported into Figma Make, it is recommended to also add
--sanitize-for-export, which will clear the oldCODE_LIBRARYchat/code history, clean up theCODE_INSTANCE.codeSnapshotpreview cache, rebuildimportedCodeFiles, and trim danglingCODE_COMPONENT - When the same path corresponds to multiple CODE_FILE nodes, they will all be updated uniformly
Acceptance criteria
node scripts/canvas-fig-sync.mjs inspect --fig <canvas.fig>can be executed successfully- The exported
canvas.figcorresponds to the current page, not the old shell content meta.json.exported_atis the latest timesrc/App.tsx/src/index.cssThere is no obvious drift from the root directory page- The final download file name in the backend is
名称.fig
Notes
canvas.figis a binary file and cannot be modified manually- Run
packBefore that, first confirm that the export shell has been synced to the current page - If the directory already contains
images/hash-named files, do not rename them arbitrarily - If it is an imported project, the original Figma Make assets must not be deleted when organizing the page structure later