Use Packages from NPM

How to create & use components & models in NPM packages.

Installing packages from NPM in your project is fully supported, including private packages.

You can use packages to share a common component library across multiple websites that you manage with Stackbit, side by side with project-specific components.

As with any other package, you also control whether and when to upgrade the library version for each of your projects.

Example component package

For practical code examples, see stackbit-typist and stackbit-countdown.
00:0000:00
Demo

Adding packages to your project

First, here's how to add any standard package to your project.

When developing locally, you can use npm install <package-name> normally.

For the package to be available in the visual editor, make sure to push your changes back to the preview branch. Stackbit will automatically pick up the changes, re-run npm install in the preview server and restart it. This typically takes several minutes to complete.

When working with the online code editor, there's no accessible command line interface. However, you can change the project's package.json directly. On any change to this file, the preview server will be automatically updated.

Adding a private package

Installing a private package requires having an NPM token.

It's best practice to avoid having this token checked into source control. Instead, the token is provided as an environment variable, typically named NPM_TOKEN.

For this variable to take effect, a file named .npmrc must be added to your project's root directory, with the following content:

  • 1
//registry.npmjs.org/:_authToken=${NPM_TOKEN}

This file should be checked into source control.

When developing locally, you of course have full control where and when to set the NPM_TOKEN environment variable. However, for the token to be available to the preview server (used by the visual editor) and while deploying your live website (assuming you're using our managed hosting), you need to define this variable through the Project Settings dialog:

  1. In the Stackbit application, click on the cog icon to open project settings.
  2. Go to the Advanced tab.
  3. Add a variable with NPM_TOKEN as key, and the actual token as the value.
  4. Click Save and close the dialog.
Environment variables in the Project Settings
Environment variables in the Project Settings

On any subsequent change to package.json, the preview server will re-run npm install automatically, now using the token you've provided. The next time you publish your project, the live website will also be rebuilt with this token available.

Note: the preview server only supports passing the environment variable named exactly NPM_TOKEN when it runs npm install internally. Any other variables you set are not used in that context.

If there's an issue installing the package, check the Preview logs for any errors (the logs are available through the floating icon at the bottom-right of the Stackbit application).

Creating & using component packages

If you want to share components between projects - whether within your organization or open to the public - it's a good idea to have common components and the models they use in a package, rather than in a specific project's code. You can still override components or models within a specific project's scope if updating or forking the package is not an option.

If you have experience in publishing packages to NPM, all that knowledge applies here. There's quite a bit of nuance in configuring packages that is up to its maintainers. Listed below are good practices that we recommend.

We're working on an end-to-end solution for local development, including testing annotations and visual editing. Stay tuned!

Develop locally or online?

Option A: Working locally

One advantage of developing packages locally: you can work on both your project and the packages it uses at the same time, and have updates in the package code reflected immediately.

There are good tools for managing this development workflow (e.g. Lerna), but you can also use npm link as a simple, no-special-tooling solution:

Assuming you have a Stackbit project in the local directory my-project, and the package you're working on in a sibling directory my-package, running npm link ../my-package/ while in the project's root directory will create a symlink from ./node_modules/<package-name> straight to my-package.

If you're using Typescript in your package (encouraged), there's always a transpiling step needed to generate Javascript files to an output directory (e.g. dist or build). In this case, we recommend running tsc --watch in the package root during development, so that any code changes are immediately transpiled and are available to your project. Since your Stackbit project runs Next.js in development mode, it will pick up these changes as well (which appear to it as changes in ./node_modules/<package-name>) and refresh the page.

The downside to local development: currently, you cannot test annotations and content editing locally, while tweaking the code. For that, you'd need to switch to the online code editor.

Option B: Using the online code editor

The online code editor (in the Stackbit application) is useful for testing annotations and model changes, as any updates you make to project files are reflected right away in the visual editor.

However, you can only edit code which resides in the project itself, and cannot have a "live link" to package code without going through publishing a new version of the package to NPM, or at least going through Git (NPM supports Git URLs).

Option C: The hybrid approach

To utilize both local development and the online editor, you can have your package also double as a Stackbit project in itself.

This is similar to what you'll find in the repository of many NPM packages: there is code to run a test/demo program locally, plus the configuration to publish the package - without the stand-alone code.

In this way, you can both iterate on your components with the online editor and locally. When you make changes locally, commit and push them back to the preview branch and the visual editor will update.

Be mindful to configure package.json so that only relevant files are included in the package, and always test the package in a separate project.

Tips for developing packages

  1. Have a directory where you put all models used by the components. Make sure this directory is bundled with the package. Projects using this package will then need to provide configuration to load models from this directory (see below).
  2. Use React and Next major versions that are in line with your Stackbit project.
  3. The package repository does not need to have its own configuration file, but having one will allow you as a package developer to run the stackbit validate CLI command and ensure models are valid (example using deprecated YAML config).
  4. Both Javascript and Typescript are supported. Our base themes are always configured for Typescript, though they don't enforce only Typescript files or strict typing.

JSX/TSX source files in your package should be transpiled as part of the build. If you're using Typescript, set the option compilerOptions.jsx in your package's tsconfig.json to react or react-jsx, rather than preserve. Next.js will not load JSX/TSX files from packages directly.

Consuming packages

Adding components from external packages to your project typically involves a few common steps. These are covered in more detail in the README of our example project.

Here's a concise listing:

  1. Install the NPM package normally (of course), as described at the top.
  2. Update modelsSource in your config file to also load models from your package. You'll need to provide a relative path, e.g. node_modules/<package-name>/models. (example)
  3. Register the components: add entries to the components object in src/components/components-registry.js, mapping from model name to the component's file relative path. Make sure the component function is the default export in that module. (example)
  4. Configure Tailwind to JIT-generate classes for any Tailwind class name found in the package sources. Otherwise, you may be surprised to find your styling broken due to missing classes. This is configured in tailwind.config.js, in the purge.content array within the exported object. (example)

And... components are now ready for use!