npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@canva/app-scripts

v1.1.1

Published

Build scripts and bundler configuration for Canva Apps

Readme

@canva/app-scripts

Build scripts for Canva Apps.

@canva/app-scripts is designed to be used through the Canva CLI: canva apps start and canva apps build are the recommended way to run and build your app. Prefer working with the package directly? Its own CLI commands and programmatic API are there for you too.

Installation

npm install -D @canva/app-scripts

Have a Canva App that isn't using @canva/app-scripts yet? You probably have a webpack.config.ts and a scripts/start/ runner at its root - see the migration guide to make the switch.

Configuration

Create an optional canva-app.config.ts file in your project root to override defaults (.js, .mjs, .cjs, .mts, and .cts are also supported; TypeScript is recommended):

Basic Configuration

import { defineConfig } from "@canva/app-scripts";

export default defineConfig({
  entry: "./src/index.tsx",
});

Bundler Selection

By default, @canva/app-scripts uses Rsbuild as the bundler. You can explicitly select a bundler:

import { defineConfig } from "@canva/app-scripts";

export default defineConfig({
  bundler: "rsbuild", // Default, can be omitted
  entry: "./src/index.tsx",
});

Bundler support:

  • rsbuild - Default bundler
  • webpack - Supported alternative

Customizing the Bundler

Use the config function to customize the underlying bundler configuration. The callback is typed per bundler, so bundler and config travel together, and the configuration types are sourced from the respective bundler's own package (@rsbuild/core, webpack).

Rsbuild (default)

import { defineConfig } from "@canva/app-scripts";
import type { RsbuildContext } from "@canva/app-scripts";
import type { RsbuildConfig } from "@rsbuild/core";

export default defineConfig({
  config: (rsbuildConfig: RsbuildConfig, { mode }: RsbuildContext) => {
    // Disable source maps for production builds
    if (mode === "production") {
      rsbuildConfig.output = { ...rsbuildConfig.output, sourceMap: false };
    }
    return rsbuildConfig;
  },
});

webpack

import { defineConfig } from "@canva/app-scripts";
import type { WebpackContext } from "@canva/app-scripts";
import type { Configuration } from "webpack";
import path from "path";

export default defineConfig({
  bundler: "webpack",
  config: (webpackConfig: Configuration, { mode }: WebpackContext) => {
    // Add SVG loader - import SVGs as React components
    webpackConfig.module?.rules?.push({
      test: /\.svg$/,
      issuer: /\.[jt]sx?$/,
      use: [
        {
          loader: "@svgr/webpack",
          options: {
            svgoConfig: {
              plugins: [{ name: "removeViewBox", active: false }],
            },
          },
        },
      ],
    });

    // Add path aliases for cleaner imports
    webpackConfig.resolve = {
      ...webpackConfig.resolve,
      alias: {
        ...webpackConfig.resolve?.alias,
        "@components": path.resolve(__dirname, "src/components"),
        "@assets": path.resolve(__dirname, "src/assets"),
      },
    };

    // Enhanced source maps for development
    if (mode === "development") {
      webpackConfig.devtool = "eval-source-map";
    }

    return webpackConfig;
  },
});

Note: Custom loaders like @svgr/webpack must be installed separately:

npm install --save-dev @svgr/webpack

The config function receives:

  • The base bundler configuration (RsbuildConfig from @rsbuild/core, or Configuration from webpack)
  • context - Build context with mode ("development" or "production")

Backend

If your app has a backend, set backend to run it alongside the dev server. It runs under nodemon with TypeScript support, and a backend crash tears the dev server down. Any backend config (even {}) enables it.

import { defineConfig } from "@canva/app-scripts";

export default defineConfig({
  entry: "./src/index.tsx",
  backend: true, // runs backend/server.ts
});

Pass an object to override the defaults:

| Option | Description | Default | | -------- | --------------------------------------------------------------------------- | ------------------- | | entry | Backend entry, relative to the project root. | backend/server.ts | | port | Port the backend listens on. Falls back to CANVA_BACKEND_PORT. | 3001 | | host | Backend host the built app calls. Falls back to CANVA_BACKEND_HOST. | — | | tunnel | Expose the backend through a public HTTPS tunnel. Overridden by --tunnel. | false |

