npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cristianglezm/flower-evolver-wasm

v4.0.2

Published

wasm module to make 2D / 3D flowers that evolve using EvoAI library

Readme

FlowerEvolver-WASM

ci cd pkg pkg-python NPM Version PyPI Version GitHub package.json version (branch)

Generates, mutates, and reproduces 2D/3D flowers from CPPN genomes evolved via EvoAI - adapted from EcoSystem. The core is a single C++17 library (fe::) shipped as a WebAssembly module for the browser, a native static/shared library for C++ apps, native Python bindings, and an Android build - one implementation, four ways to consume it.

The CPPN-encoded, evolvable flower approach the project implements follows the one introduced by Risi et al. in Petalz - see Acknowledgments.

Check the live demo here.

Contents

News

Additions

  • Native CMake build (Linux/macOS/Windows) alongside the Emscripten/WASM target, so fe:: can be linked directly into a C++ app -- see "Building" below.
  • Native Python bindings (nanobind) plus a flower-evolver CLI - see python/README.md.
  • Android build via CMake.
  • index.ts: the JS-facing FEService wrapper is now TypeScript, shipping its own generated index.d.ts.
  • Full API docs site (Doxygen+Sphinx for C++, TypeDoc for JS/WASM, Sphinx+autodoc for Python) - linked from the demo page.
  • Test coverage: C++ (Catch2), JS/Node (vitest), e2e (Playwright), Python (pytest), and libFuzzer fuzzing harnesses.
  • CI/CD: a native x wasm x Android build matrix, plus tag-triggered release automation for npm, GitHub Packages, and PyPI.

