Developing for Stackboard
What Stackboard runs
Section titled “What Stackboard runs”Stackboard reads an entry document from your repository: index.html at the
root by default, or any path you set. It inlines the local stylesheets and
scripts that document names, rewrites the other asset URLs, and serves the
result.
It does not run a build. Whatever is committed is what runs, so if your project has a build step, commit its output.
Project structure
Section titled “Project structure”The simplest Deployable is three files at the root:
index.htmlstyles.cssapp.jsindex.html links the other two the ordinary way, and Stackboard follows those
links.
With a build step, commit the output folder and point the entry path at its
index.html:
src/ source, ignored by Stackboarddist/ index.html entry path: dist/index.html assets/ app.js app.cssThe entry document’s folder is the site root. In dist/index.html, a
reference to /assets/app.js means dist/assets/app.js, not the repository
root. That’s what makes built output work unchanged.
Frameworks
Section titled “Frameworks”Anything with a static adapter works, as long as the build output is committed:
| Framework | Setting | Output |
|---|---|---|
| Vite | default | dist/ |
| Astro | default | dist/ |
| Create React App | default | build/ |
| Next.js | output: 'export' |
out/ |
| SvelteKit | adapter-static |
build/ |
Frameworks needing a Node server at runtime won’t run, since there is no server to run them on.
Plain HTML with a script tag is a perfectly good Deployable. Don’t add a build step you don’t need, because every one of them is something to remember to re-run before committing.
Assets and size
Section titled “Assets and size”Relative and root-relative paths resolve inside the repository. Absolute URLs are left alone, so libraries and fonts from a CDN load normally.
The entry document and the files it pulls in have a 20 MB budget, applied to each file and to the total. That is generous for hand-written code and easy to exceed by committing a large media file.
Environment variables
Section titled “Environment variables”Write %VAR% anywhere in your source and Stackboard substitutes the stored
value at launch:
const region = '%DEFAULT_REGION%';A placeholder with no stored value is left as the literal text %VAR%, so a
typo shows up on the page rather than silently becoming an empty string.
Substitution applies to public variables only. See Secrets.
Secrets and API targets
Section titled “Secrets and API targets”Secrets are stored in Stackboard, never in the repository, and never reach the browser. Your code cannot read one, but it can use one.
Configure an API target: a name, an origin, which secret to attach, and whether it goes in a header or a query parameter. Restrict the methods and paths it accepts, since a target otherwise grants the whole origin.
Then call the API normally. Requests to a configured target’s origin are rerouted through Stackboard’s proxy, which attaches the credential after the request leaves the browser:
const res = await fetch('https://api.example.com/v1/items');stackboard.fetch(target, path) does the same explicitly. Blocked calls are
logged with a reason, so a too-narrow allowlist is easy to tell from code asking
for something new.
Declare a variable without a value and each person supplies their own before the Deployable launches. Those are visible to nobody else, including you.
Gotchas
Section titled “Gotchas”A secret written as %VAR% is not substituted. Stackboard leaves it as the
literal placeholder on purpose. If a key is missing at runtime, that’s why: the
code is trying to inline something it must reach through a target instead.
Local development needs its own arrangement. Use a .env file, a dev
fallback, or a local proxy, and replace it with %VAR% and an API target for
Stackboard. Never commit the .env.
Only the proxy is reachable. The page runs sandboxed, and network access is
restricted to Stackboard’s origin. A fetch to an API with no configured target
fails, however permissive that API’s CORS headers are.
Browser storage is unavailable. The sandbox gives the page an opaque origin,
so localStorage, sessionStorage, and cookies don’t work.
Stale build output. Since Stackboard runs what’s committed, forgetting to rebuild before committing ships the previous version. Building in CI and committing the result avoids this.
A path that’s right locally can be wrong here. Check that your entry document’s links work when its own folder is the site root.
