@alaagh/brainkit 2.0.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/CHANGELOG.md ADDED
@@ -0,0 +1,50 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here.
4
+
5
+ ## [2.0.0] - 2026-02-14
6
+
7
+ ### Added
8
+
9
+ - Restructured repository into multi-skill layout with:
10
+ - `skills/*` for source skill folders
11
+ - `skill-artifacts/*.skill` for packaged artifacts
12
+ - Added npm package support under `@alaagh/brainkit`.
13
+ - Added CLI tool `brainkit` with commands for list/manifest/path/install.
14
+ - Added JavaScript API for listing and installing skills.
15
+ - Added comprehensive automated test suite covering API, CLI, build output, and scripts.
16
+ - Added release publish workflow for npm on GitHub release publish.
17
+
18
+ ### Changed
19
+
20
+ - Renamed project/repo identity to `brainkit`.
21
+ - Upgraded CI to run tests on every push and pull request across Node 18/20/22.
22
+
23
+ ### Removed
24
+
25
+ - Removed legacy single-skill root structure.
26
+ - Removed tracked `dist` artifact from repository; build output is generated.
27
+
28
+ ## [1.1.0] - 2026-02-14
29
+
30
+ ### Added
31
+
32
+ - Expanded README with badges, quick start, demo links, and community sections.
33
+ - Added contributor guidance in `CONTRIBUTING.md`.
34
+ - Added MIT `LICENSE`.
35
+ - Added docs set:
36
+ - `docs/DEMO.md`
37
+ - `docs/USE_CASES.md`
38
+ - `docs/API_REFERENCE.md`
39
+ - `docs/LAUNCH_PLAYBOOK.md`
40
+ - `docs/SHOWCASE.md`
41
+ - Added GitHub workflow for skill structure validation.
42
+ - Added issue templates and pull request template.
43
+
44
+ ## [1.0.0] - 2026-02-14
45
+
46
+ ### Added
47
+
48
+ - Initial release of `threejs-performance-optimizer` skill.
49
+ - Reference modules for workflow, render loop, assets/loaders, draw calls, memory, and R3F.
50
+ - Packaged distributable skill artifact.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alaa Alghazouli
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # brainkit
2
+
3
+ [![CI](https://github.com/alaa-alghazouli/brainkit/actions/workflows/ci.yml/badge.svg)](https://github.com/alaa-alghazouli/brainkit/actions/workflows/ci.yml)
4
+ [![Latest Release](https://img.shields.io/github/v/release/alaa-alghazouli/brainkit)](https://github.com/alaa-alghazouli/brainkit/releases)
5
+ [![npm version](https://img.shields.io/npm/v/%40alaagh%2Fbrainkit)](https://www.npmjs.com/package/@alaagh/brainkit)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](./LICENSE)
7
+
8
+ `brainkit` is an installable npm package for AI-ready assets:
9
+
10
+ - skills
11
+ - skill artifacts (`.skill`)
12
+ - tool registry space (future)
13
+
14
+ It currently includes one production skill: `threejs-performance-optimizer`.
15
+
16
+ ## Install with npm
17
+
18
+ ```bash
19
+ npm install @alaagh/brainkit
20
+ ```
21
+
22
+ ## Install the skill
23
+
24
+ 1. List available skills:
25
+
26
+ ```bash
27
+ npx brainkit list
28
+ ```
29
+
30
+ 2. Install the packaged skill artifact:
31
+
32
+ ```bash
33
+ npx brainkit install threejs-performance-optimizer --dest ~/.config/opencode/skills
34
+ ```
35
+
36
+ This creates:
37
+
38
+ `~/.config/opencode/skills/threejs-performance-optimizer.skill`
39
+
40
+ 3. Optional: install source folder instead of `.skill` artifact:
41
+
42
+ ```bash
43
+ npx brainkit install threejs-performance-optimizer --mode source --dest ~/.config/opencode/skills
44
+ ```
45
+
46
+ ## CLI quick reference
47
+
48
+ ```bash
49
+ brainkit list
50
+ brainkit manifest
51
+ brainkit catalog
52
+ brainkit where threejs-performance-optimizer
53
+ brainkit install <skill|all> --dest <path> [--mode artifact|source]
54
+ ```
55
+
56
+ ## JavaScript API
57
+
58
+ ```js
59
+ import { listSkills, installSkill } from "@alaagh/brainkit";
60
+
61
+ const skills = listSkills();
62
+ await installSkill("threejs-performance-optimizer", "./local-skills");
63
+ ```
64
+
65
+ ## What is included today
66
+
67
+ - `threejs-performance-optimizer`: profile-first optimization playbook for Three.js and React Three Fiber performance.
68
+
69
+ ## Repository layout
70
+
71
+ - `skills/` source skills
72
+ - `skill-artifacts/` packaged `.skill` files
73
+ - `tools/` AI tool metadata and future tool bundles
74
+ - `src/` package API and CLI implementation
75
+ - `scripts/` build and validation scripts
76
+ - `tests/` API, CLI, build, and script tests
77
+
78
+ ## Development
79
+
80
+ ```bash
81
+ npm install
82
+ npm test
83
+ ```
84
+
85
+ ## Contributing
86
+
87
+ See `CONTRIBUTING.md`.
package/dist/cli.js ADDED
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {
4
+ getManifest,
5
+ getSkillArtifactPath,
6
+ getSkillSourcePath,
7
+ getToolsManifest,
8
+ installAll,
9
+ installSkill,
10
+ listSkills,
11
+ } from "./index.js";
12
+
13
+ function parseOptions(argv) {
14
+ const options = {
15
+ mode: "artifact",
16
+ };
17
+
18
+ for (let index = 0; index < argv.length; index += 1) {
19
+ const token = argv[index];
20
+
21
+ if (token === "--dest") {
22
+ options.dest = argv[index + 1];
23
+ index += 1;
24
+ continue;
25
+ }
26
+
27
+ if (token === "--mode") {
28
+ options.mode = argv[index + 1];
29
+ index += 1;
30
+ continue;
31
+ }
32
+ }
33
+
34
+ return options;
35
+ }
36
+
37
+ function printHelp() {
38
+ console.log(`brainkit CLI
39
+
40
+ Usage:
41
+ brainkit list
42
+ brainkit catalog
43
+ brainkit manifest
44
+ brainkit where <skill> [--mode artifact|source]
45
+ brainkit install <skill|all> --dest <path> [--mode artifact|source]
46
+
47
+ Examples:
48
+ brainkit list
49
+ brainkit catalog
50
+ brainkit install threejs-performance-optimizer --dest ~/.config/opencode/skills
51
+ brainkit install all --mode source --dest ./local-skills
52
+ `);
53
+ }
54
+
55
+ async function run() {
56
+ const argv = process.argv.slice(2);
57
+ const command = argv[0];
58
+
59
+ if (
60
+ !command ||
61
+ command === "help" ||
62
+ command === "--help" ||
63
+ command === "-h"
64
+ ) {
65
+ printHelp();
66
+ return;
67
+ }
68
+
69
+ if (command === "list") {
70
+ const skills = listSkills();
71
+ for (const skill of skills) {
72
+ console.log(skill);
73
+ }
74
+ return;
75
+ }
76
+
77
+ if (command === "manifest") {
78
+ console.log(JSON.stringify(getManifest(), null, 2));
79
+ return;
80
+ }
81
+
82
+ if (command === "catalog") {
83
+ const manifest = getManifest();
84
+ const tools = getToolsManifest();
85
+
86
+ console.log(
87
+ JSON.stringify(
88
+ {
89
+ version: 1,
90
+ skills: manifest.skills,
91
+ tools: tools.tools,
92
+ },
93
+ null,
94
+ 2,
95
+ ),
96
+ );
97
+ return;
98
+ }
99
+
100
+ if (command === "where") {
101
+ const skillName = argv[1];
102
+ if (!skillName) {
103
+ throw new Error('Skill name is required for "where" command.');
104
+ }
105
+
106
+ const options = parseOptions(argv.slice(2));
107
+ if (options.mode === "source") {
108
+ console.log(getSkillSourcePath(skillName));
109
+ return;
110
+ }
111
+
112
+ console.log(getSkillArtifactPath(skillName));
113
+ return;
114
+ }
115
+
116
+ if (command === "install") {
117
+ const skillName = argv[1];
118
+ if (!skillName) {
119
+ throw new Error('Skill name is required for "install" command.');
120
+ }
121
+
122
+ const options = parseOptions(argv.slice(2));
123
+ if (!options.dest) {
124
+ throw new Error("Destination path is required. Use --dest <path>.");
125
+ }
126
+
127
+ if (!["artifact", "source"].includes(options.mode)) {
128
+ throw new Error("Invalid mode. Use --mode artifact or --mode source.");
129
+ }
130
+
131
+ if (skillName === "all") {
132
+ const results = await installAll(options.dest, { mode: options.mode });
133
+ for (const result of results) {
134
+ console.log(`${result.skill} -> ${result.outputPath}`);
135
+ }
136
+ return;
137
+ }
138
+
139
+ const result = await installSkill(skillName, options.dest, {
140
+ mode: options.mode,
141
+ });
142
+ console.log(`${result.skill} -> ${result.outputPath}`);
143
+ return;
144
+ }
145
+
146
+ throw new Error(`Unknown command: ${command}`);
147
+ }
148
+
149
+ run().catch((error) => {
150
+ console.error(error.message);
151
+ process.exitCode = 1;
152
+ });
@@ -0,0 +1,50 @@
1
+ export type InstallMode = "artifact" | "source";
2
+
3
+ export interface InstallOptions {
4
+ mode?: InstallMode;
5
+ }
6
+
7
+ export interface InstallResult {
8
+ skill: string;
9
+ mode: InstallMode;
10
+ outputPath: string;
11
+ }
12
+
13
+ export interface SkillManifestEntry {
14
+ slug: string;
15
+ name?: string;
16
+ description?: string;
17
+ version?: string;
18
+ }
19
+
20
+ export interface SkillManifest {
21
+ version: number;
22
+ skills: SkillManifestEntry[];
23
+ }
24
+
25
+ export interface ToolManifestEntry {
26
+ slug: string;
27
+ name?: string;
28
+ description?: string;
29
+ version?: string;
30
+ }
31
+
32
+ export interface ToolManifest {
33
+ version: number;
34
+ tools: ToolManifestEntry[];
35
+ }
36
+
37
+ export function listSkills(): string[];
38
+ export function getManifest(): SkillManifest;
39
+ export function getToolsManifest(): ToolManifest;
40
+ export function getSkillSourcePath(skillName: string): string;
41
+ export function getSkillArtifactPath(skillName: string): string;
42
+ export function installSkill(
43
+ skillName: string,
44
+ destination: string,
45
+ options?: InstallOptions,
46
+ ): Promise<InstallResult>;
47
+ export function installAll(
48
+ destination: string,
49
+ options?: InstallOptions,
50
+ ): Promise<InstallResult[]>;
package/dist/index.js ADDED
@@ -0,0 +1,153 @@
1
+ import {
2
+ cpSync,
3
+ copyFileSync,
4
+ existsSync,
5
+ mkdirSync,
6
+ readdirSync,
7
+ readFileSync,
8
+ } from "node:fs";
9
+ import path from "node:path";
10
+ import { fileURLToPath } from "node:url";
11
+
12
+ const moduleDirectory = fileURLToPath(new URL(".", import.meta.url));
13
+ const localSkillsDir = path.join(moduleDirectory, "skills");
14
+ const localArtifactsDir = path.join(moduleDirectory, "skill-artifacts");
15
+ const dataRoot =
16
+ existsSync(localSkillsDir) && existsSync(localArtifactsDir)
17
+ ? moduleDirectory
18
+ : path.resolve(moduleDirectory, "..");
19
+
20
+ const skillsDir = path.join(dataRoot, "skills");
21
+ const artifactsDir = path.join(dataRoot, "skill-artifacts");
22
+ const manifestPath = path.join(skillsDir, "manifest.json");
23
+ const toolsManifestPath = path.join(dataRoot, "tools", "manifest.json");
24
+ const validInstallModes = new Set(["artifact", "source"]);
25
+
26
+ function ensureDirectoryExists(directoryPath, label) {
27
+ if (!existsSync(directoryPath)) {
28
+ throw new Error(`${label} not found: ${directoryPath}`);
29
+ }
30
+ }
31
+
32
+ function resolveDestination(destination) {
33
+ if (!destination) {
34
+ throw new Error("Destination path is required.");
35
+ }
36
+
37
+ const absolutePath = path.resolve(destination);
38
+ mkdirSync(absolutePath, { recursive: true });
39
+ return absolutePath;
40
+ }
41
+
42
+ function assertSkillExists(skillName) {
43
+ const availableSkills = listSkills();
44
+ if (!availableSkills.includes(skillName)) {
45
+ throw new Error(
46
+ `Unknown skill: ${skillName}. Available skills: ${availableSkills.join(", ")}`,
47
+ );
48
+ }
49
+ }
50
+
51
+ function resolveInstallMode(mode) {
52
+ const installMode = mode ?? "artifact";
53
+
54
+ if (!validInstallModes.has(installMode)) {
55
+ throw new Error(
56
+ `Invalid mode: ${installMode}. Use \"artifact\" or \"source\".`,
57
+ );
58
+ }
59
+
60
+ return installMode;
61
+ }
62
+
63
+ export function listSkills() {
64
+ ensureDirectoryExists(skillsDir, "Skills directory");
65
+
66
+ const entries = readdirSync(skillsDir, { withFileTypes: true });
67
+ return entries
68
+ .filter((entry) => entry.isDirectory())
69
+ .map((entry) => entry.name)
70
+ .sort();
71
+ }
72
+
73
+ export function getManifest() {
74
+ if (!existsSync(manifestPath)) {
75
+ return {
76
+ version: 1,
77
+ skills: listSkills().map((skillName) => ({
78
+ slug: skillName,
79
+ })),
80
+ };
81
+ }
82
+
83
+ return JSON.parse(readFileSync(manifestPath, "utf8"));
84
+ }
85
+
86
+ export function getToolsManifest() {
87
+ if (!existsSync(toolsManifestPath)) {
88
+ return {
89
+ version: 1,
90
+ tools: [],
91
+ };
92
+ }
93
+
94
+ return JSON.parse(readFileSync(toolsManifestPath, "utf8"));
95
+ }
96
+
97
+ export function getSkillSourcePath(skillName) {
98
+ assertSkillExists(skillName);
99
+ return path.join(skillsDir, skillName);
100
+ }
101
+
102
+ export function getSkillArtifactPath(skillName) {
103
+ assertSkillExists(skillName);
104
+ ensureDirectoryExists(artifactsDir, "Skill artifacts directory");
105
+
106
+ const artifactPath = path.join(artifactsDir, `${skillName}.skill`);
107
+ if (!existsSync(artifactPath)) {
108
+ throw new Error(`Missing artifact for ${skillName}: ${artifactPath}`);
109
+ }
110
+
111
+ return artifactPath;
112
+ }
113
+
114
+ export async function installSkill(skillName, destination, options = {}) {
115
+ const mode = resolveInstallMode(options.mode);
116
+ const outputDirectory = resolveDestination(destination);
117
+
118
+ if (mode === "source") {
119
+ const sourcePath = getSkillSourcePath(skillName);
120
+ const targetPath = path.join(outputDirectory, skillName);
121
+
122
+ cpSync(sourcePath, targetPath, { recursive: true, force: true });
123
+
124
+ return {
125
+ skill: skillName,
126
+ mode,
127
+ outputPath: targetPath,
128
+ };
129
+ }
130
+
131
+ const artifactPath = getSkillArtifactPath(skillName);
132
+ const targetPath = path.join(outputDirectory, `${skillName}.skill`);
133
+
134
+ copyFileSync(artifactPath, targetPath);
135
+
136
+ return {
137
+ skill: skillName,
138
+ mode,
139
+ outputPath: targetPath,
140
+ };
141
+ }
142
+
143
+ export async function installAll(destination, options = {}) {
144
+ const skills = listSkills();
145
+ const installations = [];
146
+
147
+ for (const skillName of skills) {
148
+ const result = await installSkill(skillName, destination, options);
149
+ installations.push(result);
150
+ }
151
+
152
+ return installations;
153
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": 1,
3
+ "skills": [
4
+ {
5
+ "slug": "threejs-performance-optimizer",
6
+ "name": "Threejs Performance Optimizer",
7
+ "description": "Profile-first optimization workflow for Three.js and React Three Fiber performance.",
8
+ "version": "1.1.0",
9
+ "artifact": "threejs-performance-optimizer.skill",
10
+ "source": "skills/threejs-performance-optimizer"
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: threejs-performance-optimizer
3
+ description: Optimize and refactor Three.js and React Three Fiber code for runtime performance, memory efficiency, loading speed, and rendering quality using a profile-first workflow grounded in current Three.js and R3F docs. Use when requests mention low FPS, frame drops, stutter/jank, high draw calls, heavy post-processing, shadow cost, large GLB/texture payloads, mobile 3D slowness, memory leaks, dispose/cleanup issues, WebGPU or WebGL fallback concerns, frameloop demand/invalidate patterns, instancing, batching, LOD, or general Three.js performance tuning.
4
+ ---
5
+
6
+ # Threejs Performance Optimizer
7
+
8
+ Optimize performance by measurement, not folklore. Prioritize high-impact changes, preserve visual intent, and avoid stale APIs.
9
+
10
+ ## Core Behavior
11
+
12
+ Follow this sequence every time:
13
+
14
+ 1. Measure baseline first.
15
+ 2. Classify the bottleneck (CPU, GPU, memory, or loading).
16
+ 3. Apply one focused optimization pass.
17
+ 4. Re-measure and keep only verified improvements.
18
+
19
+ Never start by rewriting everything. Prefer the smallest change that hits the biggest bottleneck.
20
+
21
+ ## Reference Loading Order
22
+
23
+ Read references in this order and stop when enough context is collected:
24
+
25
+ 1. `references/performance-workflow.md` for triage and reporting structure.
26
+ 2. `references/renderer-and-loop-patterns.md` for render loop and renderer choices.
27
+ 3. `references/assets-and-loaders.md` for asset and decoder/transcoder pipeline.
28
+ 4. `references/draw-calls-materials-lighting.md` for scene/render cost tuning.
29
+ 5. `references/memory-and-disposal.md` for leaks, cleanup, and update flags.
30
+ 6. `references/r3f-rules.md` when code uses React Three Fiber.
31
+ 7. `references/outdated-guidance.md` before finalizing recommendations.
32
+
33
+ ## Mandatory Workflow
34
+
35
+ ### 1) Measure
36
+
37
+ Collect at least:
38
+
39
+ - FPS or frame time trend.
40
+ - Draw calls and triangles (`renderer.info`).
41
+ - Memory trend for textures/geometries/programs.
42
+ - Main-thread and GPU hotspots from profiler.
43
+
44
+ If performance metrics are missing, request them or add lightweight instrumentation.
45
+
46
+ ### 2) Classify
47
+
48
+ Classify the primary bottleneck before prescribing fixes:
49
+
50
+ - CPU-bound: heavy JS/React work, allocations, simulation, or scene graph churn.
51
+ - GPU-bound: high draw call count, expensive shaders/lights/shadows/postprocessing.
52
+ - Memory-bound: growing texture/geometry/render-target counts, context pressure.
53
+ - Load-time bound: large payloads, slow decode/transcode, blocking startup work.
54
+
55
+ ### 3) Fix in ROI Order
56
+
57
+ Use this order unless data proves otherwise:
58
+
59
+ 1. Asset payload and decode pipeline.
60
+ 2. Draw call reduction (instancing, batching, static merges).
61
+ 3. Render loop policy (on-demand and adaptive DPR where suitable).
62
+ 4. Lighting/shadow/postprocessing cost.
63
+ 5. Memory lifecycle and disposal correctness.
64
+
65
+ ### 4) Verify and Report
66
+
67
+ Report:
68
+
69
+ - What changed.
70
+ - Expected impact.
71
+ - Measured before/after.
72
+ - Tradeoffs and rollback criteria.
73
+
74
+ ## Non-Negotiable Rules
75
+
76
+ - Prefer official, current APIs over old blog snippets.
77
+ - Treat hard numeric targets as heuristics, not universal truths.
78
+ - Keep static scenes from rendering continuously when not needed.
79
+ - Avoid per-frame object allocation in hot paths.
80
+ - Explicitly dispose resources no longer needed.
81
+ - Keep anti-aliasing strategy profile-driven, not dogmatic.
82
+
83
+ ## Hard Anti-Rules
84
+
85
+ - Do not use deprecated renderer APIs in recommendations.
86
+ - Do not claim guaranteed multipliers (2x, 10x) without measurement.
87
+ - Do not assume removing from scene frees GPU memory.
88
+ - Do not use React state updates for per-frame animation.
89
+ - Do not force one compression or AA approach for all projects.
90
+
91
+ ## Output Contract
92
+
93
+ When delivering optimization advice or edits, always include:
94
+
95
+ 1. Bottleneck diagnosis.
96
+ 2. Ordered action plan.
97
+ 3. Risk notes (visual quality, compatibility, complexity).
98
+ 4. Verification steps and expected metrics movement.
99
+
100
+ Keep recommendations practical, testable, and version-safe.
@@ -0,0 +1,100 @@
1
+ # Assets and Loaders
2
+
3
+ ## Table of Contents
4
+
5
+ - Asset Strategy
6
+ - CLI Pipeline
7
+ - Loader Wiring
8
+ - Compression Choices
9
+ - Loading UX
10
+
11
+ ## Asset Strategy
12
+
13
+ Prefer glTF/GLB for runtime delivery.
14
+
15
+ Apply optimizations in this order:
16
+
17
+ 1. Remove unnecessary geometry and textures at source.
18
+ 2. Compress geometry (Draco or Meshopt).
19
+ 3. Compress textures (KTX2 Basis ETC1S or UASTC).
20
+ 4. Verify visual quality and decode cost on target devices.
21
+
22
+ ## CLI Pipeline
23
+
24
+ Use inspection before optimization:
25
+
26
+ ```bash
27
+ gltf-transform inspect input.glb
28
+ ```
29
+
30
+ Use a baseline optimization pass:
31
+
32
+ ```bash
33
+ gltf-transform optimize input.glb output.glb --compress draco --texture-compress webp
34
+ ```
35
+
36
+ Use KTX2 workflows when GPU texture compression is needed:
37
+
38
+ ```bash
39
+ gltf-transform etc1s input.glb output-etc1s.glb
40
+ gltf-transform uastc input.glb output-uastc.glb
41
+ ```
42
+
43
+ For R3F projects, consider:
44
+
45
+ ```bash
46
+ npx gltfjsx model.glb -S -T -t
47
+ ```
48
+
49
+ ## Loader Wiring
50
+
51
+ Configure shared loaders once and reuse instances:
52
+
53
+ ```js
54
+ import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
55
+ import { DRACOLoader } from "three/addons/loaders/DRACOLoader.js";
56
+ import { KTX2Loader } from "three/addons/loaders/KTX2Loader.js";
57
+
58
+ const draco = new DRACOLoader().setDecoderPath("/draco/");
59
+ const ktx2 = new KTX2Loader()
60
+ .setTranscoderPath("/basis/")
61
+ .detectSupport(renderer);
62
+
63
+ const gltfLoader = new GLTFLoader().setDRACOLoader(draco).setKTX2Loader(ktx2);
64
+ ```
65
+
66
+ Important loader rules:
67
+
68
+ - Call `detectSupport(renderer)` before KTX2 loads.
69
+ - Reuse decoder/transcoder instances to avoid repeated startup overhead.
70
+ - Dispose loader internals when the loader is no longer needed.
71
+
72
+ ## Compression Choices
73
+
74
+ Use content-aware defaults:
75
+
76
+ - ETC1S: smaller files, higher compression artifacts.
77
+ - UASTC: higher quality, larger files.
78
+
79
+ Evaluate Draco vs Meshopt per project:
80
+
81
+ - Draco often yields strong geometry compression.
82
+ - Meshopt may decode faster in some scenarios.
83
+
84
+ Always compare:
85
+
86
+ - Network transfer size.
87
+ - Decode/transcode time.
88
+ - Runtime memory.
89
+ - Visual quality.
90
+
91
+ ## Loading UX
92
+
93
+ Improve startup behavior:
94
+
95
+ - Preload only above-the-fold critical assets.
96
+ - Lazy-load offscreen 3D sections.
97
+ - Use placeholder or low-detail proxies while heavy assets load.
98
+ - Stream or chunk large worlds instead of one monolithic load.
99
+
100
+ Treat loading optimization as performance work, not only UX polish.
@@ -0,0 +1,78 @@
1
+ # Draw Calls, Materials, Lighting
2
+
3
+ ## Table of Contents
4
+
5
+ - Draw Call Reduction
6
+ - Geometry Strategy
7
+ - Material Strategy
8
+ - Lighting and Shadows
9
+ - Postprocessing
10
+
11
+ ## Draw Call Reduction
12
+
13
+ Treat draw-call reduction as a primary lever.
14
+
15
+ Use this escalation path:
16
+
17
+ 1. Share materials and geometry where possible.
18
+ 2. Use `InstancedMesh` for repeated objects.
19
+ 3. Use batch or merged static geometry for non-interactive sets.
20
+ 4. Use LOD and distance-based simplification.
21
+
22
+ Use draw-call budgets as heuristics, not hard guarantees. Validate on target devices.
23
+
24
+ ## Geometry Strategy
25
+
26
+ For repeated meshes, prefer instancing:
27
+
28
+ ```js
29
+ const mesh = new THREE.InstancedMesh(geometry, material, count);
30
+ for (let i = 0; i < count; i += 1) {
31
+ mesh.setMatrixAt(i, matrix);
32
+ }
33
+ mesh.instanceMatrix.needsUpdate = true;
34
+ mesh.computeBoundingSphere();
35
+ ```
36
+
37
+ For static scene chunks, consider merged geometry:
38
+
39
+ - Merge by material compatibility.
40
+ - Keep interactable parts separate.
41
+ - Avoid over-merging when per-object behavior is required.
42
+
43
+ ## Material Strategy
44
+
45
+ Control shader variant explosion:
46
+
47
+ - Reuse shared material instances whenever possible.
48
+ - Avoid unnecessary feature toggles at runtime that trigger recompilation.
49
+ - Update uniforms/data values instead of replacing whole materials.
50
+
51
+ Prefer simpler materials where quality permits.
52
+
53
+ ## Lighting and Shadows
54
+
55
+ Use dynamic lights selectively:
56
+
57
+ - Keep active shadow-casting lights minimal.
58
+ - Tighten shadow camera frustums.
59
+ - Use smallest acceptable shadow map sizes.
60
+ - Disable shadow auto-updates for static scenes and trigger only when needed.
61
+
62
+ Point-light shadow cost reminder:
63
+
64
+ - One point light shadow map requires six faces.
65
+ - Cost scales quickly with object count.
66
+
67
+ Prefer environment lighting and baked/static lighting when practical.
68
+
69
+ ## Postprocessing
70
+
71
+ Treat each pass as measurable cost.
72
+
73
+ - Start with the minimal pass chain.
74
+ - Merge compatible effects when possible.
75
+ - Re-test antialiasing strategy per project.
76
+ - Reduce internal effect resolution when quality permits.
77
+
78
+ Avoid rigid recommendations like "always disable native AA" or "always use FXAA". Measure and choose.
@@ -0,0 +1,95 @@
1
+ # Memory and Disposal
2
+
3
+ ## Table of Contents
4
+
5
+ - Disposal Rules
6
+ - Cleanup Patterns
7
+ - Update Flags
8
+ - Bounding Volumes
9
+ - Leak Detection
10
+
11
+ ## Disposal Rules
12
+
13
+ Removing an object from a scene does not free GPU resources.
14
+
15
+ Explicitly dispose resources no longer needed:
16
+
17
+ - `BufferGeometry.dispose()`
18
+ - `Material.dispose()`
19
+ - `Texture.dispose()`
20
+ - `WebGLRenderTarget.dispose()`
21
+ - `Skeleton.dispose()` for unused shared skeletons
22
+
23
+ If texture data uses `ImageBitmap`, close CPU-side data explicitly:
24
+
25
+ ```js
26
+ texture.source.data.close?.();
27
+ texture.dispose();
28
+ ```
29
+
30
+ ## Cleanup Patterns
31
+
32
+ Use a traversal cleanup utility for scene teardown:
33
+
34
+ ```js
35
+ function disposeScene(root) {
36
+ root.traverse((obj) => {
37
+ if (obj.geometry) {
38
+ obj.geometry.dispose();
39
+ }
40
+
41
+ if (!obj.material) {
42
+ return;
43
+ }
44
+
45
+ const materials = Array.isArray(obj.material)
46
+ ? obj.material
47
+ : [obj.material];
48
+ for (const material of materials) {
49
+ for (const key of Object.keys(material)) {
50
+ const value = material[key];
51
+ if (value && value.isTexture) {
52
+ value.dispose();
53
+ }
54
+ }
55
+ material.dispose();
56
+ }
57
+ });
58
+ }
59
+ ```
60
+
61
+ Dispose loader internals or worker resources when loader lifecycle ends.
62
+
63
+ ## Update Flags
64
+
65
+ Use update flags only when required:
66
+
67
+ - Buffer attribute changes: `attribute.needsUpdate = true`
68
+ - Texture content changes: `texture.needsUpdate = true`
69
+ - Material feature or define changes: `material.needsUpdate = true`
70
+
71
+ For static objects, disable automatic matrix updates:
72
+
73
+ ```js
74
+ object.matrixAutoUpdate = false;
75
+ object.updateMatrix();
76
+ ```
77
+
78
+ ## Bounding Volumes
79
+
80
+ Recompute bounds after structural data updates:
81
+
82
+ - Geometry vertex changes: `computeBoundingBox()` and `computeBoundingSphere()`
83
+ - Instanced transforms update: `instancedMesh.computeBoundingBox()` and `computeBoundingSphere()`
84
+
85
+ Accurate bounds protect culling and interaction correctness.
86
+
87
+ ## Leak Detection
88
+
89
+ Track `renderer.info` over repeated scene mount/unmount cycles:
90
+
91
+ - `renderer.info.memory.textures`
92
+ - `renderer.info.memory.geometries`
93
+ - `renderer.info.programs`
94
+
95
+ Stable plateaus are normal. Monotonic growth under repeated teardown/rebuild indicates leaks.
@@ -0,0 +1,25 @@
1
+ # Outdated Guidance Guardrails
2
+
3
+ Use this table to avoid stale recommendations.
4
+
5
+ | Avoid this guidance | Why | Use this instead |
6
+ | ----------------------------------------------------------- | ------------------------------------- | ------------------------------------------------------------------------- |
7
+ | "Use `renderAsync()` in the main loop" | Deprecated in current renderer docs | Use `setAnimationLoop()` with `render()` and explicit compute workflow |
8
+ | "Use `gammaFactor` / `outputEncoding` as default advice" | Legacy color pipeline terminology | Use current color-space workflow and current renderer properties |
9
+ | "`Geometry` / `BoxBufferGeometry` naming as modern default" | Legacy naming and old-era examples | Use current geometry APIs and confirm version-specific docs |
10
+ | "All textures must be power-of-two" | Too absolute for modern contexts | Prefer POT for compatibility/perf-sensitive paths; profile and validate |
11
+ | "Always disable native MSAA and use FXAA/SMAA" | Highly scene/device dependent | Compare native AA vs post AA using measurements |
12
+ | "Always keep under 100 draw calls" | Useful heuristic, not universal rule | Use target-device budgets and verify frame stability |
13
+ | "Removing mesh from scene frees memory" | Incorrect resource lifecycle model | Explicitly call `dispose()` on geometry/material/texture/targets |
14
+ | "Use React state for per-frame animation" | Causes re-render overhead and jank | Mutate refs in `useFrame`, use state for coarse events |
15
+ | "Always migrate to WebGPU now" | Context-dependent project constraints | Evaluate project requirements, browser/device support, and measured gains |
16
+
17
+ ## Source Confidence Priority
18
+
19
+ Prefer recommendations in this order:
20
+
21
+ 1. Current official docs and API reference.
22
+ 2. Official manuals and examples.
23
+ 3. Community articles and blog heuristics.
24
+
25
+ When community advice conflicts with official docs, prioritize docs and annotate the conflict.
@@ -0,0 +1,99 @@
1
+ # Performance Workflow
2
+
3
+ ## Table of Contents
4
+
5
+ - Baseline Checklist
6
+ - Bottleneck Classification
7
+ - Priority Matrix
8
+ - Verification Template
9
+
10
+ ## Baseline Checklist
11
+
12
+ Capture these values before touching code:
13
+
14
+ - Runtime profile: FPS and frame-time variance (average and worst spikes).
15
+ - Renderer stats: `renderer.info.render.calls`, triangles, and points.
16
+ - Memory trend: `renderer.info.memory.textures`, geometries, and programs.
17
+ - Startup profile: bundle size, model size, texture payload, decode/transcode duration.
18
+ - Device context: desktop/mobile, GPU class, browser, resolution, DPR.
19
+
20
+ Use at least one user interaction scenario and one idle scenario.
21
+
22
+ ## Bottleneck Classification
23
+
24
+ Use this decision path:
25
+
26
+ 1. Check profiler for long JS tasks or React re-render churn.
27
+ 2. Check draw calls, shader complexity, light/shadow/post stack cost.
28
+ 3. Check memory growth over time in repeated navigation or scene swaps.
29
+ 4. Check network/decode/transcode delays before first interactive frame.
30
+
31
+ Interpretation guide:
32
+
33
+ - CPU-bound indicators:
34
+ - Frequent long tasks.
35
+ - Per-frame allocations.
36
+ - High-frequency state updates.
37
+ - GPU-bound indicators:
38
+ - High draw calls.
39
+ - Heavy transparency, postprocessing, shadow passes.
40
+ - Lower FPS with high DPR and dense scene content.
41
+ - Memory-bound indicators:
42
+ - Steadily growing texture/geometry counts.
43
+ - Context loss or large spikes during scene transitions.
44
+ - Load-time bound indicators:
45
+ - Long time-to-first-render.
46
+ - Large GLB and texture payloads.
47
+ - Decoder/transcoder setup errors or delays.
48
+
49
+ ## Priority Matrix
50
+
51
+ Apply fixes in this order unless measurements suggest otherwise.
52
+
53
+ 1. Asset pipeline:
54
+ - Compress geometry and textures.
55
+ - Remove unused assets.
56
+ - Preload only critical resources.
57
+ 2. Draw-call pressure:
58
+ - Instancing and batching.
59
+ - Merge static geometry.
60
+ - Share materials.
61
+ 3. Render-loop policy:
62
+ - On-demand rendering where possible.
63
+ - Adaptive DPR and quality scaling.
64
+ 4. Shading and lighting:
65
+ - Reduce dynamic lights/shadows.
66
+ - Tighten shadow frustums and map sizes.
67
+ - Trim postprocessing passes.
68
+ 5. Memory lifecycle:
69
+ - Dispose obsolete resources.
70
+ - Reuse pooled objects.
71
+
72
+ Heuristic budgets (starting points only):
73
+
74
+ - Draw calls: aim for a few hundred or less on typical target hardware.
75
+ - Dynamic shadowed point lights: keep minimal, each adds substantial pass cost.
76
+ - DPR on mobile: cap aggressively when frame stability drops.
77
+
78
+ Do not treat these as hard rules. Validate against project goals.
79
+
80
+ ## Verification Template
81
+
82
+ Use this response structure after each optimization pass:
83
+
84
+ - Baseline:
85
+ - FPS/frame time:
86
+ - Draw calls:
87
+ - Memory counters:
88
+ - Change applied:
89
+ - What changed:
90
+ - Why it targets the bottleneck:
91
+ - Result:
92
+ - New FPS/frame time:
93
+ - New draw calls:
94
+ - Memory delta:
95
+ - Tradeoffs:
96
+ - Visual impact:
97
+ - Compatibility risk:
98
+ - Complexity cost:
99
+ - Keep or rollback decision:
@@ -0,0 +1,84 @@
1
+ # React Three Fiber Rules
2
+
3
+ ## Table of Contents
4
+
5
+ - Frame Loop Discipline
6
+ - Resource Reuse
7
+ - Rendering Policy
8
+ - Adaptive Quality
9
+ - Strict Anti-Patterns
10
+
11
+ ## Frame Loop Discipline
12
+
13
+ Use mutation in `useFrame` for high-frequency updates.
14
+
15
+ ```jsx
16
+ const ref = useRef();
17
+
18
+ useFrame((_, delta) => {
19
+ ref.current.rotation.y += delta;
20
+ });
21
+ ```
22
+
23
+ Use `delta` for frame-rate independence.
24
+
25
+ Avoid `setState` in `useFrame` or any high-frequency event loop.
26
+
27
+ ## Resource Reuse
28
+
29
+ Reuse geometry/material instances and loaded assets:
30
+
31
+ - Use `useLoader` for cached resource loading.
32
+ - Use memoization for reusable Three.js objects.
33
+ - Prefer visibility toggles over frequent mount/unmount churn.
34
+
35
+ Example:
36
+
37
+ ```jsx
38
+ const geometry = useMemo(() => new THREE.BoxGeometry(), []);
39
+ const material = useMemo(() => new THREE.MeshStandardMaterial(), []);
40
+ ```
41
+
42
+ ## Rendering Policy
43
+
44
+ For mostly static scenes:
45
+
46
+ ```jsx
47
+ <Canvas frameloop="demand" />
48
+ ```
49
+
50
+ Trigger renders when external mutations happen:
51
+
52
+ ```jsx
53
+ const { invalidate } = useThree();
54
+ invalidate();
55
+ ```
56
+
57
+ Attach controls change events to invalidate when needed.
58
+
59
+ ## Adaptive Quality
60
+
61
+ Use `PerformanceMonitor` or equivalent to adapt quality:
62
+
63
+ - Lower DPR on decline.
64
+ - Disable expensive postprocessing first.
65
+ - Apply fallback quality profile if repeated flip-flops occur.
66
+
67
+ Use transitions for expensive UI state updates:
68
+
69
+ ```jsx
70
+ const [isPending, startTransition] = useTransition();
71
+ startTransition(() => {
72
+ setHeavyState(next);
73
+ });
74
+ ```
75
+
76
+ ## Strict Anti-Patterns
77
+
78
+ Avoid these patterns:
79
+
80
+ - `setState` inside `useFrame`.
81
+ - Per-frame object allocation (`new Vector3()` in hot path).
82
+ - Constant remounting of heavy 3D subtrees.
83
+ - Fast pointer-driven transforms through React state.
84
+ - Unbounded postprocessing and DPR at all times.
@@ -0,0 +1,113 @@
1
+ # Renderer and Loop Patterns
2
+
3
+ ## Table of Contents
4
+
5
+ - Renderer Selection
6
+ - WebGPU/WebGL Initialization
7
+ - Render Loop Patterns
8
+ - On-Demand Rendering
9
+ - Adaptive DPR
10
+ - Renderer Flags
11
+
12
+ ## Renderer Selection
13
+
14
+ Use a profile-first selection strategy:
15
+
16
+ - Prefer `WebGPURenderer` for new work when available.
17
+ - Rely on fallback behavior when WebGPU is unavailable.
18
+ - Keep compatibility checks for advanced features.
19
+
20
+ Do not use deprecated renderer methods in new guidance.
21
+
22
+ ## WebGPU/WebGL Initialization
23
+
24
+ ```js
25
+ import { WebGPURenderer } from "three/webgpu";
26
+
27
+ const renderer = new WebGPURenderer({
28
+ antialias: false,
29
+ powerPreference: "high-performance",
30
+ });
31
+ await renderer.init();
32
+ ```
33
+
34
+ Use `forceWebGL: true` only for explicit fallback testing or compatibility debugging.
35
+
36
+ ## Render Loop Patterns
37
+
38
+ Prefer `setAnimationLoop` for continuous rendering cases:
39
+
40
+ ```js
41
+ renderer.setAnimationLoop(() => {
42
+ renderer.render(scene, camera);
43
+ });
44
+ ```
45
+
46
+ Avoid recommending deprecated async render loop APIs.
47
+
48
+ ## On-Demand Rendering
49
+
50
+ Use on-demand rendering for mostly static scenes.
51
+
52
+ Vanilla pattern:
53
+
54
+ ```js
55
+ let renderRequested = false;
56
+
57
+ function render() {
58
+ renderRequested = false;
59
+ renderer.render(scene, camera);
60
+ }
61
+
62
+ function requestRenderIfNotRequested() {
63
+ if (renderRequested) {
64
+ return;
65
+ }
66
+
67
+ renderRequested = true;
68
+ requestAnimationFrame(render);
69
+ }
70
+ ```
71
+
72
+ Hook this to input/resize/loading events.
73
+
74
+ R3F pattern:
75
+
76
+ ```jsx
77
+ <Canvas frameloop="demand" />
78
+ ```
79
+
80
+ ```jsx
81
+ const { invalidate } = useThree();
82
+ controls.addEventListener("change", invalidate);
83
+ ```
84
+
85
+ If damping is enabled, request frames through a guard to avoid redundant scheduling.
86
+
87
+ ## Adaptive DPR
88
+
89
+ Use adaptive DPR when frame stability drops.
90
+
91
+ R3F example:
92
+
93
+ ```jsx
94
+ <PerformanceMonitor
95
+ onIncline={() => setDpr(2)}
96
+ onDecline={() => setDpr(1)}
97
+ flipflops={3}
98
+ onFallback={() => setDpr(1)}
99
+ />
100
+ ```
101
+
102
+ Treat DPR changes as one tool, not a complete fix.
103
+
104
+ ## Renderer Flags
105
+
106
+ Set renderer flags by requirement, not cargo cult defaults:
107
+
108
+ - Disable `alpha` if transparent canvas is not required.
109
+ - Disable `stencil` when unused.
110
+ - Keep `depth` enabled unless the rendering model proves otherwise.
111
+ - Choose antialiasing strategy by profiling native MSAA vs post AA.
112
+
113
+ When using postprocessing, re-check final color-space and tone-mapping pipeline correctness.
@@ -0,0 +1,4 @@
1
+ {
2
+ "version": 1,
3
+ "tools": []
4
+ }
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@alaagh/brainkit",
3
+ "version": "2.0.0",
4
+ "description": "Installable npm bundle of AI skills with CLI and JavaScript API.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "bin": {
15
+ "brainkit": "dist/cli.js"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md",
20
+ "LICENSE",
21
+ "CHANGELOG.md"
22
+ ],
23
+ "scripts": {
24
+ "build": "node scripts/build.mjs",
25
+ "validate:skills": "node scripts/validate-skills.mjs",
26
+ "test": "npm run build && npm run validate:skills && node --test --test-concurrency=1 tests/*.test.mjs",
27
+ "prepare": "npm run build",
28
+ "prepublishOnly": "npm test"
29
+ },
30
+ "keywords": [
31
+ "ai",
32
+ "skills",
33
+ "threejs",
34
+ "react-three-fiber",
35
+ "webgl",
36
+ "webgpu",
37
+ "performance",
38
+ "llm",
39
+ "codex"
40
+ ],
41
+ "author": "Alaa Alghazouli",
42
+ "license": "MIT",
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git+https://github.com/alaa-alghazouli/brainkit.git"
46
+ },
47
+ "bugs": {
48
+ "url": "https://github.com/alaa-alghazouli/brainkit/issues"
49
+ },
50
+ "homepage": "https://github.com/alaa-alghazouli/brainkit#readme",
51
+ "engines": {
52
+ "node": ">=18"
53
+ },
54
+ "publishConfig": {
55
+ "access": "public"
56
+ }
57
+ }