export default defineConfig({
  backend: { entry: "./api/main.ts", port: 3100 },
});

Dev Server

Optional dev-server options. CLI flags and environment variables override these at run time.

| Option | Description | Default | | ------- | ------------------------------------------------------------------- | ------- | | port | Frontend dev-server port. Overridden by --override-frontend-port. | 8080 | | https | Serve the frontend over HTTPS. Overridden by --use-https. | false |

export default defineConfig({
  devServer: { port: 9000, https: true },
});

Translations

Optional configuration for extract-translations.

| Option | Description | Default | | ------------ | ------------------------------------------- | ------------------- | | outputDir | Directory to write extracted messages into. | dist | | outputFile | Output filename (no directory segments). | messages_en.json | | pattern | Glob for source files to scan. | src/**/*.{ts,tsx} |

export default defineConfig({
  extractTranslations: { outputDir: "i18n", pattern: "app/**/*.tsx" },
});

Environment Variables

These environment variables are supported but optional. Most can also be configured in canva-app.config.ts (recommended); some remain env-only.

| Variable | Description | When needed | | --------------------- | ------------------------------------------------------------- | ---------------------------------- | | CANVA_FRONTEND_PORT | Dev server port (default 8080). Overrides devServer.port. | Optional — prefer devServer.port | | CANVA_BACKEND_PORT | Backend server port (default 3001). Overrides backend.port. | Optional — prefer backend.port | | CANVA_BACKEND_HOST | Backend URL the built app calls. Overrides backend.host. | Optional — prefer backend.host | | CANVA_HMR_ENABLED | Enable Hot Module Replacement (true/false). | Optional | | CANVA_APP_ORIGIN | App origin URL. | Required for HMR | | CANVA_APP_ID | Canva app ID. | Required when running a backend | | NGROK_AUTHTOKEN | ngrok authtoken. | Required when using --tunnel |

Configuration precedence

When an option can be set in more than one place, highest priority wins: CLI flag > environment variable > canva-app.config.ts > package default. Not every option exists in every channel; the CLI prints a Warn: when an env var shadows a config value.

Design Philosophy

The public defineConfig() API is intentionally minimal:

  • entry, rootDir, and outputDir - Essential app configuration
  • bundler - Select the build tool (Rsbuild by default, webpack also supported)
  • devServer - Dev-server options (port, HTTPS)
  • backend - Run a backend alongside the dev server
  • extractTranslations - i18n extraction options
  • config - Escape hatch for full bundler customization

Every option is overridable at run time via CLI flags and environment variables, so the config file holds what's stable to the project while the invocation controls the rest.

CLI Commands

The package provides a canva-app-scripts CLI with the following commands. The Canva CLI's canva apps start and canva apps build are the recommended way to run these; use canva-app-scripts directly if you'd rather not go through the Canva CLI.

dev

Start the development server. Serves the app from src/index.tsx.

npx canva-app-scripts dev

If a backend is configured (or --backend-entry is passed), the backend entry is run alongside the dev server under nodemon, with SSL certificate paths passed through to its environment. A backend crash tears the whole dev server down. See Backend for the config options.

npx canva-app-scripts dev --entry ./src/app.tsx
npx canva-app-scripts dev --backend-entry ./backend/server.ts

build

Build the app for production. Outputs to dist/ by default.

npx canva-app-scripts build
npx canva-app-scripts build --entry ./src/app.tsx --output-dir ./build

extract-translations

Extract i18n messages from your source files into dist/messages_en.json.

npx canva-app-scripts extract-translations
npx canva-app-scripts extract-translations --output-dir ./i18n --pattern "src/**/*.{ts,tsx}"
npx canva-app-scripts extract-translations --output-file messages.json

Global CLI options

  • --entry - Entry file for the app (overrides entry from the config; on dev and build)
  • --tunnel - Expose the backend through a public HTTPS tunnel (alias: --ngrok)
  • --use-https - Start local development server on HTTPS
  • --override-frontend-port - Override the frontend port
  • --backend-entry - Path to the backend entry script (overrides backend.entry from the config)

Changelog

See the CHANGELOG.md file.

Contributing

We're actively developing this package but are not currently accepting third-party contributions. If you'd like to request any changes or additions to the package, submit a feature request via the Canva Developers Community.

License

See the LICENSE.md file.