### Start an Example with a Backend Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/README.md After configuring the necessary environment variables in the .env file, use this command to start an example that includes a backend service. The backend will be available at http://localhost:3001. ```bash npm start fetch ``` -------------------------------- ### Start Authentication Example Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/examples/fundamentals/authentication/SETUP.md Run the authentication example from the root of the starter kit. Ensure you have configured your provider details in the developer portal beforehand. ```sh npm start authentication ``` -------------------------------- ### Start a Specific Example App Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/README.md Use this command to launch a particular example application. You can specify the example by its category and name, or just by its name if it's unique. ```bash npm start / // or simply npm start ``` -------------------------------- ### Install Dependencies and Start Development Server Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/reference_apps/real_estate_mls/README.md Run these commands to install project dependencies and start the local development server. The server will be available at http://localhost:8080. ```bash npm install npm start ``` -------------------------------- ### Start Multi-Account Authentication Example Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/examples/fundamentals/multi_account_authentication/SETUP.md Run this command from the root of the starter kit to launch the multi-account authentication example. Ensure multi-account OAuth is configured in the developer portal beforehand. ```sh npm start multi_account_authentication ``` -------------------------------- ### List All Example Apps Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/README.md Run this command in your terminal to display a list of all available example applications within the starter kit. Use arrow keys to navigate and Enter to select. ```bash npm start examples ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/templates/content_publisher/README.md Run this command to install all the necessary dependencies for the project. ```bash npm install ``` -------------------------------- ### Run Multi-Provider Authentication Example Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/examples/fundamentals/multi_provider_authentication/SETUP.md Execute the multi-provider authentication example from the starter kit's root directory. Ensure both Meta and Google OAuth providers are configured in the Developer Portal. ```sh npm start multi_provider_authentication ``` -------------------------------- ### Install Dependencies Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/README.md Clone the repository, navigate to the directory, and install project dependencies. ```bash git clone git@github.com:canva-sdks/canva-apps-sdk-starter-kit.git cd canva-apps-sdk-starter-kit npm install ``` -------------------------------- ### Start Development Servers Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/examples/assets_and_media/digital_asset_management/SETUP.md Launch the frontend and backend development servers for the digital asset management module. ```bash npm start digital_asset_management ``` -------------------------------- ### Configure Environment Variables for Backend Examples Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/README.md When running examples with a backend, you need to copy your app's environment variables from the Canva developer portal into the starter kit's .env file. This ensures proper authentication and configuration. ```bash CANVA_APP_ID=AABBccddeeff CANVA_APP_ORIGIN=https://app-aabbccddeeff.canva-apps.com CANVA_BACKEND_PORT=3001 CANVA_FRONTEND_PORT=8080 CANVA_BACKEND_HOST=http://localhost:3001 CANVA_HMR_ENABLED=TRUE ``` -------------------------------- ### Start HTTPS Development Server for Safari Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/templates/content_publisher/README.md Starts the development server with HTTPS enabled, which is required for previewing apps in Safari. You will need to bypass security certificate warnings. ```bash npm start --use-https ``` -------------------------------- ### Start Development Server with ngrok Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/examples/assets_and_media/digital_asset_management/SETUP.md Launches the backend and frontend development servers, exposing the backend via a public ngrok URL. Ensure you are in the `canva-apps-sdk-starter-kit` directory. ```bash npm start digital_asset_management --ngrok ``` -------------------------------- ### Intent-based File Structure Example Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/AGENTS.md Illustrates the recommended file organization for apps following an intent-based architecture. Each intent has a dedicated folder under 'src/intents/'. ```tree src/ ├── intents/ │ ├── design_editor/ │ │ ├── index.tsx │ │ └── editor_app.tsx │ └── content_publisher/ │ ├── index.tsx │ ├── preview_ui.tsx │ └── setting_ui.tsx └── index.tsx ``` -------------------------------- ### Start Development Server with HTTPS for Safari Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/README.md To preview apps in Safari, the development server must be HTTPS-enabled. Use the `--use-https` flag. Navigate to https://localhost:8080 and bypass the security certificate warning. ```bash # Run the main app npm start --use-https # Run an example npm start --use-https ``` -------------------------------- ### Development Server Command Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/AGENTS.md Starts the development server on localhost:8080. Enables previewing the app in Canva via the Developer Portal or CLI. Hot Module Replacement (HMR) is supported for faster development. ```bash npm start ``` -------------------------------- ### App Entry Point and UI Setup Source: https://context7.com/canva-sdks/canva-apps-sdk-starter-kit/llms.txt Standard entry point for Canva apps using `index.tsx` to mount a React root. The `app.tsx` file demonstrates minimal starter app structure with UI components and feature detection for design modifications. ```tsx // index.tsx — standard entry point for all Canva apps import { createRoot } from "react-dom/client"; import { App } from "./app"; const root = createRoot(document.getElementById("root") as HTMLElement); root.render(); ``` ```tsx // app.tsx — minimal starter app import { Button, Rows, Text } from "@canva/app-ui-kit"; import { addElementAtPoint } from "@canva/design"; import { useFeatureSupport } from "@canva/app-hooks"; import * as styles from "styles/components.css"; export const App = () => { const isSupported = useFeatureSupport(); const handleClick = async () => { if (!isSupported(addElementAtPoint)) return; await addElementAtPoint({ type: "text", children: ["Hello from my Canva app!"], color: "#8B3DFF", fontWeight: "bold", }); }; return ( // styles.scrollContainer ensures the app panel scrolls correctly inside Canva
Welcome to my Canva app!
); }; ``` -------------------------------- ### Navigate to Starter Kit Directory Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/examples/assets_and_media/digital_asset_management/SETUP.md Change the current directory to the starter kit's root folder. ```bash cd canva-apps-sdk-starter-kit ``` -------------------------------- ### Use `editContent` to Translate Text Without Formatting Source: https://context7.com/canva-sdks/canva-apps-sdk-starter-kit/llms.txt Use `editContent` to batch edit richtext on the current page. `readPlaintext()` gets simple text content. Changes are committed with `session.sync()`. ```tsx import { editContent } from "@canva/design"; // Replace all text on the current page without preserving inline formatting const translateSimple = async () => { await editContent( { contentType: "richtext", target: "current_page" }, async (session) => { const texts = session.contents.map((range) => range.readPlaintext()); // Call a translation API; here we simulate a response const translated = texts.map((t) => `[Translated] ${t}`); session.contents.forEach((range, i) => { const length = range.readPlaintext().length; range.replaceText({ index: 0, length }, translated[i] ?? ""); }); await session.sync(); // Commit changes }, ); }; ``` -------------------------------- ### Use `useSelection` to Read and Modify Text Elements Source: https://context7.com/canva-sdks/canva-apps-sdk-starter-kit/llms.txt Use the `useSelection` hook to track plaintext selections. Call `read()` to get a draft, mutate `draft.contents`, and `draft.save()` to commit changes. Only works for text elements. ```tsx import { useSelection } from "@canva/app-hooks"; export const App = () => { // Track plaintext (text element) selections const textSelection = useSelection("plaintext"); // Track image element selections const imageSelection = useSelection("image"); const appendExclamation = async () => { // Read opens a draft copy of all selected text elements const draft = await textSelection.read(); // Mutate each selected text element's content draft.contents.forEach((s) => { s.text = `${s.text}!`; }); // Save commits the changes back to the design await draft.save(); }; const replaceSelectedImage = async () => { const draft = await imageSelection.read(); draft.contents.forEach((image) => { // Replace image ref; upload a new asset and assign the ref here // image.ref = newRef; console.log("Selected image ref:", image.ref); }); await draft.save(); }; return (
{/* selection.count reflects the number of currently selected elements */}

