@canva/cli 0.0.1-beta.9 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/README.md +131 -31
  2. package/cli.js +841 -437
  3. package/lib/cjs/index.cjs +11 -0
  4. package/lib/esm/index.mjs +11 -0
  5. package/package.json +19 -4
  6. package/templates/base/backend/routers/auth.ts +4 -4
  7. package/templates/base/backend/routers/oauth.ts +3 -3
  8. package/templates/base/eslint.config.mjs +2 -25
  9. package/templates/base/package.json +26 -23
  10. package/templates/base/scripts/ssl/ssl.ts +1 -1
  11. package/templates/base/scripts/start/app_runner.ts +42 -5
  12. package/templates/base/scripts/start/context.ts +12 -6
  13. package/templates/base/scripts/start/start.ts +12 -1
  14. package/templates/base/scripts/start/tests/start.tests.ts +61 -0
  15. package/templates/base/utils/backend/base_backend/create.ts +3 -3
  16. package/templates/base/utils/backend/bearer_middleware/bearer_middleware.ts +2 -2
  17. package/templates/base/utils/backend/jwt_middleware/jwt_middleware.ts +4 -4
  18. package/templates/base/utils/backend/jwt_middleware/tests/jwt_middleware.tests.ts +1 -1
  19. package/templates/base/utils/use_add_element.ts +1 -1
  20. package/templates/base/utils/use_feature_support.ts +1 -1
  21. package/templates/{gen_ai/webpack.config.cjs → base/webpack.config.ts} +50 -68
  22. package/templates/common/.env.template +3 -3
  23. package/templates/common/README.md +16 -17
  24. package/templates/common/jest.config.mjs +1 -1
  25. package/templates/common/jest.setup.ts +1 -0
  26. package/templates/common/utils/backend/base_backend/create.ts +3 -3
  27. package/templates/common/utils/backend/jwt_middleware/jwt_middleware.ts +4 -4
  28. package/templates/common/utils/backend/jwt_middleware/tests/jwt_middleware.tests.ts +1 -1
  29. package/templates/common/utils/tests/table_wrapper.tests.ts +1 -1
  30. package/templates/common/utils/use_add_element.ts +1 -1
  31. package/templates/common/utils/use_feature_support.ts +1 -1
  32. package/templates/dam/backend/routers/dam.ts +24 -20
  33. package/templates/dam/backend/server.ts +1 -1
  34. package/templates/dam/canva-app.json +16 -0
  35. package/templates/dam/eslint.config.mjs +2 -28
  36. package/templates/dam/package.json +38 -41
  37. package/templates/dam/scripts/ssl/ssl.ts +1 -1
  38. package/templates/dam/scripts/start/app_runner.ts +42 -5
  39. package/templates/dam/scripts/start/context.ts +12 -6
  40. package/templates/dam/scripts/start/start.ts +12 -1
  41. package/templates/dam/scripts/start/tests/start.tests.ts +61 -0
  42. package/templates/dam/src/app.tsx +24 -3
  43. package/templates/dam/src/config.ts +212 -87
  44. package/templates/dam/src/index.tsx +1 -1
  45. package/templates/dam/utils/backend/base_backend/create.ts +3 -3
  46. package/templates/dam/utils/backend/jwt_middleware/jwt_middleware.ts +4 -4
  47. package/templates/dam/utils/backend/jwt_middleware/tests/jwt_middleware.tests.ts +1 -1
  48. package/templates/{base/webpack.config.cjs → dam/webpack.config.ts} +50 -68
  49. package/templates/data_connector/README.md +84 -0
  50. package/templates/data_connector/canva-app.json +21 -0
  51. package/templates/data_connector/declarations/declarations.d.ts +29 -0
  52. package/templates/data_connector/eslint.config.mjs +14 -0
  53. package/templates/data_connector/package.json +91 -0
  54. package/templates/data_connector/scripts/ssl/ssl.ts +131 -0
  55. package/templates/data_connector/scripts/start/app_runner.ts +201 -0
  56. package/templates/data_connector/scripts/start/context.ts +171 -0
  57. package/templates/data_connector/scripts/start/start.ts +46 -0
  58. package/templates/data_connector/scripts/start/tests/start.tests.ts +61 -0
  59. package/templates/data_connector/src/api/connect_client.ts +6 -0
  60. package/templates/data_connector/src/api/data_source.ts +96 -0
  61. package/templates/data_connector/src/api/data_sources/designs.tsx +296 -0
  62. package/templates/data_connector/src/api/data_sources/index.ts +4 -0
  63. package/templates/data_connector/src/api/data_sources/templates.tsx +329 -0
  64. package/templates/data_connector/src/api/fetch_data_table.ts +55 -0
  65. package/templates/data_connector/src/api/index.ts +4 -0
  66. package/templates/data_connector/src/api/oauth.ts +8 -0
  67. package/templates/data_connector/src/api/tests/data_source.test.tsx +99 -0
  68. package/templates/data_connector/src/app.tsx +20 -0
  69. package/templates/data_connector/src/components/app_error.tsx +15 -0
  70. package/templates/data_connector/src/components/footer.tsx +26 -0
  71. package/templates/data_connector/src/components/header.tsx +40 -0
  72. package/templates/data_connector/src/components/index.ts +3 -0
  73. package/templates/data_connector/src/components/inputs/messages.tsx +99 -0
  74. package/templates/data_connector/src/components/inputs/search_filter.tsx +108 -0
  75. package/templates/data_connector/src/components/inputs/select_field.tsx +26 -0
  76. package/templates/data_connector/src/context/app_context.tsx +124 -0
  77. package/templates/data_connector/src/context/index.ts +2 -0
  78. package/templates/data_connector/src/context/use_app_context.ts +17 -0
  79. package/templates/data_connector/src/entrypoint.tsx +70 -0
  80. package/templates/data_connector/src/home.tsx +21 -0
  81. package/templates/data_connector/src/index.tsx +68 -0
  82. package/templates/data_connector/src/pages/data_source_config.tsx +9 -0
  83. package/templates/data_connector/src/pages/error.tsx +37 -0
  84. package/templates/data_connector/src/pages/index.ts +4 -0
  85. package/templates/data_connector/src/pages/login.tsx +145 -0
  86. package/templates/data_connector/src/pages/select_source.tsx +24 -0
  87. package/templates/data_connector/src/paths.ts +7 -0
  88. package/templates/data_connector/src/routes/index.ts +2 -0
  89. package/templates/data_connector/src/routes/protected_route.tsx +25 -0
  90. package/templates/data_connector/src/routes/routes.tsx +42 -0
  91. package/templates/data_connector/src/utils/data_params.ts +17 -0
  92. package/templates/data_connector/src/utils/data_table.ts +115 -0
  93. package/templates/data_connector/src/utils/fetch_result.ts +36 -0
  94. package/templates/data_connector/src/utils/index.ts +2 -0
  95. package/templates/data_connector/src/utils/tests/data_table.test.ts +133 -0
  96. package/templates/data_connector/styles/components.css +38 -0
  97. package/templates/data_connector/tsconfig.json +54 -0
  98. package/templates/{dam/webpack.config.cjs → data_connector/webpack.config.ts} +50 -68
  99. package/templates/gen_ai/backend/routers/image.ts +8 -8
  100. package/templates/gen_ai/backend/server.ts +1 -1
  101. package/templates/gen_ai/canva-app.json +20 -0
  102. package/templates/gen_ai/eslint.config.mjs +2 -25
  103. package/templates/gen_ai/package.json +42 -43
  104. package/templates/gen_ai/scripts/ssl/ssl.ts +1 -1
  105. package/templates/gen_ai/scripts/start/app_runner.ts +42 -5
  106. package/templates/gen_ai/scripts/start/context.ts +12 -6
  107. package/templates/gen_ai/scripts/start/start.ts +12 -1
  108. package/templates/gen_ai/scripts/start/tests/start.tests.ts +61 -0
  109. package/templates/gen_ai/src/app.tsx +3 -3
  110. package/templates/gen_ai/src/components/footer.tsx +20 -7
  111. package/templates/gen_ai/src/components/image_grid.tsx +1 -1
  112. package/templates/gen_ai/src/components/loading_results.tsx +8 -8
  113. package/templates/gen_ai/src/components/prompt_input.tsx +4 -4
  114. package/templates/gen_ai/src/components/remaining_credits.tsx +29 -21
  115. package/templates/gen_ai/src/components/report_box.tsx +2 -2
  116. package/templates/gen_ai/src/components/tests/remaining_credit.tests.tsx +6 -2
  117. package/templates/gen_ai/src/context/use_app_context.ts +2 -2
  118. package/templates/gen_ai/src/home.tsx +2 -2
  119. package/templates/gen_ai/src/pages/error.tsx +3 -3
  120. package/templates/gen_ai/src/pages/results.tsx +1 -1
  121. package/templates/gen_ai/src/paths.ts +4 -0
  122. package/templates/gen_ai/src/routes/routes.tsx +4 -6
  123. package/templates/gen_ai/utils/backend/base_backend/create.ts +3 -3
  124. package/templates/gen_ai/utils/backend/bearer_middleware/bearer_middleware.ts +2 -2
  125. package/templates/{hello_world/webpack.config.cjs → gen_ai/webpack.config.ts} +50 -68
  126. package/templates/hello_world/canva-app.json +16 -0
  127. package/templates/hello_world/eslint.config.mjs +2 -25
  128. package/templates/hello_world/package.json +35 -38
  129. package/templates/hello_world/scripts/copy_env.ts +10 -0
  130. package/templates/hello_world/scripts/ssl/ssl.ts +1 -1
  131. package/templates/hello_world/scripts/start/app_runner.ts +42 -5
  132. package/templates/hello_world/scripts/start/context.ts +12 -6
  133. package/templates/hello_world/scripts/start/start.ts +12 -1
  134. package/templates/hello_world/scripts/start/tests/start.tests.ts +61 -0
  135. package/templates/hello_world/src/app.tsx +1 -1
  136. package/templates/hello_world/src/index.tsx +1 -1
  137. package/templates/hello_world/src/tests/__snapshots__/app.tests.tsx.snap +5 -5
  138. package/templates/hello_world/src/tests/app.tests.tsx +3 -3
  139. package/templates/hello_world/utils/use_add_element.ts +1 -1
  140. package/templates/hello_world/utils/use_feature_support.ts +1 -1
  141. package/templates/hello_world/webpack.config.ts +254 -0
  142. package/templates/optional/.cursor/mcp.json +8 -0
  143. package/templates/optional/.vscode/mcp.json +9 -0
  144. package/templates/optional/AGENTS.md +76 -0
  145. package/templates/optional/CLAUDE.md +76 -0
  146. package/templates/common/conf/eslint-general.mjs +0 -303
  147. package/templates/common/conf/eslint-i18n.mjs +0 -41
  148. package/templates/common/conf/eslint-local-i18n-rules/index.mjs +0 -181
  149. /package/templates/base/scripts/{copy-env.ts → copy_env.ts} +0 -0
  150. /package/templates/dam/scripts/{copy-env.ts → copy_env.ts} +0 -0
  151. /package/templates/{gen_ai/scripts/copy-env.ts → data_connector/scripts/copy_env.ts} +0 -0
  152. /package/templates/{hello_world/scripts/copy-env.ts → gen_ai/scripts/copy_env.ts} +0 -0
  153. /package/templates/{common → optional}/.vscode/extensions.json +0 -0
