p5Catalyst is a GUI framework that wraps your p5.js sketches into polished, interactive web apps, ready for asset exporting and daily use. Whether you're building dynamic brand systems, data visualizations, or generative art, p5Catalyst gives your sketches the structure and tooling they need to go beyond a sketch and into production.
Initiated by creative agency Multitude, p5Catalyst grew out of real-world branding needs, and is now shared as a creative coding toolset for everyone.
- Sketch integration: integrate a finished p5 sketch easily.
- Lives in the browser: no install required, shareable and hackable by default.
- Built-in GUI system: add sliders, dropdowns, toggles, and color pickers with minimal setup.
- Export support: save outputs as PNG or video: PNG frames, MP4 or transparent WEBM.
- Theming: GUI respects system theme and the light and dark themes are easy to style.
- File I/O: save/load user settings.
- Change history: undo and redo changes.
- Internationalization: plug in translations for global-ready tools.
At Multitude, we believe branding should be fluid, flexible, and future-proof. Instead of static design systems, we embrace generative branding, where design systems evolve and adapt in real-time.
We originally started building p5Catalyst to give our clients control over the generative brand systems we designed. Now we're sharing it to help other creative coders do the same, and more!
Let's build the future of generative design!
The project now uses Vite for development and builds. Follow the steps below to get started.
git clone https://github.com/multitude-amsterdam/p5Catalyst.git YOUR_NEW_APP_NAMEor alternatively, download the code as a ZIP file by clicking the <> Code button at the top-right of this page.
Vite relies on Node.js tooling. Make sure you have Node.js (which includes npm) installed, then install the project dependencies:
cd YOUR_NEW_APP_NAME
npm installThis command downloads the packages listed in package.json.
Start an interactive development environment:
npm run devVite will print a local URL (usually https://localhost:5173) where you can preview p5Catalyst while you work. You can run "o" in the terminal to open the web page in your browser.
src/main.js is the single entry point that Vite loads. It initializes the GUI layer and spins up a p5 sketch in instance mode, meaning all sketch functions live on the sketch argument, rather than the global scope. Instance mode keeps the sketch encapsulated and avoids global name collisions as the project grows.
src/main.js is the main entrypoint for the p5 sketch. Using p5Catalyst here is done in three parts.
This is where your setup() and draw() functions live, just like in a regular p5 sketch.
// src/sketch.js
export const sketchSeed = async sketch => {
sketch.setup = async () => {
sketch.circleDiameter = 0.5;
sketch.circleColor = sketch.color(0);
sketch.bgColor = sketch.color(0);
sketch.noStroke();
};
sketch.draw = () => {
// background ellipses
sketch.background(sketch.bgColor);
// method provided by p5Catalyst to display a backdrop image
sketch.attemptDrawBackdrop();
// animated circle
sketch.fill(sketch.circleColor);
const diam =
sketch.width *
sketch.lerp(1 / sketch.nBgElements, 1, sketch.circleDiameter);
const amp = (sketch.height - diam) / 2;
// `sketch.progress` is automatically provided by p5Catalyst to animate over time
sketch.circle(
sketch.width / 2,
sketch.height / 2 +
sketch.sin(sketch.progress * sketch.TAU * 2) * amp,
diam
);
// method provided by p5Catalyst to display an overlay image
sketch.attemptDrawOverlay();
};
};This section creates user-facing controls to interact with the sketch. Think of it as all of the controllers: sliders, color pickers, textboxes, etc.
Controllers are grouped into tabs and panels. All controllers can access state via a callback, so that they can store data there that can be accessed by the sketchFunction.
Naming controller, like 'sliderCircleDiameter', is important for plugin targeting, like randomization.
export function createGui(gui, sketch) {
// get the 'Appearance' tab that is proved by p5Catalyst in `defaultPlugins`
const appearanceTab = gui.getTab('appearance');
// add a new collapsable panel to contain the controllers
const circlePanel = appearanceTab?.addPanel('Circle', true);
// add a color picker with multiple colored boxes
circlePanel?.addColorBoxes(
'colorBoxesCircle',
'Circle color',
['#FF2600', '#86D594', '#004D30', '#336DFF', '#F5CBFF'],
0,
(controller, value) => {
// these callback are called when the controller's value changes
sketch.circleColor = value;
}
);
circlePanel?.addSlider(
'sliderCircleDiameter',
'Circle size',
0,
1,
sketch.circleDiameter,
0.001,
(controller, value) => {
sketch.circleDiameter = value;
}
);
// add another collapsible panel
const bgPanel = appearanceTab?.addPanel('Background pattern', true);
bgPanel?.addColorBoxes(
'colorBoxesBg',
'Background color',
['#FF2600', '#86D594', '#004D30', '#336DFF', '#F5CBFF'],
3,
(controller, value) => {
sketch.bgColor = value;
}
);
}This section defines which p5Catalyst features your sketch will use. Many of these are additions to the GUI that add specific functionality, like video exporting.
export const plugins = [
// set the title of your app
appTitlePlugin('CircleGen'),
// add the default plugins
...defaultPlugins,
// add a randomizer (dice icons) on controllers by name
randomizerPlugin([
'colorBoxesCircle',
'sliderCircleDiameter',
'colorBoxesBg',
'sliderNBg',
]),
// create your own custom plugin to run code at specific times during initialization
{
name: 'customPlugin',
beforeGuiExists(sketch, config) {
console.log('beforeGuiExists!');
},
beforeUserCreatesGui: (gui, sketch, config) => {
console.log('beforeUserCreatesGui!');
},
afterUserCreatesGui: (gui, sketch, config) => {
console.log('afterUserCreatesGui!');
},
},
];- Extract your reusable code into JavaScript or TypeScript files in
src/andimportthem intosketch.jsas your project grows. - Share
sketchbetween the GUI and sketch by reading or updating variables inside thesketchvariable. - Access
sketch.catalystfor additional fields provided by p5Catalyst, including properties:isPlaying: a flag to pause the updateing ofsketch.frameCount, which causes a pause insketch.catalyst.progressandsketch.catalyst.timeisRecording: flag to indicate when frames are being saved for video exportinganimationFrameCount: the number of frames to record for video exportexportStage: a string describing the stage in video exporting ("idle","recording "or"exporting")duration: suration of the animation setting in secondsfps: the set frame ratemouseWheelScale: a scaling factor that updates when a mousewheel event happenssessionId: a unique string per page loadsessionHash: a unique number between 0β1- And a bunch of helper methods (see: (p5Catalyst.ts)[../src/lib/Catalyst.ts])
/* src/style.css */
body {
/* edit colors and other variables here */
--base-col: #336dff;
--text-col-on-base: var(--bg-col);
--hover-col: #90de00;
--focus-col: var(--hover-col);
}When you're ready to create an optimized build, run:
npm run buildIf there are no errors, the project has now been built into the dist/ directory and you can plop it in on a server with FTP.
When you clone this repo and create a project out of it, you also disconnect from any updates to this repo. To update your project to match this repo, you can merge this main repo into your clone.
git remote add p5catalyst https://github.com/multitude-amsterdam/p5Catalyst.gitgit fetch p5catalystYou can view these changes with:
git diff main..p5catalyst/mainOr just for an overview:
git diff --stat main..p5catalyst/maingit merge p5catalyst/mainIf any merge conflicts arise, you will need to resolve these in your editor.
git add .
git commit -m "p5catalyst update"Done!
We kindly ask: if you make something cool with p5Catalyst, please share it! Whether it's a wild new web app, an adaptation for a client, or just a fun remix, we'd love to see it π!
- Create a new thread in the Show and tell section of the Discussions
- Share screenshots or videos of your creations
- Mention us if you publish your forked project online
Keep in mind the Community Code of Conduct for this project.
We encourage you to make modifications, improvements, or entirely new generators, it's easier than you think! For more information on contributing, continue reading here.
For security concerns, please review the security policy.
Developed using Vite, p5.js, ffmpeg.wasm and jszip.
This project is licensed under the MIT License: free to use and modify.
Follow the development and join the discussion:
- GitHub Discussions: join the conversation
- Multitude's Instagram: @multitudecreativeagency