Breaking changes

  • WASM no longer touches document/OffscreenCanvas at all -- {genome, image} (image as a base64 PNG data URL) comes back directly from the module. If you were reading pixels off an injected <canvas id="canvas"> or self.canvas, switch to FEService (or read .image off its JS/WASM module's own JSON result) instead.
  • The FE_EXPORT TRUE/FALSE build split is gone -- there's one Emscripten build now (ES6 module + SINGLE_FILE). dist/public/FlowerEvolver.mjs is now dist/public/FlowerEvolver.js, and dist/index.js is compiled from index.ts rather than hand-written.
  • The native C++ API (include/fe/FlowerEvolver.hpp) now takes/returns typed fe::DNA/fe::Flower/fe::Image instead of stringified JSON -- only affects native (non-WASM) consumers; the JS/WASM API's own shape is unchanged.
  • 3D flower generation pipeline: 2D petal layers go through contour extraction, contour simplification, and mesh generation, and come out as a glTF 2.0 scene (mesh, material, texture, node) with petal droop, a generated pistil and stamens, and lighting extras.
  • Procedural normal maps (from a noise function) and emissive textures for glowing flowers, plus adjustParams/adjustStem so stem/pistil proportions and per-layer petal droop scale adaptively with the flower's own size instead of using fixed constants.
  • Layered radius scaling (applyLayeredRadiusScaling in drawLayer()) reuses the same petal image at progressively lower resolutions in 2D mode and pre-scales textures in 3D mode -- measured to cut VRAM use from 22MB to 2.2MB and file size from 1MB to 0.7MB at radius 256 / 20 layers.
  • In-memory PNG encoding and base64 encoding, so textures can be embedded directly in the glTF file instead of round-tripping through the DOM.
  • Image split into its own header/source file; numLayers is now clamped based on radius to avoid excessive memory allocation.
  • Flower Stats generation (health, stamina, temperature range, maturation, toxicity, and per-stat effects) derived from a flower's genome.
  • A companion Blender plugin, and 3D examples added to the demo page.
  • Added FEService, FEParams, and Flower to index.js -- a documented JS wrapper around the raw embind calls (makeFlower/reproduce/mutate/etc.), instead of consumers calling the wasm module's exported functions directly and reading the canvas by hand.
  • Added getDataUrl, a small helper to read the (real or offscreen) canvas back as a data URL, used internally by FEService and safe to call from a Web Worker.
  • v2.0.1: explicitly exported HEAPU8 from the Emscripten build, a same-day bugfix so FEService could reliably read pixel data back out of the wasm heap.
  • Added makePetals/makePetalLayer/makeStem and their draw* counterparts, so a consumer can generate or redraw just the petals, a single petal layer, or just the stem, instead of always paying for a full flower render.
  • Initial release: the flower generator (genome, petals, drawing) compiled to WebAssembly via Emscripten/embind, driven against a <canvas id="canvas"> element in the page.
  • v1.0.1 added npm packaging (package.json, .devops/dist.sh, pkg.yml) with an FE_EXPORT flag to build either a plain global script or an ES6 module, and auto-publish to npm and GitHub Packages on release.

Building

Follow these steps to download, build, and run the project.

Automated Build Process

Run npm run prep once to set up the dependencies (Emscripten SDK, JsonBox, EvoAI, all under build/wasm/), then npm run build to configure and build the project. npm run build is safe to re-run as often as you like -- it doesn't redo the dependency setup, so it's fast for iterating. It also compiles index.ts (via npm run build:ts, run automatically as part of npm run build) -- run npm run build:ts on its own if you're only iterating on the JS-facing FEService wrapper and don't need a full wasm rebuild.

That's genuinely all most people need for the browser/npm package -- the table below covers the other targets (native, Android, Python, docs, fuzzing), and the rest of this section is only for readers who want to see what those two commands do underneath.

Other build targets

Every target follows the same two-step shape: a one-time prep (clones and builds JsonBox/EvoAI for that target) and a repeatable build.

| Target | Setup (once) | Build | Notes | |---|---|---|---| | WASM (browser/npm) | npm run prep | npm run build | Default target; produces dist/ | | Native C++ library | npm run prep:native | npm run build:native | Add -DFlowerEvolver_BUILD_TESTS=ON (or use npm run build:native:test) to also build the Catch2 suite | | Android (all 4 ABIs) | npm run prep:android | npm run build:android -- <abi> | One ABI per build invocation; needs $ANDROID_NDK -- see Android | | Python bindings | npm run prep:native | npm run build:python | nanobind; installs the flowerevolver package + flower-evolver CLI -- see Python Bindings | | Docs (C++ + JS + Python) | npm run prep:native && npm run build:python + pip install -r docs/requirements.txt | npm run build:docs | Doxygen+Sphinx (C++), TypeDoc (JS/WASM), Sphinx+autodoc (Python) -- Python docs need build:python first, see Documentation | | Fuzzing | npm run prep:native | npm run build:native:fuzz | Needs Clang -- see tests/fuzz/README.md |

npm run prep and npm run build are themselves just bash .devops/prep.sh and bash .devops/build.sh -- there's no separate manual recipe to keep in sync with those scripts, so if you want to see (or run) each underlying step individually, read .devops/prep.sh and .devops/build.sh directly. Both document every mode (wasm/native/android/docs/python/fuzz) in a comment block at the top, and both are safe to re-run as often as you like. For a manual, non-npm cmake/cmake --build invocation, see cmake/modules/{FindEvoAI,FindJsonBox}.cmake for the _ROOT variables it expects.

Using npm run serve

After running npm run prep (once) and npm run build, run npm run serve to view the demo website.

Browser usage

The build is a single self-contained ES module (the wasm binary is inlined as base64, no separate .wasm file to fetch) -- use it directly with an import map, no bundler required. For the full function reference (native C++ API), see include/fe/FlowerEvolver.hpp.

Example Code

Below is a sample JavaScript snippet to load and use the module in your project:

<script type="importmap">
{
  "imports": {
    "@cristianglezm/flower-evolver-wasm": "./node_modules/@cristianglezm/flower-evolver-wasm/index.js"
  }
}
</script>
<script type="module">
    import { FEService } from '@cristianglezm/flower-evolver-wasm';

    const fes = new FEService();
    await fes.init();

    // Example: create a flower
    const flower = await fes.makeFlower();
    // flower.genome - stringified genome, feed back into reproduce/mutate/draw*
    // flower.image  - base64-encoded PNG data URL, ready for an <img src="...">
</script>

Notes

  • Reference FlowerEvolver.hpp: This header file contains detailed documentation on all functions and their parameters (native C++ API). index.ts's FEService is the recommended JS-facing wrapper -- see API Reference below.
  • Written in TypeScript (index.ts), the published package ships its own index.d.ts (generated straight from that source) alongside index.js, so TypeScript consumers get full type checking and autocomplete with no extra @types package to install.

Framework Usage

install it

npm install @cristianglezm/flower-evolver-wasm
import { FEService } from '@cristianglezm/flower-evolver-wasm';

let fes = new FEService();
await fes.init();

You can integrate the service into a state manager like Pinia for better state management. Here's an example setup:

import { defineStore } from 'pinia';
import { FEParams, FEService } from '@cristianglezm/flower-evolver-wasm';

export const useFlowersStore = defineStore('FlowersStore', {
    state: () => ({
        fe: null,
        flowers: [],
    }),
    getters: {},
    actions: {
        async loadFE() {
            this.fe = new FEService();
            await this.fe.init();
        },
        setParams(params) {
            // only called when you actually want to change something --
            // makeFlower() below reuses whatever was set last (or the
            // FEService default, if this was never called).
            this.fe.setParams(params);
        },
        async makeFlower() {
            const flower = await this.fe.makeFlower();
            this.flowers.push(flower);
            return flower;
        },
    },
});

// Example Usage:
const store = useFlowersStore();
await store.loadFE();
store.setParams(new FEParams(128, 2, 5.0, -1.0));
await store.makeFlower();
//...

Worker Usage

App Code

In your main application file, set up the worker and handle communication:

import { FEParams } from '@cristianglezm/flower-evolver-wasm';

// Create a new Worker instance
let worker = new Worker('worker.js');

// Handle messages from the worker
worker.onmessage = (e) => {
    // Perform actions with the received data
};

// Send data to the worker
const fn = () => {
    worker.postMessage({ params: new FEParams(radius, numLayers, P, bias) });
};

Worker code

In worker.js, initialize the FlowerEvolver service and process incoming messages:

import { FEParams, FEService } from '@cristianglezm/flower-evolver-wasm';

let FE;

self.onmessage = async (e) => {
    /// validate params to avoid OOM errors.
    let params = e.data.params;
    // Initialize FlowerEvolver service if not already initialized
    if(!FE){
        FE = new FEService();
        await FE.init();
    }
    FE.setParams(new FEParams(params.radius, params.numLayers, 
                                params.P, params.bias));
    // Use the methods from the FEService instance
    let flower;
    try{
        // Create a flower (Flower class contains genome and image)
        flower = await FE.makeFlower();
    }catch(e){
        // Handle errors
        console.error(e);
    }

    // flower.genome and flower.image (base64 PNG data URL) are both ready
    // to use directly -- no canvas readback needed.
    self.postMessage({
        genome: flower.genome,
        image: flower.image
    });
};

Notes

  • Use FE.makeFlower and other methods from FEService for creating flowers or reproduce them or mutate them.
  • Always validate the params passed to the worker to avoid unexpected errors.

Android

The native library also cross-compiles for Android via CMake's own CMAKE_SYSTEM_NAME=Android support (no Android Studio/Gradle project needed).

# needs $ANDROID_NDK pointing at a real NDK install
npm run prep:android                 # all 4 Play-Store-relevant ABIs by default
npm run prep:android -- arm64-v8a    # or just the ABI(s) you need

npm run build:android -- arm64-v8a -DFlowerEvolver_BUILD_STATIC=FALSE

This produces build/android/fe-<abi>/, packaged with cpack -G ZIP in CI (see the android/android-merge jobs in .github/workflows/ci.yml), and a merged FlowerEvolver-Android.zip with all four ABIs side by side for release tags. src/Android.mk is included for classic ndk-build consumers who'd rather drop the prebuilt .so/.a straight into an existing NDK project than adopt CMake.

Native C++ Library

Link libFlowerEvolver directly into a C++ app once it's built and installed (npm run prep:native && npm run build:native, then cmake --install):

find_package(FlowerEvolver 4 REQUIRED)
target_link_libraries(myApp PRIVATE FlowerEvolver::FlowerEvolver)
#include <fe/FlowerEvolver.hpp>

int main(){
    fe::Flower flower = makeFlower(64, 3, 6.0f, 1.0f);
    auto png = fe::encodeImageToPngInMemory(flower.petals.image);
    // flower.dna.toJson() for the genome; reproduce()/mutate() take fe::DNA in, fe::Flower out.
}

See include/fe/FlowerEvolver.hpp for the full documented API (same generation logic the WASM, Android, and Python bindings all call through fe::detail::impl_*), and cmake/modules/{FindEvoAI,FindJsonBox}.cmake for the dependency _ROOT variables a manual configure needs.

Python Bindings

Native Python bindings (via nanobind) around the same C++ core -- same Flower.to_json()/from_json() wire format as the JS/WASM API above, so genomes round-trip between both. Also installs a flower-evolver CLI matching the native desktop app's own single-flower flags.

npm run prep:native   # once
npm run build:python
from flowerevolver import make_flower

flower = make_flower(radius=64, num_layers=3, P=6.0, bias=1.0)
flower.petals.image.to_png_bytes()  # -> bytes
flower.to_json()                    # -> str, the genome

npm run test:python runs its pytest suite. See python/README.md for the manual pip install invocation, the CLI, and more usage examples; the C++ glue itself lives in src/bindings/python/.

Documentation

Three cross-linked API reference sites, built from the same source the demo page itself links to:

  • C++ docs - Doxygen + Breathe + Sphinx, from include/fe/FlowerEvolver.hpp and the rest of the public fe:: headers.
  • JS/WASM docs - TypeDoc, from index.ts and types/wasm-module.d.ts.
  • Python docs - Sphinx + autodoc, from the installed flowerevolver package's own docstrings.

Build them locally with npm run build:docs (needs npm run prep:native first, plus Doxygen/Graphviz and pip install -r docs/requirements.txt); output lands in dist/docs/{cpp,js,python}/. The Python site additionally needs the flowerevolver package itself importable -- run npm run build:python before npm run build:docs, or the C++ and JS sites build normally while the Python site is silently skipped (with a warning) instead of failing the whole command. Each site can also be built on its own -- npm run build:docs:cpp, npm run build:docs:js, npm run build:docs:python (the last one assumes build:python has already run).

Testing

| Suite | Setup | Run | |---|---|---| | C++ (Catch2) | npm run prep:native && npm run build:native:test | npm run test:cpp | | JS/Node (vitest, against a real build) | npm run prep && npm run build | npm test | | e2e (Playwright, drives the built demo) | npm run prep && npm run build | npm run test:e2e | | Python (pytest) | npm run prep:native && npm run build:python | npm run test:python | | Fuzzing (libFuzzer, Clang) | npm run prep:native && npm run build:native:fuzz | see tests/fuzz/README.md |

API Reference

Acknowledgments

The CPPN-encoded, breedable-flower approach implemented here follows the one introduced by:

Risi, S., Lehman, J., D'Ambrosio, D., Hall, R., & Stanley, K. (2012). Combining Search-Based Procedural Content Generation and Social Gaming in the Petalz Video Game. Proceedings of the AAAI Conference on Artificial Intelligence and Interactive Digital Entertainment, 8(1). https://doi.org/10.1609/aiide.v8i1.12502

Genome evolution (NEAT/CPPN) itself is provided by EvoAI.

License

SFML-derived parts (fe::Color/fe::Rect/fe::Vector2, adapted from SFML and merged into the fe:: namespace) are under SFML's own license.

stb_image_write is under its own license

the rest of the code is licensed under apache 2.0

   Copyright 2023-2026 Cristian Gonzalez <[email protected]>

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.