A Pollora project is a Laravel application, so Laravel's deployment guide applies. This page covers what is specific to Pollora: what to build, what discovery needs after a release, what runs WP-Cron and the queue, and what to check before you open the site to visitors.
The page assumes a project that is already installed and a web server whose document root is public/ (Server Configuration). Production values for .env are in Environment Management.
Run these from the project root, in this order, on every release:
-
Put the code in place (
git pull, or an artifact built in CI)..env,storage/andpublic/content/uploadsbelong to the server, not to the release. -
Install PHP dependencies.
composer install --no-dev --no-interaction
Composer applies the framework's patches to WordPress core during the install, from the committed
patches.lock.json. The skeleton'spost-autoload-dumpscript runspollora:env:setup; with no terminal to ask in, it prints a warning when the database is not configured and exits 0, so a deploy script does not hang or fail on it. -
Build the assets, unless CI already did and shipped them. See What to build, and where.
-
Run the migrations.
php artisan migrate --force
The skeleton ships migrations for sessions, cache, jobs and failed jobs, and its
.env.exampleuses thedatabasedriver for the first three. -
Refresh the discovery cache.
php artisan discovery:clear php artisan discovery:run
Outside debug mode, discovery stores its scans in Laravel's cache (the
databasestore in the skeleton), so the entries of the previous release survive a deploy and hide every class you added.discovery:cleardrops them;discovery:runscans again, which fills the cache before the first visitor does. See Auto-Discovery.discovery:runprintsCache Status: Enabledwhen it writes a cache.DisabledmeansAPP_DEBUGis on. -
Cache the configuration (optional; see What to cache).
php artisan config:cache
-
Restart the queue workers, so they load the new code. This is standard Laravel: Queue Workers and Deployment.
php artisan queue:restart
-
Gate the release on the doctor.
php artisan pollora:doctor
It exits
1when a check finds an error and0otherwise, warnings included, so a deploy script can stop on it. See the go-live checklist.
The skeleton's .gitignore excludes /public/build, so no build output, and no manifest.json, is committed. Every release has to produce it, either in CI (and ship public/build) or on the server.
| What | Build | Output |
|---|---|---|
| Project assets | npm install && npm run build at the project root |
public/build/manifest.json |
| The active theme | npm install && npm run build in the theme's folder |
public/build/theme/<slug>/, including the theme.json WordPress reads (Theming) |
Each Pollora plugin with a vite.config.js |
the same, in the plugin's folder (Plugin Development) | public/build/plugin/<slug>/ |
Each enabled module with a vite.config.js |
the same, in the module's folder (Modules) | public/build/module/<kebab-name>/ |
Things to know:
- The skeleton's
.gitignorealso excludes/themes/*. A project that versions its theme has to remove that line. - If you build in CI, ship
public/buildwith the release; there is no step on the server that regenerates it. - Never deploy a hot file (
public/hot,public/<name>.hot). While one exists, the assets are requested from the Vite dev server, andpollora:doctorreports an error when nothing answers there. - A missing build does not answer 500: the build's assets resolve to no URL, an admin notice names the manifest and the command to run, and the doctor's Theme, plugin and module builds check reports an error with the folder to build.
See Assets & Vite for the containers and the manifest.
| Cache | Status |
|---|---|
| Discovery | Used outside debug mode, filled by discovery:run. Required step in the sequence above. |
config:cache |
Optional. In production the doctor treats Laravel's caches as expected and does not warn when they are missing; in any other environment it warns when they are on. |
route:cache |
Not recommended here: how it behaves with Route::wp() routes has not been verified. |
In the production environment (APP_ENV=production), the doctor's Configuration and route caches check reports "Production: caches are expected". In any other environment, a cached configuration or route file is a warning, because edits to .env and routes/ are then ignored. A staging site with APP_ENV=staging that caches therefore gets a warning, which does not fail the doctor.
Laravel's own rule applies to config:cache: once the configuration is cached, .env is no longer loaded, so env() must only be called from config/ files.
When a module is switched on or off, a cached configuration or route file still holds the previous state: run php artisan optimize:clear, then cache again (Modules). pollora:doctor warns about it.
Pollora sets DISABLE_WP_CRON, so a page load never runs WP-Cron. Which of the two things below your site needs depends on the drivers it uses.
| You use | What must run |
|---|---|
WP-Cron events: your #[Schedule] events, WordPress and plugin events, ->async() with the wp-cron or action-scheduler driver |
A system cron that requests wp-cron.php every minute |
->async() with the queue driver |
A queue worker on the connection the actions use (HOOKS_ASYNC_CONNECTION, see Asynchronous Actions) |
The laravel scheduling driver |
A queue worker (it replaces the system cron for those events) |
Either line, in the crontab of the user that owns the project:
* * * * * curl -s https://example.com/cms/wp-cron.php > /dev/null
* * * * * cd /path/to/project && wp cron event run --due-nowBoth come from Asynchronous Actions, where the drivers are explained.
Keep php artisan queue:work running under a process manager. Supervisor is the one Laravel documents: this is adapted from the example in Laravel's documentation (path, user, log file and numprocs are ours to change; add the connection to the command if it is not the default one).
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /path/to/project/artisan queue:work --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=2
redirect_stderr=true
stdout_logfile=/path/to/project/storage/logs/worker.log
stopwaitsecs=3600sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start "laravel-worker:*"stopwaitsecs must be longer than your longest job. Pollora's own messages also name systemd as an alternative to Supervisor; any process manager that restarts queue:work does the job.
pollora:doctorreports queued asynchronous actions that nothing picks up: on adatabasequeue connection, jobs that have waited 15 minutes. It cannot read other queue drivers (Redis, SQS), so use the queue tools of your driver there. The check needs WordPress loaded: if the console reports it as skipped, read it in Tools › Site Health.- With the
laravelscheduling driver, the doctor reports events more than ten minutes late, which is what a stopped worker looks like. - WP-Cron events overdue for an hour mean nothing requests
wp-cron.php: the doctor says so and prints the cron line to add.
- Document root is
public/.curl -I https://example.com/.envmust not answer200. The doctor's Document root check does the same from Tools › Site Health in wp-admin, since it needs a web request. See Server Configuration. - Environment.
APP_ENV=production,APP_DEBUG=false(debug mode turns the discovery cache off and setsWP_DEBUG), a generatedAPP_KEY, andAPP_URLwritten with its scheme,https://. See Environment Management. - HTTPS behind a proxy trusts the proxy: Reverse Proxy & HTTPS.
- The database is MySQL or MariaDB, and the migrations have run.
- Assets are built and no hot file is present.
- Discovery is warm (
discovery:runprintedCache Status: Enabled). - The system cron is installed, and a queue worker runs if the project uses one.
php artisan pollora:doctorends without an error.
The last item is the gate. In a deploy script:
php artisan pollora:doctor || exit 1Warnings exit 0. To fail on them as well, read the JSON output, whose errors and warnings fields hold the counts:
php artisan pollora:doctor --jsonThe checks are listed in Dashboard, Status & Doctor.