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

@genart-dev/genart-script

v0.1.3

Published

Compiler and runtime for the GenArt Script language (.genart-script / .gs)

Downloads

252

Readme

@genart-dev/genart-script

Compiler and runtime for GenArt Script (.gs) — a minimal scripting language for generative art. Part of the genart.dev platform.

GenArt Script is designed to be both human-playful and AI token-efficient. It compiles to JavaScript and runs on any canvas via the GenArt renderer adapter in @genart-dev/core.

Install

npm install @genart-dev/genart-script

Quick Example

param count 200 range:10..500 step:10
color bg #0d1117

frame:
  bg $bg
  loop count:
    x = rnd(w)
    y = rnd(h)
    r = 2 + noise(x * 0.01, y * 0.01, t) * 20
    circle x y r:r fill:white.30

post:
  bloom(0.3)
  vignette(0.4)

Usage

Compiler

import { compile } from "@genart-dev/genart-script";

const result = compile(`
  bg #1a1a2e
  circle w/2 h/2 r:100 fill:coral
`);

if (result.ok) {
  console.log(result.code);    // compiled JavaScript
  console.log(result.params);  // extracted param declarations
  console.log(result.colors);  // extracted color declarations
  console.log(result.layers);  // extracted layer declarations
} else {
  console.error(result.errors); // [{ line, col, message }]
}

Runtime (for renderer adapters)

import { buildGlobals } from "@genart-dev/genart-script/runtime";

const globals = buildGlobals(ctx, params, colors, seed);
// Inject globals into compiled code via new Function(...)

Language Reference

Drawing Primitives

bg coral                                    // fill background
circle x y r:20 fill:red stroke:#000 2      // circle
rect x y w:100 h:50 fill:blue rx:8          // rectangle (rounded)
line x1 y1 x2 y2 stroke:white 2            // line
dot x y fill:coral                          // single pixel
arc x y r:50 start:0 end:3.14 fill:red      // arc
poly points fill:green stroke:black         // polygon from flat [x,y,...] array
path "M0 0 L100 100" stroke:black 1         // SVG path
text "hello" x y size:24 fill:white         // text

Color

