Search by

frootbox / workbench

82912759

Workbench for the Frootbox CMS: runs many local websites from one host and one vendor/ with the current packages

Package info

github.com/frootbox-packages/workbench

pkg:composer/frootbox/workbench

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

v0.1.0 2026-11-04 11:59 UTC

This package is auto-updated.

Last update: 2026-11-06 10:10:19 UTC


README

Runs many local Frootbox websites from one host and one vendor/ with the current packages of the monorepo. A website in the workbench is a normal project folder (composer.json, config/, extensions/, .env, storage/) without a vendor/ of its own. Live, every website keeps its own installation with the versions of its composer.lock; the workbench is for development only.

Set up

php path/to/frootbox2/packages/tools/workbench/bin/workbench init ~/Sites/frootbox-sites
cd ~/Sites/frootbox-sites && composer install

init writes workbench.yaml, composer.json, public/index.php, public/.htaccess and .gitignore lines. Then create a host in a web server with PHP 8.5, the name fb.localhost, the alias *.fb.localhost and the document root public/ of that folder. Browsers resolve *.localhost without further setup. Without a web server, vendor/bin/workbench serve runs the web server of PHP on port 8300.

In MAMP PRO:

  1. Hosts, +: name fb.localhost, document root ~/Sites/frootbox-sites/public, PHP 8.5.
  2. Tab SSL: off. MAMP makes a certificate for fb.localhost only, so every website would show a warning, and it redirects HTTP to HTTPS.
  3. Tab Web Server, additional parameters for <VirtualHost>: ServerAlias *.fb.localhost. The list of aliases in the tab General does not take *. AllowOverride stays All for .htaccess.
  4. Save. With the ports of MAMP the addresses carry :8888, e.g. http://fb.localhost:8888; the links of the workbench leave the port out.

Addresses

Every <Vendor>/<Site>/ below a root of workbench.yaml answers at <site>.<vendor>.fb.localhost and, while no other project has the same site name, at <site>.fb.localhost. fb.localhost lists all projects. Projects outside the roots are named under projects:.

domain: fb.localhost
monorepo: ../frootbox2
roots:
  - .
projects:
  sandbox: ../frootbox2/sandbox

workbench.local.yaml (not in Git) adds roots and projects for one computer.

Packages

Active in a project is what its composer.json requires, like live, plus its require-dev as in a development install (e.g. the migration tool frootbox/migrate-frootbox1): packages from the central vendor/ and packages in its path repositories inside the project (extensions/*), whose classes the workbench loads at runtime (PSR-4). Versions do not count. Shared code of a vendor lives in <Vendor>/packages/<name>/, a library a website needs is added once with composer require in the folder of the workbench. A package that is missing shows on the page and on the start page.

The variables APP_ENV, APP_SECRET, DATABASE_URL, MAILER_DSN and everything in the .env of a project never come from the environment of the workbench, so each project keeps its own database.

Commands

vendor/bin/workbench projects                 # addresses, folders, status
vendor/bin/workbench new Holl/Holl24          # skeleton, child theme, SQLite, superuser
vendor/bin/workbench run holl24 cache:clear   # any command of bin/frootbox
vendor/bin/workbench migrate holl24           # or --all
vendor/bin/workbench check                    # before a release: packages, blocks, migrations, pages
vendor/bin/workbench update                   # new packages of the monorepo, composer update
vendor/bin/workbench serve                    # without MAMP
vendor/bin/workbench build holl24 --zip       # a folder to upload, see below

With open migrations a project shows a notice with a button instead of its pages; the database is backed up to storage/backups/ first. new and run … install take the superuser from FROOTBOX_ADMIN_EMAIL, FROOTBOX_ADMIN_NAME and FROOTBOX_ADMIN_PASSWORD, from the shell or from sandbox.env of the monorepo.

Building a website to upload

build turns a project into a folder under var/workbench/builds/ that runs on a webspace as it is: its own vendor/ with the packages copied instead of linked, no require-dev, the files of the extensions published, no symlinks, so FTP works. Composer leaves out what the .gitattributes of a package mark export-ignore. Next to it are .env.live, to rename to .env on the server, and DEPLOY.md with the steps there. --zip adds a ZIP file.

The build holds code only, so an update never replaces the database or the media of a running website. --with-content adds storage/ (without backups) and public/media/, for the first upload of a website made in the workbench. Set app.url in config/app.yaml before; the build warns without it.

Each build names itself in a file BUILD. For an update by FTP, name the build that runs on the server:

vendor/bin/workbench build holl24 --since holl24-acme-20261106-091337 --zip

Next to the new build, <build>-since-<time>/ then holds only the files that are new or changed, and <build>-since-<time>.deleted.txt the ones that are gone (they do no harm on the server). The earlier build must still be in var/workbench/builds/. Upload that folder over the website, then delete var/cache/ on the server and run the update under Extensions in the backend, or bin/frootbox migrate and cache:clear with a console.

With --latest the folder with what changed is always <project>-latest/ (with its ZIP file and list), replaced on every build, so an FTP client can keep it as a fixed local folder. Let the client only upload, never mirror: the folder holds a few files, a mirror would delete the rest of the website.

The same build runs from the backend of each website in the workbench: Build under Administration, for superusers. It starts build <project> --zip --since <build> --latest in the background (a full build with the field empty) and shows the folder to upload when it is done, with the output of the run. After the upload, Uploaded notes the new build as the one on the server (<project>-server.txt); only then does the next build compare with it. Until then the field keeps the base of the last run, so building again never makes a diff too small. Behind it are the actions frootbox/workbench/build.start {since?} and frootbox/workbench/build.mark-uploaded {build} and the query frootbox/workbench/build.show. The screen exists only in the workbench: the package has no frootbox.yaml, so a build or a server never has it. var/workbench/builds/<project>-run.log holds the output of the last run.

The web server must show public/, never the folder itself: it holds .env and the database. A .htaccess in the folder locks it on Apache when the document root is wrong (from skeleton/, else the build adds one). After the upload, https://<address>/.env must give 403 or 404.

Source and issues

This package is developed in the Frootbox monorepo and mirrored here read-only. Questions, bugs and ideas go there, see the documentation.

License

MIT