configuring-taubyte-build-runtime
Configuring Taubyte Build & Runtime
When to use
- Adding a
.taubyte/build.shto a function/website/library repo for the first time - Switching the build image (e.g.
taubyte/go-wasi:latest→taubyte/go-wasi:v2) - Declaring environment variables that the build needs to see
- A website builds but serves nothing (empty
/out) - A function compiles to WASM but the runtime sees an empty / wrong env value
- The build script for one stack (Vite) was copy-pasted onto another (CRA) and now the bundle output isn't found
The two files (every Taubyte buildable resource has them)
<resource>/
└── .taubyte/
├── config.yaml # image + workflow metadata (NOT env vars)
└── build.sh # the actual build script (where env vars live)
Where <resource> is one of:
| Resource | Path |
|---|---|
| Function | <project>/code/.../functions/<name>/.taubyte/ |
| Website | <project>/websites/<repo>/.taubyte/ |
| Library | <project>/libraries/<repo>/.taubyte/ |
Hard rules
.taubyte/config.yamlis for build metadata (image, workflow). It is not a place to declare runtime env vars..taubyte/build.shis the only correct place for build-time env vars. Useexport NAME=valueat the top, before the build commands..taubyte/build.shmust be non-empty and executable. An emptybuild.sh"builds successfully" while producing nothing — this is the most common silent failure.- Websites must write deployable static output to
/out. See building-taubyte-websites. - Don't guess the website framework's output directory. Vite emits
dist/, Create React App emitsbuild/, Next.js emits.next/(then exports), etc. Readpackage.json(scripts.build) to confirm before scripting.
Function — config.yaml (canonical pattern)
version: 1.00
environment:
image: taubyte/go-wasi:latest
workflow:
- build
Picking an image:
| Image | Use for |
|---|---|
taubyte/go-wasi:latest |
Default for Go serverless functions and libraries (TinyGo + WASI; handlers use package lib in the usual scaffold). |
taubyte/go-wasi:v2 |
Pinned major when you need stability across CI runs (image/layout may differ from latest; only switch when you intend to). |
If you change the image here, also use the same image for any local Docker WASM verify (see verifying-taubyte-functions) so local and cloud builds match.
Function — build.sh (canonical pattern)
#!/bin/bash
# taubyte/go-wasi:latest: non-login build environments (Dream/monkey, some Docker invocations) often lack
# go/tinygo on default PATH — export before wasm.sh or builds fail ("go: command not found", tinygo missing).
export PATH="/usr/local/go/bin:/usr/local/tinygo/bin:${PATH}"
. /utils/wasm.sh
# Build-time env vars for this resource — declare here, NOT in config.yaml:
# export API_BASE_URL="https://api.example.com"
# export FEATURE_FLAG_X=1
build "${FILENAME}"
ret=$?
echo -n $ret > /out/ret-code
exit $ret
What this does:
export PATH=...makestaubyte/go-wasi:latestreliably findgoandtinygowhen the shell is not a full login environment (matches what verifying-taubyte-functions does inside Docker verify).. /utils/wasm.shsources the toolchain helpers provided by thetaubyte/go-wasiimage.build "${FILENAME}"invokes the helper that compiles the function into WASM.FILENAMEmust name the actual entry.gofile at the function root (the CLI scaffold usesempty.go). Renaming the file without updatingFILENAME(or renamingempty.go→lib.gohoping to fixpackage libnoise) often yields TinyGo / verify errors or missingartifact.wasmon remote builds — stay onempty.gounless you have an end-to-end verified change for both the file name andbuild.sh.- The script writes the build's exit code to
/out/ret-codeand exits with the same code (Taubyte uses both signals).
Library — build.sh and config.yaml
Libraries follow the same shape as functions (typically Go + taubyte/go-wasi:latest). Most generated library scaffolds work as-is. Edit only when you need extra build env or a different image.
Website — config.yaml (typical)
Websites usually use a Node-based image. Example minimal config.yaml (the exact image string may vary by template):
version: 1.00
environment:
image: node:20-alpine
workflow:
- build
If the template generated a different image string, leave it as-is unless you have a reason to change.
Website — build.sh patterns by stack
The script must end with deployable static files in /out. Read package.json's scripts.build to find the real output directory before scripting. Do not assume.
Plain static HTML (no bundler)
#!/bin/bash
cp index.html /out/
exit $?
Vite (default output dist/)
#!/bin/bash
set -euo pipefail
npm ci
npm run build
cp -r dist/. /out/
Create React App / react-scripts (output build/)
#!/bin/bash
set -euo pipefail
npm ci
npm run build
cp -r build/. /out/
Other stacks
For Next, Nuxt, custom webpack, etc. — run that stack's install + production build commands, then cp -r <framework-output-dir>/. /out/ using the directory that tool documents. If unsure, ask rather than guess.
Same-origin website + API pattern (Vite + HTTPS functions)
When the website and the HTTPS functions share a domain (/api/... routes on the same configured domain):
- In
vite.config.ts, setenvPrefix: ["VITE_", "APP_"]if the client readsAPP_*build-time vars. - Default the API base to
window.location.originso the browser hits same-origin functions after deploy. - Document
APP_API_BASE_URL(or whatever name you pick) in.env.examplefor Dream/local where the API may be on another host or port. - In project config, attach the website and the HTTPS functions to the same
domainsentry so relative/api/...calls resolve.
Build-time env vars (the only correct place is build.sh)
#!/bin/bash
set -euo pipefail
# Declare env vars HERE, before the build commands run:
export VITE_PUBLIC_BASE="/"
export APP_API_BASE_URL="${APP_API_BASE_URL:-}"
export NODE_OPTIONS="--max-old-space-size=4096"
npm ci
npm run build
cp -r dist/. /out/
Things to know:
- These vars are build-time (visible to the bundler / compiler), not runtime container env in the running cloud.
- The bundler will inline values that match its prefix (e.g. Vite inlines
VITE_*and any prefixes you declare inenvPrefix). - Secrets baked at build time end up in the deployed bundle. Don't use
build.shenv for secrets that must stay private — surface those through the platform's secret mechanism instead.
Common build outputs (where things land)
| Resource | What build.sh should produce |
|---|---|
| Function | Compiled WASM written by the build helper; ret-code in /out |
| Library | Compiled WASM (same shape as a function); ret-code in /out |
| Website | Whatever your stack emits, copied into /out (HTML/CSS/JS/assets) |
Validating before push
Pre-push validation progress:
- [ ] .taubyte/config.yaml exists and parses as YAML
- [ ] .taubyte/build.sh exists, is non-empty, executable (chmod +x)
- [ ] build.sh references the real output dir of this stack (Vite -> dist/, CRA -> build/, ...)
- [ ] Env vars (if any) are exported in build.sh, NOT declared in config.yaml
- [ ] For functions: image in config.yaml matches the local verify image (if local verify is in scope)
- [ ] git push the resource repo
- [ ] Remote: wait for webhook build / Dream: dream inject push-specific
Recovery — symptom → likely cause
| Symptom | Likely cause | Fix |
|---|---|---|
Remote function build: .taubyte not found under .../<app>/functions/<name> |
Sources live under code/applications/<app>/functions/... but the builder expects code/<app>/functions/... (or the path in the log differs) |
Move the function folder to the path shape in the error; see creating-taubyte-resources |
Function build: TinyGo errors / no artifact.wasm after renaming empty.go |
FILENAME / entry file / image expectations out of sync |
Revert to scaffold empty.go and build "${FILENAME}" with default FILENAME; keep export PATH=... for go/tinygo |
| Website "deploys" but serves blank / 404 | /out is empty after build.sh |
Confirm the framework output dir; copy from there into /out |
| Bundler env value is empty in browser | Var declared in config.yaml instead of build.sh |
Move to export NAME=value in build.sh |
| Function builds but old behavior persists | Not pushed / not injected on Dream | git push then dream inject push-specific (see triggering-dream-builds) |
| Cloud build uses wrong toolchain version | image: in config.yaml not updated |
Edit config.yaml; also update local verify image to match |
| Env var fine in CI but missing in deployed bundle | Bundler env-prefix policy excludes it (e.g. Vite without envPrefix) |
Add the prefix to bundler config or rename the var |
build.sh runs but exits non-zero silently |
Missing set -euo pipefail masks earlier failures |
Add it at the top of every Node-based build.sh |
Gotchas
- Dream / POSIX
shfor some website (and older) builds:/bin/shmust not useset -o pipefailorset -uunless every referenced variable exists. Prefer#!/bin/sh+set -eonly for minimal static sites;set -eu+ implicit$CODEyieldsparameter not set. Matches field reports againstillegal option -o pipefailon Alpine/sh. taubyte/go-wasiwasm.sh+.gitunderSRC=/src: if the recipe doesmv .git …insidecd "${SRC}", ensuremkdir -p /src/.gitexists before the build helper runs (Dream-class builds).- Env vars in
config.yamldo nothing for build-time use. Alwaysexportthem inbuild.sh. - Vite-only
cp -r dist/* /out/on a CRA repo silently produces an empty/out. Always confirmpackage.json'sscripts.buildoutput directory. cp -r dist /out/puts files under/out/dist/instead of into/out/. Usecp -r dist/. /out/(orcp -a dist/. /out/) to copy the contents of the directory.- Empty
build.shis the silent killer for--template emptyresources. Always populate before push. - Forgetting
chmod +x build.shcan cause "permission denied" on some build images. Templates usually mark it executable; new files you create may need it. - Local verify image drift. If
config.yamlsays:v2but you run the Docker WASM recipe with:latest, you may not reproduce a cloud failure locally. - Editing
build.shbesideindex.html. A mistaken paste can merge HTML into the shell script — especially on websites. The script must stay valid bash only; see building-taubyte-websites.
Related skills
building-taubyte-websites— the/outrule + minimal HTML baselineverifying-taubyte-functions— local Docker WASM verify with the matching imagewriting-taubyte-functions— the Go SDK + handler authoring this script buildscreating-taubyte-resources—tau newflag patterns for the resources whose builds this skill configurestriggering-dream-builds— push the rebuilt resource into Dream after editingpushing-taubyte-projects— push the repo containing the edited.taubyte/
More from taubyte/skills
verifying-taubyte-functions
Verifies a Taubyte Go function locally via the `taubyte/go-wasi` Docker recipe (preferred over `tau build`, with tmpfs+bind-mount-ro to avoid root-owned artifacts in the source tree), and verifies a function actually serves on Dream by curling the gateway with the right `Host:` header (plus `/etc/hosts` mapping for `*.localtau`). Use when locally compiling a Go function to WASM, when smoke-testing a function before pushing, or when probing a Dream-hosted HTTP function from the laptop.
12creating-taubyte-resources
Creates Taubyte resources non-interactively via `tau new` for domain, website, library, function, application, database, storage, messaging, and service. Encodes the project-vs-application scope rule, the database `min < max` constraint, the website/library `--generate-repository` + import sequence, and the forbidden `--generated-fqdn-prefix` flag. Use when adding any resource to a Taubyte project's config repo.
12diagnosing-dream-builds
Diagnoses Dream local-cloud builds when `tau list/query builds` is empty or unreliable, by hitting the jobs HTTP endpoint directly (`GET /jobs/<project_id>`, `GET /job/<job_id>`) using the GitHub token from `~/tau.yaml`, then downloading logs with `tau query logs --jid`. Use when Dream builds appear silent, the build table is empty after `dream inject`, or you need raw job ids and logs for a failing build.
11taubyte-resource-creation
Scope-aware resource creation workflow. Uses non-interactive mode by default and references the shared flags catalog.
11taubyte-push-build-verify
Pushes config/code and verifies builds/logs. Includes website/library push handling with tau command first, git fallback.
11taubyte-scope-routing
Routes project-level vs application-scoped work; defaults to a website when a browser UI is logically appropriate; avoids unnecessary applications for simple website/function-only tasks unless needed.
11