fill:red                    // named color
fill:#ff0000                // hex
fill:white.50               // alpha shorthand (50%)
fill:linear(#000, #fff)     // linear gradient
fill:radial(#fff, #000)     // radial gradient

Blocks & Execution Model

// Static — runs once
bg black
circle w/2 h/2 r:100 fill:coral

// Animation loop
frame:
  bg black
  circle w/2 h/2 r:sin(t)*50+60 fill:coral

// One-time async setup
once:
  font = await loadFont("MyFont", "font.woff2")

// Post-processing
post:
  bloom(0.3)
  vignette(0.4)
  chromatic_aberration(3)

Parameters & Colors

param count 100 range:10..500 step:10 label:"Particle Count"
param speed 1.5 range:0.1..5 step:0.1
color bg #1a1a2e label:"Background"
color accent #ff6b6b

Parameters and colors become globals in the script AND are extracted into the .genart file for UI controls.

Control Flow

if x > 100:
  circle x y r:5 fill:red
else:
  circle x y r:5 fill:blue

loop 50:
  circle rnd(w) rnd(h) r:5 fill:white     // implicit `i` variable

for x in 0..w step:20:
  line x 0 x h stroke:white.10

for i, v in arr:
  circle v.x v.y r:5 fill:coral

Functions & Lambdas

fn wobble x y:
  return sin(x * 0.1 + t) * y

// Lambda
pts = loop 100 =>
  return vec(rnd(w), rnd(h))

// Implicit `it` variable
arr.map(it * 2)
arr.filter(it > 0.5)

Transforms

at w/2 h/2:                  // translate
  rotate t:                   // rotate
    rect -25 -25 w:50 h:50 fill:coral

scale 2:                      // scale
  circle 0 0 r:10 fill:red

blend multiply:               // composite mode
  rect 0 0 w:w h:h fill:blue

Interactivity

// Frame globals: mouseX, mouseY, mouseDown, pmouseX, pmouseY,
//                touchX, touchY, touches (array of {id,x,y}),
//                prev (previous frame ImageData)

frame:
  circle mouseX mouseY r:10 fill:white

  // Draw previous frame with fade for trails
  if prev:
    draw prev 0 0 alpha:0.95

on click:
  circle mouseX mouseY r:20 fill:coral

on key "r":
  bg black

Offscreen Buffers

buf = buffer(w, h)
into buf:
  bg black
  circle w/2 h/2 r:100 fill:coral

draw buf 0 0 alpha:0.5 blend:screen

Images & Fonts

once:
  img = load("photo.jpg")
  font = await loadFont("Mono", "mono.woff2")

frame:
  draw img 0 0 w:w h:h tint:coral
  text "hello" w/2 h/2 font:font size:48 align:center fill:white

Standard Library

use easing    // ease_in, ease_out, ease_in_out, ease_cubic, elastic, bounce
use shapes    // star(x,y,n,r,ir?), hexagon(x,y,r), arrow(x,y,angle,size)
use palettes  // nord[], solarized[], pastel[], earth[]

Plugin Layers

layer "terrain:sky" "noon" opacity:0.8 blend:"multiply" name:"Sky"
layer "terrain:mountains" "alpine"
layer "particles:glow" "fireflies" visible:false

Layers are extracted at compile time — they don't emit code but populate CompileResult.layers.

Post-Processing Effects

All effects are function calls inside post: blocks.

| Effect | Signature | Description | |--------|-----------|-------------| | vignette | (strength=0.5) | Radial edge darkening | | grain | (amount=0.15) | Film grain overlay | | grade | (contrast, saturation, brightness, hue) | Color grading | | blur | (radius) | Gaussian blur | | scanlines | (opacity=0.15) | CRT scanline overlay | | pixelate | (blockSize) | Pixel mosaic | | bloom | (strength=0.5, radius=8) | Glow bloom | | chromatic_aberration | (amount=3, quality?) | RGB channel offset | | distort | (type="wave", amount=10, quality?) | Pixel displacement (wave/ripple/noise) | | dither | (strength=0.5) | Bayer ordered dithering | | halftone | (dotSize=4, angle=0.3) | Dot screen effect |

Effects with quality? accept "auto" (default), "high" (always full pixel ops), or "fast" (skip or approximate).

Built-in Globals

| Global | Description | |--------|-------------| | w, h | Canvas dimensions | | t | Elapsed time (seconds) | | frame | Frame counter | | fps | Frames per second (60) | | rnd(n), rnd(a, b) | Seeded random number | | rndInt(n) | Seeded random integer | | noise(x, y?, z?) | Perlin noise | | PI, TWO_PI, HALF_PI | Math constants | | lerp, clamp, map, dist | Math utilities | | sin, cos, tan, atan2, sqrt, abs, floor, ceil, round, min, max, pow, log, exp | Math functions | | pick(arr) | Random array element | | shuffle(arr) | Shuffle array | | vec(x, y) | 2D vector with .add .sub .mult .mag .norm .dot .angle | | buffer(w, h) | Create offscreen canvas | | load(url) | Load image | | loadFont(family, url) | Load font (async) | | measure(text, size?, family?) | Measure text dimensions |

Exports

@genart-dev/genart-script (compiler)

compile(source: string): CompileResult
tokenize(source: string): Token[]
parse(tokens: Token[]): Program
codegen(program: Program): CompileResult

@genart-dev/genart-script/runtime

buildGlobals(ctx, params, colors, seed): RuntimeGlobals
vec(x, y): Vec

Architecture

source string
  → tokenize()    Lexical analysis + indentation tracking
  → parse()       Recursive descent → AST
  → codegen()     AST → JavaScript + extracted params/colors/layers

The compiler is hand-written (no parser generators), zero-dependency, and produces standalone JavaScript that runs in any canvas context. The runtime library provides seeded PRNG, noise, math utilities, color helpers, and post-processing effects.

License

MIT