How To Use P5.js In Svelte

Joy of Code| 00:09:16|Mar 18, 2026
Chapters8
The chapter introduces using the p5.js library in Swelt, explains the goals of a simple wrapper to fix issues, and sets up the two-part video focus on integrating p5.js and handling older CJS add-ons within Swelt.

Joy of Code demonstrates using p5.js inside Svelte with a wrapper, covering instance mode, add-ons, and handling CommonJS dependencies.

Summary

Joy of Code’s video starts by outlining two audiences: folks already familiar with p5.js and those curious about integrating “stinky old” libraries in Svelte. He introduces a wrapper he built to fix memory leaks in the inactive p5-swelt library and references Dan Shiffman (Coding Train) and The Nature of Code as inspiring resources. The tutorial portion shows a minimal p5.js sketch in Swell’s global mode, creating a canvas, removing strokes, and drawing a circle whose position follows the mouse. He then walks through installing the wrapper with npm install @swelcraft/p5-swelt and confirms that p5-pure is installed automatically. The core pattern uses an instance-based approach: define a sketch function with setup and draw, then pass it to p5Sketch so multiple canvases can exist. Next, he explores adding the p5 sound add-on, noting it’s a separate package and requires a dynamic import to attach p5 to the window before instantiating). He also contrasts the pre-ESM and current ecosystem, pointing out type gaps and the need for explicit typing where possible. In a deeper dive, Joy of Code explains handling CommonJS add-ons by dynamically importing p5.js, renaming the default class, and ensuring proper cleanup without async in useEffect-like hooks. Finally, he illustrates the difference between global and instance mode with a window/iframe example and links this back to the p5.js wiki’s guidance, tying the whole workflow back to the goal of using p5.js smoothly inside Swell. If you’re curious about next steps, he teases a future look at the library itself and how to address more add-ons in Swell.

Key Takeaways

  • Install the wrapper with npm install @swelcraft/p5-swelt; it will pull in p5-pure automatically, and you can fall back to installing p5 separately if needed.
  • Use instance mode by defining a sketch function with setup and draw, then pass the sketch to p5Sketch to support multiple canvases without interfering global state.
  • To add p5 sound or other add-ons, install the separate package and use a dynamic import so the add-on can bind to the p5 instance before the global window is touched.
  • CommonJS add-ons require a dynamic import and a careful setup where you rename the imported default to p5 and then initialize the sketch to avoid module export issues.
  • Avoid declaring async cleanup functions inside a setup/effect; define async helpers separately to ensure proper cleanup and prevent memory leaks.
  • Global versus instance mode matters: global mode exposes setup/draw on window, while instance mode lets you manage multiple sketches safely, an approach explained using the p5.js wiki.
  • Joy of Code demonstrates that the ecosystem around p5.js is aging (older 2.0 changes, typings gaps), so expect some manual typing and compatibility tweaks when combining with modern frameworks.

Who Is This For?

Essential viewing for Svelte developers who want to integrate p5.js without memory leaks, and for those curious about bridging CommonJS add-ons with modern ES modules. It also helps folks who want to understand instance vs global mode in p5.js while working inside Swell.

Notable Quotes

"The only thing that you have to do is install this package inside your SWL project."
Shows the basic required step to start using the wrapper.
"In this example, we have the p5 sound add-on. So, this is a separate package now that you have to install."
Explains handling add-ons as separate packages.
"The only thing you have to do is pass the sketch to p5Sketch."
Describes the core instance mode wiring.
"Don’t use async here. If you return an async function, your cleanup is not going to run and you’re going to have a memory leak."
Important cleanup caveat when using effects/hooks.
"This is the cursed part. If you define function setup and function draw then everything is in the global context."
Clarifies global vs instance mode behavior.

Questions This Video Answers

  • How do you install and use p5.js inside a Svelte project with Swell?
  • What's the difference between p5.js global mode and instance mode in a Svelte setup?
  • How can I add p5.js add-ons like p5 sound when using CommonJS libraries in Swell?
  • How do dynamic imports help when integrating older libraries with modern JavaScript frameworks?
  • Why is instance mode preferred for multiple p5.js canvases in a single app?
