Skip to main content

Step 2: Add Build Tool for Packaged WebSpatial Apps

WebSpatial Builder

To enable the WebSpatial API features that current browser engines do not yet support and unlock spatial capabilities, your site must run inside the WebSpatial App Shell.

One way to obtain the WebSpatial App Shell is to package your existing Web project into a Packaged WebSpatial App that can be installed and run independently on spatial-computing platforms such as visionOS.

tip

Another option is to pre-install the WebSpatial Browser app (in development) on the target platform and open the WebSpatial App's URL directly in that browser.

Because you cannot assume that visionOS users have installed - or are willing to install - this browser, packaging your site and distributing it through the app store remains the only way to guarantee that your WebSpatial App is available to visionOS users.

During the development phase, you need to build an app, install it in the visionOS simulator or on your own device, and run it.

During the testing or distribution phase, you need to build an app, submit it to a platform such as App Store Connect for testing on other devices, or eventually publish it in an app store.

@webspatial/builder covers all of these needs.

WebSpatial Builder is a command-line tool. The main command is webspatial-builder, which provides three subcommands:

run

webspatial-builder run --base=$XR_DEV_SERVER

It builds a visionOS app from the current WebSpatial project, automatically launches the local visionOS simulator, installs the app, and runs it.

This command is totally for the development phase - the main one you'll use during the development process. It is the fastest way to preview and debug a Packaged WebSpatial App. It is usually combined with a Dev Server: the app built with the run command needs to load a special website URL generated by the Dev Server, specifically for the WebSpatial App Shell on visionOS.

info

Apps generated by WebSpatial Builder use the start_url field of the Web App Manifest to figure out where the HTML for its Start Scene should come from.

tip

The run command allows you to omit the Web App Manifest temporarily. Builder supplies default app information - including start_url - when the manifest file is absent.

info

In a standard PWA project, the start_url in the Web App Manifest can be set in two ways: one includes the full URL with the production domain, and the other uses a relative path without the domain.

The second option is the best practice, because when running the site locally with a dev server, it'll automatically load the manifest from the local domain, not the production one.

If your start_url is a full URL with a domain included, The run command supports a --base option that allows you to set a root path that includes your local dev server's domain, which will replace the root part of the start_url.
If the WebSpatial-specific site generated by the dev server uses a different URL root, you can include that in the --base too.
This way, you don't need to change your manifest or maintain multiple versions just to use the run command.

If your start_url is a relative path without a domain, you can still use the --base option to add the domain (which replaces the starting / in start_url).
But if you don't provide the --base, or if it doesn't include a domain too (like when it only includes the specialized root path used by the WebSpatial-specific dev server), the run command will bundle all site files within this relative path into the app package, the app will load all the web files directly from your app package.
That makes development a lot more annoying - you won't get hot reloading, and you'll have to repackage and reinstall the app every time you make a change.

Therefore, when you use run, you almost always need the --base to specify the root part of the WebSpatial-specific Dev Server URL (for example, http://localhost:3000/webspatial/avp/).

All other run's options are optional.

build

webspatial-builder build --base=$XR_PRE_SERVER --bundle-id=$XR_BUNDLE_ID --teamId=$XR_TEAM_ID

Based on your current WebSpatial project, this builds a visionOS app package (an .ipa file) that's signed with your Apple Developer account, so you can test it on your real device (like a Vision Pro).

If your Apple Developer account is an enterprise account, the package can run on other people's devices.

Otherwise, it runs only on devices that sign in with the same account as the developer. In that case, testing on other devices requires the publish command.

info

Apps generated by WebSpatial Builder use the start_url field of the Web App Manifest to figure out where the HTML for its Start Scene should come from.

info

In a standard PWA project, the start_url in the Web App Manifest can be set in two ways: one includes the full URL with the production domain, and the other uses a relative path without the domain.

The second option is the best practice, because when running the site locally with a dev server, it'll automatically load the manifest from the local domain, not the production one.

For these on-device tests, the URLs the WebSpatial app loads usually differ from the production URLs. If you want to use a testing URL, you must also include the --base option when you run build to supply the full root part (with a domain) of the testing URL.

When you configure start_url as a relative path, similar to the usage with the run command, if you either don't use the --base or only use it to replace the root path without adding a domain, the build command will package all the website files into the app package for offline use. The app will load everything locally at runtime.

tip

When using the run command, this offline packaging mode isn't recommended. But the situation differs for the build command: since it's mainly for internal testing before official release, you might not have a convenient way to deploy the current code as a publicly accessible web URL. Offline packaging avoids that network complications - once installed, the app can run right away.

Additionally, when you use build, you must always provide --bundle-id and --teamId so the visionOS app can be signed.

All other build's options are optional.

publish

webspatial-builder publish  --base=$XR_PROD_SERVER --bundle-id=$XR_BUNDLE_ID --teamId=$XR_TEAM_ID --version=$XR_VERSION --u=$XR_DEV_NAME --p=$XR_DEV_PASSWORD

Builds a visionOS app from the current WebSpatial project, applies an Apple Developer signature, adds the other metadata required by App Store Connect, and automatically submits the build to App Store Connect for later testing, review, and store release.

info

Apps generated by WebSpatial Builder use the start_url field of the Web App Manifest to figure out where the HTML for its Start Scene should come from.

info

In a standard PWA project, the start_url in the Web App Manifest can be set in two ways: one includes the full URL with the production domain, and the other uses a relative path without the domain.

The second option is the best practice, because when running the site locally with a dev server, it'll automatically load the manifest from the local domain, not the production one.

When you configure start_url as a relative path, you must always include the --base option when you run publish to supply the full root part (with a domain) of the production URL.

Additionally, when you use publish, you must always provide --bundle-id , --teamId , --version , --u , and --p for signing and App Store Connect submission.

All other publish's options are optional.

npm scripts

You could type the WebSpatial Builder command and all of the options above every time you run it, but that is inefficient. A best practice is to add npm scripts to package.json so the options become environment variables and you can run WebSpatial Builder through fixed familiar npm commands.

"run:avp": "webspatial-builder run --base=$XR_DEV_SERVER",
"build:avp": "webspatial-builder build --base=$XR_PRE_SERVER --bundle-id=$XR_BUNDLE_ID --teamId=$XR_TEAM_ID",
"publish:avp": "webspatial-builder publish --base=$XR_PROD_SERVER --bundle-id=$XR_BUNDLE_ID --teamId=$XR_TEAM_ID --version=$XR_VERSION --u=$XR_DEV_NAME --p=$XR_DEV_PASSWORD",

Once the command-line options are converted to environment variables, you can store most of them in a dotenv file, so you do not have to set them manually each time.