Apps SDK v2 Upgrade guide
This guide explains all of the code changes required to upgrade to Apps SDK v2. For general information about upgrades, including deadlines, see the Upgrade FAQ.
Automated migration tool
You can use the Canva CLI automated migration tool to handle most of the required changes. The CLI automatically updates:
- Package imports and versions
- API method signatures
- Required property additions (such as
aiDisclosure
) - Deprecated method replacements
For detailed CLI usage, see the Canva CLI documentation.
Run the migration tool
-
If you haven't already, install the Canva CLI:
npm install -g @canva/cli@latestSHELL -
In your app directory, run the migration command:
canva apps migrate apps-sdk-v1-v2SHELL
After running the automated migration, review the changes and complete any manual steps outlined in the following sections.
Manual migration steps
The following sections explain the specific code changes if you prefer to upgrade manually or need to handle cases not covered by the automated tool.
Packages
All the npm packages for the Apps SDK have been updated with new TypeScript definitions. These definitions make it easier to identify what parts of your codebase need to be updated.
To install the updates, run the following command:
npm install @canva/asset@latest @canva/design@latest @canva/error@latest @canva/platform@latest @canva/user@latest
Legacy /sdk
directory
If you're using an early version of the Apps SDK starter kit that included a local /sdk
directory at the root of the starter kit repo, you should:
-
Remove the local
/sdk
directory. -
Update any imports to use the latest npm packages instead.
For example, replace the old local imports:
// Old imports from local /sdk directoryimport { initAppElement } from "../sdk/design";import { auth } from "../sdk/user";TSXwith the latest npm package imports:
// Update to npm packagesimport { initAppElement } from "@canva/design";import { auth } from "@canva/user";TSX
AI disclosure
In v2, an aiDisclosure
property is required when uploading assets. This property indicates whether an asset was generated by AI, and helps maintain transparency about the origin of assets:
await upload({type: "audio",title: "Example audio",url: "https://www.canva.dev/example-assets/audio-import/audio.mp3",mimeType: "audio/mp3",durationMs: 86047,aiDisclosure: "none", // => Or "app_generated"});
Alternative text
In v2, creating an element requires an altText
property to be set:
await addElementAtPoint({type: "image",ref: result.ref,altText: {text: "Example image",decorative: false,},});
If need be, this value can be explicitly set to undefined
:
await addElementAtPoint({type: "image",ref: result.ref,altText: undefined,});
Authentication
In v1, apps could use manual authentication to authenticate users via third-party platforms:
import { auth } from "@canva/user";const response = await auth.requestAuthentication();switch (response.status) {case "COMPLETED":console.log("The authentication was successful.");break;case "ABORTED":console.log("The user exited the authentication flow.");break;case "DENIED":console.log("The user didn't have the required permissions.");break;}
In v2, manual authentication has been removed.
Apps have two alternatives for authenticating users:
Feature support
Apps can now run in documents, but some APIs aren't compatible with documents.
In v1, there's no workaround for this. If an app uses incompatible APIs, it will be disabled for documents.
In v2, we've introduced the following methods:
isSupported
registerOnSupportChange
Apps can use these methods to check if a method is available in the current context. This allows the app to adapt to the context in which it's running.
For example, the following Add element at point button will be disabled if the app is running in a document, since the addElementAtPoint
method (also introduced in v2) is not compatible with documents:
import { Button, Rows } from "@canva/app-ui-kit";import { addElementAtCursor, addElementAtPoint } from "@canva/design";import { useFeatureSupport } from "utils/use_feature_support";import * as styles from "styles/components.css";export const App = () => {const isSupported = useFeatureSupport();function handleAddElementAtPoint() {if (!isSupported(addElementAtPoint)) {return;}addElementAtPoint({type: "text",children: ["Hello world"],});}function handleAddElementAtCursor() {if (!isSupported(addElementAtCursor)) {return;}addElementAtCursor({type: "text",children: ["Hello world"],});}return (<div className={styles.scrollContainer}><Rows spacing="1u"><Buttonvariant="primary"onClick={handleAddElementAtPoint}disabled={!isSupported(addElementAtPoint)}>Add element at point</Button><Buttonvariant="primary"onClick={handleAddElementAtCursor}disabled={!isSupported(addElementAtCursor)}>Add element at cursor</Button></Rows></div>);};
To learn more, see Feature support.
Adding elements
In v1, elements could be added to a design with the addNativeElement
method:
await addNativeElement({type: "TEXT",children: ["Hello world"],});
In v2, this method has been deprecated and superseded by the following methods:
addElementAtPoint
, which is a renamed version ofaddNativeElement
.addElementAtCursor
, which is a new method that's compatible with documents.
These methods are only available in certain contexts and, as a result, apps should use the isSupported
method to check that the methods are available in the current context before calling them:
import { Button, Rows } from "@canva/app-ui-kit";import { addElementAtCursor, addElementAtPoint } from "@canva/design";import { useFeatureSupport } from "utils/use_feature_support";import * as styles from "styles/components.css";export const App = () => {const isSupported = useFeatureSupport();function handleAddElementAtPoint() {if (!isSupported(addElementAtPoint)) {return;}addElementAtPoint({type: "text",children: ["Hello world"],});}function handleAddElementAtCursor() {if (!isSupported(addElementAtCursor)) {return;}addElementAtCursor({type: "text",children: ["Hello world"],});}return (<div className={styles.scrollContainer}><Rows spacing="1u"><Buttonvariant="primary"onClick={handleAddElementAtPoint}disabled={!isSupported(addElementAtPoint)}>Add element at point</Button><Buttonvariant="primary"onClick={handleAddElementAtCursor}disabled={!isSupported(addElementAtCursor)}>Add element at cursor</Button></Rows></div>);};
To learn more, see:
Asset IDs
In v1, the upload
method accepted an id
property:
await upload({type: "IMAGE",id: "exampleid",mimeType: "image/jpeg",url: "https://www.canva.dev/example-assets/image-import/image.jpg",thumbnailUrl:"https://www.canva.dev/example-assets/image-import/thumbnail.jpg",});
This property has been deprecated for a while and, in v2, it's been removed entirely:
await upload({type: "IMAGE",mimeType: "image/jpeg",url: "https://www.canva.dev/example-assets/image-import/image.jpg",thumbnailUrl:"https://www.canva.dev/example-assets/image-import/thumbnail.jpg",aiDisclosure: "none",});
Discriminators
In v1, some discrimintor values were uppercase:
await addNativeElement({type: "EMBED",url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",});
In v2, all discriminator values are lowercase:
await addNativeElement({type: "embed",url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",});
Drag and drop
In v1, apps could support drag and drop with the startDrag
or makeDraggable
methods:
ui.startDrag(event, {type: "TEXT",children: ["Add text into a design"],});
ui.makeDraggable({node,dragData: {type: "TEXT",children: ["Hello world"],},onDragStart: () => {console.log("The drag event has started");},onDragEnd: () => {console.log("The drag event has ended");},});
In v2, startDrag
has been deprecated and makeDraggable
has been removed.
Instead, apps should use the following methods:
startDragToPoint
startDragToCursor
startDragToPoint
is identical to startDrag
, aside from the name, while startDragToCursor
is a new method that's compatible with documents.
Because these methods are only available in certain contexts, apps should use the isSupported
method to check that the methods are available in the current context.
To learn more, see:
Uploading assets
In v1, the queueMediaUpload
and whenUploaded
methods preceded the upload
method. These methods have been deprecated for a while and have now been removed.
Apps should only upload assets with the upload
method.