p5js

p5.js sketches: gen art, shaders, interactive, 3D.

  • creative-coding
  • generative-art
  • p5js
  • canvas
  • interactive
  • visualization
  • webgl
  • shaders
  • animation

Declared platforms: linux · macos · windows

Install
npx skills add 'https://github.com/NousResearch/hermes-agent/tree/main/skills/creative/p5js'
Download bundle ↓
main · 24fd22bScanned 2026-09-15

Contributors

GitHub-linked commit authors for this SKILL.md at the saved revision. Co-authors and history before file renames are not included.

File history ↗
View on GitHub
← Back to SKILL.md
<!DOCTYPE html><!--  p5.js Interactive Viewer Template  =================================  USE THIS AS THE STARTING POINT for interactive generative art sketches.   FIXED (keep as-is):  ✓ Layout structure (sidebar + canvas)  ✓ Seed navigation (prev/next/random/jump)  ✓ Action buttons (regenerate, reset, download PNG)  ✓ Responsive canvas sizing  ✓ Parameter update + regeneration wiring   VARIABLE (replace for each project):  ✗ The p5.js algorithm (setup/draw/classes)  ✗ The PARAMS object (define what your art needs)  ✗ The parameter controls in the sidebar (sliders, pickers)  ✗ The color palette  ✗ The title and description   For headless export: add noLoop() and window._p5Ready=true in setup().--><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Generative Art Viewer</title><script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.3/p5.min.js"></script><style>  * { margin: 0; padding: 0; box-sizing: border-box; }  body {    font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;    background: #0a0a0f;    color: #c8c8d0;    display: flex;    min-height: 100vh;    overflow: hidden;  }   /* --- Sidebar --- */  .sidebar {    width: 280px;    flex-shrink: 0;    background: #12121a;    border-right: 1px solid #1e1e2a;    padding: 20px;    overflow-y: auto;    display: flex;    flex-direction: column;    gap: 20px;  }  .sidebar h1 {    font-size: 18px;    font-weight: 600;    color: #e8e8f0;    margin-bottom: 4px;  }  .sidebar .subtitle {    font-size: 12px;    color: #666;    margin-bottom: 8px;  }  .section-title {    font-size: 11px;    font-weight: 600;    text-transform: uppercase;    letter-spacing: 1px;    color: #555;    margin-bottom: 8px;  }   /* --- Seed Controls --- */  .seed-display {    font-family: 'SF Mono', 'Fira Code', monospace;    font-size: 24px;    font-weight: 700;    color: #e8e8f0;    text-align: center;    padding: 8px;    background: #1a1a25;    border-radius: 6px;    margin-bottom: 8px;  }  .seed-nav {    display: flex;    gap: 6px;    margin-bottom: 6px;  }  .seed-nav button {    flex: 1;    padding: 6px;    font-size: 12px;  }  .seed-jump {    display: flex;    gap: 6px;  }  .seed-jump input {    flex: 1;    padding: 6px 8px;    background: #1a1a25;    border: 1px solid #2a2a35;    border-radius: 4px;    color: #c8c8d0;    font-size: 12px;    font-family: monospace;  }  .seed-jump button { padding: 6px 12px; font-size: 12px; }   /* --- Parameter Controls --- */  .control-group {    margin-bottom: 12px;  }  .control-group label {    display: flex;    justify-content: space-between;    font-size: 12px;    color: #888;    margin-bottom: 4px;  }  .control-group .value {    color: #aaa;    font-family: monospace;    font-size: 11px;  }  .control-group input[type="range"] {    width: 100%;    height: 4px;    -webkit-appearance: none;    background: #2a2a35;    border-radius: 2px;    outline: none;  }  .control-group input[type="range"]::-webkit-slider-thumb {    -webkit-appearance: none;    width: 14px; height: 14px;    border-radius: 50%;    background: #6a9bcc;    cursor: pointer;  }  .control-group input[type="color"] {    width: 100%;    height: 28px;    border: 1px solid #2a2a35;    border-radius: 4px;    background: #1a1a25;    cursor: pointer;  }   /* --- Buttons --- */  button {    padding: 8px 12px;    background: #1e1e2a;    border: 1px solid #2a2a35;    border-radius: 4px;    color: #c8c8d0;    font-size: 12px;    cursor: pointer;    transition: background 0.15s;  }  button:hover { background: #2a2a3a; }  button.primary { background: #2a4a6a; border-color: #3a5a7a; }  button.primary:hover { background: #3a5a7a; }   .actions { display: flex; flex-direction: column; gap: 6px; }  .actions button { width: 100%; }   /* --- Canvas Area --- */  .canvas-area {    flex: 1;    display: flex;    align-items: center;    justify-content: center;    padding: 20px;    background: #08080c;  }  canvas { display: block; }</style></head><body> <!-- === SIDEBAR === --><div class="sidebar">  <!-- FIXED: Title (customize text, keep structure) -->  <div>    <h1 id="art-title">Generative Sketch</h1>    <div class="subtitle" id="art-subtitle">p5.js generative art</div>  </div>   <!-- FIXED: Seed Navigation -->  <div>    <div class="section-title">Seed</div>    <div class="seed-display" id="seed-display">42</div>    <div class="seed-nav">      <button onclick="changeSeed(-1)">&#9664; Prev</button>      <button onclick="changeSeed(1)">Next &#9654;</button>      <button onclick="randomizeSeed()">Random</button>    </div>    <div class="seed-jump">      <input type="number" id="seed-input" placeholder="Seed #" min="0">      <button onclick="jumpToSeed()">Go</button>    </div>  </div>   <!-- VARIABLE: Parameters (customize for each project) -->  <div id="params-section">    <div class="section-title">Parameters</div>     <!-- === REPLACE THESE WITH YOUR PARAMETERS === -->    <div class="control-group">      <label>Count <span class="value" id="count-val">500</span></label>      <input type="range" id="count" min="50" max="2000" step="50" value="500"             oninput="updateParam('count', +this.value)">    </div>     <div class="control-group">      <label>Scale <span class="value" id="scale-val">0.005</span></label>      <input type="range" id="scale" min="0.001" max="0.02" step="0.001" value="0.005"             oninput="updateParam('scale', +this.value)">    </div>     <div class="control-group">      <label>Speed <span class="value" id="speed-val">2.0</span></label>      <input type="range" id="speed" min="0.5" max="5" step="0.1" value="2.0"             oninput="updateParam('speed', +this.value)">    </div>    <!-- === END PARAMETER CONTROLS === -->  </div>   <!-- VARIABLE: Colors (optional — include if art needs adjustable palette) -->  <!--  <div>    <div class="section-title">Colors</div>    <div class="control-group">      <label>Background</label>      <input type="color" id="bg-color" value="#0a0a14"             oninput="updateParam('bgColor', this.value)">    </div>    <div class="control-group">      <label>Primary</label>      <input type="color" id="primary-color" value="#6a9bcc"             oninput="updateParam('primaryColor', this.value)">    </div>  </div>  -->   <!-- FIXED: Actions -->  <div class="actions">    <div class="section-title">Actions</div>    <button class="primary" onclick="regenerate()">Regenerate</button>    <button onclick="resetDefaults()">Reset Defaults</button>    <button onclick="downloadPNG()">Download PNG</button>  </div></div> <!-- === CANVAS === --><div class="canvas-area" id="canvas-container"></div> <script>// ====================================================================// CONFIGURATION — REPLACE FOR EACH PROJECT// ====================================================================const DEFAULTS = {  seed: 42,  count: 500,  scale: 0.005,  speed: 2.0,  // Add your parameters here}; let PARAMS = { ...DEFAULTS }; // ====================================================================// SEED NAVIGATION — FIXED (do not modify)// ====================================================================function changeSeed(delta) {  PARAMS.seed = Math.max(0, PARAMS.seed + delta);  document.getElementById('seed-display').textContent = PARAMS.seed;  regenerate();} function randomizeSeed() {  PARAMS.seed = Math.floor(Math.random() * 99999);  document.getElementById('seed-display').textContent = PARAMS.seed;  regenerate();} function jumpToSeed() {  let v = parseInt(document.getElementById('seed-input').value);  if (!isNaN(v) && v >= 0) {    PARAMS.seed = v;    document.getElementById('seed-display').textContent = PARAMS.seed;    document.getElementById('seed-input').value = '';    regenerate();  }} // ====================================================================// PARAMETER UPDATES — CUSTOMIZE updateParam body as needed// ====================================================================function updateParam(name, value) {  PARAMS[name] = value;  let el = document.getElementById(name + '-val');  if (el) el.textContent = typeof value === 'number' && value < 1 ? value.toFixed(3) : value;  regenerate();} function resetDefaults() {  PARAMS = { ...DEFAULTS };  // Reset all sliders to default values  for (let [key, val] of Object.entries(DEFAULTS)) {    let el = document.getElementById(key);    if (el) el.value = val;    let valEl = document.getElementById(key + '-val');    if (valEl) valEl.textContent = typeof val === 'number' && val < 1 ? val.toFixed(3) : val;  }  document.getElementById('seed-display').textContent = PARAMS.seed;  regenerate();} function regenerate() {  randomSeed(PARAMS.seed);  noiseSeed(PARAMS.seed);  // Clear and redraw  clear();  initializeArt();  redraw();} function downloadPNG() {  saveCanvas('generative-art-seed-' + PARAMS.seed, 'png');} // ====================================================================// P5.JS SKETCH — REPLACE ENTIRELY FOR EACH PROJECT// ==================================================================== // Your state variableslet particles = []; function initializeArt() {  // Initialize your generative system using PARAMS  // This is called on every regenerate()  particles = [];  for (let i = 0; i < PARAMS.count; i++) {    particles.push({      x: random(width),      y: random(height),      vx: 0, vy: 0    });  }} function setup() {  // Size canvas to fit container  let container = document.getElementById('canvas-container');  let size = Math.min(container.clientWidth - 40, container.clientHeight - 40, 1080);  let cnv = createCanvas(size, size);  cnv.parent('canvas-container');  pixelDensity(1);  colorMode(HSB, 360, 100, 100, 100);   randomSeed(PARAMS.seed);  noiseSeed(PARAMS.seed);  initializeArt();   // For interactive/animated sketches: remove noLoop()  // For static generation: keep noLoop()  noLoop();} function draw() {  background(0, 0, 5);   // === YOUR ALGORITHM HERE ===  // Use PARAMS.count, PARAMS.scale, PARAMS.speed, etc.  noStroke();  for (let p of particles) {    let n = noise(p.x * PARAMS.scale, p.y * PARAMS.scale);    let hue = (n * 200 + PARAMS.seed * 0.1) % 360;    fill(hue, 70, 80, 60);    circle(p.x, p.y, n * 10 + 2);  }  // === END ALGORITHM ===} function windowResized() {  let container = document.getElementById('canvas-container');  let size = Math.min(container.clientWidth - 40, container.clientHeight - 40, 1080);  resizeCanvas(size, size);  regenerate();}</script></body></html>
Referenced from SKILL.md