selkie 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,19 +1,64 @@
1
- # Selkie
1
+ # Selkie
2
2
 
3
3
  In Celtic mythology, selkies are beings that can transform from seals into humans by shedding their seal skins. They often feature in stories of love and longing, where a selkie's human form is hidden away or discovered by a human.
4
4
 
5
- This library is heavily influenced as a template starter for generative projects. For now it only works with p5. I'll be extending it to also include other templates.
5
+ A CLI tool for scaffolding generative art projects. Quickly create projects with p5.js, Paper.js, Three.js, WebGL/GLSL shaders, or ML5.js hand tracking.
6
6
 
7
- This is a project to help better understand the process of streamlining my sketches in p5. I've been able to quickly iternate using Processing for years now. But I want to really get a grasp on creating a system that will generate the work that I will be able to use.
7
+ ## Installation
8
8
 
9
9
  ```bash
10
10
  npm install selkie
11
11
  ```
12
12
 
13
+ ## Usage
14
+
15
+ Create a new project with one of the available templates:
13
16
 
14
- In order to create a new project, use the following after it has been installed.
15
17
  ```bash
16
- selkie -t default
18
+ selkie -t default # p5.js canvas project
19
+ selkie -t svg # Paper.js vector/SVG project
20
+ selkie -t three # Three.js 3D project
21
+ selkie -t glsl # WebGL shader project
22
+ selkie -t ml5-hand # ML5.js hand tracking project
17
23
  ```
18
24
 
25
+ You'll be prompted for a folder name, then the project will be created with all dependencies installed.
26
+
27
+ ## Working on Your Sketch
28
+
29
+ Each generated project includes a dev server:
30
+
31
+ ```bash
32
+ cd your-project
33
+ npm start # Opens in browser with live reload
34
+ ```
35
+
36
+ Edit `scripts/sketch.js` to create your generative art. Press 's' to export PNG/SVG (depending on template).
37
+
38
+ ## Building a Single-File Bundle
39
+
40
+ When you're ready to share your sketch, build it into a single HTML file that works offline on any device:
41
+
42
+ ```bash
43
+ npm run build
44
+ ```
45
+
46
+ This creates `dist/bundle.html` - a minified, self-contained file you can:
47
+ - Open directly in any browser (no server needed)
48
+ - Share via email, USB, or any file transfer
49
+ - Upload to any static hosting
50
+
51
+ **Note:** The ML5 hand tracking template still requires internet for AI models.
52
+
53
+ ## Templates
54
+
55
+ | Template | Library | Output | Notes |
56
+ |----------|---------|--------|-------|
57
+ | `default` | p5.js | Canvas/PNG | Classic creative coding |
58
+ | `svg` | Paper.js | SVG vectors | Perfect for plotters |
59
+ | `three` | Three.js | WebGL 3D | 3D graphics |
60
+ | `glsl` | Native WebGL | Shaders | Smallest bundle (~5KB) |
61
+ | `ml5-hand` | ML5.js | Hand tracking | Requires webcam + internet |
62
+
63
+ All templates include a seeded random number generator for deterministic/reproducible outputs.
19
64
 
package/index.js CHANGED
@@ -6,8 +6,8 @@ import path from 'path';
6
6
  import { Command } from 'commander';
7
7
  import { fileURLToPath } from 'url';
8
8
  import { exec, execSync } from 'child_process';
9
- import { template as defaultTemplate } from './templates.js';
10
- import { packageJsonContent } from './package_details.js';
9
+ import { template as defaultTemplate, svgTemplate, threeTemplate, glslTemplate, ml5HandTrackingTemplate, buildScriptContent } from './templates/templates.js';
10
+ import { packageJsonContent, svgPackageJsonContent, threePackageJsonContent, glslPackageJsonContent, ml5HandTrackingPackageJsonContent } from './package_details.js';
11
11
 
12
12
  // Convert import.meta.url to a file path
13
13
  const __filename = fileURLToPath(import.meta.url);
