Building an App
Last updated: July 3, 2026
To publish a web app you built yourself to the marketplace as a Market App, you first need to build the app and prepare its artifacts. This process involves building a static site with HTML and JavaScript, and inspecting the build artifacts from the command line.
A Market App is an app you publish to the marketplace and install into another Space. In form it is a static web app, the same as Web Hosting. You upload a bundle of pre-built screen files, and when a visitor arrives, those screens appear as they are.
There is one difference from an ordinary web app, and because of it there is one rule you must follow when building. This page covers that difference, the rule, and the validation you do before publishing.
When installed, resources are copied into the installer's Space
When a Market App is installed, not only the app's screens but also the resources you selected when publishing it (Content Type, Content, Media, and so on) are copied into the installer's Space. Imagine you built and published a clothing-store product catalog app. When someone installs that app, the product Content Type and the product Content are copied into that person's Space along with the app's screens.
The copied resources receive new identifiers in the Space where they are installed. The Delivery Access Token used to read content is also newly created in the installing Space. So the installed app reads not the creator's Space, but its own copy that was placed into the installer's Space. Once installation finishes, the app runs entirely on the resources of the installing Space.
Why the access information is baked into the build
An installed Market App has no server. Because it is static hosting, the same as Web Hosting, there is no server runtime that computes screens for each request, and content is fetched by the browser calling the WEEGLOO delivery API (CDA, Content Delivery API) directly. So the build artifacts (the screen files) must spell out, in text, which Space to read what from, and with which credential.
The catch, as you saw above, is that installation copies the resources under new identifiers. The values written in the build files are the creator Space's identifiers and token, but what must be read in the installed location is the newly copied copy. Leave the old values as they are and the app points at the wrong place.
So WEEGLOO swaps these values in for you at install time. When you publish, it finds in advance where the creator Space's identifiers, tokens, and resource identifiers are written within the build text, and at install time it replaces those spots with the new values of the installing Space's copy. As a result, the installed app automatically points at the installing Space.
This replacement happens only for the resources you bundled with the app. So the resources the screens read (Content Type, Delivery Access Token, and so on) must all be bundled together when you publish. If you leave one out, its identifier is not replaced and remains a wrong value in the installed location. What you need to bundle is covered in the resource selection section of Publishing an App.
This automatic replacement has one prerequisite: the value must appear within the build text as a single, intact string, exactly as is. This is because the publishing step finds that string literally and records its position. If you split the value, build it at runtime, or fetch it from outside, the publishing step cannot find it, so no replacement happens at install time and the installed app does not work.
There are three values baked into the build (and replaced at install time):
- The source Space's
sys.id(spaceId): which Space to read from. - The source Space's Delivery Access Token: the read-only credential that can read that Space's published content.
- The
sys.idof the resources the app references: for example thesys.idof the Content Type that holds the products, and other resource identifiers the client code points at.
Inlining the values as literals
The key point is that the three values above must appear inside the build artifacts as a single, intact literal substring. When you open a built text file (JS, HTML, JSON, and so on), the value must appear as one piece, not split or transformed. Only then can the publishing step find the value and record its position, and the install step replace that spot with a new value.
Below is an example of configuration placed in client code. The values only show the format; replace them with your actual credentials.
// weegloo.config.js: these values are baked into the build output as-is
export const WEEGLOO = {
spaceId: "spc_xxxxxxxxxxxxxxxx", // sys.id of the source Space
deliveryAccessToken: "dat_xxxxxxxxxxxxxxxxxxxx", // Delivery Access Token of the source Space
productContentTypeId: "ct_xxxxxxxxxxxx", // sys.id of the Content Type the app reads
};The browser calls CDA directly with these values.
fetch(`https://cda.weegloo.com/v1/spaces/${WEEGLOO.spaceId}/contents`, {
headers: { Authorization: `Bearer ${WEEGLOO.deliveryAccessToken}` },
});The approaches below must not be used. All of them keep the value from remaining as an intact literal in the build artifacts, which prevents the publishing step from finding it. Then no replacement happens at install time, and the installed app cannot read its own Space's copy.
-
Reading a runtime environment variable. An installed app has no server or runtime environment to inject the value into, and the value does not remain as text in the build.
// Wrong: this environment variable does not exist where the app is installed deliveryAccessToken: process.env.DELIVERY_ACCESS_TOKEN -
Fetching it at runtime. If you make the value something to be fetched from somewhere, it does not remain in the build text, and there is nowhere to fetch it from.
-
Splitting it through string concatenation. The value does not appear as one piece, so the publishing step cannot find it.
// Wrong: "dat_xxxxxxxxxxxxxxxxxxxx" does not remain as a single substring in the output deliveryAccessToken: "dat_" + "xxxxxxxxxxxxxxxxxxxx" -
Leaving a placeholder or a blank. Filling in the value is something WEEGLOO does at install time. But that replacement finds the actual value baked into the build and changes that spot, so if you leave a blank or a temporary marker, there is no value to find and nothing becomes a replacement target. The actual value must be present as text at the moment you create the build artifacts.
Always put the values in a text file (JS, HTML, JSON, and so on). Do not put them in binary files such as images or fonts. Finding and replacing values only happens in text files.
The bundler is something to check as well. Some bundlers split or transform string literals during optimization. Do not rely on the source code alone; open the actual build artifacts and verify that the value remains an intact literal (see the next section).
Issue the token with least privilege
The Delivery Access Token you bake into the build is exposed in the browser as is. Anyone who installs the app can see this value in the app's build files (the token newly created in their Space after installation is likewise exposed). Therefore this token must be issued with a least-privilege SpaceRole that can read only the Content Type the app actually needs to read. Do not issue it with the Administrator role. If an administrator-level token is exposed in the browser, the entire source Space is at risk.
How to create a least-privilege SpaceRole and issue a Delivery Access Token with that role is covered in Tokens.
Validation before publishing
Before you publish, confirm that the values went in correctly, not in your head but in the actual build artifacts. In the built folder, grep for the source spaceId, the token, and the resource sys.id one by one, and check that each shows up as an intact literal.
grep -r "DATxxxxxxxxxxxxxxxx" dist/It is fine as long as the value you are looking for shows up as one piece (not split or transformed) inside the build artifacts. Check all three baked-in values (spaceId, Delivery Access Token, referenced resource sys.id). If even one does not turn up in grep, the publishing step cannot find that value either, so it is not replaced at install time (the bundler transformed the value, or it dropped out into a runtime lookup). In that case, refer to "Inlining the values as literals" above and fix it so the value remains an intact literal.
Static build constraints
The build artifacts of a Market App follow the same static constraints as Web Hosting.
- There is no server runtime. You must build with a static export (no SSR).
- When unzipped, there must be 100 files or fewer.
- There must be an
index.htmlat the top (root) of the bundle. - Calls to WEEGLOO APIs (CDA and so on) are made directly from the browser.
The detailed static constraints and file-bundle rules are covered in Website Deployment.
The screens you built go into the App Bundle
Once validated, the build artifacts are placed into the App Bundle (a versioned package of the app) when you publish. The resources you selected together on the publish screen are placed into the same bundle and copied into the installing Space at install time. The procedure for publishing and bumping versions is covered in Publishing an App.
If your app accepts its own members
Everything up to here covers the case of reading public content that anyone can read via CDA. If your app accepts its own sign-up and login, it uses ServiceLogin and the official client SDK. In this case the browser calls ACDA (App Content Delivery API), not CDA, with the member's token. Setup and integration are covered in Service Member Login.
The authentication method of an installed Market App is covered by App Auth, and the users who have access to an installed app are covered by App Member.
What to do next
- Publishing an App: covers the content studio procedure for publishing the app you built (the App Bundle) to the marketplace.
- Website Deployment: covers the basics of Web Hosting, such as static builds, the 100-file limit, and the
index.htmlroot. - Tokens: covers how to issue the Delivery Access Token you inline into the build with a least-privilege SpaceRole.
- API Reference: covers the technical specifications, such as the request format of CDA (the delivery API) that the app's screens call when loading content, and ACDA for apps that accept their own members.
