engine
AGENTS.md17k starsChanged 11 days agoMITView on GitHub
This document contains rules, conventions, and best practices for AI agents and developers working on the PlayCanvas Engine codebase. PlayCanvas is an open-source WebGL/WebGPU game engine written in JavaScript. It's a performance-critical library used by thousands of developers worldwide. The codebase follows a strict hierarchical structure to maintain clean architecture: Rules: - Lower-level modules cannot import from higher-level modules - Lower-level modules cannot use instances from higher-level modules - Example: core/ cannot import from platform/, scene/, or framework/ - Example:…
Trending
More talk lately.about the whole repository
Who's talking about playcanvas/engine
- Gamefromscratch“PlayCanvas Turns 1.0! Open Source 3D HTML5 Game Engine Is All Grown Up”YouTube · Apr 25, 2018 · 24k views
- PlayCanvas“Introducing SuperSplat Studio”YouTube · Feb 11, 2026 · 16k views
- PlayCanvas“PlayCanvas Engine 2.20.0: Gaussian Splatting Upgrade & WebXR on WebGPU”YouTube · Jun 24, 2026 · 3k views
- PlayCanvas“Introducing the PlayCanvas Examples Browser”YouTube · Jul 16, 2021 · 2.4k views
- TechyGirl“Build 3D Games in Your Browser for FREE! 🤯 (PlayCanvas Engine)”YouTube · Aug 8, 2026 · 2k views
The biggest 5 of 90 mentions linking to the repository that our crawl found. Each line is their own headline.
See all 90
Talked about on GitHub, YouTube, Bluesky, Hacker News and the web (90 times).
On GitHub · 50
- Oct 3, 2023WebXR — web-platform-tests/interop38 reactions · 3 comments
- Jul 3, 2025[RFC] Exposing Editor ESM Scripts — playcanvas/editor6 reactions · 12 comments
- Jun 1, 2020Expose Clear Coat properties of StandardMaterial. — playcanvas/editor4 reactions · 1 comment
- Sep 21, 2017GLSL 1.0 to 3.0 — mrdoob/three.js4 reactions · 8 comments
- Sep 4, 2025Validate against reserved script names when creating a script — playcanvas/editor3 reactions · 1 comment
45 more on GitHub
- Aug 5, 2023feat: spine 4.1 plugin support — playcanvas/playcanvas-spine3 reactions · 19 comments
- Oct 28, 2026SOG format v3 proposal — playcanvas/splat-transform2 reactions · 8 comments
- Oct 7, 2026PlayCanvas engine support (`3d-tiles-renderer/playcanvas`) — NASA-AMMOS/3DTilesRendererJS2 reactions · 3 comments
- Mar 4, 2024Import 'playcanvas' in ESM Scripts — playcanvas/editor2 reactions · 3 comments
- Aug 16, 2023onUpdate, onComplete, onLoop methods instead of events — playcanvas/playcanvas-tween2 reactions · 1 comment
- Dec 31, 2020Expose Area Lights in editor — playcanvas/editor2 reactions · 2 comments
- Nov 11, 20262026-11-12|SuperSplat 3.8.0、Viewer 1.43.1 与 Spirula 性能更新 — Shuang-su/metaflow-horizon1 reaction · 1 comment
- Nov 6, 20262026-11-07|SOG v3 进入 PlayCanvas Engine,GSL v1.7 与 InstantHand 可测 — Shuang-su/metaflow-horizon1 reaction · 1 comment
- Feb 20, 2026[KHR_gaussian_splatting] Proposal to specify anti-aliasing filter — KhronosGroup/glTF1 reaction · 12 comments
- Dec 23, 2025fix: Do not `applyProps` if value has not changed — playcanvas/react1 reaction · 3 comments
- Nov 19, 2025Add vertexColorGamma attribute to StandardMaterial — playcanvas/editor1 reaction · 4 comments
- Nov 5, 2025Remove RenderTarget copy for splat sorting now that engine PR has been merged — playcanvas/supersplat1 reaction
- Sep 25, 2025feat(inspector): Add preview for templates in the inspector — playcanvas/editor1 reaction · 3 comments
- Sep 10, 2025Gizmos settings — playcanvas/editor1 reaction · 4 comments
- May 19, 2025Support anti-aliased PLY files — playcanvas/supersplat1 reaction · 3 comments
- Apr 7, 2025Add support for WebGPU — playcanvas/supersplat1 reaction · 3 comments
- Mar 11, 2025Include a section on MeshInstance.drawBucket — playcanvas/developer-site1 reaction
- Feb 29, 2024[RFC] ESM bundling — playcanvas/editor1 reaction · 4 comments
- Feb 29, 2024First-class support for import maps — playcanvas/editor1 reaction · 3 comments
- Nov 13, 2023Add report mode: never (spam, once and never) — kungfooman/RuntimeTypeInspector.js1 reaction
- Aug 26, 2023ES6 Compatibility — playcanvas/playcanvas-spine1 reaction · 6 comments
- Aug 25, 2023chore(build): replace Grunt with Rollup — playcanvas/playcanvas-spine1 reaction · 2 comments
- Apr 24, 2023Expose debug rendering functionality — playcanvas/editor1 reaction · 6 comments
- Sep 1, 2021Expose Ambient Occlusion and Soft Shadow baking in the Editor — playcanvas/editor1 reaction · 2 comments
- Jun 21, 2021Added support for `hideconstructor` tag — playcanvas/playcanvas-jsdoc-template1 reaction · 2 comments
- Jul 27, 2020Remove engine sources and update callbacks for engine change — playcanvas/model-viewer1 reaction
- Jun 1, 2020Expose GGX Anisotropic properties of StandardMaterial — playcanvas/editor1 reaction · 8 comments
- May 27, 2020Expose 'cone' collision type in collision component UI — playcanvas/editor1 reaction · 1 comment
- Nov 18, 2019Memory leaks when destroying objects. Remaining __cache__ references? — kripken/ammo.js1 reaction · 13 comments
- Dec 7, 2018Updated spine plugin to match v1.10.7 PlayCanvas change of "Component… — playcanvas/playcanvas-spine1 reaction
- Nov 13, 2026Bump the npm-mocks group in /Source Files/Mocks with 15 updates — cmahnke/christianmahnke0 reactions
- Nov 13, 2026chore(deps-dev): bump playcanvas from 2.21.4 to 2.24.0 — CodeByKeegan/splat-studio0 reactions
- Nov 12, 2026Anim component does not expose offscreenUpdate and evaluationInterval (engine 2.25) — playcanvas/editor0 reactions
- Nov 11, 2026docs: link the formats to their repositories in the README — playcanvas/create-playcanvas0 reactions
- Nov 9, 2026chore(deps)(deps): Bump the js-minor-patch group across 1 directory with 10 updates — mickyarun/glideship0 reactions · 1 comment
- Nov 9, 2026build(deps): bump the npm-runtime group across 1 directory with 5 updates — ydngemini/oracle-cinematic0 reactions · 1 comment
- Nov 9, 2026build(deps): Bump the runtime group with 7 updates — MeteSr/HomeGentic0 reactions · 1 comment
- Nov 2, 2026chore(deps)(deps): Bump the frontend-minor-patch group across 1 directory with 7 updates — mickyarun/glideship0 reactions · 4 comments
- Nov 1, 2026Bump playcanvas from 2.23.0 to 2.23.3 — epreston/template-web-playcanvas0 reactions
- Oct 23, 2026chore(deps): bump playcanvas from 2.23.2 to 2.23.3 — AI-WonderLand1/NPC-AI-SIM0 reactions
- Oct 23, 2026chore(deps-dev): bump playcanvas from 2.21.4 to 2.23.3 — CodeByKeegan/splat-studio0 reactions · 1 comment
- Oct 21, 2026Bump playcanvas from 2.8.2 to 2.23.3 — girish-kor/playcanvas-react-tailwind-template0 reactions
- Oct 19, 2026build(deps): bump playcanvas from 2.22.0 to 2.23.3 in /app4-dashboard/frontend — olivelb/DroneAI0 reactions · 2 comments
- Oct 18, 2026chore(deps): bump the npm-production group with 13 updates — seedlands-game/seedlands-web-sandbox0 reactions
- Oct 16, 2026chore(deps): bump playcanvas from 2.22.6 to 2.23.2 — AI-WonderLand1/NPC-AI-SIM0 reactions
On YouTube · 22
- Apr 25, 2018PlayCanvas Turns 1.0! Open Source 3D HTML5 Game Engine Is All Grown Up — Gamefromscratch24k views · 36 comments
- Feb 11, 2026Introducing SuperSplat Studio — PlayCanvas16k views · 5 comments
- Jun 24, 2026PlayCanvas Engine 2.20.0: Gaussian Splatting Upgrade & WebXR on WebGPU — PlayCanvas3k views · 8 comments
- Jul 16, 2021Introducing the PlayCanvas Examples Browser — PlayCanvas2.4k views · 5 comments
- Aug 8, 2026Build 3D Games in Your Browser for FREE! 🤯 (PlayCanvas Engine) — TechyGirl2k views · 1 comment
17 more on YouTube
- Oct 2, 2026PlayCanvas: The 3D Web Graphics Platform — PlayCanvas1.8k views · 2 comments
- Mar 20, 2020Let’s Build a Game! (with halvves) — Learn With Jason — CodeTV1.3k views
- Jul 21, 2026PlayCanvas Engine 2.21.0: Splat Refraction, Water, Volumetric Fog & Fat Lines — PlayCanvas1.2k views · 1 comment
- Oct 1, 2026PlayCanvas Engine 2.23.0: Up to 3.8× Faster Rendering, New UI Examples & More — PlayCanvas1k views · 1 comment
- Jun 9, 2022How to create 3D Text Meshes - PlayCanvas Office Hours #12 — PlayCanvas1k views
- Sep 16, 2023Alternative a Unity? / PLAYcanvas — Mille e Una Avventura756 views · 28 comments
- Feb 3, 2022PlayCanvas not running on certain iOS devices — SeunghoChoi Portfolio702 views
- Jul 27, 2020PlayCanvas Intro — GAMEDEV ZONE518 views · 3 comments
- May 25, 2022お手軽ポストエフェクト [PLAYCANVAS #TIPS] — PLAYCANVAS運営事務局338 views
- Jun 30, 2020PlayCanvas + AssemblyScript PR — kung foo man266 views · 5 comments
- May 22, 2023PlayCanvas Latest Updates ~2023/05/19 (Editor ~v1.30.8) — PLAYCANVAS運営事務局159 views
- Nov 9, 2022PlayCanvas Latest Updates ~2022/10/25 (Editor ~v1.21.89) — PLAYCANVAS運営事務局141 views
- Dec 16, 2022PlayCanvas Latest Updates ~2022/12/14 (Engine ~v1.59.0 | Editor ~v1.23.3) — PLAYCANVAS運営事務局132 views
- Jan 22, 2023最新バージョンのEngineでLaunch! [PLAYCANVAS #TIPS] — PLAYCANVAS運営事務局119 views
- Nov 13, 2025GitHub - playcanvas/engine: Powerful web graphics runtime built on WebGL, WebGPU, WebXR and glTF — GitHub Daily Trend AI Podcast81 views
- Jul 26, 2021[#TIPS] Launchでエンジンバージョンが変えられるの知ってた? [#PLAYCANVAS] — PLAYCANVAS運営事務局79 views
- Nov 13, 2025playcanvas/engine - Gource visualisation — Gourcer10 views
On Bluesky · 13
- Nov 28, 2025PlayCanvas : un moteur de jeu Open Source qui utilise HTML5 et WebGL pour exécuter des contenus 3D interactifs sur navigateur, mobile ou… — @bearstech.com9 likes and reposts
- Nov 20, 2025Je découvre PlayCanvas, un moteur sous licence MIT conçu pour le web avec WebGL, WebGPU, Etc. Il permet de créer des jeux, des… — @ponceto91.bsky.social9 likes and reposts
- Nov 29, 2025It's wild how PlayCanvas brings real-time 3D to the browser with just a few lines of JavaScript. No plugins, just WebGL and WebGPU. Makes… — @iam.slys.dev2 likes and reposts
- Nov 21, 2025🔥 Hot Repo! 🔥 (100+ new stars) 📦 playcanvas / engine ⭐ 12,505 (+147) 🗒 JavaScript Powerful web graphics runtime built on WebGL, WebGPU,… — @github-trending.bsky.social2 likes and reposts
- Jul 31, 2025📦 playcanvas / engine ⭐ 10,558 (+46) 🗒 JavaScript Powerful web graphics runtime built on WebGL, WebGPU, WebXR and glTF — @github-trending-js.bsky.social2 likes and reposts
8 more on Bluesky
- Nov 7, 2024PlayCanvas : un moteur de jeu Open Source, optimisé pour le web. Basé sur WebGL, il prend en charge le rendu avancé, la physique et le son… — @bearstech.com2 likes and reposts
- Sep 24, 2026📦 playcanvas / engine ⭐ 16,896 (+31) 🗒 JavaScript Powerful web graphics runtime built on WebGL, WebGPU, WebXR and glTF — @github-trending-js.bsky.social1 likes and repost
- May 9, 2026🚀 Skyrocketing! 🚀 (200+ new stars) 📦 playcanvas / engine ⭐ 15,437 (+376) 🗒 JavaScript Powerful web graphics runtime built on WebGL,… — @github-trending-js.bsky.social1 likes and repost · 1 reply
- Nov 28, 2025🔥 Hot Repo! 🔥 (100+ new stars) 📦 playcanvas / engine ⭐ 13,301 (+114) 🗒 JavaScript Powerful web graphics runtime built on WebGL, WebGPU,… — @github-trending-js.bsky.social1 likes and repost
- Nov 25, 2025🔥 Hot Repo! 🔥 (100+ new stars) 📦 playcanvas / engine ⭐ 12,969 (+120) 🗒 JavaScript Powerful web graphics runtime built on WebGL, WebGPU,… — @github-trending.bsky.social1 likes and repost
- Nov 23, 2025🔥 Hot Repo! 🔥 (100+ new stars) 📦 playcanvas / engine ⭐ 12,842 (+123) 🗒 JavaScript Powerful web graphics runtime built on WebGL, WebGPU,… — @github-trending-js.bsky.social1 likes and repost
- Nov 16, 2025🔥 Hot Repo! 🔥 (100+ new stars) 📦 playcanvas / engine ⭐ 11,910 (+137) 🗒 JavaScript Powerful web graphics runtime built on WebGL, WebGPU,… — @github-trending.bsky.social1 likes and repost
- Nov 12, 2025📦 playcanvas / engine ⭐ 11,127 (+45) 🗒 JavaScript Powerful web graphics runtime built on WebGL, WebGPU, WebXR and glTF — @github-trending.bsky.social1 likes and repost
On Hacker News · 4
- Jun 4, 2014PlayCanvas: WebGL 3D game engine5 points
- Jul 29, 2019PlayCanvas: Fast and lightweight WebGL game engine3 points
- Mar 20, 20163D WebGL game engine with online toolset2 points
- Sep 13, 2023PlayCanvas: Free and Open Source JavaScript Game Engine1 point
On the web · 1
- Jun 4, 2014PlayCanvas Takes its WebGL Game Engine Open Source — thenextweb.com
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,542 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
The file
Show its rules and text
We split this AGENTS.md into the rules it gives an agent
49 rules. About 0 are common, 30 are distinctive, and 19 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈30
Distinctive · estimate
This author's own choices. Worth a look.
19
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Very specific: line 21
Follow ESLint rules: Always run npm run lint before committing
- Distinctive: line 22
Important: Only fix lint issues in code you are actively modifying or creating
- Distinctive: line 23
Do not fix pre-existing lint issues in unrelated code unless specifically asked
- Distinctive: line 25
Use JSDoc comments: All public APIs must have comprehensive JSDoc documentation
- Distinctive: line 26
Module imports: Use ES6 import/export syntax
- Very specific: line 34
Source files: All engine source code goes in src/
- Very specific: line 46
Use kebab-case for file names (e.g., graphics-device.js for GraphicsDevice class)
- Distinctive: line 47
If a class is renamed, the file should be renamed to match
- Distinctive: line 67
When in doubt, ask before breaking the hierarchy
- Very specific: line 90
Link related APIs: Use @see tags to cross-reference
- Very specific: line 91
Mark deprecations: Use @deprecated with migration instructions
- Very specific: line 96
Run npm run build:types to generate .d.ts files
- Very specific: line 97
Test types with npm run test:types.
- Distinctive: line 98
Use proper JSDoc type annotations:
- Very specific: line 103
Type-only imports: Use @import for types referenced in JSDoc comments
- Distinctive: line 105
Place at the top of the file in a JSDoc comment block
- Distinctive: line 119
Test naming: Use descriptive names that explain what is being tested
- Distinctive: line 145
Use abstraction layers: Don't call WebGL/WebGPU APIs directly in high-level code
- Very specific: line 150
When adding public API methods to GraphicsDevice, add stub implementations to NullGraphicsDevice
- Distinctive: line 161
Add console warning in development builds
- Distinctive: line 162
Keep deprecated code for at least one major version
- Distinctive: line 163
Consider removing jsdocs completely
- Very specific: line 168
Source is in
src/: Never edit files in build/ directory - Very specific: line 174
Never add module-scope side effects (top-level calls, prototype patches, registry writes, window access).
- Distinctive: line 181
Minimal dependencies: Avoid adding new dependencies unless absolutely necessary
- Very specific: line 186
Debug class: Use Debug class (src/core/debug.js) for logging and assertions
- Distinctive: line 188
Important: All Debug methods are stripped out in production builds
- Very specific: line 189
Use *Once() variants to avoid spam in loops or frequent calls
- Distinctive: line 190
Don't use Debug in hot paths - even in debug builds, excessive logging impacts performance
- Distinctive: line 202
Avoid very obvious comments: Don't state what the code clearly does
- Distinctive: line 206
Clear commit messages: Use conventional commits format
- Very specific: line 215
No generated files: Don't commit files in build/ directory
- Distinctive: line 222
WebGPU support: Must maintain compatibility with WebGPU API
- Distinctive: line 271
Always address the root cause of issues rather than implementing workarounds that hide or suppress problems:
- Distinctive: line 273
Identify the root cause: When you encounter an error or unexpected behavior, investigate why it's happening
- Distinctive: line 274
Don't mask symptoms: Avoid solutions that simply hide errors or suppress warnings without fixing the underlying issue
- Distinctive: line 275
Fix at the source: When you identify the root cause, fix it where the problem originates, not where it manifests
- Very specific: line 281
Don't use
var: Use const or let (except in legacy scripts/ directory) - Distinctive: line 286
Don't bypass abstractions: Use the platform API, not direct WebGL/WebGPU calls
- Very specific: line 302
Lint your changes: Run npm run lint
- Very specific: line 310
Follow existing example structure (see other example.mjs files)
- Distinctive: line 312
Keep examples simple and focused on one feature
- Very specific: line 321
Import the engine constants and resolve the strings via lookup maps where the script applies them (see scripts/esm/camera-frame.mjs for the …
- Distinctive: line 323
Keep accepting raw numeric values (pass them through unchanged) so existing attribute data continues to work
- Distinctive: line 328
Format as a single code block: Always deliver PR descriptions wrapped in triple backticks for easy copy/paste
- Very specific: line 339
Only document public APIs: Do not list functionality tagged with @ignore, @protected, or @private as these are internal implementation …
- Distinctive: line 356
Look at similar existing code in the codebase
- Distinctive: line 357
Check the ESLint configuration
- Distinctive: line 359
If unclear or multiple valid approaches exist, ask instead of picking a possibly incorrect solution
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Agent Guidelines for PlayCanvas Engine
This document contains rules, conventions, and best practices for AI agents and developers working on the PlayCanvas Engine codebase.
Project Overview
PlayCanvas is an open-source WebGL/WebGPU game engine written in JavaScript. It's a performance-critical library used by thousands of developers worldwide.
- Language: JavaScript (ES2022) with JSDoc for TypeScript type definitions
- Module System: ES Modules
- Node Version: >=18.3.0 (see
enginesinpackage.json) - Build System: esbuild for the JavaScript bundles (
build.mjs); TypeScript plus Rollup (rollup-plugin-dts) for the bundled.d.ts - Testing: Mocha + Chai + Sinon
- Linting: ESLint with @playcanvas/eslint-config
- License: MIT
General Code Rules
1. Code Style and Formatting
- Follow ESLint rules: Always run
npm run lintbefore committing- Important: Only fix lint issues in code you are actively modifying or creating
- Do not fix pre-existing lint issues in unrelated code unless specifically asked
- Focus on ensuring new and refactored code is lint-free
- Use JSDoc comments: All public APIs must have comprehensive JSDoc documentation
- Module imports: Use ES6 import/export syntax
- Naming conventions:
- Classes: PascalCase (e.g.,
GraphicsDevice,Entity) - Functions/methods: camelCase (e.g.,
createShader,setPosition) - Constants: UPPER_SNAKE_CASE (e.g.,
PIXELFORMAT_RGBA8)
- Classes: PascalCase (e.g.,
2. File Organization
- Source files: All engine source code goes in
src/ - Directory structure:
src/core/- Core utilities and data structuressrc/platform/- Platform-specific code (graphics, audio, input)src/scene/- Scene graph, rendering, materials, shaderssrc/framework/- High-level components and application frameworksrc/extras/- Optional extras and utilitiessrc/deprecated/- Side-effect-free aliases for deprecated APIs (see section 9)
- Build output: Generated files go in
build/(never edit these directly) - Examples: Live in
examples/src/examples/<category>/<example>/, one folder per example - Tests: Unit tests go in
test/with.mjsextension - File naming: Module file names should match the main class they contain
- Use kebab-case for file names (e.g.,
graphics-device.jsforGraphicsDeviceclass) - If a class is renamed, the file should be renamed to match
- Multiple related classes can share a file if they're tightly coupled
- Use kebab-case for file names (e.g.,
Module Dependency Hierarchy
The codebase follows a strict hierarchical structure to maintain clean architecture:
core → platform → scene → frameworkRules:
- Lower-level modules cannot import from higher-level modules
- Lower-level modules cannot use instances from higher-level modules
- Example:
core/cannot import fromplatform/,scene/, orframework/ - Example:
scene/cannot import fromframework/
Known Exception:
CameraComponent(fromframework/) is currently used in multiple places at thescene/level- Do not introduce new exceptions unless explicitly requested and confirmed
- When in doubt, ask before breaking the hierarchy
This hierarchy ensures:
- Clean separation of concerns
- Prevents circular dependencies
- Makes the codebase more maintainable and testable
3. Documentation Standards
- JSDoc is mandatory for all public APIs:
/** * Brief description of the function. * * @param {string} name - Parameter description. * @param {number} [optional=0] - Optional parameter with default. * @returns {boolean} Return value description. * @example * const result = myFunction('test', 5); */ - Include examples for complex APIs
- Document side effects: Mention if a function modifies state
- Link related APIs: Use
@seetags to cross-reference - Mark deprecations: Use
@deprecatedwith migration instructions
4. TypeScript Definitions
- JSDoc comments are used to generate TypeScript definitions
- Run
npm run build:typesto generate.d.tsfiles - Test types with
npm run test:types. This compiles the bundled declarations and the consumer-side type tests intest/type-tests, which check inference and augmentation againstbuild/playcanvas.d.ts - Use proper JSDoc type annotations:
@type {TypeName}for variables@param {TypeName} paramNamefor parameters@returns {TypeName}for return values- Support for generics, unions, and complex types
- Type-only imports: Use
@importfor types referenced in JSDoc comments- These imports are only for type information, not runtime code
- Place at the top of the file in a JSDoc comment block
- Example:
/** * @import { Texture } from './texture.js' * @import { Shader } from './shader.js' */ - These help TypeScript understand types without adding runtime dependencies
5. Testing
- Write tests for all new features and bug fixes if instructed
- Test location:
test/directory, organized by module - Test naming: Use descriptive names that explain what is being tested
- Run tests:
npm test(ornpm run test:coveragefor coverage) - Bundle tests:
test/bundles/checks the built bundles (exports, tree shaking, live bindings). Runnpm run buildfirst, thennpm run test:build - Test structure:
describe('ClassName', function () { describe('#methodName', function () { it('should do something specific', function () { // Test implementation }); }); });
6. Performance Considerations
This is a performance-critical engine. Always consider:
- Avoid allocations in hot paths: Reuse objects, use object pools
- Minimize function calls: Inline critical code when necessary
- Cache property access: Store frequently accessed properties in local variables
- Use typed arrays: For numeric data (Float32Array, Uint8Array, etc.)
7. Graphics API Considerations
- Multi-backend support: Code must work with both WebGL2 and WebGPU
- Use abstraction layers: Don't call WebGL/WebGPU APIs directly in high-level code
- Shader code: Maintain both GLSL and WGSL versions
- GLSL:
src/scene/shader-lib/glsl/ - WGSL:
src/scene/shader-lib/wgsl/
- GLSL:
- NullGraphicsDevice: A dummy graphics device for headless/testing scenarios
- When adding public API methods to
GraphicsDevice, add stub implementations toNullGraphicsDevice - Stub methods should be empty or return safe default values to avoid crashes
- This ensures the engine can run without a real graphics backend for testing/server-side use
- When adding public API methods to
Project-Specific Rules
8. API Stability and Deprecation
- Backward compatibility matters: Breaking changes require major version bump
- Deprecation process:
- Mark API as
@deprecatedwith alternatives - Add console warning in development builds
- Keep deprecated code for at least one major version
- Consider removing jsdocs completely
- Mark API as
- Never remove public APIs without proper deprecation cycle
9. Build System
- Source is in
src/: Never edit files inbuild/directory - Module exports: Main exports defined in
src/index.js - Bundler:
build.mjsdrives esbuild (utils/esbuild-build-target.mjs). Each build type (rel,dbg,prf,min) is emitted as a UMD bundle (build/playcanvas*.js) and an ESM bundle (build/playcanvas*.mjs). Therel,dbgandprfESM builds also emit an unbundled module tree (build/playcanvas/src/,build/playcanvas.dbg/src/,build/playcanvas.prf/src/), which is whatimport 'playcanvas'resolves to - Type declarations:
npm run build:typesrunstscover the JSDoc, patches the output withutils/plugins/rollup-types-fixup.mjs(hand-declaredStandardMaterialaccessors, optionalScriptTypelifecycle methods, and theAssetMaptypedef rewritten into an augmentable interface) and bundles it with Rollup (rollup-plugin-dts) intobuild/playcanvas.d.ts - Debug stripping: the
Debug,DebugHelper,DebugGraphicsandWebgpuDebugcalls listed inSTRIP_FUNCTIONS(utils/esbuild-build-target.mjs) are removed from every build exceptdbg.// #if _DEBUGblocks survive only indbg;// #if _PROFILERblocks survive indbgandprf - Tree shaking:
package.jsondeclares"sideEffects": false, so consumers' bundlers drop every module they don't import from. Therefore:- Never add module-scope side effects (top-level calls, prototype patches, registry writes,
windowaccess). Do registration inside constructors or functions - Deprecated constant aliases and helper functions go in
src/deprecated/deprecated.js, which must stay free of module-scope side effects - Deprecated prototype shims (e.g.
Object.defineProperty(Foo.prototype, ...)) go at the bottom of the module that defines the class, so they ship only when that class does test/bundles/treeshake.test.mjsguards both rules
- Never add module-scope side effects (top-level calls, prototype patches, registry writes,
10. Dependencies
- Minimal dependencies: Avoid adding new dependencies unless absolutely necessary
- Types only:
@types/*and@webgpu/typesare the main dependencies
11. Error Handling
- Debug class: Use
Debugclass (src/core/debug.js) for logging and assertions- Methods include:
assert(),warn(),warnOnce(),error(),errorOnce(),deprecated(),removed(),log(),logOnce(),trace() - Important: All Debug methods are stripped out in production builds
- Use
*Once()variants to avoid spam in loops or frequent calls - Don't use Debug in hot paths - even in debug builds, excessive logging impacts performance
- Methods include:
- DebugHelper class: Helper methods for debugging (also stripped in production)
setName(),setLabel(),setDestroyed()for marking objects
12. Code Comments
- Explain "why" not "what": Code should be self-documenting, but comments help with quick understanding
- Complex algorithms: Explain the approach and any non-obvious optimizations
- TODOs: Include issue reference or context
// TODO: Optimize this when texture streaming is implemented (#1234) - Avoid very obvious comments: Don't state what the code clearly does
13. Commit and PR Guidelines
- Clear commit messages: Use conventional commits format
feat: Add feature descriptionfix: Bug fix descriptionperf: Performance improvement descriptiondocs: Documentation updaterefactor: Code refactoringtest: Test updates
- Reference issues: Include issue number in commit message in format 'Fixed #1234'
- Small, focused commits: Each commit should be a logical unit
- No generated files: Don't commit files in
build/directory
14. Browser Compatibility
- Modern browsers only: ES6+ features are allowed
- No polyfills in engine: Users can add their own if needed
- WebGL 2.0 minimum: WebGL 1.0 is not supported
- WebGPU support: Must maintain compatibility with WebGPU API
Common Patterns
15. Object Creation
// Prefer class syntax with TypeScript-like property declarations
class MyClass {
/**
* @type {GraphicsDevice}
*/
device;
/**
* @type {string}
*/
name;
constructor(device, options = {}) {
this.device = device;
this.name = options.name ?? 'default';
}
destroy() {
// Clean up resources
this.device = null;
}
}16. Resource Management
// Always provide destroy() method for objects holding resources
class Resource {
constructor() {
this._resource = createResource();
}
destroy() {
this._resource?.destroy();
this._resource = null;
}
}17. Root Cause Analysis
Always address the root cause of issues rather than implementing workarounds that hide or suppress problems:
- Identify the root cause: When you encounter an error or unexpected behavior, investigate why it's happening
- Don't mask symptoms: Avoid solutions that simply hide errors or suppress warnings without fixing the underlying issue
- Fix at the source: When you identify the root cause, fix it where the problem originates, not where it manifests
Things to Avoid
18. Anti-Patterns
- Don't use
var: Useconstorlet(except in legacyscripts/directory) - Avoid
anytypes: Be specific in JSDoc type annotations - No global state: Everything should be instance-based
- Exception: Module-scope variables for local optimization are allowed (e.g., reusable Mat4 instances)
- These must never be exported and should only be used within the module
- Don't bypass abstractions: Use the platform API, not direct WebGL/WebGPU calls
- Don't suppress linter warnings: Fix the underlying issue
19. Performance Anti-Patterns
- No allocations in render loop: Pre-allocate and reuse if feasible
- Don't use
try/catchin hot paths: It prevents optimizations - No string concatenation in loops: Build arrays and join
- Don't create functions in loops: Define functions outside
AI Agent-Specific Guidelines
20. When Making Changes
- Read existing code first: Understand the context and patterns
- Follow existing style: Match the style of surrounding code
- Lint your changes: Run
npm run lint - Update documentation: Modify JSDoc comments when changing APIs
- Consider performance: This is a real-time engine, every microsecond counts
- Check both WebGL and WebGPU: Changes may affect both backends
21. When Creating Examples
- Each example is a folder,
examples/src/examples/<category>/<example>/, holdingexample.mjs, optionalcontrols.jsx, any other files it imports, and itsthumbnail-large.webp/thumbnail-small.webp - Follow existing example structure (see other
example.mjsfiles) - Include descriptive comments
- Keep examples simple and focused on one feature
22. When Authoring Scripts
- Reusable scripts live in
scripts/esm/and expose their configuration as script attributes - Attribute enums must use readable string values: declare them as
@enum {string}with human-readable values (e.g.,LINEAR: 'linear'), never as raw numeric engine constants- Numeric constant values (e.g.,
PIXELFORMAT_RGBA16F = 12) are implementation details that can change between releases and make attribute data unreadable ("renderFormat": 12) - Import the engine constants and resolve the strings via lookup maps where the script applies
them (see
scripts/esm/camera-frame.mjsfor the pattern) - Keep accepting raw numeric values (pass them through unchanged) so existing attribute data continues to work
- Numeric constant values (e.g.,
23. When Writing PR Descriptions
- Format as a single code block: Always deliver PR descriptions wrapped in triple backticks for easy copy/paste
- Structure:
- Brief title and overview
- Bullet points for functionality changes
- Technical details section (if relevant)
- Clearly list all public API changes with before/after code examples
- List updated examples (if applicable)
- Performance considerations (if relevant)
- Focus on user-facing changes: What developers using the engine will see/use
- Be concise but complete: Include all breaking changes and new APIs
- Avoid excessive detail: Group related changes together, don't list every tiny implementation detail or internal refactoring
- Only document public APIs: Do not list functionality tagged with
@ignore,@protected, or@privateas these are internal implementation details
Resources
- API Reference: https://api.playcanvas.com/engine/
- User Manual: https://developer.playcanvas.com/user-manual/engine/
- Developer Site: https://github.com/playcanvas/developer-site
- For large features, ask to add documentation to the User Manual
- Manual pages are Markdown files in the
docs/directory
- Examples: https://playcanvas.github.io
- Forum: https://forum.playcanvas.com
- Discord: https://discord.gg/RSaMRzg
- GitHub Issues: https://github.com/playcanvas/engine/issues
Questions?
When in doubt:
- Look at similar existing code in the codebase
- Check the ESLint configuration
- Review recent commits for patterns
- If unclear or multiple valid approaches exist, ask instead of picking a possibly incorrect solution
Remember: This is a library used by thousands of developers. Quality, performance, and stability are paramount. When in doubt, prefer conservative, well-tested changes over clever optimizations.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

