ps-lando
v1.0.0
Published
Interactive CLI to bootstrap PrestaShop + Panda + Easy Builder sandboxes with Lando
Maintainers
Readme
ps-lando
Interactive CLI to bootstrap PrestaShop + Panda (SunnyToo) + Easy Builder sandboxes with Lando in one command. Cross-platform (macOS / Linux / Windows+WSL).
Built for small dev teams working on PrestaShop projects with the Panda theme. Each developer brings their own licensed SunnyToo zips — no shared infra, no licensing gray area, no GitHub private repo with paid assets.
Table of contents
- 5-minute quickstart
- Credentials & URLs
- Team onboarding (first time on a new laptop)
- Getting the SunnyToo zips
- Commands reference
- Selecting modules
- Workflows — daily life with a sandbox
- Hooks & Recipes
- PrestaShop version matrix
- Concepts you need to know
- Backup, restore, persistence
- Troubleshooting
- FAQ
- Contributing / dev
5-minute quickstart
If you already have the tools installed and your SunnyToo zips downloaded:
mkdir my-shop && cd my-shop
cp ~/Downloads/panda.zip . # required
cp ~/Downloads/steasybuilder.zip . # optional
cp ~/Downloads/steasy_trans_panda.zip . # optional (Easy Builder bridge)
npx ps-lando@latest create -y # create sandbox + install every Panda st* module (up to 56)
npx ps-lando@latest open bo # open back-office in browserTotal: ~5 min for both PS 8.2.5 and PS 9.1.0 (PS 9 pulls a pre-built edition from the official PrestaShop CDN — no composer inside Lando required since 0.3.0). Since 0.4.2, safe module groups install in parallel (concurrency 3), which typically saves 2-3 minutes vs the legacy sequential path.
Since 0.2.0,
createruns the full Panda module install at the end of the wizard by default. Pass--no-install-modulesto skip it and install later viaps-lando install-modules. Pass--sequential(new in 0.4.2) to force one-at-a-time installs if you need to debug a flaky sandbox.
One-line version (interactive wizard — safer for first time):
mkdir my-shop && cd my-shop && cp ~/Downloads/panda*.zip ~/Downloads/steasy*.zip . && npx ps-lando@latest createCredentials & URLs
All sandbox credentials are either set during create (interactive mode) or fixed defaults (with -y). You can always recover them running ps-lando info inside the project folder.
Default URLs (every sandbox)
Domain is always <project-name>.lndo.site (Lando manages /etc/hosts transparently).
| Service | URL |
|---|---|
| Front-office | http://<project>.lndo.site/ |
| Back-office | http://<project>.lndo.site/admin/ |
| phpMyAdmin | random port — run ps-lando info or lando info |
| Mailhog | random port — run ps-lando info or lando info |
Back-office (PrestaShop admin) credentials
If you ran create with -y (non-interactive), the defaults are:
| Field | Default value |
|---|---|
| Email | [email protected] |
| Password | sandbox1234 |
| First name | Admin |
| Last name | User |
If you ran create interactively, you chose them in the wizard. They're stored in .ps-lando.json at the project root — recover with ps-lando info.
Database credentials (MySQL/MariaDB)
Hard-coded by Lando's LAMP recipe, identical in every sandbox:
| Field | Value |
|---|---|
| Host (from inside containers, e.g. for PS parameters.php) | database |
| Host (from macOS — phpMyAdmin, Sequel Pro, TablePlus, etc.) | localhost + random port (see lando info) |
| User | lamp |
| Password | lamp |
| Database name | lamp |
| Table prefix | ps_ |
Default locale (with -y)
| Field | Default |
|---|---|
| Language | es (Spanish) |
| Country | es |
| Timezone | Europe/Madrid |
| Shop name | Same as project name |
To see the credentials of an existing sandbox
cd my-project
npx ps-lando infoOutput example:
URLs
Front: http://my-shop.lndo.site/
Back-office: http://my-shop.lndo.site/admin/
phpMyAdmin: http://localhost:53947
Mailhog: http://localhost:53946
BO credentials
Email: [email protected]
Password: sandbox1234
Database (from Lando)
Host: database (from inside containers)
User: lamp
Password: lamp
Database: lamp[!warning]
.ps-lando.jsoncontains plaintext credentials It's a local sandbox only, never a production file. Add it to.gitignoreif you version-control the project folder:echo ".ps-lando.json" >> .gitignore
Team onboarding (first time on a new laptop)
1. Install prerequisites
| Tool | Why | How |
|---|---|---|
| Node.js 20+ | Runs this CLI + npm | nodejs.org or brew install node |
| Docker Desktop | Container engine Lando uses | docker.com — recommended. OrbStack works but has known Lando compatibility issues (lando/core#138). |
| Lando 3.26+ | Orchestrates the containers | docs.lando.dev/install |
| unzip, curl, git | CLI uses these | Usually preinstalled on macOS/Linux. Windows: use WSL. |
2. Get your SunnyToo zips
See Getting the SunnyToo zips below. Download once from your SunnyToo account — each dev uses their own license.
3. First project
cd ~/Developer # or wherever you keep code
mkdir acme-store && cd acme-store
cp ~/Downloads/panda.zip .
cp ~/Downloads/steasybuilder.zip . # if Easy Builder licensed
cp ~/Downloads/steasy_trans_panda.zip . # if Easy Builder licensed
npx ps-lando@latest createAnswer the wizard prompts:
- Project name: defaults to folder name (
acme-store) — fine - PrestaShop version: pick 8.2.5 (fastest) or 9.1.0 (latest)
- PHP version: auto-suggested based on PS
- Database: MySQL (default)
- Extras: phpMyAdmin + Mailhog (recommended)
- Install Panda: yes
- Create child theme: yes (critical — see concepts)
- Install Easy Builder: yes if zips present
- Admin email + password: for back-office login
- Locale: es / es / Europe/Madrid (or your preference)
When done you'll see a summary box with URLs + credentials. The sandbox is fully operational: PrestaShop installed, Panda active, child theme created, Easy Builder deployed, and — since 0.2.0 — every Panda st* module bundled with your Panda zip (typically 54, or 56 including the two Easy Builder zips when present) installed and enabled. Since 0.5.0 you can opt out of groups (blog, easybuilder, social, marketing) via --skip-* flags — see Selecting modules. If any module fails, check .ps-lando-install.log in the project root.
If you passed --no-install-modules, run the batch install whenever you want:
npx ps-lando@latest install-modulesTakes ~3-4 min. You'll see a ✓ per module, final count along the lines of 56/56 active (exact total depends on how many st* modules your Panda zip ships + whether Easy Builder is present — see Module math). Full stdout/stderr of any failure is appended to .ps-lando-install.log (see "Troubleshooting" below).
4. Open and explore
npx ps-lando@latest open front # frontend
npx ps-lando@latest open bo # back-officeLog into the back-office with the credentials from the wizard (you can reprint them anytime with ps-lando info).
Getting the SunnyToo zips
You need (optionally all three):
| File | What it is | Source | Required? |
|---|---|---|---|
| panda.zip (or panda-theme.zip) | The Panda theme bundle | Your SunnyToo account → Downloads | Yes to install Panda |
| steasybuilder.zip | Easy Builder main module (visual editor) | Your SunnyToo account → Downloads | Only if you licensed Easy Builder |
| steasy_trans_panda.zip | Easy Builder ↔ Panda bridge module | Your SunnyToo account → Downloads | Only if you have steasybuilder — it's useless alone |
How to get them
- Log in to your SunnyToo customer account.
- Go to your product downloads.
- Download each zip. Keep them somewhere durable (e.g.
~/Documents/sunnytoo-assets/). - For each new sandbox you create, just
cpthe zips into the project folder.
File name conventions the CLI accepts
The CLI does case-insensitive prefix matching:
- Panda: any file starting with
pandaand ending in.zip(e.g.panda.zip,panda-theme.zip,Panda2.zip). - Easy Builder: any file starting with
steasybuilderorsteasy-builderoreasybuilder. - Bridge: any file starting with
steasy_trans_pandaorsteasy-trans-panda.
If you have multiple matching files in the folder, the CLI picks one (usually the first sorted alphabetically). Use a clean folder per project to avoid surprises.
Commands reference
| Command | What it does |
|---|---|
| create [name] | Interactive wizard with dynamic PS version picker (since 0.3.0). -y for defaults. --ps-version 9.1.0 to pin a tag. --ps-zip <path> for an offline install. --hummingbird-build for Hummingbird 2.0 assets. |
| info [path] | Consolidated summary: URLs, BO creds, active theme, st* module count, versions. |
| open <target> [path] | Open URL in browser. Targets: front / bo (or admin) / phpmyadmin (or pma) / mail (or mailhog). |
| install-modules [path] | Batch-install the Panda st* modules on disk (alias: im). --dry-run to preview order. --include <prefix> to scope. Since 0.4.2, installs safe groups in parallel (concurrency 3); pass --sequential for legacy one-at-a-time. Since 0.5.0, --skip-blog / --skip-easybuilder / --skip-social / --skip-marketing / --skip <list> / --only <list> let you opt out of groups or cherry-pick individual modules. |
| activate-theme <name> [path] | Switch active theme (alias: at). Falls back to SQL if prestashop:theme:enable fails (PS 8.2.5 bug). --force-sql to skip console attempt. |
| list [path] | Show detected SunnyToo zips in a dir (alias: ls). |
| destroy [path] | lando destroy — removes containers + database, keeps files on disk. |
| repair [path] | lando start + cache clear on an existing project. Use after reboot or if the BO looks stale. |
| db reset [path] | (0.6.0+) Drop the DB and re-run install + module install + theme activation against the files already on disk. ~1-2 min vs ~6 min for a full create. Reuses params + module_selection from .ps-lando.json. -y to skip the confirm. |
| db dump [output] [path] | (0.6.0+) Gzipped MySQL dump. Default: <project>-<YYYY-MM-DD-HHMM>.sql.gz. --with-files switches to a .tar.gz bundle that also includes img/ and themes/<active>/ overrides. |
| db restore <path> [project] | (0.6.0+) Auto-detects format (.sql.gz → DB only, .tar.gz → DB + files) and restores. -y to skip the confirm. |
| doctor [path] | (0.6.0+) Diagnostic checklist: Lando running, DB, active modules, theme, front + BO HTTP, hooks dirs, recent errors, install log summary, purifier dirs. Prints ✓/⚠/✗ per item with suggested fix commands. --fix prompts to auto-recover anything fixable (Lando start, mkdir purifier, retry inactive modules, theme SQL fallback). |
Common flags on create
| Flag | Purpose |
|---|---|
| -y, --yes | Non-interactive, accept defaults (CI friendly) |
| --ps-version <v> | PrestaShop tag (e.g. 8.2.5, 9.1.0, 9.0.3). Skips the interactive picker. Legacy --ps alias still works. |
| --ps-zip <path> | Use a pre-downloaded PS zip. Bypasses download entirely — useful for offline installs. |
| -z, --zips <dir> | Directory with SunnyToo zips (default: project dir) |
| --hummingbird-build | After install, build Hummingbird 2.0 assets via node:20 docker container |
| --no-install-modules | Skip the batch st* module install at the end of create. Modules are still copied into modules/. Run ps-lando install-modules later. |
| --sequential | Install Panda modules one at a time (slower, easier to debug). Default (since 0.4.2) installs safe groups in parallel with concurrency 3, saving 2-3 min on a typical create. Infra modules (stthemeeditor, stoverride, stupgrader, stblog) always install sequentially regardless of this flag. |
| --skip-blog / --skip-easybuilder / --skip-social / --skip-marketing | (0.5.0+) Exclude one or more module groups. Combinable. |
| --skip <list> | (0.5.0+) Comma-separated module names to skip individually (e.g. --skip stbanner,stinstagram). |
| --only <list> | (0.5.0+) Install ONLY the listed modules (e.g. --only stmegamenu,stbanner). Mutually exclusive with --skip-*. |
| --no-copy-skipped | (0.5.2+) When paired with --skip-* / --only, also exclude the filtered st* modules from the copy step — modules/ ends up clean. Without this flag, skipped modules are still copied (so install-modules can pick them up later without rehacking the create); only install is filtered. No-op when used without --skip-* / --only. |
Selecting modules
Since 0.5.0, create and install-modules can install a subset of the Panda st* modules instead of the full set. Useful when the client doesn't have a blog, doesn't use Easy Builder, or when you're reproducing a bug with just 2-3 modules.
Module math
ps-lando copies and installs the st* modules bundled in your Panda zip (typically 54) plus steasybuilder + steasy_trans_panda when those zips are present in the project folder (+2 = 56 total). PS stock stats* modules are never touched.
Use --skip-* flags to opt out of groups, or --only <list> to cherry-pick. The exact final count depends on your selection.
Groups (0.5.0+)
Each group is a hard-coded list of modules you can exclude with one flag:
| Group | Flag | Modules |
|---|---|---|
| blog | --skip-blog | stblog, stblogarchives, stblogblockcategory, stblogcomments, stblogeditor, stblogfeaturedarticles, stbloglinknav, stblogrecentarticles, stblogrelatedarticles, stblogsearch, stblogtags (11) |
| easybuilder | --skip-easybuilder | steasybuilder, steasy_trans_panda (2). Also prevents those zips from being copied into modules/ — warns explicitly when the zips are present in the cwd. |
| social | --skip-social | stsocial, stfblikebox, stinstagram, sttwitterembeddedtimelines (4) |
| marketing | --skip-marketing | stcountdown, stnewsletter, stnotification, ststickers (4) |
Groups are combinable. Skipping blog + easybuilder drops 13 modules; skipping all four drops 21.
Individual flags
--skip <list>— comma-separated module names to skip, e.g.--skip stbanner,stinstagram. Unknown names log a warning and continue.--only <list>— install ONLY the listed modules, e.g.--only stmegamenu,stbanner. Unknown names error out. Mutually exclusive with every--skip-*form; combining them exits with code 2.
Filtering install vs. filtering copy (0.5.2+)
By default, --skip-* / --only only filter what gets installed — every st* module in the Panda zip is still copied into modules/, so you can re-run ps-lando install-modules later (without flags) to pick up modules you originally skipped. Pass --no-copy-skipped alongside any --skip-* / --only flag to also skip the copy step — modules/ ends up clean (43 of 54 copied — 11 skipped). No-op when used without a --skip-* / --only flag.
Common combos
# Shop that doesn't need the blog (46 modules).
ps-lando create -y --skip-blog
# No Easy Builder (54 Panda st* modules — warns if EB zips are in cwd).
ps-lando create -y --skip-easybuilder
# Minimal core: no blog, no EB, no social, no marketing.
ps-lando create -y --skip-blog --skip-easybuilder --skip-social --skip-marketing
# Debugging just 2 modules on an existing sandbox.
ps-lando install-modules --only stmegamenu,stbanner
# Full install except two modules you don't like.
ps-lando install-modules --skip stqrcode,sttagsInteractive mode
When you run ps-lando create without -y and without any --skip-* / --only flag, a multiselect after the locale step asks what to install:
? What modules to install?
◉ All modules — default, backwards-compat
◯ Core only — skips blog, easybuilder, social, marketing
◯ Custom... — second prompt: which groups to includePre-0.5.0 behavior is the default (install everything), so existing scripts keep working.
Workflows — daily life with a sandbox
Coming back to an existing sandbox tomorrow
cd ~/Developer/acme-store
lando start # starts containers (~10s)
npx ps-lando info # reminds you of URLs + creds
npx ps-lando open bo # click aroundDeveloping the child theme
Never edit themes/panda/ — it gets wiped on Panda updates. Edit only themes/<your-project>_child/.
Common files to touch:
themes/acme-store_child/assets/css/custom.css— your custom CSSthemes/acme-store_child/assets/js/custom.js— your custom JSthemes/acme-store_child/templates/**/*.tpl— template overrides (mirror the path fromthemes/panda/templates/)themes/acme-store_child/modules/<module>/views/templates/hook/*.tpl— module template overrides
To activate the child theme (after making edits):
npx ps-lando at acme-store_childTo go back to the parent (e.g. to see untouched Panda):
npx ps-lando at pandaTrying a specific module that isn't active yet
lando ssh -c "php bin/console prestashop:module install <module-name>"Or install the full Panda module set in one go:
npx ps-lando install-modulesSince 0.5.0 you can scope the install — e.g. skip blog + easybuilder:
npx ps-lando install-modules --skip-blog --skip-easybuilderSee Selecting modules for the full flag list + the common combos.
Testing with Hummingbird 2.0 (PS 9)
Only relevant if you're on PS 9. At create time:
npx ps-lando create --ps-version 9.1.0 --hummingbird-buildLater, activate it:
npx ps-lando at hummingbirdStopping for the night
lando stop # stops containers, DATA IS KEPTRestarting an existing project
lando startNuking everything (sandbox only — files kept)
npx ps-lando destroy
# Files still on disk. DB and uploaded files inside containers are GONE.Nuking everything INCLUDING files
npx ps-lando destroy
rm -rf . # or `cd .. && rm -rf acme-store`Hooks & Recipes
Since 0.4.0, ps-lando ships with a lightweight hooks mechanism so you can automate project-specific customizations (seed data, tax rules, cache warm-up, etc.) without forking the CLI.
How it works
Two convention folders live at the root of any ps-lando project:
| Folder | When it runs |
| --------------- | -------------------------------------------- |
| init-scripts/ | After install-modules, before smoke test. |
| post-scripts/ | After smoke test, before the outro. |
Drop any executable *.sh file in there. Scripts run in lexicographic order (prefix with 01-, 02-... for control). Non-executable files and non-.sh files are ignored.
Every script receives these env vars:
PS_LANDO_PROJECT # e.g. my-shop
PS_LANDO_DOMAIN # e.g. my-shop.lndo.site
PS_LANDO_ADMIN_DIR # e.g. admin233kcmq1wuumt38aojg
PS_LANDO_ADMIN_EMAIL # e.g. [email protected]
PS_LANDO_PS_VERSION # e.g. 9.1.0
PS_LANDO_PROJECT_DIR # absolute path to the project
PS_LANDO_RECIPE_DIR # only set for bundled recipes — path to recipes/<name>/By default, if a script fails the CLI logs a warning and continues. Pass --on-hook-failure fail to abort the install at the first failure.
Bundled recipes
ps-lando ships 6 recipes out-of-the-box. Discover them with:
ps-lando hooks list| Recipe | Phase | Requires | What it does |
| ---------------------------- | ----- | -------- | --------------------------------------------------------------------- |
| demo-catalog-10 | init | panda | 10 demo products in a "Demo" category with picsum.photos images. |
| demo-customer-with-orders | init | — | [email protected] + Spain address + 3 orders in different states. |
| demo-cms-pages | init | — | About / Contact / Terms CMS pages in ES + EN. |
| spain-taxes | init | — | ES IVA 21% / 10% / 4% tax rules groups; ES default country + EUR. |
| clean-seed | init | — | Wipes PS built-in demo data (products 1-9, demo customers, images). |
| cache-warmup | post | — | Hits front + BO + category + cart + contact with curl to prime cache. |
Compatibility matrix
Every bundled recipe is validated against PS 8.2.5 and PS 9.1.0 live sandboxes. PS 9.0.x is listed as "expected OK" — it shares the 9.x schema but hasn't been exercised in our smoke runs, so we don't claim it formally.
| Recipe | PS 8.2.x | PS 9.0.x | PS 9.1.x |
| ----------------------------- | -------- | ------------------ | -------- |
| demo-catalog-10 | ✓ | expected OK | ✓ |
| demo-customer-with-orders | ✓ | expected OK | ✓ |
| demo-cms-pages | ✓ | expected OK | ✓ |
| spain-taxes | ✓ | expected OK | ✓ |
| clean-seed | ✓ | expected OK | ✓ |
| cache-warmup | ✓ | expected OK | ✓ |
Since 0.4.1:
createalso pre-creates/app/var/cache/{prod,dev}/purifier/after the PrestaShop CLI installer — the PS 8.2.x installer leaves those dirs out and modules using HTMLPurifier (e.g.stbanner,stswiper) would otherwise fail with%Cache.SerializerPath. The directories are created unconditionally (no-op on 9.x where they already exist).install-modulesalso auto-retries any module that hits the error on older sandboxes.
Running recipes
Three ways to apply a recipe:
# 1. At create time — interactive multiselect shows up after locale prompts
ps-lando create
# 2. At create time — non-interactive, pick by name
ps-lando create -y --recipes spain-taxes,demo-cms-pages
# 3. On an existing sandbox, one at a time
cd my-shop
ps-lando hooks run spain-taxes
ps-lando hooks run demo-cms-pagesInstalling a recipe as a project hook
Copy a recipe into your project's init-scripts/ (or post-scripts/ if it's phase post) so every fresh create applies it automatically:
ps-lando hooks install spain-taxes # → init-scripts/50-spain-taxes/run.sh
ps-lando hooks install spain-taxes --prefix 10 # control orderingWriting your own recipe
Any *.sh in init-scripts/ or post-scripts/ is automatically picked up. Example — seed a custom employee group:
# init-scripts/10-custom-group.sh
#!/usr/bin/env bash
set -eu
cd "$PS_LANDO_PROJECT_DIR"
lando ssh -s appserver -c "mysql -hdatabase -ulamp -plamp lamp" <<SQL
INSERT IGNORE INTO ps_group (reduction, price_display_method, show_prices, date_add, date_upd)
VALUES (0, 0, 1, NOW(), NOW());
SQLchmod +x init-scripts/10-custom-group.sh and it will run on every ps-lando create from this directory.
PrestaShop version matrix
Since 0.3.0, the wizard queries the official prestashop-flashlight/prestashop-versions.json manifest on startup and lists every stable release — no hard-coded list in the CLI.
| You say | What the CLI does | Time |
|---|---|---|
| (nothing) or -y | Newest stable from the manifest (currently PS 9.1.0 via CDN) | ~5 min |
| --ps-version 8.x.y | Downloads zip from GitHub Releases | ~3 min |
| --ps-version 9.x.y | Downloads the pre-built edition zip from the PrestaShop CDN (assets.prestashop3.com) with ?source=ps-lando for telemetry | ~5 min |
| --ps-zip /path/prestashop_x.y.z.zip | Uses your local zip — skips the network entirely | ~3 min |
PS 9.x ships pre-built edition zips on
assets.prestashop3.com(vendor/, compiled assets, 55+ bundled modules). PS 8.x stays on GitHub Releases. If the manifest fetch fails, the CLI falls back to a 24h-cached copy at~/.cache/ps-lando/manifest/prestashop-versions.json(XDG-compliant since 0.5.0; older layouts auto-migrate silently), then to a bundled list — offline-capable.
Concepts you need to know
Child theme convention (CRITICAL)
NEVER edit the parent theme (themes/panda/). Always make a child theme (the CLI does this automatically with create unless you decline). Changes go in:
themes/<project>_child/assets/css/custom.cssthemes/<project>_child/assets/js/custom.jsthemes/<project>_child/templates/...(mirroring parent path = override)themes/<project>_child/modules/<module>/views/templates/hook/...
The child declares parent: panda and use_parent_assets: true in config/theme.yml. PrestaShop's template cascade automatically uses child templates when they exist, parent otherwise. CSS/JS from both are merged.
Why this matters: when SunnyToo releases Panda 2.9.3, you update themes/panda/ and your custom work in themes/<project>_child/ stays intact. If you edited Panda directly, the update wipes your changes.
Easy Builder is OPTIONAL
Easy Builder (steasybuilder) is a paid SunnyToo add-on — a visual page builder that sits on top of Panda. Not every client has it. Workflow:
- Has Easy Builder → include
steasybuilder.zip+steasy_trans_panda.zip(the bridge) in your project folder beforecreate. - Doesn't → just omit them. The CLI auto-detects which zips are present.
The bridge (steasy_trans_panda) is useless alone. If you have it without steasybuilder.zip, the CLI warns and skips both.
Metadata file: .ps-lando.json
Written by create at the project root. Contains:
- project name, domain (
<name>.lndo.site), versions - PRESHOP credentials (admin email + password in plaintext — this is a local sandbox, not prod)
- feature flags (panda yes/no, easybuilder yes/no, child theme name)
Used by info, open, activate-theme to avoid re-prompting. Add .ps-lando.json to your .gitignore if you version-control the sandbox — it contains credentials.
Hummingbird 2.0 (PS 9)
PS 9 ships with Hummingbird 2.0 as default theme — open-source, Bootstrap 5, accessibility-first. Panda is the paid alternative from SunnyToo.
On PS 9 install, Hummingbird is present in themes/hummingbird/ but not activated (the CLI activates Panda). You can switch with at hummingbird — but note: its assets need building first via --hummingbird-build on create, or manually:
docker run --rm -v "$PWD:/app" -w /app/themes/hummingbird node:20 sh -c "npm ci && npm run build"Backup, restore, persistence
What's persistent (survives lando stop + lando start)
- Everything in the project folder on your host (themes, modules, files)
- The MySQL database — stored in a Lando-managed Docker volume
- Lando configuration (
.lando.yml)
What's NOT persistent
- Anything written outside
/app/inside the container (temp files, package caches)
lando stop vs lando destroy
lando stop→ containers stopped, volumes preserved.lando startbrings everything back exactly as it was. Use this nightly.lando destroy→ containers removed, volumes removed = database wiped. You'd have to re-install PrestaShop. Use this when you want a clean slate.
Backup the database
cd my-project
lando ssh -c "mysqldump -hdatabase -ulamp -plamp lamp" > backup-$(date +%F).sqlRestore the database
cd my-project
lando ssh -c "mysql -hdatabase -ulamp -plamp lamp" < backup-2026-04-19.sqlBackup the whole sandbox (files + db dump)
cd ~/Developer
lando ssh -c "mysqldump -hdatabase -ulamp -plamp lamp" < /dev/null > acme-store/backup.sql
tar -czf acme-store-backup-$(date +%F).tgz acme-storeMove a sandbox to another machine
- Backup (above)
- Copy the
.tgzto the other machine - Extract:
tar -xzf acme-store-backup-*.tgz cd acme-store && lando startlando ssh -c "mysql -hdatabase -ulamp -plamp lamp" < backup.sql(if DB needs restoring)
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| lando start fails with "Docker is not running" but docker IS running | Lando's daemon check prefers Docker Desktop over other engines | If using OrbStack: also install Docker Desktop once (no need to run it daily) so /Applications/Docker.app exists. See lando/core#138. |
| Could not download PrestaShop x.y.z | Network down or CDN/GitHub unavailable | Check connectivity. For offline installs, pass --ps-zip <path> with a locally stored zip. |
| prestashop:theme:enable fails on PS 8.2.5 | Known PS 8.2.5 cache serializer bug | The CLI auto-falls back to SQL. For ad-hoc switching, just use ps-lando at <theme>. |
| install-modules fails on a specific module | Missing dependency or already-installed | Full stdout/stderr is appended to .ps-lando-install.log in the project root. Install manually: lando ssh -c "php bin/console prestashop:module install <name>". Non-fatal — other modules continue. |
| npx ps-lando uses a cached old version | npm cache | Force latest: npx ps-lando@latest. Or clear: npx clear-npx-cache. |
| Stuck sandbox, want fresh | Anything | ps-lando destroy (DB wipe) then rm -rf <project>/* then create again. |
| ~/.lando/config.yml has stale engineConfig.socketPath | Switched Docker engine | Reset: echo '{}' > ~/.lando/config.yml |
| Browser trusts errors on HTTPS URL | Lando's self-signed cert not trusted | Either brew install mkcert && mkcert -install or just use the HTTP URL. |
| lando start hangs forever | Docker daemon bad state | docker ps to check. Restart Docker Desktop. |
FAQ
Q: Do I need SunnyToo zips to use this? A: Only if you want Panda. You can create a bare PrestaShop sandbox without any zips — just answer "no" to Panda. Useful for testing stock PS or Hummingbird.
Q: Can multiple sandboxes run at the same time?
A: Yes. Each has its own domain (<name>.lndo.site) and ports. lando stop one before starting another if you're RAM-constrained.
Q: Where are the BO credentials?
A: Run ps-lando info in the project dir. They're in .ps-lando.json (plaintext — local sandbox only, never commit this file). Also see the Credentials & URLs section.
Q: What's the default admin email / password with -y?
A: [email protected] / sandbox1234. You can (and should, if exposing the sandbox to others on the LAN) change it from the BO afterward.
Q: What's the database password?
A: lamp. User lamp, database lamp. Hardcoded by Lando's LAMP recipe, identical in every sandbox. Host is database from inside containers, or localhost:<random-port> from your Mac (see lando info).
Q: Can I change the admin password after install?
A: Yes — log into the BO and change it there. Also update .ps-lando.json manually so info shows the new one.
Q: I lost the .ps-lando.json file — how do I recover credentials?
A: If you ran with -y: defaults are [email protected] / sandbox1234. If you ran interactively: reset from the command line via ps-lando activate-theme's same SQL approach, or recreate the sandbox. The DB user lamp/lamp/lamp is always the same.
Q: How do I connect to the database from TablePlus / Sequel Ace / DBeaver?
A: Run lando info and look under the database service for the external URL (something like localhost:53947). Use user lamp, password lamp, database lamp.
Q: How do I install an additional module that's not st*?
A: Drop its folder in modules/, then lando ssh -c "php bin/console prestashop:module install <name>".
Q: Can I use this for production? A: No. This is a local development sandbox. Production needs real hosting, real SSL, real backups, real security.
Q: What PHP versions are supported? A: 7.4, 8.0, 8.1, 8.2, 8.3. PS 9 needs 8.1+. PS 8 works with 7.4+ but the CLI defaults to 8.1 for PS 8 and 8.2 for PS 9.
Q: Does this work with Apple Silicon (M1/M2/M3/M4)? A: Yes. Docker images run natively or via Rosetta seamlessly.
Q: Can a colleague and I share a sandbox?
A: Not directly — each dev runs their own local sandbox. You share code via Git (commit the theme/modules, ignore .ps-lando.json and volumes). DB state is local to each sandbox.
Q: I updated Panda to 2.9.3 — do I need a new sandbox?
A: No. Drop the new panda.zip in the project, then:
rm -rf themes/panda
unzip -q panda.zip -d /tmp/panda-new && cp -R /tmp/panda-new/panda themes/
rm -rf /tmp/panda-new
lando ssh -c "cd /app && php bin/console cache:clear --env=prod --no-warmup"(A dedicated update-theme command is on the roadmap.)
Q: Can I disable the update-check banner?
A: export PS_LANDO_NO_UPDATE_CHECK=1
Q: How do I undo destroy?
A: You can't. Recreate with create and restore DB from a backup dump if you have one.
Contributing / dev
Local dev
git clone https://github.com/educlopez/ps-lando.git
cd ps-lando
pnpm install
pnpm dev -- create --help # run via tsx
pnpm build # tsup bundle → dist/
pnpm typecheck # tsc --noEmit
pnpm test # vitest watch mode
pnpm test:run # vitest one-shot
node bin/ps-lando.mjs <cmd> # run built versionTesting
Unit tests live in tests/*.test.ts and cover the pure logic: zip detection, .lando.yml generation, .ps-lando.json read/write, semver comparison for update check, module install ordering.
pnpm test:run
# → 159 tests across 15 files in ~1.5sprepublishOnly runs typecheck + tests + build — you can't publish a broken version accidentally.
What's NOT unit-tested (and why): create, install-modules, activate-theme, info, open have Lando/Docker/network side-effects that are fragile to mock. Those are exercised by manually running them against a real sandbox during development.
Continuous integration
GitHub Actions workflow at .github/workflows/ci.yml runs typecheck + tests + build on every push and PR, across macOS + Ubuntu and Node 20 + 22.
Architecture
src/
├── index.ts # commander entrypoint + update check
├── commands/
│ ├── create.ts # main wizard
│ ├── info.ts # sandbox summary
│ ├── open.ts # open URL in browser
│ ├── activate-theme.ts # theme switcher with SQL fallback
│ ├── install-modules.ts # batch st* install
│ ├── list.ts # zip detection debug
│ ├── destroy.ts # lando destroy wrapper
│ └── repair.ts # lando start + cache clear
└── lib/
├── cache-paths.ts # XDG cache layout + legacy-path migration (0.5.0+)
├── detect.ts # panda*/steasybuilder* zip finder
├── lando.ts # .lando.yml + start/stop/destroy/ssh/mysql
├── module-groups.ts # group definitions + --skip/--only resolver (0.5.0+)
├── prestashop.ts # download + extract + CLI install + finalize
├── ps-versions.ts # Flashlight manifest fetch + cache + CDN resolver
├── panda.ts # theme deploy + st* copy + child + activation
├── easybuilder.ts # steasybuilder + bridge deploy
├── hummingbird.ts # docker ephemeral node:20 build
├── metadata.ts # .ps-lando.json read/write
├── update-check.ts # npm registry version poll
└── utils.ts # execa helpers + lando PATH detectionStack: TypeScript 5 + Node 20 + ESM + commander + @clack/prompts + execa + kleur + tsup.
Publishing
git commit -m "feat|fix|docs|chore: ..." # conventional commits
pnpm version patch # or minor / major
git push --follow-tags
npm publish # requires OTP (2FA)Changelog
See CHANGELOG.md.
License
MIT © Eduardo Calvo