Text elements selected: {textSelection.count}

Image elements selected: {imageSelection.count}

); }; ``` -------------------------------- ### Third-Party OAuth Flow with Canva Source: https://context7.com/canva-sdks/canva-apps-sdk-starter-kit/llms.txt Implement third-party OAuth flows using `auth.initOauth()`. This involves requesting authorization, getting access tokens, and handling deauthorization. Ensure you manage the access token state effectively. ```tsx import { auth } from "@canva/user"; import { useMemo, useState, useEffect } from "react"; const BACKEND_URL = `${BACKEND_URL}/custom-route`; // --- Pattern 2: Third-party OAuth flow --- export const OAuthExample = () => { const oauth = useMemo(() => auth.initOauth(), []); const scope = new Set(["openid"]); const [accessToken, setAccessToken] = useState(null); useEffect(() => { // Try to retrieve an existing token silently on mount oauth.getAccessToken({ forceRefresh: false, scope }) .then((res) => setAccessToken(res?.token ?? null)) .catch(() => setAccessToken(null)); }, []); const authorize = async () => { // Opens Canva's OAuth consent dialog await oauth.requestAuthorization({ scope }); const res = await oauth.getAccessToken({ forceRefresh: true, scope }); setAccessToken(res?.token ?? null); }; const logout = async () => { await oauth.deauthorize(); // Revoke authorization and clear cached tokens setAccessToken(null); }; const callApi = async () => { if (!accessToken) return; const res = await fetch(BACKEND_URL, { headers: { Authorization: `Bearer ${accessToken}` }, }); console.log(await res.json()); }; return (
{accessToken ? ( <> ) : ( )}
); }; ``` -------------------------------- ### Production Build Command Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/AGENTS.md Use this command for a production build. The output is placed in the 'dist' directory for submission to Canva. ```bash npm run build ``` -------------------------------- ### Prettier Formatting and Check Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/AGENTS.md Applies Prettier formatting to the codebase. Use 'npm run format:check' to verify formatting without making changes. Formatting is encouraged. ```bash npm run format ``` ```bash npm run format:check ``` -------------------------------- ### Add Page and Get Design Metadata with Canva SDK Source: https://context7.com/canva-sdks/canva-apps-sdk-starter-kit/llms.txt Use `addPage` to insert new pages with optional titles and pre-populated elements. `getDesignMetadata` retrieves design information like dimensions and page count. Ensure dimensions are loaded before adding pages. Handles `CanvaError` for quota and rate limits. ```tsx import { addPage, getDesignMetadata } from "@canva/design"; import { upload } from "@canva/asset"; import { CanvaError } from "@canva/error"; import { useEffect, useState } from "react"; export const App = () => { const [dimensions, setDimensions] = useState<{ width: number; height: number } | undefined>(); useEffect(() => { getDesignMetadata().then(({ defaultPageDimensions }) => { setDimensions(defaultPageDimensions); }); }, []); const handleAddPage = async () => { if (!dimensions) return; const { ref } = await upload({ type: "image", mimeType: "image/png", url: "https://example.com/icon.png", thumbnailUrl: "https://example.com/icon.png", aiDisclosure: "none", width: 100, height: 100, }); try { await addPage({ title: "My New Page", elements: [ { type: "group", children: [ { type: "image", ref, top: 0, left: 0, width: 50, height: 50, altText: { text: "icon", decorative: undefined }, }, { type: "text", children: ["Page Header"], top: 55, left: 0, width: 200 }, ], top: dimensions.height * 0.1, left: dimensions.width / 2 - 100, width: 200, height: "auto", }, { type: "embed", url: "https://www.youtube.com/watch?v=tBe79N-4zm4", top: dimensions.height * 0.4, left: dimensions.width / 2 - 160, width: 320, height: "auto", }, ], }); } catch (e) { if (e instanceof CanvaError) { if (e.code === "quota_exceeded") console.error("Page limit reached"); else if (e.code === "rate_limited") console.error("Rate limited — max 3 pages/sec"); } } }; return ; }; ``` -------------------------------- ### ui.startDragToPoint / ui.startDragToCursor Source: https://context7.com/canva-sdks/canva-apps-sdk-starter-kit/llms.txt Enables users to drag content from the app panel directly onto the design canvas. Use `ui.startDragToPoint` or `ui.startDragToCursor` as a fallback. ```APIDOC ## `ui.startDragToPoint` / `ui.startDragToCursor` ### Description Allows users to drag and drop elements from your app panel directly onto the Canva design canvas. `ui.startDragToCursor` is available as a fallback for older editor versions. ### Method Signatures - `ui.startDragToPoint(event: React.DragEvent, dragData: ImageDragConfig): void` - `ui.startDragToCursor(event: React.DragEvent, dragData: ImageDragConfig): void` ### Parameters #### Event - **event** (React.DragEvent) - Required - The drag event object. #### dragData - **type** (string) - Required - The type of the dragged item (e.g., "image"). - **resolveImageRef** (Function) - Required - A function called when the user drops the element, responsible for resolving the image reference. - **previewUrl** (string) - Required - The URL of the preview image for the dragged item. - **previewSize** (object) - Required - An object containing the `width` and `height` of the preview image. - **fullSize** (object) - Required - An object containing the `width` and `height` of the full-size image. ### Request Example ```typescript import { ui, type ImageDragConfig } from "@canva/design"; import { upload } from "@canva/asset"; import { useFeatureSupport } from "@canva/app-hooks"; const uploadImage = () => /* ... implementation ... */; const isSupported = useFeatureSupport(); const onDragStart = (event: React.DragEvent) => { const dragData: ImageDragConfig = { type: "image", resolveImageRef: uploadImage, previewUrl: "https://www.canva.dev/example-assets/image-import/grass-image-thumbnail.jpg", previewSize: { width: 320, height: 212 }, fullSize: { width: 320, height: 212 }, }; if (isSupported(ui.startDragToPoint)) { ui.startDragToPoint(event, dragData); } else if (isSupported(ui.startDragToCursor)) { ui.startDragToCursor(event, dragData); } }; ``` ``` -------------------------------- ### Enable Hot Module Replacement (HMR) Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/README.md Configure environment variables to enable HMR, which allows for faster development by reflecting changes without a full app reload. Restart the development server after updating the .env file. ```bash CANVA_APP_ORIGIN=https://app-aabbccddeeff.canva-apps.com CANVA_HMR_ENABLED=true ``` -------------------------------- ### requestExport Source: https://context7.com/canva-sdks/canva-apps-sdk-starter-kit/llms.txt Prompts the user to choose a file format and then exports the design, returning download URLs for each page/element. Accepted formats include "png", "jpg", "pdf_standard", "gif", "svg", "video", and "pptx". ```APIDOC ## `requestExport` ### Description Exports a design to a chosen file format, returning download URLs for each page or element. Supports PNG, JPG, PDF, GIF, SVG, video, and PPTX. ### Method Signature `requestExport(options: { acceptedFileTypes: string[] }) => Promise` ### Parameters #### Options - **acceptedFileTypes** (string[]) - Required - An array of accepted file types for export. ### Response #### ExportResponse - **exportBlobs** (Array<{ url: string }>) - An array of objects, each containing a `url` for downloading an exported page or element. ### Request Example ```typescript import { requestExport, type ExportResponse } from "@canva/design"; const response = await requestExport({ acceptedFileTypes: ["png", "pdf_standard", "jpg", "gif", "svg", "video", "pptx"], }); console.log("Export URLs:", response.exportBlobs?.map((b) => b.url)); ``` ### Response Example ```json { "exportBlobs": [ { "url": "https://export.canva.com/...". } ] } ``` ``` -------------------------------- ### Root index.tsx for Canva App Intents Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/AGENTS.md The root index file should import prepare functions and intents, then call prepare for each intent implementation. This sets up the main entry point for your Canva app. ```tsx import { prepareContentPublisher } from "@canva/intents/content"; import { prepareDesignEditor } from "@canva/intents/design"; import contentPublisher from "./intents/content_publisher"; import designEditor from "./intents/design_editor"; prepareContentPublisher(contentPublisher); prepareDesignEditor(designEditor); ``` -------------------------------- ### Configure HTTPS for Safari Development Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/README.md When running the development server with HTTPS enabled for Safari testing, ensure the CANVA_BACKEND_HOST environment variable is set to https://localhost:3001. ```bash CANVA_BACKEND_HOST=https://localhost:3001 ``` -------------------------------- ### Initialize Re-editable App Elements with Canva SDK Source: https://context7.com/canva-sdks/canva-apps-sdk-starter-kit/llms.txt Initializes a client to manage the lifecycle of re-editable custom elements. The `render` function maps stored data to design elements. Use `addElement` to place new elements and `update` to modify existing ones. Ensure data is uploaded before rendering. ```typescript import { initAppElement, type AppElementOptions, type ImageRef } from "@canva/design"; import { upload } from "@canva/asset"; import { useEffect, useState } from "react"; type AppElementData = { imageId: string; width: number; height: number; rotation: number; }; // imageRefs is a module-level cache — in production use a database or API const imageRefs: Record = {}; // initAppElement must be called at module scope (not inside a component) const appElementClient = initAppElement({ render: (data) => { const ref = imageRefs[data.imageId]; if (!ref) throw new Error(`Image ${data.imageId} has not been uploaded yet`); return [ { type: "image", top: 0, left: 0, ref, width: data.width, height: data.height, rotation: data.rotation, altText: { text: `photo of ${data.imageId}`, decorative: undefined }, }, ]; }, }); export const App = () => { const [updateFn, setUpdateFn] = useState< ((opts: AppElementOptions) => Promise) | undefined >(undefined); // Listen for when the user selects an existing app element in the design useEffect(() => { appElementClient.registerOnElementChange((appElement) => { setUpdateFn(() => appElement?.update); }); }, []); const addOrUpdate = async () => { const data: AppElementData = { imageId: "dog", width: 400, height: 400, rotation: 0 }; // Ensure the image is uploaded before rendering if (!imageRefs["dog"]) { const { ref } = await upload({ type: "image", mimeType: "image/jpeg", url: "https://example.com/dog.jpg", thumbnailUrl: "https://example.com/dog-thumb.jpg", aiDisclosure: "none", }); imageRefs["dog"] = ref; } if (updateFn) { // Update the currently selected app element await updateFn({ data }); } else { // Insert a new app element at the default position await appElementClient.addElement({ data }); } }; return ; }; ``` -------------------------------- ### Set ngrok Authtoken (macOS/Linux) Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/examples/assets_and_media/digital_asset_management/SETUP.md Configure the ngrok authtoken environment variable for the current terminal session on macOS and Linux. ```bash export NGROK_AUTHTOKEN= ``` -------------------------------- ### Run Jest Tests Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/AGENTS.md Executes Jest tests. Use 'npm run test:watch' for continuous testing during development. Tests are encouraged but not submitted to Canva. ```bash npm test ``` -------------------------------- ### `initAppElement` — Create interactive, re-editable app elements Source: https://context7.com/canva-sdks/canva-apps-sdk-starter-kit/llms.txt Initializes an app element client that manages the lifecycle of re-editable custom elements embedded in Canva designs. The `render` function maps stored data to design elements. ```APIDOC ## `initAppElement` — Create interactive, re-editable app elements Initializes an app element client that manages the lifecycle of re-editable custom elements embedded in Canva designs. The `render` function maps stored data (up to 5 KB) to an array of native design elements. Use `addElement` to place a new app element and `update` to modify an existing one. ### Parameters - **render** (function) - Required - A function that takes stored data and returns an array of design elements to render. - **options** (object) - Optional - Configuration options for the app element client. - **options.initialData** (any) - The initial data for the app element. - **options.onElementChange** (function) - A callback function that is called when the selected app element changes. ### Methods - **addElement(options)**: Adds a new app element to the design. - **options** (object) - Required - Options for adding the element. - **options.data** (any) - The data for the new app element. - **update(options)**: Updates an existing app element. - **options** (object) - Required - Options for updating the element. - **options.data** (any) - The new data for the app element. - **registerOnElementChange(callback)**: Registers a callback function to be called when the selected app element changes. - **callback** (function) - The function to call when the element changes. It receives the app element object as an argument. ### Example ```tsx import { initAppElement } from "@canva/design"; const appElementClient = initAppElement({ render: (data) => [ { type: "image", ref: data.ref, width: data.width, height: data.height, }, ], }); // To add a new element: await appElementClient.addElement({ data: { ref: "some-ref", width: 100, height: 100 } }); // To update an existing element (requires an updateFn obtained from registerOnElementChange): // await updateFn({ data: { ref: "new-ref", width: 200, height: 200 } }); ``` ``` -------------------------------- ### Set Custom Backend Host URL Source: https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/templates/dam/README.md Customize the `CANVA_BACKEND_HOST` environment variable in your `.env` file to specify the server's URL. This is useful for differentiating between development and production environments. ```dotenv CANVA_BACKEND_HOST=http://localhost:3001 ```