p5.jsSveltep5-sweltSwellinstance modeglobal modep5 sound add-onCommonJSdynamic importTypeScript typings
Full Transcript
Hey friends, today's video is going to be aimed at two people or maybe they're the same person. In the first part, I'm going to show you how you can easily use the library p5 js in Swelt without any problems using the library I created. So, this video isn't going to be a tutorial on how to use p5.js. It already assumes that you're familiar with it. And if you still want to hear me yet, the second part of the video is going to be all about the library I created. So, we're going to talk about how you can use stinky old libraries in Swelt, which are CJS, right? So, it's going to pose a problem to you. All right. So, this all started when someone asked how to use p5.js in Swelt. And while there's already a p5 swelt library, it's inactive and it also has a memory leak. So, I decided to make a simple wrapper myself and fix some of the issues. So, even though I don't use p5 regular, when I think of p5, I think of Dan Shipman from the coding train, which has a special place in my heart. and then also has a fantastic book called The Nature of Code which you can read for free online. So if you're curious about randomness, vectors, forces, oscillation, and etc. I'm going to put all of the links in the description. And if you're not familiar, P5JS is a library that makes it simple to work with the canvas. So here we have something that's called global mode where you can just specify the setup and draw function. So in the setup, we're going to create a canvas and specify no stroke. Then in the draw method, which is going to run in a loop, we're going to constantly be drawing the background and we're going to lur the X and Y value based on the mouse position. We're going to fill our circle. And lastly, we're going to draw the circle. So, if I press play, I'm going to see that we can drag this circle around. All right, enough yapping. Here's how you use P5. JS in Swell. The only thing that you have to do is install this package inside your SWL project. So if you're using npm, it's npm install at swelcraft/p5-swelt. And that's it. It should also automatically install the p5 pure dependency for you. But if it doesn't, then you should install p5 yourself. All right. So this is just a basic swell kit project. So we can just say npm install at swellcraft p5 swelt. And we can just install it like any other package. All right. And once you're done, we can start the development server. And if we navigate back to local host, you're going to see that we have a working p5 js example in swel. And of course, we also have swel reactivity. So we can change the diameter of the circle and everything works great. All right. So let me explain how this works. The only thing that you have to import is this p5 sketch, but you can name this whatever you want because this is just a default export. So you can name this banana if you want. And then we also import this type sketch. So we get great autocomp completion. And here we have defined two variables x and y. And we have a reactive variable called diameter. But this actually doesn't have to be reactive because this runs in a loop here inside of our draw function. So it's always going to be updated. This only shows that swel reactivity also works because we bind the value here. And the only thing that we have to do is create this sketch function with this setup and draw functions. So inside of setup, we're creating this canvas and we're using something that's called instance mode. So we have to take P dot and now we can get all of the type completion. So you can get pi whatever else that you want. But basically this allows us to create multiple p5 sketches or however many that you want. So here we're creating a canvas. We're saying no stroke same as before. And now in the draw function we're drawing a background. We're interpolating between X and Y using the mouse position. And then we're filling the circle. And then we're drawing the circle. And then the only thing we have to do is pass the sketch to p5 sketch. And that's basically it. In the next example, I'm going to show you how you can even use add-ons like p5 sound, which is a bit more complicated because we're using the 2.0 version of p5.js that's slightly different than before. All right, so here's an example how we can use add-ons. In this example, we have the p5 sound add-on. So, this is a separate package now that you have to install. So, unfortunately, it doesn't come with types. Keep in mind, p5 js is an old library. So, the entire ecosystem around it hasn't caught up. Honestly, if you don't want to use p5 sound, you can just use stone.js. That's basically just a wrapper around it. But in this case, we have to specify this add-on variable and you have to use a dynamic import because in the library, I have to put this before specifying p5 on the window because this old stinky add-ons look for a global instance of p5. So I try to make it as simple as possible. So here we're defining the sound variable and again this isn't typed. So we have to use ts expect error if you get typescript warning. So we can just say p load sound and then it's going to work. So here where we have mouse press we're going to say sound play and we also have to use a custom type for this if you want type safety because again it's not typed and the only thing you have to do is pass this add-ons to this component. All right so now if I click anywhere on the page it's going to play the sound. All right. So, let me give you a bit more context why we have to do this. So, in the past, p5.ound was part of p5 itself, but later they just removed it from the library and now it's a standalone package. So, here we're looking at the react wrapper for p5 and they're using an older version. So, before it was way simpler as you can see here, they have to do this thing where they specify p5 on the window. Then they're loading this library which attaches its method on the class. And then it was also way easier when you could just use this type. So you could say p5 soundfile, p5.element and etc. But in our example, we're using a newer version of p5.js, so the ecosystem hasn't caught up. All right, friends, that's everything that you have to know to use p5 js in swelt. And if you find any issues, feel free to file them in the p5 swelt repository. All right, if you're interested in the next part, I'm going to talk about the library itself. All right, let me show you how you can deal with stinky old ass add-ons that use CommonJS instead of ESM. And to be fair to p5 js, I think they're starting to use eggmascript modules now. It's just that some libraries they depend on still use common js. So let me actually show you this library is really simple. Well, it's just a wrapper, right? So here the only thing I'm doing is importing this p5 type from p5 library. That works great. Thank god. All right. And then I'm just importing this sketch, which is not important. So here we have our props, sketch, add-on style, and class. And here we have also the target element or node. and then the instance itself which you're going to use later for cleanup. All right, so here is the interesting part. So let's say that you have some library and you want to import it. So let's import p5 and let's save. So now let me open the console. Let's run the development server and you're going to immediately see the issue you're going to run into. Named export gif encoder not found. The requested module gif encode is a commonjs module which may not support all module exports as named exports. All right and now you're screwed. So what do you do? Well, now we have to use a dynamic import. So, let me just remove this code. And now inside this setup here, I'm using a dynamic import to import p5 js and then we're going to dstructure the default class or instance and we're going to rename it to p5. And then later we're going to reassign this instance and create a new p5 instance. Then we get p5 itself. And then we can invoke our function prop sketch. And then we can pass p5. And here I have this props add-on. if you passed any add-ons. Then I'm going to define p5 on the window for you. So you don't have to do it yourself like in that react wrapper example. And then I'm just going to use promise all to await all of the imports. So inside this effect, we're going to use setup.catch if there's any errors and we're going to return a cleanup. All right. But there's one thing that you should never do regardless if you use all mount or effect. Don't use async here. If you return an async function, your cleanup is not going to run and you're going to have a memory leak. So you can define an async function somewhere else. You can use an asyncy if you want or you can just use den. So now if you reload the page you're going to see everything is going to work as expected and that is how you deal with these stinky old ass packages. There is also one more interesting thing to talk about and that is global versus instance mode. So if you remember previously how I mentioned global and instance mode. So how does this even work? Like this isn't some magic. How does just defining setup and draw just work? And this is the cursed part. So if you didn't know, if you specify a function inside a regular script tag, it becomes part of the window. So later p5.js in its set of phase just invokes these functions. So let me actually show you this because this is an iframe. We have to actually select the iframe here. So I think it's this blob. All right. So if we say window, so you can see that we get a bunch of interesting thing from the p5. JS instance. But what happens if we say for example window setup we get our setup function same as our draw function. How cursed is this friends? There is even an entire section on global and instance mode in the p5 js wiki. As you can see when we define function setup and function draw then everything is in the global context. But of course we want to have multiple sketches and so on. In that case we use the instance mode. And this looks really familiar. So, this is the exact same method that we use. All right, that's it. Thank you for watching and I'll catch you in the next one. Peace.

Related Videos

Get daily recaps from
Joy of Code

AI-powered summaries delivered to your inbox. Save hours every week while staying fully informed.