@@ -0,0 +1,254 @@
1
+ import type { Configuration } from "webpack";
2
+ import { DefinePlugin, optimize } from "webpack";
3
+ import * as path from "path";
4
+ import * as TerserPlugin from "terser-webpack-plugin";
5
+ import { transform } from "@formatjs/ts-transformer";
6
+ import * as chalk from "chalk";
7
+ import { config } from "dotenv";
8
+ import { Configuration as DevServerConfiguration } from "webpack-dev-server";
9
+
10
+ config();
11
+
12
+ type DevConfig = {
13
+ port: number;
14
+ enableHmr: boolean;
15
+ enableHttps: boolean;
16
+ appOrigin?: string;
17
+ appId?: string; // Deprecated in favour of appOrigin
18
+ certFile?: string;
19
+ keyFile?: string;
20
+ };
21
+
22
+ export function buildConfig({
23
+ devConfig,
24
+ appEntry = path.join(process.cwd(), "src", "index.tsx"),
25
+ backendHost = process.env.CANVA_BACKEND_HOST,
26
+ // For IN_HARNESS, refer to the following docs for more information: https://www.canva.dev/docs/apps/test-harness/
27
+ inHarness = process.env.IN_HARNESS?.toLowerCase() === "true",
28
+ }: {
29
+ devConfig?: DevConfig;
30
+ appEntry?: string;
31
+ backendHost?: string;
32
+ inHarness?: boolean;
33
+ } = {}): Configuration & DevServerConfiguration {
34
+ const mode = devConfig ? "development" : "production";
35
+
36
+ if (!backendHost) {
37
+ console.error(
38
+ chalk.redBright.bold("BACKEND_HOST is undefined."),
39
+ `Refer to "Customizing the backend host" in the README.md for more information.`,
40
+ );
41
+ process.exit(-1);
42
+ } else if (backendHost.includes("localhost") && mode === "production") {
43
+ console.error(
44
+ chalk.redBright.bold(
45
+ "BACKEND_HOST should not be set to localhost for production builds!",
46
+ ),
47
+ `Refer to "Customizing the backend host" in the README.md for more information.`,
48
+ );
49
+ }
50
+
51
+ return {
52
+ mode,
53
+ context: path.resolve(process.cwd(), "./"),
54
+ entry: inHarness
55
+ ? {
56
+ harness: path.join(process.cwd(), "harness", "harness.tsx"),
57
+ init: path.join(process.cwd(), "harness", "init.ts"),
58
+ }
59
+ : {
60
+ app: appEntry,
61
+ },
62
+ target: "web",
63
+ resolve: {
64
+ alias: {
65
+ assets: path.resolve(process.cwd(), "assets"),
66
+ utils: path.resolve(process.cwd(), "utils"),
67
+ styles: path.resolve(process.cwd(), "styles"),
68
+ src: path.resolve(process.cwd(), "src"),
69
+ },
70
+ extensions: [".ts", ".tsx", ".js", ".css", ".svg", ".woff", ".woff2"],
71
+ },
72
+ infrastructureLogging: {
73
+ level: inHarness ? "info" : "none",
74
+ },
75
+ module: {
76
+ rules: [
77
+ {
78
+ test: /\.tsx?$/,
79
+ exclude: /node_modules/,
80
+ use: [
81
+ {
82
+ loader: "ts-loader",
83
+ options: {
84
+ transpileOnly: true,
85
+ getCustomTransformers() {
86
+ return {
87
+ before: [
88
+ transform({
89
+ overrideIdFn: "[sha512:contenthash:base64:6]",
90
+ }),
91
+ ],
92
+ };
93
+ },
94
+ },
95
+ },
96
+ ],
97
+ },
98
+ {
99
+ test: /\.css$/,
100
+ exclude: /node_modules/,
101
+ use: [
102
+ "style-loader",
103
+ {
104
+ loader: "css-loader",
105
+ options: {
106
+ modules: true,
107
+ },
108
+ },
109
+ {
110
+ loader: "postcss-loader",
111
+ options: {
112
+ postcssOptions: {
113
+ plugins: [require("cssnano")({ preset: "default" })],
114
+ },
115
+ },
116
+ },
117
+ ],
118
+ },
119
+ {
120
+ test: /\.(png|jpg|jpeg)$/i,
121
+ type: "asset/inline",
122
+ },
123
+ {
124
+ test: /\.(woff|woff2)$/,
125
+ type: "asset/inline",
126
+ },
127
+ {
128
+ test: /\.svg$/,
129
+ oneOf: [
130
+ {
131
+ issuer: /\.[jt]sx?$/,
132
+ resourceQuery: /react/, // *.svg?react
133
+ use: ["@svgr/webpack", "url-loader"],
134
+ },
135
+ {
136
+ type: "asset/resource",
137
+ parser: {
138
+ dataUrlCondition: {
139
+ maxSize: 200,
140
+ },
141
+ },
142
+ },
143
+ ],
144
+ },
145
+ {
146
+ test: /\.css$/,
147
+ include: /node_modules/,
148
+ use: [
149
+ "style-loader",
150
+ "css-loader",
151
+ {
152
+ loader: "postcss-loader",
153
+ options: {
154
+ postcssOptions: {
155
+ plugins: [require("cssnano")({ preset: "default" })],
156
+ },
157
+ },
158
+ },
159
+ ],
160
+ },
161
+ ],
162
+ },
163
+ optimization: {
164
+ minimizer: [
165
+ new TerserPlugin({
166
+ terserOptions: {
167
+ format: {
168
+ // Turned on because emoji and regex is not minified properly using default
169
+ // https://github.com/facebook/create-react-app/issues/2488
170
+ ascii_only: true,
171
+ },
172
+ },
173
+ }),
174
+ ],
175
+ },
176
+ output: {
177
+ filename: `[name].js`,
178
+ path: path.resolve(process.cwd(), "dist"),
179
+ clean: true,
180
+ },
181
+ plugins: [
182
+ new DefinePlugin({
183
+ BACKEND_HOST: JSON.stringify(backendHost),
184
+ }),
185
+ // Apps can only submit a single JS file via the Developer Portal
186
+ new optimize.LimitChunkCountPlugin({ maxChunks: 1 }),
187
+ ].filter(Boolean),
188
+ ...buildDevConfig(devConfig),
189
+ };
190
+ }
191
+
192
+ function buildDevConfig(options?: DevConfig): {
193
+ devtool?: string;
194
+ devServer?: DevServerConfiguration;
195
+ } {
196
+ if (!options) {
197
+ return {};
198
+ }
199
+
200
+ const { port, enableHmr, appOrigin, appId, enableHttps, certFile, keyFile } =
201
+ options;
202
+ const host = "localhost";
203
+
204
+ let devServer: DevServerConfiguration = {
205
+ server: enableHttps
206
+ ? {
207
+ type: "https",
208
+ options: {
209
+ cert: certFile,
210
+ key: keyFile,
211
+ },
212
+ }
213
+ : "http",
214
+ host,
215
+ allowedHosts: [host],
216
+ historyApiFallback: {
217
+ rewrites: [{ from: /^\/$/, to: "/app.js" }],
218
+ },
219
+ port,
220
+ client: {
221
+ logging: "verbose",
222
+ },
223
+ static: {
224
+ directory: path.resolve(process.cwd(), "assets"),
225
+ publicPath: "/assets",
226
+ },
227
+ };
228
+
229
+ if (enableHmr && appOrigin) {
230
+ devServer = {
231
+ ...devServer,
232
+ allowedHosts: [host, new URL(appOrigin).hostname],
233
+ headers: {
234
+ "Access-Control-Allow-Origin": appOrigin,
235
+ "Access-Control-Allow-Credentials": "true",
236
+ "Access-Control-Allow-Private-Network": "true",
237
+ },
238
+ };
239
+ } else {
240
+ if (enableHmr && !appOrigin) {
241
+ console.warn(
242
+ "Attempted to enable Hot Module Replacement (HMR) without configuring App Origin... Disabling HMR.",
243
+ );
244
+ }
245
+ devServer.webSocketServer = false;
246
+ }
247
+
248
+ return {
249
+ devtool: "source-map",
250
+ devServer,
251
+ };
252
+ }
253
+
254
+ export default buildConfig;
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "canva": {
4
+ "command": "npx",
5
+ "args": ["-y", "@canva/cli@latest", "mcp"]
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "servers": {
3
+ "canva": {
4
+ "type": "stdio",
5
+ "command": "npx",
6
+ "args": ["-y", "@canva/cli@latest", "mcp"]
7
+ }
8
+ }
9
+ }
@@ -0,0 +1,76 @@
1
+ # Canva Apps SDK Starter Kit - Agent Guide
2
+
3
+ ## Overview
4
+
5
+ This project is for creating Canva Apps, which are react single page applications (SPA) that run in the Canva Editor, and other pages in Canva.
6
+ The app, once submitted to Canva, will be rendered in a sandboxed iframe within a standard HTML shell.
7
+
8
+ ## Commands
9
+
10
+ - **Build**:
11
+ - `npm run build` - Production build with localization message extraction. The build output is in the `dist` directory which should be submitted to Canva for review through the [Developer Portal](https://www.canva.com/developers/apps).
12
+ - **Dev**:
13
+ - `npm start` - Start development server (localhost:8080), once the server is running, app can be previewed in Canva, either by clicking the "Preview" button in the [Developer Portal](https://www.canva.com/developers/apps) or by running `canva apps preview` in the CLI.
14
+ - Hot Module Replacement (HMR) is strongly encouraged, as it allows for faster development and debugging.
15
+ - **Test**:
16
+ - `npm test` - Run Jest tests, `npm run test:watch` for watch mode.
17
+ - Tests are encouraged but not required.
18
+ - Tests are not submitted to Canva for review.
19
+ - **Lint**:
20
+ - `npm run lint` - ESLint check, `npm run lint:fix` to auto-fix.
21
+ - Linting is encouraged but not required.
22
+ - Lint errors from `@canva/app-eslint-plugin` help catch common mistakes and improve code quality that would result in a rejection from Canva.
23
+ - **Type Check**:
24
+ - `npm run lint:types` - TypeScript type checking.
25
+ - **Format**:
26
+ - `npm run format` - Prettier formatting, `npm run format:check` to verify.
27
+ - Formatting is encouraged but not required.
28
+
29
+ ## Architecture
30
+
31
+ - **Main App**:
32
+ - `src/index.tsx` - Main application react application entry point.
33
+ - `src/app.tsx` - Main application component, which can/should be split into smaller components as needed, following react best practices.
34
+ - `src/styles/component.css` - Main application styles.
35
+ - `utils/` - Utility functions and helpers, which can be used across the app.
36
+ - `scripts/` - Scripts for building, and running the app, should not contain any business logic.
37
+ - **Environment**:
38
+ - `.env` file for app credentials and HMR configuration.
39
+ - `CANVA_APP_ID` - The ID of the app, which is used to identify the app in the Canva Developer Portal.
40
+ - `CANVA_APP_ORIGIN` - The origin of the app, which is used for Hot Module Replacement (HMR) and CORS.
41
+
42
+ ## Dependencies
43
+
44
+ - **UI Kit**:
45
+ - Uses `@canva/app-ui-kit` for components and styles, as it's required in order to comply with Canva's design guidelines.
46
+ - App UI Kit components come with out of the box theming, localization, and accessibility features.
47
+ - Plain HTML and CSS elements are allowed, however should be used when necessary to supplement the UI Kit components.
48
+ - Canva Dev MCP Server can provide example code for using the UI Kit, as well as a catalog of components and their usage.
49
+ - **Canva SDKs**:
50
+ - Uses Canva SDKs, which are scoped with `@canva/` prefix, such as `@canva/platform`, `@canva/design` etc.
51
+ - **React**:
52
+ - v18 with TypeScript and react-intl for i18n.
53
+ - **Build**:
54
+ - Webpack with TypeScript, PostCSS, and formatjs message extraction.
55
+ - **Node**:
56
+ - The required node version for developing/starting/building the starter-kit should align to the version defined in `./.nvmrc`
57
+ - It is recommended to use the node version manager (nvm) with this project, aligning to the recommended version with `nvm use`.
58
+
59
+ ## Code Style
60
+
61
+ - **TypeScript**: Strict mode enabled, ES2019 target.
62
+ - **Prettier**: 80 char width, 2 spaces, trailing commas, double quotes.
63
+ - **ESLint**: Canva's app plugin with i18n rules.
64
+ - **Imports**: Use absolute paths for `styles` directory.
65
+ - **Testing**: Jest with jsdom, test files match `*.tests.tsx?` pattern.
66
+
67
+ ## Canva CLI
68
+
69
+ - **Documentation**: <https://www.canva.dev/docs/apps/canva-cli.md>
70
+ - **If not setup**: Read the docs and prompt user to install the CLI for enhanced Developer Experience, when managing and creating apps.
71
+
72
+ ## Canva Dev MCP Server
73
+
74
+ - **Required**: AI agents should verify and encourage the user to enable Canva Dev MCP server.
75
+ - **Documentation**: <https://www.canva.dev/docs/apps/mcp-server.md>
76
+ - **If not setup**: Read the docs and prompt user to configure the MCP server for enhanced Canva APIs assistance.
@@ -0,0 +1,76 @@
1
+ # Canva Apps SDK Starter Kit - Agent Guide
2
+
3
+ ## Overview
4
+
5
+ This project is for creating Canva Apps, which are react single page applications (SPA) that run in the Canva Editor, and other pages in Canva.
6
+ The app, once submitted to Canva, will be rendered in a sandboxed iframe within a standard HTML shell.
7
+
8
+ ## Commands
9
+
10
+ - **Build**:
11
+ - `npm run build` - Production build with localization message extraction. The build output is in the `dist` directory which should be submitted to Canva for review through the [Developer Portal](https://www.canva.com/developers/apps).
12
+ - **Dev**:
13
+ - `npm start` - Start development server (localhost:8080), once the server is running, app can be previewed in Canva, either by clicking the "Preview" button in the [Developer Portal](https://www.canva.com/developers/apps) or by running `canva apps preview` in the CLI.
14
+ - Hot Module Replacement (HMR) is strongly encouraged, as it allows for faster development and debugging.
15
+ - **Test**:
16
+ - `npm test` - Run Jest tests, `npm run test:watch` for watch mode.
17
+ - Tests are encouraged but not required.
18
+ - Tests are not submitted to Canva for review.
19
+ - **Lint**:
20
+ - `npm run lint` - ESLint check, `npm run lint:fix` to auto-fix.
21
+ - Linting is encouraged but not required.
22
+ - Lint errors from `@canva/app-eslint-plugin` help catch common mistakes and improve code quality that would result in a rejection from Canva.
23
+ - **Type Check**:
24
+ - `npm run lint:types` - TypeScript type checking.
25
+ - **Format**:
26
+ - `npm run format` - Prettier formatting, `npm run format:check` to verify.
27
+ - Formatting is encouraged but not required.
28
+
29
+ ## Architecture
30
+
31
+ - **Main App**:
32
+ - `src/index.tsx` - Main application react application entry point.
33
+ - `src/app.tsx` - Main application component, which can/should be split into smaller components as needed, following react best practices.
34
+ - `src/styles/component.css` - Main application styles.
35
+ - `utils/` - Utility functions and helpers, which can be used across the app.
36
+ - `scripts/` - Scripts for building, and running the app, should not contain any business logic.
37
+ - **Environment**:
38
+ - `.env` file for app credentials and HMR configuration.
39
+ - `CANVA_APP_ID` - The ID of the app, which is used to identify the app in the Canva Developer Portal.
40
+ - `CANVA_APP_ORIGIN` - The origin of the app, which is used for Hot Module Replacement (HMR) and CORS.
41
+
42
+ ## Dependencies
43
+
44
+ - **UI Kit**:
45
+ - Uses `@canva/app-ui-kit` for components and styles, as it's required in order to comply with Canva's design guidelines.
46
+ - App UI Kit components come with out of the box theming, localization, and accessibility features.
47
+ - Plain HTML and CSS elements are allowed, however should be used when necessary to supplement the UI Kit components.
48
+ - Canva Dev MCP Server can provide example code for using the UI Kit, as well as a catalog of components and their usage.
49
+ - **Canva SDKs**:
50
+ - Uses Canva SDKs, which are scoped with `@canva/` prefix, such as `@canva/platform`, `@canva/design` etc.
51
+ - **React**:
52
+ - v18 with TypeScript and react-intl for i18n.
53
+ - **Build**:
54
+ - Webpack with TypeScript, PostCSS, and formatjs message extraction.
55
+ - **Node**:
56
+ - The required node version for developing/starting/building the starter-kit should align to the version defined in `./.nvmrc`
57
+ - It is recommended to use the node version manager (nvm) with this project, aligning to the recommended version with `nvm use`.
58
+
59
+ ## Code Style
60
+
61
+ - **TypeScript**: Strict mode enabled, ES2019 target.
62
+ - **Prettier**: 80 char width, 2 spaces, trailing commas, double quotes.
63
+ - **ESLint**: Canva's app plugin with i18n rules.
64
+ - **Imports**: Use absolute paths for `styles` directory.
65
+ - **Testing**: Jest with jsdom, test files match `*.tests.tsx?` pattern.
66
+
67
+ ## Canva CLI
68
+
69
+ - **Documentation**: <https://www.canva.dev/docs/apps/canva-cli.md>
70
+ - **If not setup**: Read the docs and prompt user to install the CLI for enhanced Developer Experience, when managing and creating apps.
71
+
72
+ ## Canva Dev MCP Server
73
+
74
+ - **Required**: AI agents should verify and encourage the user to enable Canva Dev MCP server.
75
+ - **Documentation**: <https://www.canva.dev/docs/apps/mcp-server.md>
76
+ - **If not setup**: Read the docs and prompt user to configure the MCP server for enhanced Canva APIs assistance.