Using the Engine Standalone
It is possible to build applications on the PlayCanvas Engine without using the Editor. Some examples of applications built directly against the Engine are:
- glTF Viewer [GitHub]
- SuperSplat [GitHub]
- ...and, of course, the PlayCanvas Editor itself!
This page guides you in how to get started.
Before you begin, ensure you have Node.js installed.
For a Vite and TypeScript project, use the official create-playcanvas tool and choose the Engine format:
npm create playcanvas@latest my-app -- -f engine
The generated project includes a runnable starter and PlayCanvas Skills for compatible AI coding agents.
When setting up your project, there are two main options to consider.
Option 1: Build Tool and NPM
This is the recommended set up that should suit most developers.
A build tool can bundle your application into an optimized package that can run on a wide range of browsers. There are many build tools such as webpack, Rollup and esbuild, and PlayCanvas will work with all of them. Here, we will use Vite, a popular build tool that aims to provide a faster and leaner development experience for modern web projects.
First, select whether you prefer to develop in JavaScript or TypeScript:
- JavaScript
- TypeScript
-
Open a Terminal/Command Prompt, create a folder for your app and
cdinside it. -
Install
playcanvasandvite:npm install playcanvasnpm install vite --save-dev -
Create an
index.htmland paste this:index.html<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><style>body { margin: 0; overflow: hidden; }</style></head><body><script type="module" src="main.js"></script><canvas id='application'></canvas></body></html> -
Create a
main.jsand paste this:main.jsimport * as pc from 'playcanvas';// create a graphics device, preferring WebGPU over WebGL 2.0const canvas = document.getElementById('application');const device = await pc.createGraphicsDevice(canvas, {deviceTypes: [pc.DEVICETYPE_WEBGPU]});// create an application with the systems and handlers it usesconst options = new pc.AppOptions();options.graphicsDevice = device;options.componentSystems = [pc.RenderComponentSystem,pc.CameraComponentSystem,pc.LightComponentSystem];options.resourceHandlers = [pc.TextureHandler,pc.ContainerHandler];const app = new pc.AppBase(canvas);app.init(options);app.setCanvasResolution(pc.RESOLUTION_AUTO);app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);app.start();// resize the canvas when the window is resizedwindow.addEventListener('resize', () => app.resizeCanvas());// create a cameraconst camera = new pc.Entity();camera.addComponent('camera', {clearColor: new pc.Color(0.3, 0.3, 0.7)});camera.setPosition(0, 0, 3);app.root.addChild(camera);// create a lightconst light = new pc.Entity();light.addComponent('light');light.setEulerAngles(45, 45, 0);app.root.addChild(light);// create a boxconst box = new pc.Entity();box.addComponent('render', {type: 'box'});app.root.addChild(box);// rotate the boxapp.on('update', (dt) => box.rotate(10 * dt, 20 * dt, 30 * dt)); -
Run the Vite development server:
npx viteThis starts a server at
http://localhost:5173. Visit this URL in your browser and you will see the following:
tipEvery time you save your source files, the tab will reload automatically.
-
Open a Terminal/Command Prompt, create a folder for your app and
cdinside it. -
Install
playcanvasandvite:npm install playcanvasnpm install vite --save-dev -
Create an
index.htmland paste this:index.html<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><style>body { margin: 0; overflow: hidden; }</style></head><body><script type="module" src="main.ts"></script><canvas id='application'></canvas></body></html> -
Create a
main.tsand paste this:main.tsimport * as pc from 'playcanvas';// create a graphics device, preferring WebGPU over WebGL 2.0const canvas = document.getElementById('application') as HTMLCanvasElement;const device = await pc.createGraphicsDevice(canvas, {deviceTypes: [pc.DEVICETYPE_WEBGPU]});// create an application with the systems and handlers it usesconst options = new pc.AppOptions();options.graphicsDevice = device;options.componentSystems = [pc.RenderComponentSystem,pc.CameraComponentSystem,pc.LightComponentSystem];options.resourceHandlers = [pc.TextureHandler,pc.ContainerHandler];const app = new pc.AppBase(canvas);app.init(options);app.setCanvasResolution(pc.RESOLUTION_AUTO);app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);app.start();// resize the canvas when the window is resizedwindow.addEventListener('resize', () => app.resizeCanvas());// create a cameraconst camera = new pc.Entity();camera.addComponent('camera', {clearColor: new pc.Color(0.3, 0.3, 0.7)});camera.setPosition(0, 0, 3);app.root.addChild(camera);// create a lightconst light = new pc.Entity();light.addComponent('light');light.setEulerAngles(45, 45, 0);app.root.addChild(light);// create a boxconst box = new pc.Entity();box.addComponent('render', {type: 'box'});app.root.addChild(box);// rotate the boxapp.on('update', (dt: number) => box.rotate(10 * dt, 20 * dt, 30 * dt)); -
Run the Vite development server:
npx viteThis starts a server at
http://localhost:5173. Visit this URL in your browser and you will see the following:
tipEvery time you save your source files, the tab will reload automatically.
Option 2: Import Map and CDN
An import map can resolve module specifiers in JavaScript modules. Consider this import statement:
import * as pc from 'playcanvas';
An import map can resolve playcanvas to a CDN-hosted build of the engine that can be dynamically loaded by the browser. This means that we can skip the build step described in Option 1.
First, select whether you prefer to develop in JavaScript or TypeScript:
- JavaScript
- TypeScript
-
Open a Terminal/Command Prompt, create a folder for your app and
cdinside it. -
Create an
index.htmland paste this:index.html<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><style>body { margin: 0; overflow: hidden; }</style><script type="importmap">{"imports": {"playcanvas": "https://cdn.jsdelivr.net/npm/playcanvas/+esm"}}</script></head><body><script type="module" src="main.js"></script><canvas id='application'></canvas></body></html> -
Create a
main.jsand paste this:main.jsimport * as pc from 'playcanvas';// create a graphics device, preferring WebGPU over WebGL 2.0const canvas = document.getElementById('application');const device = await pc.createGraphicsDevice(canvas, {deviceTypes: [pc.DEVICETYPE_WEBGPU]});// create an application with the systems and handlers it usesconst options = new pc.AppOptions();options.graphicsDevice = device;options.componentSystems = [pc.RenderComponentSystem,pc.CameraComponentSystem,pc.LightComponentSystem];options.resourceHandlers = [pc.TextureHandler,pc.ContainerHandler];const app = new pc.AppBase(canvas);app.init(options);app.setCanvasResolution(pc.RESOLUTION_AUTO);app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);app.start();// resize the canvas when the window is resizedwindow.addEventListener('resize', () => app.resizeCanvas());// create a cameraconst camera = new pc.Entity();camera.addComponent('camera', {clearColor: new pc.Color(0.3, 0.3, 0.7)});camera.setPosition(0, 0, 3);app.root.addChild(camera);// create a lightconst light = new pc.Entity();light.addComponent('light');light.setEulerAngles(45, 45, 0);app.root.addChild(light);// create a boxconst box = new pc.Entity();box.addComponent('render', {type: 'box'});app.root.addChild(box);// rotate the boxapp.on('update', (dt) => box.rotate(10 * dt, 20 * dt, 30 * dt)); -
Run
serve:npx serveThis starts a server at
http://localhost:3000. Visit this URL in your browser and you will see the following:
-
Open a Terminal/Command Prompt, create a folder for your app and
cdinside it. -
Create an
index.htmland paste this:index.html<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><style>body { margin: 0; overflow: hidden; }</style><script type="importmap">{"imports": {"playcanvas": "https://cdn.jsdelivr.net/npm/playcanvas/+esm"}}</script></head><body><script type="module" src="main.js"></script><canvas id='application'></canvas></body></html> -
Create a
main.tsand paste this:main.tsimport * as pc from 'playcanvas';// create a graphics device, preferring WebGPU over WebGL 2.0const canvas = document.getElementById('application') as HTMLCanvasElement;const device = await pc.createGraphicsDevice(canvas, {deviceTypes: [pc.DEVICETYPE_WEBGPU]});// create an application with the systems and handlers it usesconst options = new pc.AppOptions();options.graphicsDevice = device;options.componentSystems = [pc.RenderComponentSystem,pc.CameraComponentSystem,pc.LightComponentSystem];options.resourceHandlers = [pc.TextureHandler,pc.ContainerHandler];const app = new pc.AppBase(canvas);app.init(options);app.setCanvasResolution(pc.RESOLUTION_AUTO);app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);app.start();// resize the canvas when the window is resizedwindow.addEventListener('resize', () => app.resizeCanvas());// create a cameraconst camera = new pc.Entity();camera.addComponent('camera', {clearColor: new pc.Color(0.3, 0.3, 0.7)});camera.setPosition(0, 0, 3);app.root.addChild(camera);// create a lightconst light = new pc.Entity();light.addComponent('light');light.setEulerAngles(45, 45, 0);app.root.addChild(light);// create a boxconst box = new pc.Entity();box.addComponent('render', {type: 'box'});app.root.addChild(box);// rotate the boxapp.on('update', (dt: number) => box.rotate(10 * dt, 20 * dt, 30 * dt)); -
Install
playcanvasandtypescript:npm install playcanvas typescript --save-dev -
Compile
main.tstomain.js:npx tsc main.ts --target es2022 --lib esnext,dom --module esnext --moduleResolution bundler --types webxr -
Run
serve:npx serveThis starts a server at
http://localhost:3000. Visit this URL in your browser and you will see the following:
Configuring the Application
The samples create the application in two steps:
createGraphicsDevicecreates the graphics device. ListingDEVICETYPE_WEBGPUindeviceTypesrequests WebGPU, and the Engine falls back to WebGL 2.0 when WebGPU isn't available.AppBaseis initialized with anAppOptionsobject that lists the component systems and resource handlers the application uses. Because nothing else is registered, a build tool can leave the rest out of your bundle.
As your application grows, register what it needs:
- Components: Each component type needs its component system. For example, add
pc.ScriptComponentSystemto use thescriptcomponent. TheApplicationconstructor lists every component type with its system. If a system is missing,addComponentreturnsnull, and the debug build of the Engine logs an error. - Assets: Each asset type needs its resource handler. The samples register
pc.TextureHandlerfor textures andpc.ContainerHandlerfor GLB models. - Other features: Sound, batching, lightmapping and XR are enabled with further
AppOptionsproperties. For example, thesoundcomponent also needsoptions.soundManager = new pc.SoundManager().
The Application class sets all of this up for you. However, its constructor can't create a WebGPU device, it adds every component system and resource handler to your bundle, and it is expected to be deprecated in a future release.