Install
Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/jeydweirdough/code-builder/releases/download/v1.1.0/code-builder-1.1.0.zipDeploys Git repositories on your own WordPress server. It clones the repo to
disk, runs its install and build commands, and serves the build output as real
files at /app/{project}/ — with per-project access control, live build logs,
and one-click rollback across the last 5 builds.
Because the output is real files on disk, everything that normally breaks when
a site is reassembled from a database works here: relative paths, @font-face
URLs, video files, source maps, and bundler-hashed filenames like
index-BaR9xQ7z.js.
A project can also take over the site root
instead of living at /app/, be built in CI and posted here
when the server can't build it, and keep its
rollback history in cloud storage when disk
is tight. Projects → System Health tells you what your server actually
supports.
Filling in the Build settings
This is the part most people get stuck on, so start here.
You usually don't have to fill anything in. Leave Install Command, Build
Command and Output Directory blank and hit Deploy. Code Builder reads your
repository — its package.json, lockfile and config files — works out the right
values, uses them, and then writes them back into the form so you can see
exactly what it decided and adjust from there.
Fill a field in yourself only when you want to override that decision. A value you type always wins; a blank field means "figure it out".
The three fields
| Field | What it is | Blank means |
|---|---|---|
| Install Command | Fetches dependencies. Runs first. | Detected from your lockfile |
| Build Command | Compiles the site. Runs second. | Detected from your package.json scripts |
| Output Directory | The folder that gets published | Auto-probed after the build |
All three are optional. A repository of hand-written HTML needs none of them.
What gets detected, by project type
Find your project in the left column. The three right-hand columns are what Code Builder fills in — and what you should enter if you'd rather set it manually.
| Your repository has… | Install Command | Build Command | Output Directory |
|---|---|---|---|
vite.config.js / .ts |
npm install |
npm run build |
dist |
| Vite + React | npm install |
npm run build |
dist |
| Vite + Vue | npm install |
npm run build |
dist |
next.config.js or a next dependency |
npm install |
npm run build |
out |
angular.json |
npm install |
npm run build |
dist (see note) |
nuxt.config.ts or a nuxt dependency |
npm install |
npm run build |
dist |
react-scripts (Create React App) |
npm install |
npm run build |
build |
| React without a bundler config | npm install |
npm run build |
build |
tailwind.config.js, or @tailwindcss/cli |
npm install |
npm run build:css |
(blank — repo root) |
composer.json only |
composer install --no-dev --optimize-autoloader |
(none) | (blank — repo root) |
index.php / header.php, no JS build |
(none) | (none) | (blank — repo root) |
Plain .html / .css / .js files |
(none) | (none) | (blank — repo root) |
npm install is shortened for readability in that table — the real detected
value carries flags (npm install --no-audit --no-fund), and a pnpm/yarn/bun
project gets its own tool instead. The next section gives the exact strings.
Angular and Nuxt nest one level deeper than everyone else —
dist/my-app/browser. You don't need to write that out. When the folder you point at contains exactly one folder and nothing else, Code Builder walks down into it automatically, up to three levels.
Which package manager gets used
Your lockfile decides, not your preference. Running npm install in a repo
with a pnpm-lock.yaml produces a different dependency tree than the one the
project's authors tested, and that difference is a real source of "works
locally, breaks on the server".
| Lockfile in the repo | Install Command used |
|---|---|
pnpm-lock.yaml |
pnpm install --frozen-lockfile |
bun.lockb or bun.lock |
bun install |
yarn.lock |
yarn install --frozen-lockfile |
package-lock.json |
npm install --no-audit --no-fund |
package.json, no lockfile |
npm install --no-audit --no-fund |
composer.json, no package.json |
composer install --no-dev --optimize-autoloader |
The build command uses the same tool: a pnpm project gets pnpm run build, not
npm run build.
Why
npm installand notnpm ci?npm ciis stricter and technically more correct, but it hard-fails whenpackage-lock.jsonandpackage.jsonhave drifted apart — which happens constantly in repos wherepackage.jsongets edited by hand. A deploy shouldn't need babysitting, so the more forgiving command is the default. Typenpm ciinto the field yourself if you want the strict behaviour.
Which npm script gets picked
Code Builder looks through your package.json scripts block in this order and
takes the first one that exists:
build → build:prod → build:production → build:css → export → generate
If none of those exist, no build command runs — which is correct for a repository that has nothing to compile.
That build:css entry is there for a specific and common case: a hand-written
HTML or PHP site whose only build step compiles a Tailwind stylesheet in place.
Such a repo typically has no build script at all, just:
{
"scripts": {
"build:css": "tailwindcss -i ./assets/input.css -o ./assets/tailwind.css --minify"
}
}
Nothing is bundled, so the output directory is the repository root — the site is the source tree, with one stylesheet freshly compiled inside it. Leave Output Directory blank for these.
How Output Directory is auto-probed
When you leave it blank, Code Builder looks for the first of these that exists and isn't empty, then descends into any single-folder nesting:
dist → build → out → _site → public
If none of them exist, it publishes the repository root. That is the right answer for static sites, PHP sites and Tailwind-only sites, and the wrong answer for a bundled app whose build failed to produce anything — which is why an empty result stops the deploy with an error rather than publishing a source tree.
Rules for the command fields
One command per field. No shell operators.
This is rejected:
npm install && npm run build ✗ no &&
npm run build; echo done ✗ no ;
npm run build | tee build.log ✗ no pipes
npm run build > output.txt ✗ no redirects
npm run $(cat which-script.txt) ✗ no command substitution
Chain steps inside a package.json script instead, and call that:
{
"scripts": {
"deploy": "npm run clean && npm run build:css && vite build"
}
}
…then set Build Command to npm run deploy. This is better anyway: the steps
live in your repo where they're version-controlled and reviewable, and the build
log attributes failures to the step that actually failed.
The executable must be one of these:
npm npx pnpm pnpx yarn bun bunx node
composer php git make hugo tailwindcss sass vite
A command that breaks either rule isn't saved, and the form tells you so rather than accepting it and silently skipping the step at deploy time.
Flags and arguments are fine — composer install --no-dev,
npx tailwindcss -i ./src/input.css -o ./dist/out.css --minify. Quoted
arguments with spaces in them are preserved.
The other project settings
Root Directory
For a monorepo: the subfolder the build runs in. If your site lives in
packages/web/, put that here, and Install/Build/Output are all resolved
relative to it. Blank means the repository root.
Framework
Cosmetic — it sets the badge shown on the project card. What actually determines the build is the three command fields above. It's filled in automatically on first deploy.
Who can view it
Checked on every request, including images, fonts and scripts.
| Setting | Who gets through |
|---|---|
| Public | Everyone |
| Logged-in users | Any logged-in WordPress user (others are sent to the login form) |
| Administrators only | Users with manage_options |
This is meaningful rather than decorative: build files are made unreadable
directly on disk (a deny rule is written into
wp-content/code-builder/), so /app/{project}/ is the only route to them.
SPA fallback
Turn this on for a client-routed app — React Router, Vue Router, TanStack
Router. Without it, loading /app/mysite/dashboard directly returns 404,
because there is no dashboard file on disk; with it, index.html is served
and your router takes over.
Requests that look like an asset (anything with an extension other than
.html) still 404 properly. Handing index.html to a missing .js request
would turn a clean 404 into a JavaScript syntax error, which is much harder to
debug.
Leave it off for static sites and multi-page sites — it would mask genuine broken links.
You may not need it at all: an extensionless URL is already matched against a
matching .html file, so /app/mysite/about finds about.html on its own.
That covers most static site generators without any fallback.
Auto-deploy
Deploys on every push to the tracked branch. Two mechanisms, and you get whichever works on your host:
- Deploy hook — copy the Payload URL and Secret from the project's Settings tab into your repository's Settings → Webhooks (content type: JSON). Instant.
- Hourly check — if GitHub can't reach your site (local, staging behind a VPN, IP-allowlisted), a scheduled check compares the branch's latest commit against the last one deployed and deploys only when it has changed.
Serving a project at the site root
By default a project lives at /app/{project}/. If you want it to be the
site — at example.com/ rather than example.com/app/mysite/ — go to
GitHub Defaults → Override Controls, pick the project, and tick what it
should take over.
There are two switches because they're useful separately.
Override Main Site (/)
The project becomes your site's front end. It answers / and every page URL
beneath it, and a URL the build has no file for returns the project's 404.
This means your WordPress pages, posts and archives stop being reachable at their URLs. That is the intended behaviour, not a side effect: two different answers for one URL is exactly what makes a migrated site feel broken. Nothing is deleted — unticking the box brings everything back immediately.
What is never taken over, so you can always get back in and turn it off:
/wp-admin/ /wp-login.php /wp-json/ admin-ajax.php
wp-cron.php xmlrpc.php /feed/ wp-sitemap.xml
robots.txt ?rest_route=… ?preview=… /app/{project}/
That last one matters: the project stays addressable at its own /app/ URL even
while it's serving the root, so you can always compare the two.
If the project has never been deployed, nothing is taken over. With no build on disk the override stands aside entirely and your site carries on as it was. The same applies if a build's files are later deleted — it fails open rather than blanking the site.
Override Assets (/assets/)
Serves static files — images, CSS, JS, fonts — from the build at root-level
paths. Useful on its own when you want project pages to stay at /app/{project}/
but their assets to resolve from /assets/….
One thing to know: "asset" is decided by file extension, and
.xmlcounts as one. If a plugin such as Yoast serves/sitemap.xml, it will 404 while this is ticked. WordPress's ownwp-sitemap.xmlis unaffected.
Deploying a build made somewhere else
Some repositories can't be built on the WordPress host at all — proc_open is
disabled, or the build needs more memory or a newer Node than the server has.
For those, build in CI and post the finished output here.
Endpoint — shown on the project's Settings tab:
POST /wp-json/code-builder/v1/deploy-artifact/{project-slug}
From GitHub Actions, or any CI:
cd dist && zip -qr ../build.zip . && cd ..
gzip -kc build.log > build.log.gz
curl -f -X POST "https://example.com/wp-json/code-builder/v1/deploy-artifact/mysite" \
-H "X-CPB-Token: $CODE_BUILDER_SECRET" \
-F "artifact=@build.zip" \
-F "log=@build.log.gz" \
-F "sha=$GITHUB_SHA"
$CODE_BUILDER_SECRET is the same webhook secret from the Settings tab. Only
artifact is required.
Everything after extraction is the normal pipeline, so an artifact deploy gets
the same release directory, the same rollback, the same pruning and the same
access control as a git deploy. It needs no git, no Node and no proc_open —
only PHP's zip extension.
The build log
Send your CI log as log and it's stored with the deployment and shown in the
Logs tab, so the record of how a build was produced lives next to the build.
Gzipped or plain text — either works. Compression is detected from the file's
own bytes rather than a header, because a CI job that gzips but can't set
Content-Encoding is common, and so is a header that claims gzip over plain
text. Only the last 2,000 lines (up to 500 KB) are kept; the end of a build
log is the part that explains it.
Details worth knowing
| Zip what? | The contents of your build directory. A single wrapping folder (zip -r build.zip dist) is unwrapped automatically. |
| Authentication | X-CPB-Token header, or Authorization: Bearer. A raw .zip request body can use X-Hub-Signature-256 HMAC instead — multipart can't, because PHP consumes the request stream and there's no raw body left to sign. |
| Optional fields | sha records which commit this was, so the hourly check doesn't rebuild it. actor sets who gets credited in the Deployments table. |
| Response | Synchronous — you get the real outcome and deployment_id, not "started". |
| Size limit | The archive may expand to 2 GB (cpb_artifact_max_uncompressed_bytes). Your host's upload_max_filesize and post_max_size apply to the upload itself. |
Archive entries are checked before anything is written: an entry that would
escape the build directory (../../wp-config.php) rejects the whole archive
rather than being skipped, and nothing is extracted.
Environment Variables
Per-project, on the project's own tab. They're passed to the install and build commands and stored encrypted.
The Sensitive tick-box
Each variable is either a secret or it isn't, and that changes two things:
| Sensitive ✓ | Not sensitive | |
|---|---|---|
| On this screen | Masked, and never sent back to the browser after saving. Leave the field blank to keep the stored value. | Shown in full, so you can read and check it |
| In build logs | Replaced with *** wherever it appears |
Left alone |
Tick it for API keys, tokens and passwords. Leave it unticked for ordinary
configuration — an API_URL you can't read is a setting you can't verify, and
a base URL replaced by *** in every line of build output hides the one detail
you opened the log to check.
New variables are sensitive by default. Revealing a value should be a deliberate act, not something you get by forgetting a checkbox.
Variables saved before this existed are all treated as sensitive, because that's exactly how they already behaved. Nothing is revealed by upgrading. Untick the ones that aren't really secret and save.
Anything your build tool exposes to browser code ends up in the published files. Names starting with
VITE_,NEXT_PUBLIC_,REACT_APP_,PUBLIC_,NUXT_PUBLIC_,GATSBY_orEXPO_PUBLIC_are compiled into your bundle by design and are readable by anyone who loads the site. Ticking Sensitive cannot prevent that — it only affects this screen and your logs. Such names are markedpublicin the table, and saving one as sensitive tells you so.
When your variables are available
This depends on what kind of project it is, and the difference catches people out.
A bundled site (Vite, Next, React, Vue, Tailwind) uses its variables during the build. They're passed to the install and build commands, the bundler bakes whatever it needs into the output, and nothing is read afterwards — the published site is static files.
A PHP application (Runtime set to PHP Application) reads its configuration on every request, long after the build finished. So its variables are also made available at runtime, two ways, because application code picks whichever its author preferred:
getenv(),$_ENVand$_SERVERare populated before your PHP file runs.- A
.envfile is generated in the live directory, for code that loads one withvlucas/phpdotenvor parses it directly.
That file is written from what's on this screen and rewritten on every deploy and every rollback — so a release promoted six weeks later runs against today's credentials, not the ones that happened to be set when it was built. Editing it by hand is pointless; the next deploy overwrites it.
Saving takes effect immediately for PHP projects. There's nothing to rebuild, so fixing a password doesn't need a redeploy.
A
.envcommitted to your repository is ignored. It's excluded from the release along with.gitandnode_modules, so the generated file is the only one your app sees. Put the values on this screen instead.The generated file is never web-readable. Any path whose name begins with a dot is refused by the router before the file is opened, and the builds directory carries its own deny rules.
/app/{project}/.envis a 404.
The site-wide Environment Variables screen is a different thing — it holds
configuration for the plugin itself (the default GitHub token, CPB_ALLOW_PHP,
acceleration, cloud storage), not values for your builds. See
Site-wide settings for the full list.
Deployments and rollback
Every successful build is kept as an immutable release directory. The last 5 are retained; older ones keep their record in the Deployments table but lose their files.
Rollback ("Make live") re-publishes a retained release. There's no rebuild and no network access involved — the files are already on disk exactly as they shipped — so it's effectively instant and can't fail on a dependency that has since disappeared from the registry.
A failed deploy never touches what's live. The previous build keeps serving while you read the log.
The currently-live release is never pruned, even after you've rolled back to an old one.
Keeping history in cloud storage
Five releases of a modern front-end build is easily a gigabyte, and shared hosting quotas are smaller than people expect. Point Code Builder at an S3-compatible bucket and the history moves there instead.
Works with AWS S3, Cloudflare R2, DigitalOcean Spaces, MinIO and Backblaze
B2's S3 endpoint. No Composer package and no AWS SDK — requests are signed
directly. Set these in .env or the site-wide Environment Variables screen:
CPB_S3_BUCKET=my-bucket
CPB_S3_ACCESS_KEY=…
CPB_S3_SECRET_KEY=…
CPB_S3_REGION=auto # 'auto' for R2
CPB_S3_ENDPOINT=https://<account>.r2.cloudflarestorage.com # blank for AWS
It's off until all three of bucket, access key and secret key are set.
What changes when it's on: local disk keeps one release — the one being served — and the other four live in the bucket. Rolling back to a release that isn't local downloads it first, which is slow exactly once, for an operation you're already waiting on.
Visitors are never served from cloud storage. The live release is always a local file, so the router stays a filesystem read. A bucket outage, an expired key or a typo'd endpoint costs you the older releases and nothing else — the site keeps serving, and deploys keep succeeding.
That's also why a failed upload never fails a deployment. The site is already live by the time the archiving runs; turning "the bucket is unreachable" into a failed deploy would invent an outage rather than report one. It's reported on the System Health screen instead, and until it succeeds the full history simply stays on local disk.
System Health
Projects → System Health. Answers "will a deploy actually work on this server?" before you find out by reading a failed build log.
| Row | What it tells you |
|---|---|
External processes (proc_open) |
Whether anything can be cloned or built here at all |
| PHP memory limit | Whether large builds and archive extraction will fit |
| Disk space | Free space and total capacity of the volume holding the builds |
| Used by Code Builder | How much of that is yours, broken down by builds, checkouts, caches, logs and scratch |
| Storage directory | Whether the web server can write where builds go |
| ZIP / Gzip support | Whether pre-built archive deploys and compressed CI logs will work |
git, node, npm, pnpm, yarn, bun, composer |
Found or not, and the version — resolved against the web server's PATH |
| Cloud release storage | Whether the bucket is configured and reachable |
That PATH distinction is the point of the whole screen. The web server runs as a
different user than your shell, so "but node -v works when I SSH in" is a
common dead end. This screen resolves each binary the way a deploy will and then
actually runs it, so it can tell "not installed" apart from "installed but this
user can't execute it".
Results are cached for five minutes — reading a binary's version means launching
it, seven times over. Re-check now skips the cache, which is what you want
while you're fixing a PATH. The size of repositories/ is measured under a file
budget, so a huge node_modules reports "at least N" rather than holding the
page open.
Speeding up file serving
Once a request has passed its access check, copying the bytes is work PHP adds nothing to — but it holds a PHP worker for the whole transfer. That's fine for a small page and wasteful for a 200 MB video or a page pulling sixty assets.
Both nginx and Apache can be handed the file instead. Set CPB_ACCEL:
| Value | Behaviour |
|---|---|
auto (default) |
Uses X-Sendfile only if mod_xsendfile is visible to PHP. Otherwise streams from PHP, exactly as before. Always safe. |
nginx |
X-Accel-Redirect. Add the config block first — see below. |
apache / litespeed |
X-Sendfile. Apache also needs an XSendFilePath covering wp-content/code-builder/builds/. |
off |
Never hand off. |
auto deliberately won't guess at nginx or LiteSpeed. PHP runs as a separate
FastCGI process there, so it can't see what the server supports — and a header
the server doesn't understand doesn't degrade to "slower", it returns an empty
body. So those stay opt-in.
For nginx, System Health prints the exact block to paste, with your site's real build path already filled in:
location /cpb-internal/ {
internal;
alias /path/to/wp-content/code-builder/builds/;
access_log off;
}
internal is what keeps it safe — nginx serves that location only in response
to Code Builder's own header, never to a visitor who requests the path directly,
so per-project visibility still holds. Paste it, reload nginx, then set
CPB_ACCEL=nginx.
HTML files are always served by PHP whichever mode you use, because Code Builder
rewrites their <base> tag on the way out.
Cache headers
A bundler-hashed filename can't change contents without changing name, so it's
cached for a year as immutable. Both common shapes are recognised —
app.4f3a91b2.js and Vite's index-BaR9xQ.css.
Everything else is cached for an hour and revalidated, and HTML always
revalidates, so a redeploy is visible immediately. A filename without a hash
is never marked immutable, however static it looks: a year-long immutable cache
on style.css would make your redeploy invisible with no way to bust it. Files
in a non-public project are never stored by a shared cache at all.
When a deploy fails
Open the Logs tab — the full output of every step is there, and it streams live while the build runs.
| What you see | What it means |
|---|---|
"npm" was not found in this server's PATH |
Node isn't installed for the web server user, or isn't on its PATH. Different from your shell's PATH. |
PHP cannot start external processes (proc_open is disabled) |
Your host blocks running commands. Static/PHP repos still deploy; anything needing npm or composer won't. |
git was not found |
Not fatal — repositories are downloaded as archives instead. Slower, since it transfers everything each time. |
The build finished but its output directory "dist" does not exist |
Output Directory doesn't match what the build produced. Check the log for where files were actually written. |
The build produced no files to publish |
The build command "succeeded" but wrote nothing. Usually a wrong Output Directory or a build script that exits 0 without doing anything. |
Refusing to run "…" |
The command broke one of the two rules above — shell operators, or a binary that isn't allowlisted. |
was still running after 600 seconds and was stopped |
Build timed out. Raise it with the cpb_build_timeout filter, or find out what's hanging (usually a command waiting for input). |
The deploy process stopped unexpectedly |
PHP died mid-build — nearly always the memory limit or a hard request timeout. Check your host's PHP error log. |
"…" is not in this project's current build |
The file isn't in what was published. Check Output Directory; for a client-routed app, turn on SPA fallback. |
Your PHP app says its config or .env is missing |
Set Runtime to PHP Application on the Settings tab. Variables are only made available at runtime for PHP projects — a bundled site consumes them at build time. Then redeploy once. |
That is not a ZIP archive |
The posted artifact isn't a zip — a tarball, or a truncated upload. Checked by the file's own magic bytes, not its name. |
The archive contains an entry that would write outside the build directory |
A path in the zip escapes its root. Nothing was extracted. Zip from inside the build directory. |
The archive contained no publishable files |
The zip is empty, or holds only excluded files (.git, node_modules, .env). |
Send the project's webhook secret as an X-CPB-Token header |
The artifact request wasn't authenticated. Generate a secret on the Settings tab if there isn't one. |
| Cloud storage warning on System Health | Releases aren't being archived. Deploys and everything visitors see are unaffected; rollback to a non-live release won't work until it's fixed. |
Where files live on disk
wp-content/code-builder/
repositories/{project}/ the git checkout
builds/{project}/ what's live right now
builds/{project}_history/{id}/ the last 5 releases, for rollback
cache/ npm / composer / pnpm caches
logs/{project}_{id}.log build logs
temp/ scratch space
Nothing here is web-readable: .htaccess, web.config and an index.php stub
are written into the directory on activation so that the per-project access
rules can't be bypassed by requesting a build file directly.
Deactivating the plugin removes its scheduled check and rewrite rules and nothing else. Builds, checkouts and project settings all survive — deactivating a plugin isn't a request to delete a site's deployed content. Deleting a project does remove its files, and says so before it does.
Requirements
- WordPress 5.9+, PHP 7.3+
proc_openenabled — needed for any project with a build step. Without it you can still deploy pre-built archives from CI.gitrecommended; without it, repositories are fetched as archives- Node.js / npm (or pnpm, yarn, bun) installed and on the web server user's PATH — only for projects that need a JavaScript build
- PHP
zipextension — only for pre-built archive deploys - PHP
zlib— only to read gzipped CI logs (plain text is also accepted)
Projects → System Health checks every one of these on your actual server and tells you which are missing.
Site-wide settings
Set in .env (site root or plugin folder), as a constant in wp-config.php, or
on the Environment Variables screen. A constant beats the admin screen, which
beats .env. See .env.example for the annotated version.
| Setting | Default | Purpose |
|---|---|---|
CPB_ALLOW_PHP |
false |
Let a build's .php files execute — see below |
CPB_ACCEL |
auto |
Web server file-send acceleration |
CPB_ACCEL_INTERNAL_PATH |
/cpb-internal/ |
nginx internal location prefix |
CPB_S3_BUCKET |
— | Cloud release storage; off unless bucket + both keys are set |
CPB_S3_ACCESS_KEY |
— | |
CPB_S3_SECRET_KEY |
— | |
CPB_S3_REGION |
auto |
auto for R2; a real region for AWS |
CPB_S3_ENDPOINT |
— | Required for anything but AWS |
CPB_S3_PREFIX |
code-builder/ |
Key prefix, so one bucket can hold several sites |
CPB_GITHUB_OWNER / CPB_GITHUB_TOKEN |
— | Default credentials for private repos |
These are configuration for the plugin. Values for your builds are per-project, on the project's own Environment tab.
Filters
| Filter | Default | Purpose |
|---|---|---|
cpb_build_timeout |
600 |
Seconds a single install or build command may run |
cpb_max_build_history |
5 |
Releases retained per project |
cpb_route_base |
'app' |
First URL segment — change to serve at /sites/{project}/ |
cpb_user_can_view_project |
— | Override the visibility check with your own logic |
cpb_wants_runtime_env |
PHP projects only | Whether a project gets its variables at runtime (getenv() + generated .env) |
cpb_accel_mode |
detected | Force 'nginx', 'xsendfile' or '' per request |
cpb_local_release_limit |
1 with cloud storage, else 5 |
Releases kept on local disk |
cpb_low_disk_percent |
10 |
Free-space percentage that triggers a pre-build cleanup |
cpb_storage_provider |
S3 if configured | Supply your own CPB_Storage_Provider_Interface |
cpb_artifact_max_uncompressed_bytes |
2 GB |
Largest size a posted archive may expand to |
cpb_s3_timeout |
30 |
Seconds per cloud storage request |
PHP projects
A project whose output contains .php files needs CPB_ALLOW_PHP=true in your
.env or the site-wide Environment Variables screen. It's off by default
because it means repository content executes as real PHP with full WordPress
function access — equivalent in risk to the Theme/Plugin File Editor.
While it's off, a request for a .php file inside a build returns 403 — never
the file's source. Static, Vite, React, Vue, Angular and Tailwind projects never
need it.
Releases
1 release. Each count is every asset in that release; expand a row for the breakdown.