I’ve been exploring different approaches for creating dynamic NFTs and came across a technique where developers embed SVG content directly in smart contracts like this:
function generateImageData() public pure returns (string memory) {
string memory svgContent = "data:image/svg+xml;base64,ENCODED-SVG-DATA-HERE";
return svgContent;
}
The thing is, I want my NFT to be generative rather than static. I have a p5.js sketch that creates unique variations every time it runs. My goal is to store the actual JavaScript code on the blockchain and pass a random seed value to it so each token generates a different visual output. Has anyone figured out how to embed p5.js scripts in smart contracts while maintaining the generative aspect? I’m wondering if there’s a standard way to handle the seed parameter and execute the script on-chain.
Honestly, metadata standards were my biggest pain point. OpenSea and other marketplaces want specific JSON formats, so you’ve got to wrap your generative HTML with proper metadata - name, description, attributes, all that stuff. Also, definitely use IPFS for bigger sketches. Store a hash on-chain that points to your p5 code. Way cheaper than cramming everything into the contract and you still get decent decentralization.
Oh this is really interesting! I’ve been tinkering with something similar but haven’t cracked it yet. When you store the p5.js code in the contract, do you hit gas limit issues? I’m curious how much code you can actually fit before hitting those constraints.
Also, how do you handle the randomness? How do you make sure the “randomness” from blockhash doesn’t change over time? If someone views the same NFT months later, will it generate the exact same image? I’ve heard people use token ID combined with specific block data for a deterministic seed, but I’m not sure if that’s the best approach.
One thing that’s bugging me - are you including the entire p5.js library in your contract or just referencing it externally? If it’s external, what happens when the CDN goes down or the library version changes?
Have you tested this with complex sketches that use noise functions or particle systems? I’m wondering if there are performance issues when the browser tries to render really computation-heavy generative art.
You can’t run JavaScript directly on-chain, but I’ve found a solid workaround that actually works. Store your p5.js code as a string in the contract’s metadata or tokenURI function, then build an HTML doc that includes the p5.js library and your sketch. The trick is feeding the token ID or a seed into your sketch’s random() function. When someone loads the NFT, their browser runs the JavaScript and creates the unique art. I encode the whole HTML structure with the p5.js sketch into base64 and return it as a data URI. The smart contract generates seeds using blockhash or token data, so each token creates consistent but unique results every time someone views it.
I tried this exact thing last year with mixed results. Blockchain storage costs are insane - storing even a medium-sized p5.js sketch can run you hundreds in gas fees. What worked for me was compressing the JavaScript aggressively and only storing the core algorithm logic, not the entire p5.js framework. Just reference p5.js externally through CDN in your HTML wrapper. For deterministic randomness, I use a keccak256 hash of the token ID plus contract address as the seed. This keeps the output identical every time someone views it while staying unique per token. In your p5 setup function, call randomSeed() with this hash converted to an integer. Just make sure every random() call in your sketch follows the same sequence. One gotcha I discovered - browsers handle floating point math slightly differently, so complex operations might produce different results across devices. Keep your generative logic simple to stay consistent.