Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Generate interactive generative art using p5.js with seeded randomness, flow fields, and particle systems
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
templates/viewer.html
1<!DOCTYPE html>2<!--3THIS IS A TEMPLATE THAT SHOULD BE USED EVERY TIME AND MODIFIED.4WHAT TO KEEP:5✓ Overall structure (header, sidebar, main content)6✓ Anthropic branding (colors, fonts, layout)7✓ Seed navigation section (always include this)8✓ Self-contained artifact (everything inline)910WHAT TO CREATIVELY EDIT:11✗ The p5.js algorithm (implement YOUR vision)12✗ The parameters (define what YOUR art needs)13✗ The UI controls (match YOUR parameters)1415Let your philosophy guide the implementation.16The world is your oyster - be creative!17-->18<html lang="en">19<head>20<meta charset="UTF-8">21<meta name="viewport" content="width=device-width, initial-scale=1.0">22<title>Generative Art Viewer</title>23<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.min.js"></script>24<link rel="preconnect" href="https://fonts.googleapis.com">25<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>26<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&family=Lora:wght@400;500&display=swap" rel="stylesheet">27<style>28/* Anthropic Brand Colors */29:root {30--anthropic-dark: #141413;31--anthropic-light: #faf9f5;32--anthropic-mid-gray: #b0aea5;33--anthropic-light-gray: #e8e6dc;34--anthropic-orange: #d97757;35--anthropic-blue: #6a9bcc;36--anthropic-green: #788c5d;37}3839* {40margin: 0;41padding: 0;42box-sizing: border-box;43}4445body {46font-family: 'Poppins', sans-serif;47background: linear-gradient(135deg, var(--anthropic-light) 0%, #f5f3ee 100%);48min-height: 100vh;49color: var(--anthropic-dark);50}5152.container {53display: flex;54min-height: 100vh;55padding: 20px;56gap: 20px;57}5859/* Sidebar */60.sidebar {61width: 320px;62flex-shrink: 0;63background: rgba(255, 255, 255, 0.95);64backdrop-filter: blur(10px);65padding: 24px;66border-radius: 12px;67box-shadow: 0 10px 30px rgba(20, 20, 19, 0.1);68overflow-y: auto;69overflow-x: hidden;70}7172.sidebar h1 {73font-family: 'Lora', serif;74font-size: 24px;75font-weight: 500;76color: var(--anthropic-dark);77margin-bottom: 8px;78}7980.sidebar .subtitle {81color: var(--anthropic-mid-gray);82font-size: 14px;83margin-bottom: 32px;84line-height: 1.4;85}8687/* Control Sections */88.control-section {89margin-bottom: 32px;90}9192.control-section h3 {93font-size: 16px;94font-weight: 600;95color: var(--anthropic-dark);96margin-bottom: 16px;97display: flex;98align-items: center;99gap: 8px;100}101102.control-section h3::before {103content: '•';104color: var(--anthropic-orange);105font-weight: bold;106}107108/* Seed Controls */109.seed-input {110width: 100%;111background: var(--anthropic-light);112padding: 12px;113border-radius: 8px;114font-family: 'Courier New', monospace;115font-size: 14px;116margin-bottom: 12px;117border: 1px solid var(--anthropic-light-gray);118text-align: center;119}120121.seed-input:focus {122outline: none;123border-color: var(--anthropic-orange);124box-shadow: 0 0 0 2px rgba(217, 119, 87, 0.1);125background: white;126}127128.seed-controls {129display: grid;130grid-template-columns: 1fr 1fr;131gap: 8px;132margin-bottom: 8px;133}134135.regen-button {136margin-bottom: 0;137}138139/* Parameter Controls */140.control-group {141margin-bottom: 20px;142}143144.control-group label {145display: block;146font-size: 14px;147font-weight: 500;148color: var(--anthropic-dark);149margin-bottom: 8px;150}151152.slider-container {153display: flex;154align-items: center;155gap: 12px;156}157158.slider-container input[type="range"] {159flex: 1;160height: 4px;161background: var(--anthropic-light-gray);162border-radius: 2px;163outline: none;164-webkit-appearance: none;165}166167.slider-container input[type="range"]::-webkit-slider-thumb {168-webkit-appearance: none;169width: 16px;170height: 16px;171background: var(--anthropic-orange);172border-radius: 50%;173cursor: pointer;174transition: all 0.2s ease;175}176177.slider-container input[type="range"]::-webkit-slider-thumb:hover {178transform: scale(1.1);179background: #c86641;180}181182.slider-container input[type="range"]::-moz-range-thumb {183width: 16px;184height: 16px;185background: var(--anthropic-orange);186border-radius: 50%;187border: none;188cursor: pointer;189transition: all 0.2s ease;190}191192.value-display {193font-family: 'Courier New', monospace;194font-size: 12px;195color: var(--anthropic-mid-gray);196min-width: 60px;197text-align: right;198}199200/* Color Pickers */201.color-group {202margin-bottom: 16px;203}204205.color-group label {206display: block;207font-size: 12px;208color: var(--anthropic-mid-gray);209margin-bottom: 4px;210}211212.color-picker-container {213display: flex;214align-items: center;215gap: 8px;216}217218.color-picker-container input[type="color"] {219width: 32px;220height: 32px;221border: none;222border-radius: 6px;223cursor: pointer;224background: none;225padding: 0;226}227228.color-value {229font-family: 'Courier New', monospace;230font-size: 12px;231color: var(--anthropic-mid-gray);232}233234/* Buttons */235.button {236background: var(--anthropic-orange);237color: white;238border: none;239padding: 10px 16px;240border-radius: 6px;241font-size: 14px;242font-weight: 500;243cursor: pointer;244transition: all 0.2s ease;245width: 100%;246}247248.button:hover {249background: #c86641;250transform: translateY(-1px);251}252253.button:active {254transform: translateY(0);255}256257.button.secondary {258background: var(--anthropic-blue);259}260261.button.secondary:hover {262background: #5a8bb8;263}264265.button.tertiary {266background: var(--anthropic-green);267}268269.button.tertiary:hover {270background: #6b7b52;271}272273.button-row {274display: flex;275gap: 8px;276}277278.button-row .button {279flex: 1;280}281282/* Canvas Area */283.canvas-area {284flex: 1;285display: flex;286align-items: center;287justify-content: center;288min-width: 0;289}290291#canvas-container {292width: 100%;293max-width: 1000px;294border-radius: 12px;295overflow: hidden;296box-shadow: 0 20px 40px rgba(20, 20, 19, 0.1);297background: white;298}299300#canvas-container canvas {301display: block;302width: 100% !important;303height: auto !important;304}305306/* Loading State */307.loading {308display: flex;309align-items: center;310justify-content: center;311font-size: 18px;312color: var(--anthropic-mid-gray);313}314315/* Responsive - Stack on mobile */316@media (max-width: 600px) {317.container {318flex-direction: column;319}320321.sidebar {322width: 100%;323}324325.canvas-area {326padding: 20px;327}328}329</style>330</head>331<body>332<div class="container">333<!-- Control Sidebar -->334<div class="sidebar">335<!-- Headers (CUSTOMIZE THIS FOR YOUR ART) -->336<h1>TITLE - EDIT</h1>337<div class="subtitle">SUBHEADER - EDIT</div>338339<!-- Seed Section (ALWAYS KEEP THIS) -->340<div class="control-section">341<h3>Seed</h3>342<input type="number" id="seed-input" class="seed-input" value="12345" onchange="updateSeed()">343<div class="seed-controls">344<button class="button secondary" onclick="previousSeed()">← Prev</button>345<button class="button secondary" onclick="nextSeed()">Next →</button>346</div>347<button class="button tertiary regen-button" onclick="randomSeedAndUpdate()">↻ Random</button>348</div>349350<!-- Parameters Section (CUSTOMIZE THIS FOR YOUR ART) -->351<div class="control-section">352<h3>Parameters</h3>353354<!-- Particle Count -->355<div class="control-group">356<label>Particle Count</label>357<div class="slider-container">358<input type="range" id="particleCount" min="1000" max="10000" step="500" value="5000" oninput="updateParam('particleCount', this.value)">359<span class="value-display" id="particleCount-value">5000</span>360</div>361</div>362363<!-- Flow Speed -->364<div class="control-group">365<label>Flow Speed</label>366<div class="slider-container">367<input type="range" id="flowSpeed" min="0.1" max="2.0" step="0.1" value="0.5" oninput="updateParam('flowSpeed', this.value)">368<span class="value-display" id="flowSpeed-value">0.5</span>369</div>370</div>371372<!-- Noise Scale -->373<div class="control-group">374<label>Noise Scale</label>375<div class="slider-container">376<input type="range" id="noiseScale" min="0.001" max="0.02" step="0.001" value="0.005" oninput="updateParam('noiseScale', this.value)">377<span class="value-display" id="noiseScale-value">0.005</span>378</div>379</div>380381<!-- Trail Length -->382<div class="control-group">383<label>Trail Length</label>384<div class="slider-container">385<input type="range" id="trailLength" min="2" max="20" step="1" value="8" oninput="updateParam('trailLength', this.value)">386<span class="value-display" id="trailLength-value">8</span>387</div>388</div>389</div>390391<!-- Colors Section (OPTIONAL - CUSTOMIZE OR REMOVE) -->392<div class="control-section">393<h3>Colors</h3>394395<!-- Color 1 -->396<div class="color-group">397<label>Primary Color</label>398<div class="color-picker-container">399<input type="color" id="color1" value="#d97757" onchange="updateColor('color1', this.value)">400<span class="color-value" id="color1-value">#d97757</span>401</div>402</div>403404<!-- Color 2 -->405<div class="color-group">406<label>Secondary Color</label>407<div class="color-picker-container">408<input type="color" id="color2" value="#6a9bcc" onchange="updateColor('color2', this.value)">409<span class="color-value" id="color2-value">#6a9bcc</span>410</div>411</div>412413<!-- Color 3 -->414<div class="color-group">415<label>Accent Color</label>416<div class="color-picker-container">417<input type="color" id="color3" value="#788c5d" onchange="updateColor('color3', this.value)">418<span class="color-value" id="color3-value">#788c5d</span>419</div>420</div>421</div>422423<!-- Actions Section (ALWAYS KEEP THIS) -->424<div class="control-section">425<h3>Actions</h3>426<div class="button-row">427<button class="button" onclick="resetParameters()">Reset</button>428</div>429</div>430</div>431432<!-- Main Canvas Area -->433<div class="canvas-area">434<div id="canvas-container">435<div class="loading">Initializing generative art...</div>436</div>437</div>438</div>439440<script>441// ═══════════════════════════════════════════════════════════════════════442// GENERATIVE ART PARAMETERS - CUSTOMIZE FOR YOUR ALGORITHM443// ═══════════════════════════════════════════════════════════════════════444445let params = {446seed: 12345,447particleCount: 5000,448flowSpeed: 0.5,449noiseScale: 0.005,450trailLength: 8,451colorPalette: ['#d97757', '#6a9bcc', '#788c5d']452};453454let defaultParams = {...params}; // Store defaults for reset455456// ═══════════════════════════════════════════════════════════════════════457// P5.JS GENERATIVE ART ALGORITHM - REPLACE WITH YOUR VISION458// ═══════════════════════════════════════════════════════════════════════459460let particles = [];461let flowField = [];462let cols, rows;463let scl = 10; // Flow field resolution464465function setup() {466let canvas = createCanvas(1200, 1200);467canvas.parent('canvas-container');468469initializeSystem();470471// Remove loading message472document.querySelector('.loading').style.display = 'none';473}474475function initializeSystem() {476// Seed the randomness for reproducibility477randomSeed(params.seed);478noiseSeed(params.seed);479480// Clear particles and recreate481particles = [];482483// Initialize particles484for (let i = 0; i < params.particleCount; i++) {485particles.push(new Particle());486}487488// Calculate flow field dimensions489cols = floor(width / scl);490rows = floor(height / scl);491492// Generate flow field493generateFlowField();494495// Clear background496background(250, 249, 245); // Anthropic light background497}498499function generateFlowField() {500// fill this in501}502503function draw() {504// fill this in505}506507// ═══════════════════════════════════════════════════════════════════════508// PARTICLE SYSTEM - CUSTOMIZE FOR YOUR ALGORITHM509// ═══════════════════════════════════════════════════════════════════════510511class Particle {512constructor() {513// fill this in514}515// fill this in516}517518// ═══════════════════════════════════════════════════════════════════════519// UI CONTROL HANDLERS - CUSTOMIZE FOR YOUR PARAMETERS520// ═══════════════════════════════════════════════════════════════════════521522function updateParam(paramName, value) {523// fill this in524}525526function updateColor(colorId, value) {527// fill this in528}529530// ═══════════════════════════════════════════════════════════════════════531// SEED CONTROL FUNCTIONS - ALWAYS KEEP THESE532// ═══════════════════════════════════════════════════════════════════════533534function updateSeedDisplay() {535document.getElementById('seed-input').value = params.seed;536}537538function updateSeed() {539let input = document.getElementById('seed-input');540let newSeed = parseInt(input.value);541if (newSeed && newSeed > 0) {542params.seed = newSeed;543initializeSystem();544} else {545// Reset to current seed if invalid546updateSeedDisplay();547}548}549550function previousSeed() {551params.seed = Math.max(1, params.seed - 1);552updateSeedDisplay();553initializeSystem();554}555556function nextSeed() {557params.seed = params.seed + 1;558updateSeedDisplay();559initializeSystem();560}561562function randomSeedAndUpdate() {563params.seed = Math.floor(Math.random() * 999999) + 1;564updateSeedDisplay();565initializeSystem();566}567568function resetParameters() {569params = {...defaultParams};570571// Update UI elements572document.getElementById('particleCount').value = params.particleCount;573document.getElementById('particleCount-value').textContent = params.particleCount;574document.getElementById('flowSpeed').value = params.flowSpeed;575document.getElementById('flowSpeed-value').textContent = params.flowSpeed;576document.getElementById('noiseScale').value = params.noiseScale;577document.getElementById('noiseScale-value').textContent = params.noiseScale;578document.getElementById('trailLength').value = params.trailLength;579document.getElementById('trailLength-value').textContent = params.trailLength;580581// Reset colors582document.getElementById('color1').value = params.colorPalette[0];583document.getElementById('color1-value').textContent = params.colorPalette[0];584document.getElementById('color2').value = params.colorPalette[1];585document.getElementById('color2-value').textContent = params.colorPalette[1];586document.getElementById('color3').value = params.colorPalette[2];587document.getElementById('color3-value').textContent = params.colorPalette[2];588589updateSeedDisplay();590initializeSystem();591}592593// Initialize UI on load594window.addEventListener('load', function() {595updateSeedDisplay();596});597</script>598</body>599</html>