@@ -45,15 +45,36 @@ async function createProject() {
45
45
  await fs.ensureDir(scriptsPath);
46
46
 
47
47
  // Choose the template
48
- let htmlContent, sketchContent, randomContent;
49
-
48
+ let htmlContent, sketchContent, randomContent, selectedPackageJson;
49
+ let templateType = options.template || 'default';
50
50
 
51
- if (options.template === 'default' || !options.template) {
51
+ if (templateType === 'default') {
52
52
  htmlContent = defaultTemplate.htmlContent;
53
53
  sketchContent = defaultTemplate.sketchContent;
54
54
  randomContent = defaultTemplate.randomContent;
55
+ selectedPackageJson = packageJsonContent;
56
+ } else if (templateType === 'svg') {
57
+ htmlContent = svgTemplate.htmlContent;
58
+ sketchContent = svgTemplate.sketchContent;
59
+ randomContent = svgTemplate.randomContent;
60
+ selectedPackageJson = svgPackageJsonContent;
61
+ } else if (templateType === 'three') {
62
+ htmlContent = threeTemplate.htmlContent;
63
+ sketchContent = threeTemplate.sketchContent;
64
+ randomContent = threeTemplate.randomContent;
65
+ selectedPackageJson = threePackageJsonContent;
66
+ } else if (templateType === 'glsl') {
67
+ htmlContent = glslTemplate.htmlContent;
68
+ sketchContent = glslTemplate.sketchContent;
69
+ randomContent = glslTemplate.randomContent;
70
+ selectedPackageJson = glslPackageJsonContent;
71
+ } else if (templateType === 'ml5-hand') {
72
+ htmlContent = ml5HandTrackingTemplate.htmlContent;
73
+ sketchContent = ml5HandTrackingTemplate.sketchContent;
74
+ randomContent = ml5HandTrackingTemplate.randomContent;
75
+ selectedPackageJson = ml5HandTrackingPackageJsonContent;
55
76
  } else {
56
- throw new Error('Unknown template type');
77
+ throw new Error('Unknown template type. Available templates: default, svg, three, glsl, ml5-hand');
57
78
  }
58
79
 
59
80
  // Create index.html
@@ -61,33 +82,61 @@ async function createProject() {
61
82
 
62
83
  // Create package.json
63
84
  const packageJsonPath = path.join(folderPath, 'package.json');
64
- const packageJson = packageJsonContent.replace(/"project-name"/, `"${folderName}"`);
85
+ const packageJson = selectedPackageJson.replace(/"project-name"/, `"${folderName}"`);
65
86
  await fs.writeFile(packageJsonPath, packageJson.trim());
66
87
 
67
- // Install dependencies
68
- console.log('Installing dependencies...');
69
- execSync('npm install -s', { cwd: folderPath, stdio: 'inherit' });
70
-
71
- // Check if p5.min.js exists and copy it to the scripts folder
72
- const p5Path = path.join(__dirname, 'node_modules', 'p5', 'lib', 'p5.min.js');
73
- if (await fs.pathExists(p5Path)) {
74
- await fs.copyFile(p5Path, path.join(scriptsPath, 'p5.js'));
75
- console.log('p5.js copied successfully.');
88
+ // Install dependencies
89
+ console.log('Installing dependencies...');
90
+ execSync('npm install -s', { cwd: folderPath, stdio: 'inherit' });
91
+
92
+ // Copy the appropriate library to the scripts folder
93
+ if (templateType === 'svg') {
94
+ // Copy paper.js for SVG template
95
+ const paperPath = path.join(__dirname, 'node_modules', 'paper', 'dist', 'paper-full.js');
96
+ if (await fs.pathExists(paperPath)) {
97
+ await fs.copyFile(paperPath, path.join(scriptsPath, 'paper-full.js'));
98
+ console.log('paper.js copied successfully.');
99
+ } else {
100
+ throw new Error(`paper-full.js not found at ${paperPath}`);
101
+ }
102
+ } else if (templateType === 'three') {
103
+ // Copy three.js module for Three.js template
104
+ const threePath = path.join(__dirname, 'node_modules', 'three', 'build', 'three.module.js');
105
+ if (await fs.pathExists(threePath)) {
106
+ await fs.copyFile(threePath, path.join(scriptsPath, 'three.module.js'));
107
+ console.log('three.js copied successfully.');
108
+ } else {
109
+ throw new Error(`three.module.js not found at ${threePath}`);
110
+ }
111
+ } else if (templateType === 'glsl') {
112
+ // GLSL template uses native WebGL, no external library needed
113
+ console.log('GLSL template - using native WebGL (no library needed).');
114
+ } else if (templateType === 'ml5-hand') {
115
+ // ML5 template uses CDN, no local library needed
116
+ console.log('ML5 hand tracking template - using ml5.js from CDN.');
76
117
  } else {
77
- throw new Error(`p5.min.js not found at ${p5Path}`);
118
+ // Copy p5.js for default template
119
+ const p5Path = path.join(__dirname, 'node_modules', 'p5', 'lib', 'p5.min.js');
120
+ if (await fs.pathExists(p5Path)) {
121
+ await fs.copyFile(p5Path, path.join(scriptsPath, 'p5.js'));
122
+ console.log('p5.js copied successfully.');
123
+ } else {
124
+ throw new Error(`p5.min.js not found at ${p5Path}`);
125
+ }
78
126
  }
79
127
 
80
128
  // Create sketch.js
81
129
  await fs.writeFile(path.join(scriptsPath, 'sketch.js'), sketchContent.trim());
82
-
83
130
 
84
- // Create random.js
85
- await fs.writeFile(path.join(scriptsPath, 'random.js'), randomContent.trim());
86
-
131
+ // Create random.js
132
+ await fs.writeFile(path.join(scriptsPath, 'random.js'), randomContent.trim());
87
133
 
88
134
  // Create index.html
89
135
  await fs.writeFile(path.join(folderPath, 'index.html'), htmlContent.trim());
90
136
 
137
+ // Create build.js for single-file bundling
138
+ await fs.writeFile(path.join(folderPath, 'build.js'), buildScriptContent.trim());
139
+ console.log('build.js created - run "npm run build" to create a single-file bundle.');
91
140
 
92
141
  console.log(`Project ${folderName} created successfully.`);
93
142
 
package/package.json CHANGED
@@ -1,23 +1,45 @@
1
1
  {
2
2
  "name": "selkie",
3
- "version": "1.0.0",
4
- "description": "Simple generative template creation",
3
+ "version": "1.1.0",
4
+ "description": "CLI for scaffolding generative art projects with p5.js, Paper.js, Three.js, GLSL, and ML5.js",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "bin": {
8
8
  "selkie": "./index.js"
9
9
  },
10
+ "files": [
11
+ "index.js",
12
+ "templates/",
13
+ "package_details.js",
14
+ "README.md"
15
+ ],
10
16
  "scripts": {
11
17
  "test": "echo \"Error: no test specified\" && exit 1"
12
18
  },
13
- "keywords": [],
19
+ "keywords": [
20
+ "generative-art",
21
+ "creative-coding",
22
+ "p5js",
23
+ "paperjs",
24
+ "threejs",
25
+ "glsl",
26
+ "webgl",
27
+ "scaffold",
28
+ "cli"
29
+ ],
14
30
  "author": "generatecoll",
15
31
  "license": "ISC",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/generatecoll/selkie"
35
+ },
16
36
  "dependencies": {
17
37
  "commander": "^12.1.0",
18
38
  "fs-extra": "^11.2.0",
19
39
  "inquirer": "^9.2.22",
20
- "p5": "^1.9.4"
40
+ "p5": "^1.9.4",
41
+ "paper": "^0.12.18",
42
+ "three": "^0.170.0"
21
43
  },
22
44
  "devDependencies": {
23
45
  "live-server": "^1.2.2"
@@ -5,16 +5,95 @@ export const packageJsonContent = `{
5
5
  "description": "",
6
6
  "main": "index.js",
7
7
  "scripts": {
8
- "start": "live-server"
8
+ "start": "live-server",
9
+ "build": "node build.js"
9
10
  },
10
11
  "dependencies": {
11
- "p5": "^1.4.0"
12
+ "p5": "^1.4.0"
12
13
  },
13
14
  "devDependencies": {
14
- "live-server": "^1.2.1"
15
+ "live-server": "^1.2.1",
16
+ "terser": "^5.31.0"
15
17
  },
16
18
  "keywords": [],
17
19
  "author": "",
18
20
  "license": "ISC"
19
- }
20
- `;
21
+ }`;
22
+
23
+ export const svgPackageJsonContent = `{
24
+ "name": "project-name",
25
+ "version": "1.0.0",
26
+ "description": "Paper.js SVG generative art project",
27
+ "main": "index.js",
28
+ "scripts": {
29
+ "start": "live-server",
30
+ "build": "node build.js"
31
+ },
32
+ "dependencies": {
33
+ "paper": "^0.12.18"
34
+ },
35
+ "devDependencies": {
36
+ "live-server": "^1.2.1",
37
+ "terser": "^5.31.0"
38
+ },
39
+ "keywords": ["generative", "svg", "paper.js"],
40
+ "author": "",
41
+ "license": "ISC"
42
+ }`;
43
+
44
+ export const threePackageJsonContent = `{
45
+ "name": "project-name",
46
+ "version": "1.0.0",
47
+ "description": "Three.js 3D generative art project",
48
+ "main": "index.js",
49
+ "scripts": {
50
+ "start": "live-server",
51
+ "build": "node build.js"
52
+ },
53
+ "dependencies": {
54
+ "three": "^0.170.0"
55
+ },
56
+ "devDependencies": {
57
+ "live-server": "^1.2.1",
58
+ "terser": "^5.31.0"
59
+ },
60
+ "keywords": ["generative", "3d", "three.js", "webgl"],
61
+ "author": "",
62
+ "license": "ISC"
63
+ }`;
64
+
65
+ export const glslPackageJsonContent = `{
66
+ "name": "project-name",
67
+ "version": "1.0.0",
68
+ "description": "GLSL WebGL shader project",
69
+ "main": "index.js",
70
+ "scripts": {
71
+ "start": "live-server",
72
+ "build": "node build.js"
73
+ },
74
+ "devDependencies": {
75
+ "live-server": "^1.2.1",
76
+ "terser": "^5.31.0"
77
+ },
78
+ "keywords": ["generative", "glsl", "webgl", "shader"],
79
+ "author": "",
80
+ "license": "ISC"
81
+ }`;
82
+
83
+ export const ml5HandTrackingPackageJsonContent = `{
84
+ "name": "project-name",
85
+ "version": "1.0.0",
86
+ "description": "ML5.js hand tracking project",
87
+ "main": "index.js",
88
+ "scripts": {
89
+ "start": "live-server",
90
+ "build": "node build.js"
91
+ },
92
+ "devDependencies": {
93
+ "live-server": "^1.2.1",
94
+ "terser": "^5.31.0"
95
+ },
96
+ "keywords": ["generative", "ml5", "hand-tracking", "computer-vision"],
97
+ "author": "",
98
+ "license": "ISC"
99
+ }`;