{"id":20264303,"url":"https://github.com/thi-ng/genart-api","last_synced_at":"2025-04-11T02:10:59.273Z","repository":{"id":255613433,"uuid":"848514110","full_name":"thi-ng/genart-api","owner":"thi-ng","description":"Generalized API for browser-based generative art projects, plug \u0026 play support for platform specifics, parameter declarations, GUI creation, IPC","archived":false,"fork":false,"pushed_at":"2025-04-04T22:34:45.000Z","size":2596,"stargazers_count":19,"open_issues_count":1,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-04T23:25:35.128Z","etag":null,"topics":["declarative","generative-art","interoperability","parameters","ui"],"latest_commit_sha":null,"homepage":"https://demo.thi.ng/genart-api/param-editors/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thi-ng.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"postspectacular","patreon":"thing_umbrella","liberapay":"thi.ng"}},"created_at":"2024-08-27T22:47:27.000Z","updated_at":"2025-04-04T22:34:49.000Z","dependencies_parsed_at":"2024-11-07T13:27:06.599Z","dependency_job_id":"6e0ee783-3d09-466b-babf-a68a0dab3957","html_url":"https://github.com/thi-ng/genart-api","commit_stats":null,"previous_names":["thi-ng/genart-api"],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thi-ng%2Fgenart-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thi-ng%2Fgenart-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thi-ng%2Fgenart-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thi-ng%2Fgenart-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thi-ng","download_url":"https://codeload.github.com/thi-ng/genart-api/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248328160,"owners_count":21085261,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["declarative","generative-art","interoperability","parameters","ui"],"created_at":"2024-11-14T11:39:19.376Z","updated_at":"2025-04-11T02:10:59.259Z","avatar_url":"https://github.com/thi-ng.png","language":"TypeScript","funding_links":["https://github.com/sponsors/postspectacular","https://patreon.com/thing_umbrella","https://liberapay.com/thi.ng"],"categories":[],"sub_categories":[],"readme":"# Platform independent API for generative art\n\n[![npm version](https://img.shields.io/npm/v/@genart-api/core.svg)](https://www.npmjs.com/package/@genart-api/core)\n![npm downloads](https://img.shields.io/npm/dm/@genart-api/core.svg)\n[![Mastodon Follow](https://img.shields.io/mastodon/follow/109331703950160316?domain=https%3A%2F%2Fmastodon.thi.ng\u0026style=social)](https://mastodon.thi.ng/@toxi)\n\n-   [Status](#status)\n-   [About](#about)\n    -   [Goals](#goals)\n    -   [Non-goals](#non-goals)\n-   [Core API](#core-api)\n    -   [Definitions / terminology](#definitions--terminology)\n    -   [Architecture overview](#architecture-overview)\n        -   [Lifecycle](#lifecycle)\n        -   [State machine](#state-machine)\n        -   [Message types](#message-types)\n        -   [Message handling](#message-handling)\n    -   [API documentation](#api-documentation)\n-   [Parameters](#parameters)\n    -   [Static parameter types](#static-parameter-types)\n        -   [BigInt](#bigint-parameter)\n        -   [Binary](#binary-parameter)\n        -   [Choice](#choice-parameter)\n        -   [Color](#color-parameter)\n        -   [Date](#date-parameter)\n        -   [Datetime](#datetime-parameter)\n        -   [Image](#image-parameter)\n        -   [List](#list-parameter)\n        -   [Range](#range-parameter)\n        -   [Text](#text-parameter)\n        -   [Time](#time-of-day-parameter)\n        -   [Toggle](#toggle-parameter)\n        -   [Vector](#vector-parameter)\n        -   [Weighted choice](#weighted-choice-parameter)\n        -   [XY](#xy-parameter)\n    -   [Dynamic parameter types](#dynamic-parameter-types)\n        -   [Ramp](#ramp-parameter)\n    -   [Custom parameter types](#custom-parameter-types)\n        -   [Example: Oscillator parameter type](#example-oscillator-parameter-type)\n    -   [Composite parameter types](#composite-parameter-types)\n-   [Traits](#traits)\n-   [Platform adapters](#platform-adapters)\n    -   [Parameter sourcing](#parameter-sourcing)\n    -   [Parameter updates](#parameter-updates)\n    -   [Determinism \u0026 PRNG provision](#determinism--prng-provision)\n    -   [Screen configuration](#screen-configuration)\n        -   [Handling dynamic resizing](#handling-dynamic-resizing)\n    -   [Thumbnail/preview generation](#thumbnailpreview-generation)\n-   [Time providers](#time-providers)\n    -   [Existing time provider implementations](#existing-time-provider-implementations)\n        -   [RAF](#raf)\n        -   [Offline](#offline)\n        -   [FPS overlay](#fps-overlay)\n-   [WebAssembly bindings](#webassembly-bindings)\n-   [Getting started](#getting-started)\n    -   [Existing adapter implementations](#existing-adapter-implementations)\n    -   [Examples projects](#example-projects)\n    -   [Project template](#project-template)\n    -   [Installion as package](#installion-as-package)\n    -   [Manual installation](#manual-installation)\n    -   [Use in your own projects: Artist's Hello world](#use-in-your-own-projects-an-artists-hello-world)\n    -   [Creating a basic PlatformAdapter](#platforms)\n-   [Build information](#build-information)\n    -   [Building core API files](#building-core-api-files)\n    -   [Building examples](#build-information)\n-   [Parameter editors](#parameter-editors)\n-   [License](#license)\n\n## Status\n\n**ALPHA** — Work in progress... **Welcoming feedback!** 🙏\n\n[Projects updates on Mastodon](https://mastodon.thi.ng/@toxi/tagged/GenArtAPI)\n\nPlease also see RFCs and open questions in the [issue\ntracker](https://github.com/thi-ng/genart-api/issues). Thanks!\n\n\u003e [!NOTE]\n\u003e In the future this repo might be moved to a standalone GitHub org to emphasize\n\u003e that this project is **not** directly related to other\n\u003e [thi.ng](https://thi.ng) projects and instead is intended for **any browser\n\u003e based generative art** projects and related tooling.\n\u003e\n\u003e tl;dr Jump to the [Getting started section](#getting-started).\n\n## About\n\nOver the past years, generative/computational art has experienced a surge in\npopularity because of the availability of online art platforms for publishing\nthese works. The number of these platforms keeps on mushrooming, each one\ndefining their own ad hoc solutions to deal with common aspects (e.g. [handling\nof parameters](#parameters) to customize pieces/variations, generating previews,\netc.). Often, this means artists have to either already decide on which platform\nto publish a new piece before they work on it and/or spend a considerable amount\nof time reworking key aspects (like parameter, [screen\nresolution](#screen-configuration) or [time handling](#time-providers)) when\nrepurposing a piece for a different use (e.g. creating hires print versions,\nhigh-quality video assets, or displaying the piece in a gallery with different\nconfigurations or requirements). Since online platforms/startups usually only\noptimize for their own uses and neglecting the needs of artists regarding asset\npreparation, adaptation and re-use, we must take it upon ourselves to address\nthese workflow issues more efficiently.\n\nTo improve this situation, this project proposes an API layer and a message\nprotocol addressing recurring issues artists encounter when publishing and\nrepurposing browser-based generative artworks — be it for diverse online\nplatforms, environments (incl. offline, galleries, installations), but also\naforementioned aspects of media production (for example helping to deal with\nrealtime/non-realtime rendering when recording image sequences for video\nproduction, and do so in an unintrusive \u0026 externally controlled manner).\n\n![Overview](https://raw.githubusercontent.com/thi-ng/genart-api/main/diagrams/overview.svg)\n\nSchematic overview of the proposed architecture\n\nThe primary purpose of this API is to decouple key aspects commonly used for\nmost generative/computational artworks, to deduplicate feature implementations\nand reduce the time \u0026 effort required for adapting browser-based artworks for\ndifferent uses/environments. These benefits are not _only_ in the interest of\nartists, but also simplify how online art platforms can use this API layer to\nreduce effort on their end, simplify providing customization features for such\ngenerative artworks (and even re-use tooling).\n\nAnother positive side effect of adapting the system proposed here: The emergence\nof secondary re-usable tooling to manage parameters and variations, for example:\ntooling to generate GUI controls for editing params, creating/storing/retrieving\nparameter presets/collections (aka variations), asset downloaders, transcoding\ntools. Even at this stage, some of these are existing already and actively being\nworked on...\n\nIn this document \u0026 repository we describe the approach, the proposed\narchitecture and provide a TypeScript-based reference implementation, including\nfully documented interfaces \u0026 types, and some example test cases to demonstrate\n(and validate!) the approach and its benefits.\n\n### Goals\n\n-   Decouple artworks from presentation platform:\n    -   artworks can be authored without direct knowledge of which platform(s)\n        they're being displayed or published at\n-   Straightforward repurposing/integration of artworks into diverse environments:\n    -   Online art platforms\n    -   Personal websites/portfolios\n    -   Offline, museums, galleries...\n    -   Non-realtime use cases (high-res video/frame recording)\n-   Any platform-specifics can be injected via small plugin adapters which can\n    be added to an artwork's HTML wrapper without any code changes required\n    -   Examples of platform-specifics:\n        -   Handling parameter and/or feature declarations exposed by the artwork\n        -   Handling parameter value overrides, param value decoding/encoding\n        -   Handling thumbnail/preview generation\n        -   Defining/forcing display size \u0026 densities\n-   Provide an extensible, platform-independent parameter system with a set of\n    commonly used parameter types\n    -   Parameter type-specific validation, coercion, randomization\n    -   Composite parameter types\n    -   Randomized parameter lookups (per individual read)\n    -   Timebased parameters (e.g. [ramps](#ramp-parameter))\n    -   Built-in support for custom parameter types and their implementation\n-   Define a messaging/event system for notification of state \u0026 param changes\n-   For time-based works\n    -   Transport control (aka start/stop/resume)\n    -   Provide choice of time provider plugins:\n        -   Real-time (i.e. `requestAnimationFrame()`-based animation) and/or\n        -   Offline (non-realtime, with configurable fixed time base)\n-   Enable re-usable secondary tooling:\n    -   Auto-generated GUIs for param controls/overrides\n    -   Variation/snapshot/preset creation/selection\n    -   Asset export (w/ param metadata)\n\n### Non-goals\n\nThis API aims to **remain as minimal as possible** and will not directly support\nevery feature of every platform, which would cause feature creep, bloat and\nunsustainable maintenance effort.\n\nArtworks requiring or relying on advanced integrations with a specific platform\nare naturally highly dependent on those platform features, and so would not\nbenefit from a more platform-independent approach in any way. Therefore, we\nconsider these use cases as out-of-scope.\n\nHowever, the proposed system is designed to enable platform-specific extensions\nin several ways, which can highly benefit all parties involved when adopted and\ncan be supported unintrusively. For example, a platform/device can provide\nsensor input and expose it through a custom parameter type, allowing a mock\nimplementation to be provided when running elsewhere.\n\n## Core API\n\n### Definitions / terminology\n\n-   **Artwork**: A browser-based art piece running in a standard HTML\n    environment\n-   **Platform**: The host website, application, or system in which the\n    artwork's HMTL wrapper will be deployed and which might provide parameter\n    customizations, PRNG seeds, control playback behavior, handle preview\n    generation etc.\n-   **Platform adpater**: A software plugin for the proposed GenArt API which\n    handles and/or translates all platform specifics\n-   **Time provider**: A software plugin for the proposed GenArt API which is\n    used to provide animation time information and schedule animation frames,\n    all controlled by the main GenArt API layer.\n\n### Architecture overview\n\n#### Lifecycle\n\n![Overview](https://raw.githubusercontent.com/thi-ng/genart-api/main/diagrams/lifecycle.svg?20241008)\n\n[Diagram source code](https://github.com/thi-ng/genart-api/blob/main/diagrams/lifecycle.puml)\n\n#### State machine\n\nThe API implements a finite state machine with the following possible states:\n\n-   `init`: Initial state until the [platform adapter](#platform-adapters), [time\n    provider](#time-providers) and the artwork's update function have been\n    registered or an error occurred during any init steps\n-   `ready`: All init steps have been completed and playback of the artwork can\n    commence\n-   `play`: API is currently running the animation loop, ruuning the artwork\n-   `stop`: Animation loop has been paused/stopped\n-   `error`: API is in an unrecoverable error state\n\n#### Message types\n\n\u003e [!IMPORTANT]\n\u003e Message names have been updated in recent versions and are partially\n\u003e incompatible with older versions. Please see [commit\n\u003e details](https://github.com/thi-ng/genart-api/commit/35b627d7380bad75d280cc1e051ec7ed23aa8995)\n\u003e for what has changed and why, and what (might) need to be changed in your\n\u003e projects.\n\u003e\n\u003e **At this stage of the project, the [parameter editors](#parameter-editors)\n\u003e are only compatible with artworks using the current version of the GenArtAPI\n\u003e reference implementation.**\n\nThe API also defines and uses a message protocol to communicate certain\nlifecycle events, state changes and requests to both internal \u0026 external\nparticipants. Please see links for descriptions of each message type.\n\n-   `genart:capture`: [CaptureMessage](https://docs.thi.ng/genart-api/core/interfaces/CaptureMessage.html)\n-   `genart:configure`: [ConfigureMessage](https://docs.thi.ng/genart-api/core/interfaces/ConfigureMessage.html)\n-   `genart:frame`: [AnimFrameMessage](https://docs.thi.ng/genart-api/core/interfaces/AnimFrameMessage.html)\n-   `genart:get-info`: [GetInfoMessage](https://docs.thi.ng/genart-api/core/interfaces/GetInfoMessage.html)\n-   `genart:info`: [InfoMessage](https://docs.thi.ng/genart-api/core/interfaces/InfoMessage.html)\n-   `genart:params`: [ParamsMessage](https://docs.thi.ng/genart-api/core/interfaces/ParamsMessage.html)\n-   `genart:param-change`: [ParamChangeMessage](https://docs.thi.ng/genart-api/core/interfaces/ParamChangeMessage.html)\n-   `genart:param-error`: [ParamErrorMessage](https://docs.thi.ng/genart-api/core/interfaces/ParamErrorMessage.html)\n-   `genart:randomize-param`: [RandomizeParamMessage](https://docs.thi.ng/genart-api/core/interfaces/RandomizeParamMessage.html)\n-   `genart:resize`: [ResizeMessage](https://docs.thi.ng/genart-api/core/interfaces/ResizeMessage.html)\n-   `genart:resume`: [ResumeMessage](https://docs.thi.ng/genart-api/core/interfaces/ResumeMessage.html)\n-   `genart:set-param-value`: [SetParamValueMessage](https://docs.thi.ng/genart-api/core/interfaces/SetParamValueMessage.html)\n-   `genart:start`: [StartMessage](https://docs.thi.ng/genart-api/core/interfaces/StartMessage.html)\n-   `genart:state-change`: [StateChangeMessage](https://docs.thi.ng/genart-api/core/interfaces/StateChangeMessage.html)\n-   `genart:stop`: [StopMessage](https://docs.thi.ng/genart-api/core/interfaces/StopMessage.html)\n-   `genart:traits`: [TraitsMessage](https://docs.thi.ng/genart-api/core/interfaces/TraitsMessage.html)\n\n#### Message handling\n\nMessages received via the browser's\n[`postMessage()`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/postMessage)\nmechanism will only be processed by `GenArtAPI` if the [`apiDI`]() included in\nthe message matches, or if it's the wildcard ID `\"*\"`. The latter can be used to\nbroadcast messages to **all** currently active/receiving `GenArtAPI` instances.\n\nUse cases for the wildcard ID (`\"*\"`) are related to handling multiple artworks\nrunning in multiple iframes, for example:\n\n-   Detection/registration of all currently running `GenArtAPI` instances by\n    broadcasting a\n    [GetInfoMessage](https://docs.thi.ng/genart-api/core/interfaces/GetInfoMessage.html),\n    to which each instance then responds with a\n    [InfoMessage](https://docs.thi.ng/genart-api/core/interfaces/InfoMessage.html)\n    (which then also includes each instance's actual configured `id`)\n-   Starting/stopping all currently running `GenArtAPI` instances via single\n    message, e.g. `postMessage({ type: \"genart:start\", apiID: \"*\"}, \"*\")`.\n\nTODO — for now please also see the following links for more messaging related information:\n\n-   [.emit()](https://docs.thi.ng/genart-api/core/interfaces/GenArtAPI.html#emit)\n-   [.on()](https://docs.thi.ng/genart-api/core/interfaces/GenArtAPI.html#on)\n-   [.id](https://docs.thi.ng/genart-api/core/interfaces/GenArtAPI.html#id)\n-   [.setParams()](https://docs.thi.ng/genart-api/core/interfaces/GenArtAPI.html#setparams)\n-   [.setTraits()](https://docs.thi.ng/genart-api/core/interfaces/GenArtAPI.html#settraits)\n-   [.setUpdate()](https://docs.thi.ng/genart-api/core/interfaces/GenArtAPI.html#setupdate)\n-   [.start()](https://docs.thi.ng/genart-api/core/interfaces/GenArtAPI.html#start)\n-   [.stop()](https://docs.thi.ng/genart-api/core/interfaces/GenArtAPI.html#stop)\n\n### API documentation\n\nIn addition to the detailed API docs, this readme, the source code and the\n[example projects](#example-projects) are the best reference.\n\n-   [@genart-api/core](https://docs.thi.ng/genart-api/core/)\n-   [@genart-api/adapter-editart](https://docs.thi.ng/genart-api/adapter-editart/)\n-   [@genart-api/adapter-fxhash](https://docs.thi.ng/genart-api/adapter-fxhash/)\n-   [@genart-api/adapter-layer](https://docs.thi.ng/genart-api/adapter-layer/)\n-   [@genart-api/adapter-urlparams](https://docs.thi.ng/genart-api/adapter-urlparams/)\n-   [@genart-api/time-fps-overlay](https://docs.thi.ng/genart-api/time-fps-overlay/)\n\n## Parameters\n\nAlmost all generative artworks use parameters and randomization to produce\nnumerous variations. Exposing some of these parameters to the outside world can\nallow people/agents to have more participation and direct control over the\ngenerative outcomes.\n\nThe API supports an extensible set of parameters types with a selection of\ncommonly used types supplied as built-ins (described below).\n\nEach parameter declared by the artwork is a simple vanilla JS object and any\nparam value changes are being handled by the API and the param type’s\n[registered\nimplementation](https://docs.thi.ng/genart-api/core/interfaces/ParamImpl.html)\n(a set of functions dealing with validation, coercion, updating and reading\nparam values). For convenience \u0026 type safety, the API provides factory functions\nfor all built-in parameter types.\n\nThe following parameter types are available, but other custom ones can be\nregistered, making the entire system extensible. Each declared param spec is a\nsimple JS object, and the API provides factory functions for all built-in types,\nhelping to fill in any default options.\n\n**IMPORTANT**: All param declarations must include a `desc` (brief description).\nThere's also the option to define `default` values for most parameter types. If\nno default value is provided, a randomized value will be chosen within the\nconstraints of the param.\n\n### Static parameter types\n\nGenerally speaking, parameters can be grouped into static \u0026 dynamic parameters\nwith the former providing the same values each time they're read/evaluated and\nthe latter being used for time-based values obtained from otherwise dynamic\nsources (e.g. sensors).\n\nThis section describes the set of _static_ param types:\n\n#### Bigint parameter\n\n-   [API docs](https://docs.thi.ng/genart-api/core/interfaces/BigIntParam.html)\n-   [Factory function](https://docs.thi.ng/genart-api/core/interfaces/ParamFactories.html#bigint)\n\nTODO example\n\n#### Binary parameter\n\n-   [API docs](https://docs.thi.ng/genart-api/core/interfaces/BinaryParam.html)\n-   [Factory function](https://docs.thi.ng/genart-api/core/interfaces/ParamFactories.html#binary)\n\nTODO example\n\n#### Choice parameter\n\n-   [API docs](https://docs.thi.ng/genart-api/core/interfaces/ChoiceParam.html)\n-   [Factory function](https://docs.thi.ng/genart-api/core/interfaces/ParamFactories.html#choice)\n\nThis enum-like param can only take on values from a fixed list of options. For\nsimplicity values are always strings, but optionally can also define labels\n(only used for display purposes by external tooling).\n\n```ts\n// options\n$genart.params.choice({\n\tname: \"Test param\",\n\tdesc: \"Shape size preset\",\n\toptions: [\"s\", \"m\", \"l\"],\n\tdefault: \"m\",\n});\n\n// ...or using options with labels\n$genart.params.choice({\n\tname: \"Test param\",\n\tdesc: \"Shape size preset\",\n\toptions: [\n\t\t[\"s\", \"Small\"],\n\t\t[\"m\", \"Medium\"],\n\t\t[\"l\", \"Large\"],\n\t],\n\toptions: \"m\",\n});\n```\n\n##### Recommended GUI widget\n\n-   Drop-down menu\n-   Radio buttons\n\n#### Color parameter\n\n-   [API docs](https://docs.thi.ng/genart-api/core/interfaces/ColorParam.html)\n-   [Factory function](https://docs.thi.ng/genart-api/core/interfaces/ParamFactories.html#color)\n\nCSS hex color value (6 digits only). Other/newer color types (e.g. `oklch()`)\nmight be supported later, but currently omitted due to lack of native browser\nwidgets for editing these colors...\n\n```ts\n$genart.params.color({\n\tname: \"Test param\",\n\tdesc: \"Background color\",\n\tdefault: \"#aabbcc\",\n});\n```\n\n##### Recommended GUI widget\n\n-   Color picker\n\n#### Date parameter\n\n-   [API docs](https://docs.thi.ng/genart-api/core/interfaces/DateParam.html)\n-   [Factory function](https://docs.thi.ng/genart-api/core/interfaces/ParamFactories.html#date)\n\nJS `Date` value in precision of full days only (UTC midnight).\n\n```ts\n$genart.params.date({\n\tname: \"Test param\",\n\tdesc: \"Best before date\",\n\t// default can be given as Date or string in this format\n\tdefault: \"2024-09-05\",\n});\n```\n\n##### Recommended GUI widget\n\n-   Date \u0026 time chooser\n-   Numeric range slider (UNIX epoch)\n\n#### Datetime parameter\n\n-   [API docs](https://docs.thi.ng/genart-api/core/interfaces/DateTimeParam.html)\n-   [Factory function](https://docs.thi.ng/genart-api/core/interfaces/ParamFactories.html#datetime)\n\nJS `Date` value.\n\n```ts\n$genart.params.datetime({\n\tname: \"Test param\",\n\tdesc: \"Date and time\",\n\t// default can be given as Date or string in ISO8601 format\n\tdefault: \"2024-09-05T12:34:56+02:00\",\n});\n```\n\n##### Recommended GUI widget\n\n-   Date \u0026 time chooser\n-   Numeric range slider (UNIX epoch)\n\n#### Image parameter\n\n-   [API docs](https://docs.thi.ng/genart-api/core/interfaces/ImageParam.html)\n-   [Factory function](https://docs.thi.ng/genart-api/core/interfaces/ParamFactories.html#image)\n\nImage parameters are used to provide spatially varied param values (e.g.\ngradient maps, masks etc.) by allowing the artwork to read pixel values from\ndifferent points in the image.\n\nAn image param has a pixel array as `value`, alongside `width`, `height` and\n`format`, which can be:\n\n-   `gray` (8 bits)\n-   `rgba` (packed int, 32 bits, channels in MSB order: A,R,G,B)\n\nThe `format` is only used as hint for platform adapters and external tooling\n(e.g. GUI param editors) to optimize their handling of the image data. I.e. an\nimage with mode `gray` can be encoded as byte sequence vs. `rgba` requiring 4\nbytes per pixel. Likewise a param editor allowing image uploads/customizations\nis responsible to resize an image to the expected dimensions and provide its\ndata in the expected format.\n\n[Related example](https://github.com/thi-ng/genart-api/tree/main/examples/param-image)\n\n\u003e [!IMPORTANT]\n\u003e Note to artists: Ensure to keep your image size requirements as low as\n\u003e possible! Storing image data in URL parameters (as done by most platforms) has\n\u003e hard browser-defined limits and this param type is not (yet?) supported by any\n\u003e of the major online art platforms.\n\nThe [reference implementation platform\nadapter](#existing-adapter-implementations) encodes image data using gzip\ncompression and base64 encoding.\n\n#### List parameter\n\nFor simplicity, only lists of numeric or string values are supported by default:\n\n\u003e ![IMPORTANT]\n\u003e These param types are fully functioning, but please see [editor\n\u003e support](#parameter-editors) for implementation progress to allow user\n\u003e customizations.\n\n##### Numeric list\n\n-   [API docs](https://docs.thi.ng/genart-api/core/interfaces/NumListParam.html)\n-   [Factory function](https://docs.thi.ng/genart-api/core/interfaces/ParamFactories.html#numlist)\n\n```ts\n$genart.params.numlist({\n\tname: \"test\",\n\tdesc: \"List of numbers\",\n\tdefault: [1, 2, 3],\n});\n```\n\n##### String list\n\n-   [API docs](https://docs.thi.ng/genart-api/core/interfaces/StringListParam.html)\n-   [Factory function](https://docs.thi.ng/genart-api/core/interfaces/ParamFactories.html#strlist)\n\n```ts\n$genart.params.strlist({\n\tname: \"test\",\n\tdesc: \"List of strings\",\n\tdefault: [\"a\", \"b\", \"c\"],\n});\n```\n\n#### Range parameter\n\n-   [API docs](https://docs.thi.ng/genart-api/core/interfaces/RangeParam.html)\n-   [Factory function](https://docs.thi.ng/genart-api/core/interfaces/ParamFactories.html#range)\n\nNumeric value from a closed range/interval (defined by `min`/`max`, defaulting\nto [0, 100]). If `step` is given, the value will be rounded to multiples of\n`step` (always clamped to min/max).\n\n```ts\n$genart.params.range({\n\tname: \"Test param\",\n\tdesc: \"Pick a multiple of 5 between 0-100\",\n\tmin: 0,\n\tmax: 100,\n\tstep: 5,\n});\n```\n\n##### Recommended GUI widget\n\n-   number dial/slider with value label\n-   number input field\n\n#### Text parameter\n\n-   [API docs](https://docs.thi.ng/genart-api/core/interfaces/TextParam.html)\n-   [Factory function](https://docs.thi.ng/genart-api/core/interfaces/ParamFactories.html#text)\n\nSingle or multi-line text, optionally with `minLength`/`maxLength` and/or\n`match` regexp pattern validation.\n\n```ts\n$genart.params.text({\n\tname: \"Test param\",\n\tdesc: \"Seed phrase\",\n\tmaxLength: 256,\n\tmatch: \"^[a-z ]+$\",\n\tmultiline: true,\n});\n```\n\n##### Recommended GUI widget\n\n-   Single or multiline text input field\n\n#### Time parameter\n\n-   [API docs](https://docs.thi.ng/genart-api/core/interfaces/TimeParam.html)\n-   [Factory function](https://docs.thi.ng/genart-api/core/interfaces/ParamFactories.html#time)\n\nTime-of-day parameter with values as `[hour, minute, second]`-tuples in 24h format.\n\n##### Recommended GUI widget\n\n-   HMS time chooser\n-   HMS dropdown menus\n-   HMS text input fields\n\n#### Toggle parameter\n\n-   [API docs](https://docs.thi.ng/genart-api/core/interfaces/ToggleParam.html)\n-   [Factory function](https://docs.thi.ng/genart-api/core/interfaces/ParamFactories.html#toggle)\n\nOn/off switch (boolean) parameter.\n\n##### Recommended GUI widget\n\n-   checkbox\n\n#### Vector parameter\n\n-   [API docs](https://docs.thi.ng/genart-api/core/interfaces/VectorParam.html)\n-   [Factory function](https://docs.thi.ng/genart-api/core/interfaces/ParamFactories.html#vector)\n\nn-dimensional vector parameter.\n\n-   `size` defines vector size (number of dimensions)\n-   `min` / `max` / `step` can be given as scalars or vectors\n-   `labels` are only mandatory for `size \u003e 4`, otherwise default to XYZW\n\nIf `step` is given, each vector component value will be rounded to multiples of\n`step` (always clamped to min/max).\n\n```ts\n$genart.params.vector({\n\tname: \"Test param\",\n\tdesc: \"3D vector\",\n\tsize: 3, // dimensions, mandatory\n\tmin: 0,\n\tmax: 1,\n\tstep: 0.01,\n\tlabels: [\"X\", \"Y\", \"Z\"],\n\tdefault: [0.1, 0.2, 0.3],\n});\n```\n\n##### Recommended GUI widget\n\n-   per-component slider/dial\n\n#### Weighted choice parameter\n\n-   [API docs](https://docs.thi.ng/genart-api/core/interfaces/WeightedChoiceParam.html)\n-   [Factory function](https://docs.thi.ng/genart-api/core/interfaces/ParamFactories.html#weighted)\n\nSimilar to the [Choice parameter type](#choice), but here each option also\nhas an associated weight/importance. When randomizing this parameter, a new\nvalue is chosen based on the probability distribution defined by the relative\nweights given to each option.\n\nNote: The options can be given in any order and their weights are always only\ntreated relative to each other. The `$genart.params.weighted()` factory function\nis automatically sorting these options by weight and pre-computes their total\nweight.\n\nIf no default value is given, it will be picked randomly (using the weights, as\ndescribed above).\n\n```ts\n// define color options with these probabilities:\n// - black:   8/15th (53%)\n// - cyan:    4/15th (27%)\n// - magenta: 2/15th (13%)\n// - yellow:  1/15th (7%)\n$genart.params.weighted({\n\tname: \"Test param\",\n\tdesc: \"Controlled randomness\",\n\toptions: [\n\t\t// format: [weight, value]\n\t\t[8, \"black\"],\n\t\t[4, \"cyan\"],\n\t\t[2, \"magenta\"],\n\t\t[1, \"yellow\"],\n\t],\n});\n\n// optionally, labels can be provided for each option\n$genart.params.weighted({\n\tname: \"Test param\",\n\tdesc: \"With labels\",\n\toptions: [\n\t\t// format: [weight, value, label]\n\t\t[8, \"#000\", \"black\"],\n\t\t[4, \"#0ff\", \"cyan\"],\n\t\t[2, \"#f0f\", \"magenta\"],\n\t\t[1, \"#ff0\", \"yellow\"],\n\t],\n});\n```\n\n##### Recommended GUI widget\n\n-   Drop-down menu\n-   Radio buttons\n\n#### XY parameter\n\n-   [API docs](https://docs.thi.ng/genart-api/core/interfaces/XYParam.html)\n-   [Factory function](https://docs.thi.ng/genart-api/core/interfaces/ParamFactories.html#xy)\n\nA 2D dimensional tuple for values in the [0,0] .. [1,1] range. Useful to control\ntwo co-dependent parameters using an XY controller/touchpad...\n\n```ts\n$genart.params.xy({\n\tname: \"Test param\",\n\tdesc: \"Bottom-left: [dark,dry] / Top-right: [bright,wet]\",\n\tdefault: [0.5, 0.5],\n});\n```\n\n##### Recommended GUI widget\n\n-   XY pad controller\n-   Pair of sliders (X \u0026 Y individually)\n\n### Dynamic parameter types\n\nDynamic parameters are either time-based (using a abstract notion of \"time\") or\notherwise produce values which could change each time a parameter is being\nread/evaluated by the artwork (e.g. sensor inputs).\n\nUnlike [static param types](#static-parameter-types), these parameters have **no\ndefault value** and their actual value is always computed.\n\n#### Ramp parameter\n\n-   [API docs](https://docs.thi.ng/genart-api/core/interfaces/RampParam.html)\n-   [Factory function](https://docs.thi.ng/genart-api/core/interfaces/ParamFactories.html#ramp)\n\nA ramp defines a one-dimensional curve/gradient via a number of stops/keyframes,\nfrom which then an actual value will be derived by sampling the curve at a\nspecific position. Ramp are different to other parameter types in that they're\nmostly intended for time-based parameters whose value should evolve over time\n(rather than being a static quantity).\n\nRamps support any number of stops/keyframes (though, at least 2 are required!)\nand by default the API supports the following interpolation modes:\n\n-   `linear`: linear interpolation (default)\n-   `exp`: exponential interpolation\n-   `smooth`: smoothstep\n\n**Recommended GUI widget:**\n\n-   [Curve editor](https://github.com/thi-ng/umbrella/tree/develop/examples/ramp-synth)\n\n```ts\n$genart.params.ramp({\n\tname: \"Test param\",\n\tdesc: \"Brightness over time\",\n\tstops: [\n\t\t[0, 0.1],\n\t\t[0.9, 1],\n\t\t[1, 0],\n\t],\n\tmode: \"smooth\",\n});\n```\n\n### Custom parameter types\n\nThe system supports registering custom parameter types and their implementation\nvia\n[`$genart.registerParamType()`](https://docs.thi.ng/genart-api/core/interfaces/GenArtAPI.html#registerparamtype).\nThese can be useful to provide additional app-specific or platform-specific\nparameters (e.g. values obtained from arbitrary hardware sensors to which an\nartwork might respond dynamically).\n\n-   [`ParamImpl` interface definition](https://docs.thi.ng/genart-api/core/interfaces/ParamImpl.html)\n-   [`registerParamType()`](https://docs.thi.ng/genart-api/core/interfaces/GenArtAPI.html#registerparamtype)\n\nThe `registerParamType()` allows overriding of existing param type\nimplementations, but doing so will print a warning. When an artwork or platform\nregisters its own types, it SHOULD consider namespacing the type name, e.g.\n`platformname:customtype`.\n\n#### Example: Oscillator parameter type\n\nThe following example shows how to implement, register and then use a sine wave\noscillator parameter type, providing time-based values. A more advanced version\nis shown in the [param-custom\nexample](https://github.com/thi-ng/genart-api/blob/main/examples/param-custom).\n\n```ts\n// define a new param type with given name and implementation.\ninterface OscParam extends Param\u003cnumber\u003e {\n\ttype: \"user:sinosc\";\n\tfreq: number;\n\tamp: number;\n\toffset: number;\n}\n\n// this implementation does not allow any customizations or value randomization\n// (the latter is common to all dynamic params, since the value is ALWAYS computed)\n$genart.registerParamType(\"user:sinosc\", {\n\t// for brevity we decide this param cannot be customized (once defined)\n\tvalid: (spec, key, value) =\u003e false,\n\t// the read function is called each time this param is evaluated,\n\t// here to provide a time-based value\n\tread: (spec, t) =\u003e {\n\t\tconst { freq, amp, offset } = \u003cOscParam\u003espec;\n\t\treturn Math.sin(t * freq * Math.PI * 2) * amp + offset;\n\t},\n});\n\n// register parameter\nconst param = $genart.setParams({\n\tsine: {\n\t\ttype: \"user:sinosc\", // param type (should be unique)\n\t\tfreq: 0.25, // frequency in Hz\n\t\tamp: 5, // amplitude\n\t\toffset: 5, // center offset\n\t\tdefault: 0, // ignored\n\t},\n});\n\n$genart.setUpdate((t) =\u003e {\n\t// current time in seconds\n\tt *= 0.001;\n\t// evaluate param\n\tconsole.log(t, param(\"sine\", t));\n\t// keep on animating\n\treturn true;\n});\n```\n\n### Composite parameter types\n\nComposite parameter types contain child parameters to allow the main param be\nconfigured in more detailed/complex ways. Usually, a composite parameter type\nwill define a\n[`.read()`](https://docs.thi.ng/genart-api/core/interfaces/ParamImpl.html#read)\nmethod to dynamically produce values, based on the current configuration\nof its child params.\n\nAn example of such a composite parameter type is an extended version of the\noscillator described in the [previous\nsection](#example-oscillator-parameter-type).\n\nTODO\n\nPlease see the [param-custom\nexample](https://github.com/thi-ng/genart-api/blob/main/examples/param-custom)\nfor reference...\n\n## Traits\n\nSome platforms support the concept of artist-defined metadata, commonly called\n\"traits\" or \"features\". In most cases, this metadata is a key-value dictionary,\nwhere the keys are arbitrarily defined criteria the artist wants to expose, and\nusually, the values are derived from the current parameter configuration of a\nparticular variation.\n\nThis API principally supports this use case via the `$genart.setTraits()`\nfunction, but it's the platform adapter's responsibility to deal with this\ninformation provided, i.e. declaring traits has zero impact on any other\nworkings or state of the API layer.\n\nThe value of a single trait can be a number, string or boolean.\n\n```ts\n// declare a single param\nconst param = await $genart.setParams({\n\tbright: $genart.params.range({\n\t\tname: \"brightness\",\n\t\tdesc: \"overall brightness\",\n\t\tmin: 0,\n\t\tmax: 100,\n\t}),\n});\n\n// internal random param\nconst density = $genart.random.rnd();\n\n// declare traits to outside world\n$genart.setTraits({\n\tbrightness: param(\"bright\") \u003c 50 ? \"dark\" : \"light\",\n\tdensity: Math.floor(density * 100) + \"%\",\n});\n```\n\n## Platform adapters\n\nTODO This section will describe the role(s) of adapters responsible for\nproviding (deployment) platform-specific functionality and interop features.\n\n-   [`PlatformAdapter` interface documentation](https://docs.thi.ng/genart-api/core/interfaces/PlatformAdapter.html)\n\n### Parameter sourcing\n\nTODO write docs\n\n### Parameter updates\n\nTODO write docs\n\n### Determinism \u0026 PRNG provision\n\nRelated issues/RFCs:\n\n-   [#1: Provide single PRNG or allow platfom adapters to define implementation?](https://github.com/thi-ng/genart-api/issues/1)\n\nPlatform adapters are responsible to provide a seedable and resettable,\ndeterministic pseudo-random number generator which the artwork can access via\n[`$genart.random`](https://docs.thi.ng/genart-api/core/interfaces/GenArtAPI.html#random).\nUsually, the adapter just has to wrap the PRNG provided by the respective\nplatform.\n\n-   [PRNG interface definition](https://docs.thi.ng/genart-api/core/interfaces/PRNG.html)\n-   [Example implementation in a platform adapter](https://github.com/thi-ng/genart-api/blob/main/packages/adapter-urlparams/index.ts)\n\nFor cases where a platform does not provide its own PRNG, the API core package\nprovides the widely used SFC32 PRNG implementation, which can be used by an\nadapter (or artwork) — also see the related [`defPRNG()` helper\nfunction](https://docs.thi.ng/genart-api/core/interfaces/PRNGBuiltins.html#defprng):\n\n-   [SFC32](https://github.com/thi-ng/genart-api/blob/main/packages/core/src/prng.ts)\n\n### Screen configuration\n\nPlatform adapters are responsible to provide screen/canvas dimensions (and pixel\ndensity information) to the artwork, and the latter MUST use the\n[`$genart.screen`](https://docs.thi.ng/genart-api/core/interfaces/GenArtAPI.html#screen)\naccessor to obtain this information (rather than directly querying\n`window.innerWidth` etc.). This accessor returns a [`ScreenConfig`\nobject](https://docs.thi.ng/genart-api/core/interfaces/ScreenConfig.html).\n\nThis approach gives the platform full control to define fixed dimensions,\nirrespective of actual window dimensions and also be in charge of resizing\nbehavior.\n\n#### Handling dynamic resizing\n\nSimilar to the above, artwork which aims to be responsive to changing screen\nconfigurations MUST NOT listen to `window` resize events directly, but MUST add\na listener for `genart:resize` messages, like so:\n\n```ts\n// resize events contain the new screen config\n$genart.on(\"genart:resize\", ({ screen }) =\u003e {\n\tconsole.log(\"new screen info:\", screen.width, screen.height, screen.dpr);\n});\n```\n\nIf an artwork is unable to dynamically respond to resize events, it should at\nleast implement a handler which reloads the window on resize, like so:\n\n```ts\n$genart.on(\"genart:resize\", () =\u003e location.reload());\n```\n\n### Thumbnail/preview generation\n\nTODO\n\n## Time providers\n\nA time provider is a further decoupling mechanism to allow artists (or\nplatforms) to re-purpose an artwork in different media production or asset\nmanagement contexts. Common scenarios include: an artist (or platform) might\nwant to produce high-res outputs or high-quality video assets which can only be\ncreated by running the piece at a much lower frame rate (or a frame rate\ncontrolled via external events/triggers). In order to protect the artwork code\nfrom having to be adjusted for these use cases, the API uses pluggable timing\nproviders which are merely responsible to schedule the next animation frame and\nprovide a related timestamp and frame number.\n\nThe API defaults to using a [`requestAnimationFrame()`-based\nprovider](https://github.com/thi-ng/genart-api/blob/main/packages/core/src/time/raf.ts),\nbut this one can be replaced by loading an alternative implementation via\nanother `\u003cscript\u003e` tag, like so:\n\n```html\n\u003c!-- main GenArtAPI script --\u003e\n\u003cscript src=\"./lib/genart.js\"\u003e\u003c/script\u003e\n\u003c!--\n    optional: use custom time provider (e.g. for non-realtime rendering of image sequences)\n    configure API to use offline time (new frame every 250 ms, time base: 60 fps)\n    IMPORTANT: MUST be loaded AFTER the main genart script!\n--\u003e\n\u003cscript\u003e\n\t$genart.setTimeProvider($genart.time.offline(250, 60));\n\u003c/script\u003e\n```\n\n### Existing time provider implementations\n\nThe following [time providers are\nincluded](https://docs.thi.ng/genart-api/core/interfaces/TimeProviders.html)\nin the API reference implementation:\n\n#### RAF\n\nDefault TimeProvider, requestAnimationFrame()-based. Start time \u0026 frame offsets\ncan be provided (both defaulting to zero).\n\n[Source](https://github.com/thi-ng/genart-api/blob/main/packages/core/src/time/raf.ts)\n\n#### Offline\n\nA time provider for fixed frame rates, offline (aka non-realtime) animation use\ncases, e.g. recording image sequences. Supports arbitrary delays between frames\n(default: 250ms) and reference frame rates (default: 60fps).\n\n[Source](https://github.com/thi-ng/genart-api/blob/main/packages/core/src/time/offline.ts)\n\n#### FPS overlay\n\n\u003e [!IMPORTANT]\n\u003e Since v0.22.0 this time provider is distributed as separate package\n\u003e [`@genart-api/time-fps-overlay`](https://github.com/thi-ng/genart-api/blob/main/packages/time-fps-overlay)\n\nSimilar to the [RAF time provider](#raf), but also collects FPS samples and\ninjects a canvas overlay to visualize recent frame rates and compute moving min,\nmax and average. The visualization can be configured via provided\n[options](https://docs.thi.ng/genart-api/time-fps-overlay/interfaces/FPSOverlayOpts.html).\n\n[Source](https://github.com/thi-ng/genart-api/blob/main/packages/time-fps-overlay/src/index.ts)\n\n## WebAssembly bindings\n\nAltough the main GenArtAPI project is a JavaScript-centric GenArt API\nworkflow/setup, we also want to provide integrations for other languages, e.g.\nvia WebAssembly.\n\nThe [@genart-api/wasm\npackage](https://github.com/thi-ng/genart-api/blob/main/packages/wasm/) provides\nWASM bindings for GenArtAPI and is designed as an API module/plugin for the\n[thi.ng/wasm-api](https://thi.ng/wasm-api) toolchain, and includes polyglot\nbindings code for both [Zig](https://ziglang.org) \u0026 TypeScript/JavaScript.\n\n## Getting started\n\n\u003e [!NOTE]\n\u003e The reference implementation of the API provided has no dependencies.\n\n### Example projects\n\nThis repo contains several examples used for testing and evaluating the\nreference API implementation. These are all separate projects/packages located\nin the [/examples](https://github.com/thi-ng/genart-api/tree/main/examples)\ndirectory. Please ensure you read their README instructions, since a certain\nbuild order must be used in some situations:\n\n| **Project**                                                                            | **Live demo w/ editor**                                                                                | **Description**                                        |\n| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------ |\n| [p5-basic](https://github.com/thi-ng/genart-api/tree/main/examples/p5-basic/)          | [Demo](https://demo.thi.ng/genart-api/param-editors/?url=https://demo.thi.ng/genart-api/p5-basic/)     | Basic p5.js example                                    |\n| [param-test](https://github.com/thi-ng/genart-api/tree/main/examples/param-test/)      | [Demo](https://demo.thi.ng/genart-api/param-editors/?url=https://demo.thi.ng/genart-api/param-test/)   | Minimal \"art\" example using various parameter types    |\n| [param-image](https://github.com/thi-ng/genart-api/tree/main/examples/param-image/)    | [Demo](https://demo.thi.ng/genart-api/param-editors/?url=https://demo.thi.ng/genart-api/param-image/)  | Example using an image map parameter                   |\n| [param-custom](https://github.com/thi-ng/genart-api/tree/main/examples/param-custom/)  | [Demo](https://demo.thi.ng/genart-api/param-editors/?url=https://demo.thi.ng/genart-api/param-custom/) | Custom \u0026 composite parameter type example              |\n| [param-editors](https://github.com/thi-ng/genart-api/tree/main/examples/param-custom/) | [Demo](https://demo.thi.ng/genart-api/param-editors/)                                                  | Reference [editor implementations](#parameter-editors) |\n| [zig-test](https://github.com/thi-ng/genart-api/tree/main/examples/zig-test/)          | [Demo](https://demo.thi.ng/genart-api/param-editors/?url=https://demo.thi.ng/genart-api/zig-test/)     | Zig/WebAssembly API wrapper example (WIP)              |\n\n### Existing adapter implementations\n\n\u003e [!NOTE]\n\u003e Please refer or contribute to issue [#2: List of art platforms we should\n\u003e provide adapters for](https://github.com/thi-ng/genart-api/issues/2)\n\nThe following art platforms are already supported and projects can be easily\nadapted by merely installing and switching to a different platform adapter.\n\nPlease refer to the readme's of the individual adapter packages for further\ndetails about handling any platform specifics:\n\n| **Package**                                                                                                          | **Art platform**               | **Description**                                                                                  |\n| -------------------------------------------------------------------------------------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------ |\n| [@genart-api/adapter-editart](https://github.com/thi-ng/genart-api/blob/main/packages/adapter-editart/README.md)     | [EditArt](https://editart.xyz) | Adapter for the EditArt platform                                                                 |\n| [@genart-api/adapter-fxhash](https://github.com/thi-ng/genart-api/blob/main/packages/adapter-fxhash/README.md)       | [fx(hash)](https://fxhash.xyz) | Adapter for the fx(hash) art platform                                                            |\n| [@genart-api/adapter-layer](https://github.com/thi-ng/genart-api/blob/main/packages/adapter-layer/README.md)         | Layer.com                      | Adapter for the Layer art platform                                                               |\n| [@genart-api/adapter-urlparams](https://github.com/thi-ng/genart-api/blob/main/packages/adapter-urlparams/README.md) |                                | Reference implementation (used for the [param editors](#parameter-editors) bundled in this repo) |\n\n### Project template\n\nThis repo contains an empty project template as starting point for new projects.\nThe template uses TypeScript \u0026 Vite, but can be _very_ easily adapted to other\ntooling (eg. there's hardly any code, so switching to JavaScript requires just\nrenaming the source file).\n\n-   TODO move template to own repo for easier use\n\n```bash\ngit clone https://github.com/thi-ng/genart-api.git\n\n# copy template to new directory\ncp -R genart-api/project-template my-new-art-project\n\n# install dependencies (genart api, typescript, vite)\ncd my-new-art-project\nyarn install\n```\n\n### Installion as package\n\nThe [@genart-api/core package](https://www.npmjs.com/@genart-api/core) contains\nthe pre-built release files \u0026 type declarations, but it's **not** an ESM module\nwhich can (or even should) be imported via `import` syntax. The API is always\nprovided as singleton via the global `$genart` variable.\n\nInstead, the JS file(s) should be copied to your project's `/lib` dir (or\nsimilar) to be referenced by a `\u003cscript\u003e` tag in your HTML wrapper (see below):\n\n```bash\nyarn add @genart-api/core\n\n# you'll also need a platform adapter, for example\nyarn add @genart-api/adpater-urlparams\n\n# create dest dir\nmkdir -p lib\n\n# copy files\ncp node_modules/@genart-api/core/*.js lib\ncp node_modules/@genart-api/adapter-urlparams/*.js lib\n```\n\nIf you're a TypeScript user, you'll also want to add the `@genart-api/core`\npackage to the `types` field in your `tsconfig.json`:\n\ntsconfig.json:\n\n```json\n{\n\t\"compilerOptions\": {\n\t\t\"types\": [\"@genart-api/core\"]\n\t}\n}\n```\n\n...or add a type declaration file with the following content to your `/src`\ndirectory...\n\n/src/types.d.ts:\n\n```ts\n/// \u003creference types=\"@genart-api/core\" /\u003e\n```\n\nThen you should be ready to go to [the next\nstep](#use-in-your-own-projects-an-artists-hello-world)...\n\n### Manual installation\n\nIf you don't want to use a package manager, the\n[/dist](https://github.com/thi-ng/genart-api/tree/main/dist) directory contains\nall pre-built release files and type declarations which you should copy to your\nproject directory (e.g. in a `/lib` dir or similar).\n\nIf you're a TypeScript user, you'll also want to add a declaration file with the\nfollowing content to your `/src` directory:\n\n/src/types.d.ts:\n\n```ts\n/// \u003creference types=\"../lib/genart.d.ts\" /\u003e\n```\n\n### Use in your own projects: An artist's \"Hello world\"\n\nThis section explains the basic approach to create a `GenArtAPI` conformant art\nproject and assumes you have installed the API files/types via one of the ways\ndescribed above.\n\n```html\n\u003cscript src=\"./lib/genart.min.js\"\u003e\u003c/script\u003e\n```\n\n#### Reference platform adapter\n\nThe repo provides a basic [platform adapter](#platform-adapters) for sourcing\nparameters via URL query string (aka\n[`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)).\nThis adapter can be useful during local development, or used as basis for other\nuse cases:\n\n```html\n\u003cscript src=\"./lib/adapter-urlparams.min.js\"\u003e\u003c/script\u003e\n```\n\n-   [TypeScript source code](https://github.com/thi-ng/genart-api/blob/main/packages/adapter-urlparams/src/index.ts)\n\n#### Example files\n\n\u003cdetails\u003e\u003csummary\u003eHTML example wrapper (click to expand)\u003c/summary\u003e\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\t\u003chead\u003e\n\t\t\u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" /\u003e\n\t\t\u003ctitle\u003eHello GenArtAPI\u003c/title\u003e\n\t\t\u003c!-- main GenArtAPI script --\u003e\n\t\t\u003cscript src=\"./lib/genart.js\"\u003e\u003c/script\u003e\n\t\t\u003c!-- platform adapter --\u003e\n\t\t\u003cscript src=\"./lib/adapter-urlparams.js\"\u003e\u003c/script\u003e\n\t\t\u003cstyle\u003e\n\t\t\tbody {\n\t\t\t\tmargin: 0;\n\t\t\t\toverflow: hidden;\n\t\t\t}\n\t\t\u003c/style\u003e\n\t\u003c/head\u003e\n\t\u003cbody\u003e\n\t\t\u003c!--\n            optional: use custom time provider (e.g. for non-realtime rendering of image sequences)\n            configure API to use offline time (new frame every 250 ms, time base: 60 fps)\n        --\u003e\n\t\t\u003cscript\u003e\n\t\t\t// $genart.setTimeProvider($genart.time.offline(250, 60));\n\t\t\u003c/script\u003e\n\t\t\u003c!-- User artwork script --\u003e\n\t\t\u003cscript type=\"module\" src=\"/src/index.js\"\u003e\u003c/script\u003e\n\t\u003c/body\u003e\n\u003c/html\u003e\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eMinimal example artwork script (click to expand)\u003c/summary\u003e\n\n```js\n// index.js\n(async () =\u003e {\n\t// ensure platform adapter is ready\n\tawait $genart.waitForAdapter();\n\n\t// declare parameters\n\tconst param = await $genart.setParams({\n\t\tbgColor: $genart.params.color({\n\t\t\tname: \"Bg color\", // mandatory human readable name\n\t\t\tdesc: \"Canvas background color\", // mandatory brief description\n\t\t\tdoc: \"Optional extended documentation or usage hints\",\n\t\t\tdefault: \"#0000ff\", // default value (if omitted, will be initialized to random...)\n\t\t\tupdate: \"reload\", // trigger reload on value change\n\t\t}),\n\n\t\t// this param has no default, so will be initialized to random value\n\t\t// (unless the platform provides a customized value)\n\t\tmaxR: $genart.params.range({\n\t\t\tname: \"Max radius\",\n\t\t\tdesc: \"Maximum brush size\",\n\t\t\tmin: 10,\n\t\t\tmax: 100,\n\t\t\tstep: 5,\n\t\t}),\n\t});\n\n\t// obtain screen config\n\tconst { width, height, dpr } = $genart.screen;\n\n\t// alias PRNG function (for convenience)\n\tconst random = $genart.random.rnd;\n\n\t// create canvas\n\tconst canvas = document.createElement(\"canvas\");\n\tcanvas.width = width;\n\tcanvas.height = height;\n\tdocument.body.appendChild(canvas);\n\n\tconst ctx = canvas.getContext(\"2d\");\n\n\t// use param (in TS param value types will be inferred automatically)\n\tctx.fillStyle = param(\"bgColor\");\n\t// clear canvas\n\tctx.fillRect(0, 0, width, height);\n\n\t// main update/draw function\n\t// time (in milliseconds) and frame number supplied by GenArtAPI \u0026 time provider\n\tconst update = (time, frame) =\u003e {\n\t\tconst radius = random() * param(\"maxR\");\n\t\tctx.strokeStyle = \"#000\";\n\t\tctx.beginPath();\n\t\tctx.arc(random() * width, random() * height, radius, 0, Math.PI * 2);\n\t\tctx.stroke();\n\t\tconsole.log(time, frame);\n\n\t\t// function must return true for animation to continue\n\t\treturn true;\n\t};\n\n\t// register update function\n\t// depending on platform adapter/specifics, in most cases\n\t// this will also auto-start animation...\n\t$genart.setUpdate(update);\n})();\n```\n\n\u003c/details\u003e\n\n## Build information\n\n### Building core API files\n\n```bash\nyarn install\n\n# output files will be written to /dist\nyarn build\n\n# generate TypeScript type declarations (also written to /dist)\nyarn build:types\n```\n\n### Building examples\n\nThe following command is used to create production builds of _all_ examples:\n\n```bash\n# from the repo root\nyarn build:examples\n```\n\n## Parameter editors\n\n\u003e [!IMPORTANT]\n\u003e\n\u003e **At this stage of the project, the parameter editors are only compatible with\n\u003e artworks using the current version of the GenArtAPI reference\n\u003e implementation.**\n\nThe repo contains two reference implementations of GUI parameter editors to\nmodify param values exposed by an artwork running in an embedded `\u003ciframe\u003e`.\nThese editors can be used to customize parameters of the other [bundled\nexamples](#bundled-examples) (or any other project using GenArt API and the\nsupplied [reference platform adapter](#reference-platform-adapter)). See the\n[param-editors\nreadme](https://github.com/thi-ng/genart-api/tree/main/examples/param-editors/)\nfor details.\n\nThe following table provides an overview of the **current (WIP)** support of\nparameter types in both editors:\n\n| Param type       | thi.ng/rdom editor | thi.ng/imgui editor |\n| ---------------- | ------------------ | ------------------- |\n| Bigint           | ❌                 | ❌                  |\n| Binary           | ❌                 | ❌                  |\n| Choice           | ✅                 | ✅                  |\n| Color            | ✅                 | ✅ (1)              |\n| Composite params | ❌                 | ✅ (2)              |\n| Date             | ✅                 | ✅                  |\n| Datetime         | ✅                 | ❌                  |\n| Image            | ✅                 | ❌                  |\n| List (3)         | ❌                 | ❌                  |\n| Range            | ✅                 | ✅                  |\n| Ramp             | ❌                 | ✅                  |\n| Text             | ✅                 | ✅ (4)              |\n| Time             | ✅                 | ❌                  |\n| Toggle           | ✅                 | ✅                  |\n| Vector           | ✅                 | ✅                  |\n| Weighted choice  | ✅                 | ✅                  |\n| XY               | ✅ (1)             | ✅                  |\n\n-   (1) No dedicated widget yet, using fallback only\n-   (2) See [composite parameter types](#composite-parameter-types)\n-   (3) Both [number](#numeric-list) or [string](#string-list)\n-   (4) Only single line, not mobile friendly\n\n## License\n\n\u0026copy; 2024 - 2025 Karsten Schmidt and contributors // MIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthi-ng%2Fgenart-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthi-ng%2Fgenart-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthi-ng%2Fgenart-api/lists"}