Build configuration
When you push to your release branch, VelvetPress clones the repo, runs your
build, and packages the result into the ZIP your customers install. Not
everything in the repo belongs in that ZIP — VCS metadata, node_modules, the
uncompiled sources you build from, and local dev tooling all add weight (and
sometimes secrets) without helping the customer's site. This page covers how
VelvetPress decides what to exclude.
What gets excluded
Three layers decide whether a file ships, applied as a union — a file is dropped if any layer excludes it:
Built-in defaults. Out of the box VelvetPress drops the development files no WordPress ZIP should carry: VCS metadata (
.git,.github), dependency trees (node_modules), uncompiled sources (src), lockfiles, and editor / linter config. The exact patterns are pre-seeded into the dashboard's Exclude Patterns field (see below), so the dashboard always shows the live, authoritative list.Exclude Patterns (dashboard). The Exclude Patterns field under Configure Product holds the list above and lets you replace it with your own — one minimatch glob per line, where a directory needs a
/**suffix (tests/**, nottests/). Leaving it empty ships everything; clearing it back to the defaults is one click on Reset to defaults. Use this for per-product rules you manage from the dashboard..distignore(in the repo). A repo-local.distignorefile adds further exclusions that live with your code. See below.
The precedence is defaults → dashboard Exclude Patterns → .distignore.
Because the layers union, a .distignore rule can only add exclusions on top
of whatever the first two layers already drop — it cannot re-include a file that
the defaults or your Exclude Patterns already removed.
.distignore
.distignore is the WP-CLI wp dist-archive
community standard: a file you commit to your repo's root that names the dev
infrastructure which should never ship — docker-compose.yml, scripts/,
.DS_Store, CI config, and the like. Because it's version-controlled alongside
the code, the exclude list travels with the repo and is reviewed like any other
change, rather than living only in the dashboard.
Syntax
.distignore uses gitignore syntax, so the rules read exactly like a
.gitignore:
# Comments and blank lines are ignored
docker-compose.yml # a single file
scripts/ # a directory and everything under it
*.log # a glob
!keep.log # re-include a file an earlier pattern dropped
Negation (!pattern), trailing-slash directories, and nested ** all behave as
they do in git. .distignore itself is always excluded from the artifact — it's
a build instruction, not something your customers need.
When it takes effect
.distignore is read at deploy time, from the commit being packaged. It
takes effect on your next push — there's no history rewrite and no need to
backfill old releases. Add or edit the file, push to your release branch, and
the new exclude list applies to that build.
A malformed .distignore (for example a binary file) is skipped with a warning
in the build log rather than failing the build, so a stray file can never block
a release.
First use case
The velvetpress.co theme
ships a .distignore so its docker-compose.yml, scripts/, and editor cruft
stay out of the production WordPress install on every push.
Debugging a missing file
When a file you expected is absent from a build, check the build log: the worker
logs the files .distignore removed from the artifact (e.g. ".distignore
excluded files from the artifact"). If your file isn't in that list, it was
dropped by the built-in defaults or your dashboard Exclude Patterns instead —
work back up the three layers above.