Importing External Code
How to use code from other sources such as NPM or es-module CDNs.
Framer code works entirely based on ES Modules, meaning that any code expressed as an ES module on an HTTPS endpoint will work. So the easiest way to bring external code into Framer is to just write some vanilla JavaScript like this:
// https://gist.github.com/koenbok/5f844e61e1266ac9ac5514023997c750
import React from "react"
export function TestComponent() { return React.createElement("div", {}, "Hello World")}
Now in a Framer code file, you can simply import the code file inside a Framer code file and start using it (I'm using a production hosted version of the script via GitHack):
import { TestComponent } from "https://gist.githack.com/koenbok/5f844e61e1266ac9ac5514023997c750/raw/8f7b64eb628921bed4862b6795612ed2002e463d/test-component.js"
export function MyComponent() { return <TestComponent />}
Now you can add the MyComponent
to the canvas and you'll see it uses the externally imported component!
These are some other typical sources you would publish and load your code from. Remember, it's all pure ES Modules.
- If you have your code as a public npm package, you can use jspm.dev/<your-package>. As long as JSPM can figure out how to convert it into a code module, it should work.
- If you have your code published as an es module on an HTTP endpoint, you can directly import that URL from any code file in Framer.
- If you build your JavaScript with a bundler (like esbuild, Rollup or Vite) you’ll have to set the output format to ES Module.
You can optionally decorate React Components using propertyControls to add an interface to control the props for the user on the canvas.
Gotchas
When importing external code directly, make sure these are on your radar:
- While some folks try to bring in their full production design systems, we currently advise against this and don’t actively support it. Production components need a lot of tweaking to be consumable by designers so that they get broad adoption. Additionally, the often custom build tooling around production components is not always easy to integrate.
- All the external code needs to needs to be vanilla JavaScript. If packages import extra files (like for example CSS styling) you need to make sure they get added to the dom within the script.
- If you are using code that imports the same library multiple times, but with different versions, it will end up with multiple instances of that library. This will be soon fixed using more extensive import map support. For now, we only map React, Framer, and framer-motion so import those directly (instead of the full URL).
#How do I use NPM?
This is currently in beta but you are free to play and try if you keep an eye out for the issues below. We know how to fix them and will be working on them over the next few weeks. You’re welcome to play and follow along, but be careful relying on it too much until we ship a few small updates.
Issues
NPM packages that import libraries that cannot deal with two instances won’t work. Most notably this is React (or Framer). Right now this only works if all packages relying on React import using "react". If they do a module URL import, another version of React will get loaded and things will break. We are making import map improvements to solve this structurally.
Example
There are cool CDNs that expose every NPM package as an ES Module. You can for example use jspm. This would be how you would use lodash for example:
import * as _ from "https://jspm.dev/lodash@4.17.21"// Use lodash code here...
#How do I use private code inside Framer?
To be honest, you probably shouldn’t.
Your compiled JavaScript will be shipped to customers at some point, and putting it behind a password now will make your project fragile without any added real security.
Your source code should obviously stay private in a secured repository. Also, consider minifying your compiled code and don’t forget to strip the source map.
If you really want to do this anyway…
You have three options, from non-ideal to pretty bad.
Put them behind a secret URL that nobody can guess. This is how a lot of things get reasonable security on the internet. As long as you keep the Framer project secure, folks won’t be able to find your scripts.
import { MyCode } from "https://bigco.com/e5ecc4a1420ce145b4003a38f84bda63/lib.esm.js"
Put them on a server within the vpn. Everyone connected to the vpn will be able to see your prototype. As a bonus you can implement a warning like this:
// check.js: add this check anywhere in your projectimport("https://internal.bigco.com/lib.esm.js").catch((err) => { alert("Please connect to the VPN of BigCo") window.location = "https://internal.bigco.com/vpn-instructions"})
Another alternative would be to set up HTTP basic auth, but this requires the user to log in on your own site before they can see or use your project, which isn’t a great experience. You can implement a warning like this:
// check.js: add this check anywhere in your projectimport("https://internal.bigco.com/lib.esm.js").catch((err) => { alert("Please login at the BigCo site with a password") window.location = "https://internal.bigco.com/login"})
But again, all of these are pretty non-ideal for users, and they don't add much real security.
#How do I use GitHub?
Framer contains a pretty great editor and has a built-in module repository, which should be great for most use cases.
But if you're looking to bring external code in that you can keep in GitHub, you can build your own setup, as long as the output us vanilla JavaScript in ES Modules format.
You can use this example setup on GitHub as a reference. It uses esbuild
, supports local development and works with css module imports.
Please beware that we don't have the bandwidth to support every custom JavaScript build setup, so while we're always happy to drop a hint in our community if we can, we can't officially support custom setups.
#Help and Support with Custom Code
You can always join the community where we hang out to get support from peers. If you have an enterprise contract, you can access product specialists directly and they can help within the following limitations:
- We officially support everything you can do from inside Framer. While we’re happy to drop hints on how to get your own external integrated setup to work, we offer consulting for your custom setup at a fair price if you want us to materially help you set up a custom-built system(depending on availability and scope).
- Unfortunately, we can’t really offer support on an enterprise network and security setups and custom JavaScript build tool setups.
, meaning that any code expressed as an ES module on an HTTPS endpoint will work. So the easiest way to bring external code into Framer is to just write some vanilla JavaScript like this:
// This lives at a web server with url:// https://my.site.com/my-code.jsexport const add = (a, b) => { return a + b;}