Basic layout
Create a publish extension with the "Basic" layout.
A publish extension adds a publish destination to Canva. Users can then publish their design to this destination via Canva's Publish menu.
This tutorial explains how to create a publish extension that uses the Basic layout. This layout is intended for platforms that don't organize content into folders, such as social media platforms with a single feed for each user (for example, Twitter or Instagram).
To learn more about the available layouts for publish extensions, refer to Choose a layout for a publish extension.

Step 1: Set up a Base URL

In the Developer Portal, publish extensions have a Base URL field. This indicates that the extension must provide the URL of a server that can receive and respond to HTTP requests from Canva.
To set up a Base URL, refer to either of the following guides:
You can use any programming language, framework, or architecture to handle requests from Canva, but the examples in this documentation use Express.js.

Step 2: Set up the required endpoints

A publish extension that uses the Basic layout must support the following endpoint:
The following snippet demonstrates how to set up these endpoints with Express.js:
1
const express = require("express");
2
const fs = require("fs-extra");
3
const jimp = require("jimp");
4
const path = require("path");
5
const url = require("url");
6
7
const app = express();
8
9
app.use(express.json());
10
app.use(express.static("public"));
11
12
app.post("/publish/resources/upload", async (request, response) => {
13
// code goes here
14
});
15
16
app.listen(process.env.PORT || 3000);
Copied!
This snippet also assumes the following Node.js dependencies are installed:

Step 3: Create an app via the Developer Portal

  1. 1.
    Log in to the Developer Portal.
  2. 2.
    Navigate to the Your integrations page.
  3. 3.
    Click Create an app.
  4. 4.
    In the App name field, enter a name for the app.
  5. 5.
    Agree to the Canva Developer Terms.
  6. 6.
    Click Create app.

Step 4: Add a publish extension to the app

  1. 1.
    Select Publish.
  2. 2.
    In the Base URL field, enter the URL of the server.
  3. 3.
    For the Layout option, select Basic.
  4. 4.
    For the Output file types option, select the types of files a user can publish to the destination platform. The example in this tutorial requires the file types to be JPG and PNG.
  5. 5.
    For the Max number of pages field, enter the maximum number of pages that a user can publish of their design. The example in this tutorial requires the number of pages to be 1.
Any changes to the form save automatically.

Step 5: Upload the user's design

When a user opens a publish extension, Canva displays a handful of options and a Save button. The available options depend on how the extension is configured.
When the user clicks the Save button, Canva sends a request to the extension. The request body includes an array of assets. Each asset has a url, which the extension must use to download the assets to the destination platform.
The following snippet demonstrates how to download an asset to the public directory and create a URL that lets the user view the published asset:
1
app.post("/publish/resources/upload", async (request, response) => {
2
// Ensure the "public" directory exists
3
await fs.ensureDir(path.join(__dirname, "public"));
4
5
// Get the first asset from the "assets" array
6
const [asset] = request.body.assets;
7
8
// Download the asset
9
const image = await jimp.read(asset.url);
10
const filePath = path.join(__dirname, "public", asset.name);
11
await image.writeAsync(filePath);
12
13
// Respond with the URL of the published design
14
response.send({
15
type: "SUCCESS",
16
url: url.format({
17
protocol: request.protocol,
18
host: request.get("host"),
19
pathname: asset.name,
20
}),
21
});
22
});
Copied!
If the user publishes their design as an image, Canva provides each page of the design as a separate asset. Otherwise, Canva provides the entire design as a single asset.
If you'd like to release your app to Canva's users, the url property must point to a page that lets users view their published design in context on the destination platform. For example, if a user publishes a tweet, the URL should point to the page of that tweet.

Example

1
const express = require("express");
2
const fs = require("fs-extra");
3
const jimp = require("jimp");
4
const path = require("path");
5
const url = require("url");
6
7
const app = express();
8
9
app.use(express.json());
10
app.use(express.static("public"));
11
12
app.post("/publish/resources/upload", async (request, response) => {
13
// Ensure the "public" directory exists
14
await fs.ensureDir(path.join(__dirname, "public"));
15
16
// Get the first asset from the "assets" array
17
const [asset] = request.body.assets;
18
19
// Download the asset
20
const image = await jimp.read(asset.url);
21
const filePath = path.join(__dirname, "public", asset.name);
22
await image.writeAsync(filePath);
23
24
// Respond with the URL of the published design
25
response.send({
26
type: "SUCCESS",
27
url: url.format({
28
protocol: request.protocol,
29
host: request.get("host"),
30
pathname: asset.name,
31
}),
32
});
33
});
34
35
app.listen(process.env.PORT || 3000);
Copied!