From dfb3d4a7acaaa04890b8e841f53aa855e9249a48 Mon Sep 17 00:00:00 2001 From: George Dumitrescu Date: Mon, 19 Oct 2026 17:03:38 +0300 Subject: [PATCH] feat: add Slim, Laminas, Contao, Craft CMS, ExpressionEngine, Jigsaw, Joomla!, Kirby, October CMS and Sculpin These are ten more PHP frameworks and CMSs lerd did not know yet. Each is a definition per supported major: Slim 4, Laminas 3 (which also recognises a project still on the zendframework packages), Contao 6 and 5, Craft CMS 5 and 4, ExpressionEngine 7, Jigsaw 1, Joomla! 6 and 5, Kirby 5 and 4, October CMS 4 and 3, and Sculpin 3. Contao and Craft wire the database into their own env keys, DATABASE_URL in .env.local and the CRAFT_DB_* set in .env, default to MySQL, and run Contao's cron and Craft's queue as workers. October follows Winter, serving a mirrored public folder, with setup steps that create and mirror it and run both October's and Tailor's migrations. Joomla! and ExpressionEngine are installed from their release packages, so they are recognised by a file they lay down with the major read from their source, and their web installers keep the database settings they write. Jigsaw and Sculpin are static generators served from their build folders, with a build step and, for Sculpin, a watcher. Kirby and ExpressionEngine are served from the project root and rely on .htaccess rules nginx never reads, so their definitions refuse content/, site/, kirby/ and system/ in nginx instead. Joomla! ships no scheduler worker: its lazy scheduler already runs due tasks on page views, and scheduler:run exits non-zero whenever nothing is due, which would show as a failing worker every minute. Every one of them carries its mark. Contao, Craft CMS, Joomla!, Kirby and October CMS come from Simple Icons; Laminas uses the slashes from its own pinned-tab icon, and Slim, ExpressionEngine, Jigsaw and Sculpin are traced from their official logos as single-colour silhouettes, with the brand colours taken from the same logos. --- .github/logos/contao.svg | 1 + .github/logos/craft.svg | 1 + .github/logos/expressionengine.svg | 1 + .github/logos/jigsaw.svg | 1 + .github/logos/joomla.svg | 1 + .github/logos/kirby.svg | 1 + .github/logos/laminas.svg | 1 + .github/logos/october.svg | 1 + .github/logos/sculpin.svg | 1 + .github/logos/slim.svg | 1 + README.md | 23 +++- frameworks/contao.svg | 1 + frameworks/contao/5.yaml | 86 +++++++++++++ frameworks/contao/6.yaml | 86 +++++++++++++ frameworks/craft.svg | 1 + frameworks/craft/4.yaml | 93 ++++++++++++++ frameworks/craft/5.yaml | 93 ++++++++++++++ frameworks/expressionengine.svg | 1 + frameworks/expressionengine/7.yaml | 47 +++++++ frameworks/index.json | 93 ++++++++++++++ frameworks/jigsaw.svg | 1 + frameworks/jigsaw/1.yaml | 33 +++++ frameworks/joomla.svg | 1 + frameworks/joomla/5.yaml | 49 ++++++++ frameworks/joomla/6.yaml | 49 ++++++++ frameworks/kirby.svg | 1 + frameworks/kirby/4.yaml | 52 ++++++++ frameworks/kirby/5.yaml | 52 ++++++++ frameworks/laminas.svg | 1 + frameworks/laminas/3.yaml | 43 +++++++ frameworks/october.svg | 1 + frameworks/october/3.yaml | 192 +++++++++++++++++++++++++++++ frameworks/october/4.yaml | 192 +++++++++++++++++++++++++++++ frameworks/sculpin.svg | 1 + frameworks/sculpin/3.yaml | 40 ++++++ frameworks/slim.svg | 1 + frameworks/slim/4.yaml | 25 ++++ 37 files changed, 1267 insertions(+), 1 deletion(-) create mode 100644 .github/logos/contao.svg create mode 100644 .github/logos/craft.svg create mode 100644 .github/logos/expressionengine.svg create mode 100644 .github/logos/jigsaw.svg create mode 100644 .github/logos/joomla.svg create mode 100644 .github/logos/kirby.svg create mode 100644 .github/logos/laminas.svg create mode 100644 .github/logos/october.svg create mode 100644 .github/logos/sculpin.svg create mode 100644 .github/logos/slim.svg create mode 100644 frameworks/contao.svg create mode 100644 frameworks/contao/5.yaml create mode 100644 frameworks/contao/6.yaml create mode 100644 frameworks/craft.svg create mode 100644 frameworks/craft/4.yaml create mode 100644 frameworks/craft/5.yaml create mode 100644 frameworks/expressionengine.svg create mode 100644 frameworks/expressionengine/7.yaml create mode 100644 frameworks/jigsaw.svg create mode 100644 frameworks/jigsaw/1.yaml create mode 100644 frameworks/joomla.svg create mode 100644 frameworks/joomla/5.yaml create mode 100644 frameworks/joomla/6.yaml create mode 100644 frameworks/kirby.svg create mode 100644 frameworks/kirby/4.yaml create mode 100644 frameworks/kirby/5.yaml create mode 100644 frameworks/laminas.svg create mode 100644 frameworks/laminas/3.yaml create mode 100644 frameworks/october.svg create mode 100644 frameworks/october/3.yaml create mode 100644 frameworks/october/4.yaml create mode 100644 frameworks/sculpin.svg create mode 100644 frameworks/sculpin/3.yaml create mode 100644 frameworks/slim.svg create mode 100644 frameworks/slim/4.yaml diff --git a/.github/logos/contao.svg b/.github/logos/contao.svg new file mode 100644 index 0000000..5381245 --- /dev/null +++ b/.github/logos/contao.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/craft.svg b/.github/logos/craft.svg new file mode 100644 index 0000000..fc9f5b5 --- /dev/null +++ b/.github/logos/craft.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/expressionengine.svg b/.github/logos/expressionengine.svg new file mode 100644 index 0000000..c910ffa --- /dev/null +++ b/.github/logos/expressionengine.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/jigsaw.svg b/.github/logos/jigsaw.svg new file mode 100644 index 0000000..f916eeb --- /dev/null +++ b/.github/logos/jigsaw.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/joomla.svg b/.github/logos/joomla.svg new file mode 100644 index 0000000..a8df931 --- /dev/null +++ b/.github/logos/joomla.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/kirby.svg b/.github/logos/kirby.svg new file mode 100644 index 0000000..f4b3274 --- /dev/null +++ b/.github/logos/kirby.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/laminas.svg b/.github/logos/laminas.svg new file mode 100644 index 0000000..9a53a40 --- /dev/null +++ b/.github/logos/laminas.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/october.svg b/.github/logos/october.svg new file mode 100644 index 0000000..0793068 --- /dev/null +++ b/.github/logos/october.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/sculpin.svg b/.github/logos/sculpin.svg new file mode 100644 index 0000000..e60e60d --- /dev/null +++ b/.github/logos/sculpin.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/slim.svg b/.github/logos/slim.svg new file mode 100644 index 0000000..c4a46ef --- /dev/null +++ b/.github/logos/slim.svg @@ -0,0 +1 @@ + diff --git a/README.md b/README.md index 604b553..4075b93 100644 --- a/README.md +++ b/README.md @@ -15,13 +15,24 @@ Bedrock CakePHP CodeIgniter + Contao + Craft CMS Drupal + ExpressionEngine + Jigsaw + Joomla! + Kirby + Laminas Laravel Lumen Magento + October CMS + Sculpin + Slim Statamic Symfony Tempest + Testbench TYPO3 Winter CMS WordPress @@ -30,7 +41,7 @@ When you run `lerd link` on a project, Lerd detects which framework it is and pulls the matching definition from this store — then it knows how to serve it, which workers to run, how to set up its `.env`, how to scaffold it, and how to health-check it. Everything is a versioned YAML file. Add a framework here and every Lerd install can use it within 24 hours, with no new Lerd release and no Go code. -That's the whole point: **Lerd is framework-agnostic, and this repo is where that agnosticism lives.** Laravel, Symfony, WordPress, Drupal, CakePHP, CodeIgniter, Statamic, Winter CMS, Magento, Tempest, and Yii are all defined here — not hardcoded in the binary — and so is whatever framework you add next. +That's the whole point: **Lerd is framework-agnostic, and this repo is where that agnosticism lives.** Laravel, Symfony, WordPress, Drupal, CakePHP, CodeIgniter, Statamic, Winter CMS, October CMS, Magento, Tempest, Yii, Slim, Laminas, Contao, Craft CMS, Joomla!, ExpressionEngine, Kirby, Jigsaw, and Sculpin are all defined here — not hardcoded in the binary — and so is whatever framework you add next. ## What a definition powers @@ -53,10 +64,20 @@ All of it is data. None of it ships in the binary. | | **Bedrock** | `1` | `web/wp-config.php` file or `web/wp/wp-login.php` file | | | **CakePHP** | `5` `4` `3` | `bin/cake` file or `cakephp/cakephp` in composer.json | | | **CodeIgniter** | `4` `3` | `spark` file or `codeigniter4/framework` in composer.json | +| | **Contao** | `6` `5` | `contao/manager-bundle` or `contao/core-bundle` in composer.json | +| | **Craft CMS** | `5` `4` | `craftcms/cms` in composer.json | | | **Drupal** | `11` `10` `9` `8` | `drupal/core-recommended` or `drupal/core` in composer.json | +| | **ExpressionEngine** | `7` | `system/ee/ExpressionEngine/Boot/boot.php` file | +| | **Jigsaw** | `1` | `tightenco/jigsaw` in composer.json | +| | **Joomla!** | `6` `5` | `administrator/manifests/files/joomla.xml` file | +| | **Kirby** | `5` `4` | `getkirby/cms` in composer.json or `kirby/bootstrap.php` file | +| | **Laminas** | `3` | `laminas/laminas-mvc` or `zendframework/zend-mvc` in composer.json | | | **Laravel** | `13` `12` `11` `10` `9` `8` `7` `6` | `artisan` file or `laravel/framework` in composer.json | | | **Lumen** | `11` `10` `9` `8` `7` `6` | `laravel/lumen-framework` in composer.json | | | **Magento** | `2` | `bin/magento` file or `magento/product-community-edition` in composer.json | +| | **October CMS** | `4` `3` | `october/rain` in composer.json | +| | **Sculpin** | `3` | `sculpin/sculpin` in composer.json | +| | **Slim** | `4` | `slim/slim` in composer.json | | | **Statamic** | `6` `5` `4` `3` | `statamic/cms` in composer.json | | | **Symfony** | `8` `7` `6` `5` `4` | `symfony.lock` file or `symfony/framework-bundle` in composer.json | | | **Tempest** | `3` | `tempest` file or `tempest/framework` in composer.json | diff --git a/frameworks/contao.svg b/frameworks/contao.svg new file mode 100644 index 0000000..21a323a --- /dev/null +++ b/frameworks/contao.svg @@ -0,0 +1 @@ + diff --git a/frameworks/contao/5.yaml b/frameworks/contao/5.yaml new file mode 100644 index 0000000..4e87fea --- /dev/null +++ b/frameworks/contao/5.yaml @@ -0,0 +1,86 @@ +name: contao +version: "5" +label: Contao +color: "#f47c00" +public_dir: public +create: composer create-project contao/managed-edition:^5.0 +php: + min: "8.1" + max: "8.5" + +# Contao runs on Symfony but ships no symfony.lock and no flex-require, so the +# Symfony definition never claims it. The managed edition requires the manager +# bundle; a project assembled by hand requires the core bundle. +detect: + - composer: contao/manager-bundle + - composer: contao/core-bundle + +env: + file: .env.local + format: dotenv + # The site's URL is kept per root page in the database, not in the env. + url_key: none + # Contao supports MySQL and MariaDB only. + default_service: mysql + services: + mysql: + detect: + - key: DATABASE_URL + value_prefix: "mysql://" + - key: DATABASE_URL + value_prefix: "mariadb://" + vars: + - "DATABASE_URL=mysql://root:lerd@lerd-mysql:3306/{{site}}" + mailpit: + detect: + - key: MAILER_DSN + vars: + - "MAILER_DSN=smtp://lerd-mailpit:1025" + +composer: auto +npm: auto +console: vendor/bin/contao-console +# Run after a connection change: the compiled container is built against the +# old database and answers every request with an error. +cache_command: cache:clear + +workers: + # Contao's cron runs its scheduled jobs and, since 5.1, its messenger queue; + # without a real cron it falls back to running them on page views. + schedule: + label: Cron + icon: clock + command: vendor/bin/contao-console contao:cron + schedule: minutely + +logs: + - path: var/logs/*.log + format: monolog + +setup: + - label: Run migrations + command: vendor/bin/contao-console contao:migrate --no-interaction + default: true + +commands: + - name: contao:migrate + label: Run migrations + command: vendor/bin/contao-console contao:migrate --no-interaction + description: Update the database schema and run pending migrations + output: text + icon: database + - name: cache:clear + label: Clear cache + command: vendor/bin/contao-console cache:clear + description: Clear and warm up the Symfony cache + output: silent + icon: broom + - name: contao:user:create + label: Create a back end user + command: vendor/bin/contao-console contao:user:create --admin + description: Add an administrator to log in to the back end at /contao + output: terminal + icon: key + +doctor: + migrate_command: contao:migrate diff --git a/frameworks/contao/6.yaml b/frameworks/contao/6.yaml new file mode 100644 index 0000000..06a3977 --- /dev/null +++ b/frameworks/contao/6.yaml @@ -0,0 +1,86 @@ +name: contao +version: "6" +label: Contao +color: "#f47c00" +public_dir: public +create: composer create-project contao/managed-edition:^6.0 +php: + min: "8.4" + max: "8.5" + +# Contao runs on Symfony but ships no symfony.lock and no flex-require, so the +# Symfony definition never claims it. The managed edition requires the manager +# bundle; a project assembled by hand requires the core bundle. +detect: + - composer: contao/manager-bundle + - composer: contao/core-bundle + +env: + file: .env.local + format: dotenv + # The site's URL is kept per root page in the database, not in the env. + url_key: none + # Contao supports MySQL and MariaDB only. + default_service: mysql + services: + mysql: + detect: + - key: DATABASE_URL + value_prefix: "mysql://" + - key: DATABASE_URL + value_prefix: "mariadb://" + vars: + - "DATABASE_URL=mysql://root:lerd@lerd-mysql:3306/{{site}}" + mailpit: + detect: + - key: MAILER_DSN + vars: + - "MAILER_DSN=smtp://lerd-mailpit:1025" + +composer: auto +npm: auto +console: vendor/bin/contao-console +# Run after a connection change: the compiled container is built against the +# old database and answers every request with an error. +cache_command: cache:clear + +workers: + # Contao's cron runs its scheduled jobs and, since 5.1, its messenger queue; + # without a real cron it falls back to running them on page views. + schedule: + label: Cron + icon: clock + command: vendor/bin/contao-console contao:cron + schedule: minutely + +logs: + - path: var/logs/*.log + format: monolog + +setup: + - label: Run migrations + command: vendor/bin/contao-console contao:migrate --no-interaction + default: true + +commands: + - name: contao:migrate + label: Run migrations + command: vendor/bin/contao-console contao:migrate --no-interaction + description: Update the database schema and run pending migrations + output: text + icon: database + - name: cache:clear + label: Clear cache + command: vendor/bin/contao-console cache:clear + description: Clear and warm up the Symfony cache + output: silent + icon: broom + - name: contao:user:create + label: Create a back end user + command: vendor/bin/contao-console contao:user:create --admin + description: Add an administrator to log in to the back end at /contao + output: terminal + icon: key + +doctor: + migrate_command: contao:migrate diff --git a/frameworks/craft.svg b/frameworks/craft.svg new file mode 100644 index 0000000..1923b2c --- /dev/null +++ b/frameworks/craft.svg @@ -0,0 +1 @@ + diff --git a/frameworks/craft/4.yaml b/frameworks/craft/4.yaml new file mode 100644 index 0000000..0696a8c --- /dev/null +++ b/frameworks/craft/4.yaml @@ -0,0 +1,93 @@ +name: craft +version: "4" +label: Craft CMS +color: "#e5422b" +public_dir: web +create: composer create-project craftcms/craft:^4.0 +php: + min: "8.0" + max: "8.4" + +# Craft is built on Yii 2, but a project requires craftcms/cms rather than +# yiisoft/yii2, so the Yii definition never claims it. +detect: + - composer: craftcms/cms + +env: + file: .env + example_file: .env.example.dev + format: dotenv + url_key: PRIMARY_SITE_URL + key_generation: + env_key: CRAFT_SECURITY_KEY + command: setup/security-key + default_service: mysql + services: + mysql: + detect: + - key: CRAFT_DB_DRIVER + value_prefix: mysql + vars: + - CRAFT_DB_DRIVER=mysql + - CRAFT_DB_SERVER=lerd-mysql + - CRAFT_DB_PORT=3306 + - CRAFT_DB_DATABASE={{site}} + - CRAFT_DB_USER=root + - CRAFT_DB_PASSWORD=lerd + postgres: + detect: + - key: CRAFT_DB_DRIVER + value_prefix: pgsql + vars: + - CRAFT_DB_DRIVER=pgsql + - CRAFT_DB_SERVER=lerd-postgres + - CRAFT_DB_PORT=5432 + - CRAFT_DB_DATABASE={{site}} + - CRAFT_DB_USER=postgres + - CRAFT_DB_PASSWORD=lerd + +composer: auto +npm: auto +console: craft +cache_command: clear-caches/all + +workers: + queue: + label: Queue Worker + icon: queue + command: php craft queue/listen --verbose + restart: always + +logs: + - path: storage/logs/*.log + format: raw + +# Craft's installer creates the first user and site interactively, so lerd +# leaves it to `php craft install` or the browser at /admin/install. +setup: + - label: Apply migrations and project config + command: php craft up --interactive=0 + default: false + +commands: + - name: up + label: Run migrations + command: php craft up --interactive=0 + description: Run pending migrations and apply project config changes + output: text + icon: database + - name: clear-caches + label: Clear all caches + command: php craft clear-caches/all + description: Clear the data, template and asset caches + output: silent + icon: broom + - name: project-config-apply + label: Apply project config + command: php craft project-config/apply + description: Load config/project YAML into the database + output: text + icon: refresh + +doctor: + migrate_command: up diff --git a/frameworks/craft/5.yaml b/frameworks/craft/5.yaml new file mode 100644 index 0000000..247dafd --- /dev/null +++ b/frameworks/craft/5.yaml @@ -0,0 +1,93 @@ +name: craft +version: "5" +label: Craft CMS +color: "#e5422b" +public_dir: web +create: composer create-project craftcms/craft:^5.0 +php: + min: "8.2" + max: "8.5" + +# Craft is built on Yii 2, but a project requires craftcms/cms rather than +# yiisoft/yii2, so the Yii definition never claims it. +detect: + - composer: craftcms/cms + +env: + file: .env + example_file: .env.example.dev + format: dotenv + url_key: PRIMARY_SITE_URL + key_generation: + env_key: CRAFT_SECURITY_KEY + command: setup/security-key + default_service: mysql + services: + mysql: + detect: + - key: CRAFT_DB_DRIVER + value_prefix: mysql + vars: + - CRAFT_DB_DRIVER=mysql + - CRAFT_DB_SERVER=lerd-mysql + - CRAFT_DB_PORT=3306 + - CRAFT_DB_DATABASE={{site}} + - CRAFT_DB_USER=root + - CRAFT_DB_PASSWORD=lerd + postgres: + detect: + - key: CRAFT_DB_DRIVER + value_prefix: pgsql + vars: + - CRAFT_DB_DRIVER=pgsql + - CRAFT_DB_SERVER=lerd-postgres + - CRAFT_DB_PORT=5432 + - CRAFT_DB_DATABASE={{site}} + - CRAFT_DB_USER=postgres + - CRAFT_DB_PASSWORD=lerd + +composer: auto +npm: auto +console: craft +cache_command: clear-caches/all + +workers: + queue: + label: Queue Worker + icon: queue + command: php craft queue/listen --verbose + restart: always + +logs: + - path: storage/logs/*.log + format: raw + +# Craft's installer creates the first user and site interactively, so lerd +# leaves it to `php craft install` or the browser at /admin/install. +setup: + - label: Apply migrations and project config + command: php craft up --interactive=0 + default: false + +commands: + - name: up + label: Run migrations + command: php craft up --interactive=0 + description: Run pending migrations and apply project config changes + output: text + icon: database + - name: clear-caches + label: Clear all caches + command: php craft clear-caches/all + description: Clear the data, template and asset caches + output: silent + icon: broom + - name: project-config-apply + label: Apply project config + command: php craft project-config/apply + description: Load config/project YAML into the database + output: text + icon: refresh + +doctor: + migrate_command: up diff --git a/frameworks/expressionengine.svg b/frameworks/expressionengine.svg new file mode 100644 index 0000000..f01ce1d --- /dev/null +++ b/frameworks/expressionengine.svg @@ -0,0 +1 @@ + diff --git a/frameworks/expressionengine/7.yaml b/frameworks/expressionengine/7.yaml new file mode 100644 index 0000000..61244b0 --- /dev/null +++ b/frameworks/expressionengine/7.yaml @@ -0,0 +1,47 @@ +name: expressionengine +version: "7" +label: ExpressionEngine +color: "#5c64f4" +public_dir: . +php: + min: "7.2" + max: "8.4" + +# ExpressionEngine is installed from its release zip rather than composer, so it +# is recognised by its boot file, with the major read off the version constant. +detect: + - file: system/ee/ExpressionEngine/Boot/boot.php + version_file: system/ee/legacy/libraries/Core.php + version_pattern: "define\\('APP_VER',\\s*'([^']+)'\\)" + +# EE's install guide keeps system/ out of the web root; served from the root +# as here, nginx has to refuse it instead. +nginx: + snippet: | + location ^~ /system/ { + return 404; + } + +# system/user/config/config.php is written by the web installer at admin.php, +# which takes the database it is given, so lerd leaves the file to it. +env: + file: "" + format: none + +composer: false +npm: false +console: system/ee/eecli.php + +commands: + - name: cache:clear + label: Clear caches + command: php system/ee/eecli.php cache:clear + description: Clear the page, tag and database caches + output: silent + icon: broom + - name: migrate + label: Run migrations + command: php system/ee/eecli.php migrate:all + description: Run pending core and add-on migrations + output: text + icon: database diff --git a/frameworks/index.json b/frameworks/index.json index 78d3f89..8b76df2 100644 --- a/frameworks/index.json +++ b/frameworks/index.json @@ -145,6 +145,99 @@ "detect": [ {"file": "testbench.yaml"} ] + }, + { + "name": "slim", + "label": "Slim", + "versions": ["4"], + "latest": "4", + "detect": [ + {"composer": "slim/slim"} + ] + }, + { + "name": "laminas", + "label": "Laminas", + "versions": ["3"], + "latest": "3", + "detect": [ + {"composer": "laminas/laminas-mvc"}, + {"composer": "zendframework/zend-mvc"} + ] + }, + { + "name": "contao", + "label": "Contao", + "versions": ["6", "5"], + "latest": "6", + "detect": [ + {"composer": "contao/manager-bundle"}, + {"composer": "contao/core-bundle"} + ] + }, + { + "name": "craft", + "label": "Craft CMS", + "versions": ["5", "4"], + "latest": "5", + "detect": [ + {"composer": "craftcms/cms"} + ] + }, + { + "name": "expressionengine", + "label": "ExpressionEngine", + "versions": ["7"], + "latest": "7", + "detect": [ + {"file": "system/ee/ExpressionEngine/Boot/boot.php", "version_file": "system/ee/legacy/libraries/Core.php", "version_pattern": "define\\('APP_VER',\\s*'([^']+)'\\)"} + ] + }, + { + "name": "jigsaw", + "label": "Jigsaw", + "versions": ["1"], + "latest": "1", + "detect": [ + {"composer": "tightenco/jigsaw"} + ] + }, + { + "name": "joomla", + "label": "Joomla!", + "versions": ["6", "5"], + "latest": "6", + "detect": [ + {"file": "administrator/manifests/files/joomla.xml", "version_file": "libraries/src/Version.php", "version_pattern": "MAJOR_VERSION\\s*=\\s*(\\d+)"} + ] + }, + { + "name": "kirby", + "label": "Kirby", + "versions": ["5", "4"], + "latest": "5", + "detect": [ + {"composer": "getkirby/cms"}, + {"file": "kirby/bootstrap.php", "version_file": "kirby/composer.json", "version_pattern": "\"version\":\\s*\"([^\"]+)\""} + ] + }, + { + "name": "october", + "label": "October CMS", + "versions": ["4", "3"], + "latest": "4", + "detect": [ + {"composer": "october/rain"} + ] + }, + { + "name": "sculpin", + "label": "Sculpin", + "versions": ["3"], + "latest": "3", + "detect": [ + {"composer": "sculpin/sculpin"} + ] } ], "packages": [ diff --git a/frameworks/jigsaw.svg b/frameworks/jigsaw.svg new file mode 100644 index 0000000..7eadc0b --- /dev/null +++ b/frameworks/jigsaw.svg @@ -0,0 +1 @@ + diff --git a/frameworks/jigsaw/1.yaml b/frameworks/jigsaw/1.yaml new file mode 100644 index 0000000..773b776 --- /dev/null +++ b/frameworks/jigsaw/1.yaml @@ -0,0 +1,33 @@ +name: jigsaw +version: "1" +label: Jigsaw +color: "#349ccc" +# Jigsaw is a static site generator: a local build lands in build_local, and +# that folder is the whole site. +public_dir: build_local +php: + min: "8.2" + max: "8.5" + +detect: + - composer: tightenco/jigsaw + +env: + file: "" + format: none + +composer: auto +npm: auto + +setup: + - label: Build the site + command: vendor/bin/jigsaw build + default: true + +commands: + - name: build + label: Build the site + command: vendor/bin/jigsaw build + description: Regenerate build_local from the source folder + output: text + icon: refresh diff --git a/frameworks/joomla.svg b/frameworks/joomla.svg new file mode 100644 index 0000000..05f82be --- /dev/null +++ b/frameworks/joomla.svg @@ -0,0 +1 @@ + diff --git a/frameworks/joomla/5.yaml b/frameworks/joomla/5.yaml new file mode 100644 index 0000000..14b55ab --- /dev/null +++ b/frameworks/joomla/5.yaml @@ -0,0 +1,49 @@ +name: joomla +version: "5" +label: Joomla! +color: "#5091cd" +public_dir: . +php: + min: "8.1" + max: "8.4" + +# Joomla is installed from its release package rather than composer, so it is +# recognised by the manifest the package lays down, with the major read off the +# version class. +detect: + - file: administrator/manifests/files/joomla.xml + version_file: libraries/src/Version.php + version_pattern: 'MAJOR_VERSION\s*=\s*(\d+)' + +# configuration.php is a class of properties the web installer writes, a shape +# none of lerd's env formats can edit, so the database is given to the installer +# at /installation instead. +env: + file: "" + format: none + +composer: false +npm: false +console: cli/joomla.php + +# No scheduler worker: Joomla's lazy scheduler runs due tasks on page views out +# of the box, and `scheduler:run` exits non-zero whenever nothing is due, which +# a minutely unit would report as a failing worker. + +logs: + - path: administrator/logs/*.php + format: raw + +commands: + - name: cache:clean + label: Clean expired cache + command: php cli/joomla.php cache:clean + description: Remove expired entries from the cache + output: silent + icon: broom + - name: update:extensions:check + label: Check extension updates + command: php cli/joomla.php update:extensions:check + description: List installed extensions that have an update available + output: text + icon: list diff --git a/frameworks/joomla/6.yaml b/frameworks/joomla/6.yaml new file mode 100644 index 0000000..a5644bb --- /dev/null +++ b/frameworks/joomla/6.yaml @@ -0,0 +1,49 @@ +name: joomla +version: "6" +label: Joomla! +color: "#5091cd" +public_dir: . +php: + min: "8.3" + max: "8.5" + +# Joomla is installed from its release package rather than composer, so it is +# recognised by the manifest the package lays down, with the major read off the +# version class. +detect: + - file: administrator/manifests/files/joomla.xml + version_file: libraries/src/Version.php + version_pattern: 'MAJOR_VERSION\s*=\s*(\d+)' + +# configuration.php is a class of properties the web installer writes, a shape +# none of lerd's env formats can edit, so the database is given to the installer +# at /installation instead. +env: + file: "" + format: none + +composer: false +npm: false +console: cli/joomla.php + +# No scheduler worker: Joomla's lazy scheduler runs due tasks on page views out +# of the box, and `scheduler:run` exits non-zero whenever nothing is due, which +# a minutely unit would report as a failing worker. + +logs: + - path: administrator/logs/*.php + format: raw + +commands: + - name: cache:clean + label: Clean expired cache + command: php cli/joomla.php cache:clean + description: Remove expired entries from the cache + output: silent + icon: broom + - name: update:extensions:check + label: Check extension updates + command: php cli/joomla.php update:extensions:check + description: List installed extensions that have an update available + output: text + icon: list diff --git a/frameworks/kirby.svg b/frameworks/kirby.svg new file mode 100644 index 0000000..19bc373 --- /dev/null +++ b/frameworks/kirby.svg @@ -0,0 +1 @@ + diff --git a/frameworks/kirby/4.yaml b/frameworks/kirby/4.yaml new file mode 100644 index 0000000..2c3390f --- /dev/null +++ b/frameworks/kirby/4.yaml @@ -0,0 +1,52 @@ +name: kirby +version: "4" +label: Kirby +color: "#000000" +# The starterkit serves from the project root, where index.php sits beside the +# kirby, site and content folders; Kirby guards those itself through its router. +public_dir: . +create: composer create-project getkirby/starterkit:^4.0 +php: + min: "8.1" + max: "8.4" + +# A Kirby site is just as often a downloaded kit with no composer.json of its +# own, so the core folder it ships is detected too, with the major read from +# the composer.json inside it. +detect: + - composer: getkirby/cms + - file: kirby/bootstrap.php + version_file: kirby/composer.json + version_pattern: '"version":\s*"([^"]+)"' + +# Kirby's .htaccess keeps content, config and its own source off the web; +# nginx never reads it, so the same rules from Kirby's nginx guide go here. +nginx: + snippet: | + location ~ ^/content/.*\.(txt|md|mdown)$ { + return 404; + } + location ~ ^/(site|kirby|vendor)/ { + return 404; + } + location ~ ^/(composer\.(json|lock)$|\.(?!well-known/)) { + return 404; + } + +# Kirby is a flat-file CMS: content lives in content/ and config in PHP under +# site/config, so there is no env file and no database. +env: + file: "" + format: none + +composer: auto +npm: auto + +commands: + - name: clear-cache + label: Clear cache + command: rm -rf site/cache/* media/* + description: Drop the page cache and generated thumbnails so they are rebuilt on demand + output: silent + icon: broom + confirm: true diff --git a/frameworks/kirby/5.yaml b/frameworks/kirby/5.yaml new file mode 100644 index 0000000..060ecaa --- /dev/null +++ b/frameworks/kirby/5.yaml @@ -0,0 +1,52 @@ +name: kirby +version: "5" +label: Kirby +color: "#000000" +# The starterkit serves from the project root, where index.php sits beside the +# kirby, site and content folders; Kirby guards those itself through its router. +public_dir: . +create: composer create-project getkirby/starterkit:^5.0 +php: + min: "8.2" + max: "8.5" + +# A Kirby site is just as often a downloaded kit with no composer.json of its +# own, so the core folder it ships is detected too, with the major read from +# the composer.json inside it. +detect: + - composer: getkirby/cms + - file: kirby/bootstrap.php + version_file: kirby/composer.json + version_pattern: '"version":\s*"([^"]+)"' + +# Kirby's .htaccess keeps content, config and its own source off the web; +# nginx never reads it, so the same rules from Kirby's nginx guide go here. +nginx: + snippet: | + location ~ ^/content/.*\.(txt|md|mdown)$ { + return 404; + } + location ~ ^/(site|kirby|vendor)/ { + return 404; + } + location ~ ^/(composer\.(json|lock)$|\.(?!well-known/)) { + return 404; + } + +# Kirby is a flat-file CMS: content lives in content/ and config in PHP under +# site/config, so there is no env file and no database. +env: + file: "" + format: none + +composer: auto +npm: auto + +commands: + - name: clear-cache + label: Clear cache + command: rm -rf site/cache/* media/* + description: Drop the page cache and generated thumbnails so they are rebuilt on demand + output: silent + icon: broom + confirm: true diff --git a/frameworks/laminas.svg b/frameworks/laminas.svg new file mode 100644 index 0000000..8bb1cf7 --- /dev/null +++ b/frameworks/laminas.svg @@ -0,0 +1 @@ + diff --git a/frameworks/laminas/3.yaml b/frameworks/laminas/3.yaml new file mode 100644 index 0000000..b419601 --- /dev/null +++ b/frameworks/laminas/3.yaml @@ -0,0 +1,43 @@ +name: laminas +version: "3" +label: Laminas +color: "#013755" +public_dir: public +create: composer create-project laminas/laminas-mvc-skeleton:^2.0 +php: + min: "8.1" + max: "8.3" + +# Laminas is the Zend Framework renamed, so a project that never moved off the +# zendframework packages is the same application and is recognised too. The +# skeleton's own major (2) is not the framework's; laminas-mvc's is. +detect: + - composer: laminas/laminas-mvc + - composer: zendframework/zend-mvc + +# Configuration is PHP arrays under config/autoload, merged at boot, and the +# skeleton reads no dotenv, so there is nothing for lerd to write into. +env: + file: "" + format: none + +composer: auto +npm: auto + +commands: + - name: development-enable + label: Enable development mode + command: composer development-enable + description: Turn on the development config overrides and disable the config cache + output: silent + icon: edit + check: + composer: laminas/laminas-development-mode + - name: development-disable + label: Disable development mode + command: composer development-disable + description: Go back to the production config and its cache + output: silent + icon: edit + check: + composer: laminas/laminas-development-mode diff --git a/frameworks/october.svg b/frameworks/october.svg new file mode 100644 index 0000000..e3701c2 --- /dev/null +++ b/frameworks/october.svg @@ -0,0 +1 @@ + diff --git a/frameworks/october/3.yaml b/frameworks/october/3.yaml new file mode 100644 index 0000000..3c3d834 --- /dev/null +++ b/frameworks/october/3.yaml @@ -0,0 +1,192 @@ +name: october +version: "3" +label: October CMS +color: "#db6a26" +# October serves from the project root out of the box, where .env, composer.json +# and vendor/ would answer over HTTP too. `october:mirror public` builds a public +# folder of symlinks to the files that should be served, and that is the root +# lerd serves; setup builds it when it is missing. +public_dir: public +create: composer create-project october/october:^3.0 +php: + min: "8.0" + max: "8.3" + +# October ships artisan and requires laravel/framework, so the Laravel +# definition would claim it too. october/rain is its own core, whose major is +# October's, and Winter (the fork) requires neither. +detect: + - composer: october/rain + +env: + file: .env + example_file: .env.example + format: dotenv + key_generation: + env_key: APP_KEY + command: key:generate + fallback_prefix: "base64:" + sqlite: + detect: + - key: DB_CONNECTION + value_prefix: sqlite + vars: + - DB_CONNECTION=sqlite + - DB_DATABASE=storage/database.sqlite + services: + mysql: + detect: + - key: DB_CONNECTION + value_prefix: mysql + vars: + - DB_CONNECTION=mysql + - DB_HOST=lerd-mysql + - DB_PORT=3306 + - DB_DATABASE={{site}} + - DB_USERNAME=root + - DB_PASSWORD=lerd + postgres: + detect: + - key: DB_CONNECTION + value_prefix: pgsql + vars: + - DB_CONNECTION=pgsql + - DB_HOST=lerd-postgres + - DB_PORT=5432 + - DB_DATABASE={{site}} + - DB_USERNAME=postgres + - DB_PASSWORD=lerd + redis: + detect: + - key: REDIS_HOST + vars: + - REDIS_HOST=lerd-redis + - REDIS_PORT=6379 + - REDIS_PASSWORD= + rustfs: + detect: + - key: FILESYSTEM_DISK + value_prefix: s3 + - key: AWS_ENDPOINT + vars: + - AWS_ACCESS_KEY_ID=lerd + - AWS_SECRET_ACCESS_KEY=lerdpassword + - AWS_BUCKET={{site}} + - AWS_ENDPOINT=http://lerd-rustfs:9000 + - AWS_URL=http://localhost:9000/{{site}} + - AWS_USE_PATH_STYLE_ENDPOINT=true + - FILESYSTEM_DISK=s3 + mailpit: + detect: + - key: MAIL_HOST + vars: + - MAIL_MAILER=smtp + - MAIL_HOST=lerd-mailpit + - MAIL_PORT=1025 + - MAIL_USERNAME=null + - MAIL_PASSWORD=null + - MAIL_ENCRYPTION=null + +composer: auto +npm: auto +console: artisan +# Run after a connection change: October caches the compiled config and the CMS +# object cache, and both answer from the old database until they are dropped. +cache_command: cache:clear + +workers: + queue: + label: Queue Worker + icon: queue + command: php artisan queue:work --queue=default --tries=3 --timeout=60 + tune_command: php artisan queue:work --queue={queue} --tries={tries} --timeout={timeout} + restart_command: php artisan queue:restart + requires_service: + name: redis + when_env: QUEUE_CONNECTION=redis + restart: always + schedule: + label: Task Scheduler + icon: clock + command: php artisan schedule:run + schedule: minutely +logs: + - path: storage/logs/*.log + format: monolog + +setup: + # Setup steps run without a shell, and the mirror refuses a folder that is + # not there yet, so creating it is a step of its own. + - label: mkdir -p public + command: mkdir -p public + default: true + check: + missing_file: public + - label: php artisan october:mirror public --relative + command: php artisan october:mirror public --relative + default: true + check: + missing_file: public + - label: php artisan october:migrate + command: php artisan october:migrate + default: true + # Tailor's content tables come from the theme's blueprints and are built by + # their own command; until then any page that reads them fails. + - label: php artisan tailor:migrate + command: php artisan tailor:migrate + default: true + +tinker: + command: ["artisan", "tinker"] + execute_flag: "--execute" + requires_package: laravel/tinker + requires_file: artisan + +commands: + - name: october:migrate + label: Run migrations + command: php artisan october:migrate + description: Apply outstanding module and plugin migrations + output: silent + icon: database + - name: tailor:migrate + label: Migrate Tailor + command: php artisan tailor:migrate + description: Build the content tables the theme's blueprints describe + output: silent + icon: database + - name: cache:clear + label: Clear all caches + command: php artisan cache:clear + description: Drop the application and CMS caches + output: silent + icon: broom + - name: october:mirror + label: Rebuild the public folder + command: mkdir -p public && php artisan october:mirror public --relative + description: Relink public/ to the files October serves, after adding a plugin or theme + output: silent + icon: link + - name: plugin:refresh + label: Refresh a plugin + command: php artisan plugin:refresh + description: Roll a plugin's tables back and migrate them again + output: text + icon: refresh + confirm: true + +doctor: + migrate_command: october:migrate + checks: + - name: app_debug + type: env_combo + when: + APP_ENV: production + warn_if: + APP_DEBUG: "true" + detail: "APP_DEBUG is on while APP_ENV=production, so stack traces and config will leak. Turn debug off." + - name: public_mirror + type: command + command: test -d public + fix: october:mirror + detail: "public/ is missing, so nothing is served: October builds it with `october:mirror public`, and serving the project root instead would put .env and vendor/ on the web." diff --git a/frameworks/october/4.yaml b/frameworks/october/4.yaml new file mode 100644 index 0000000..e272005 --- /dev/null +++ b/frameworks/october/4.yaml @@ -0,0 +1,192 @@ +name: october +version: "4" +label: October CMS +color: "#db6a26" +# October serves from the project root out of the box, where .env, composer.json +# and vendor/ would answer over HTTP too. `october:mirror public` builds a public +# folder of symlinks to the files that should be served, and that is the root +# lerd serves; setup builds it when it is missing. +public_dir: public +create: composer create-project october/october:^4.0 +php: + min: "8.2" + max: "8.5" + +# October ships artisan and requires laravel/framework, so the Laravel +# definition would claim it too. october/rain is its own core, whose major is +# October's, and Winter (the fork) requires neither. +detect: + - composer: october/rain + +env: + file: .env + example_file: .env.example + format: dotenv + key_generation: + env_key: APP_KEY + command: key:generate + fallback_prefix: "base64:" + sqlite: + detect: + - key: DB_CONNECTION + value_prefix: sqlite + vars: + - DB_CONNECTION=sqlite + - DB_DATABASE=storage/database.sqlite + services: + mysql: + detect: + - key: DB_CONNECTION + value_prefix: mysql + vars: + - DB_CONNECTION=mysql + - DB_HOST=lerd-mysql + - DB_PORT=3306 + - DB_DATABASE={{site}} + - DB_USERNAME=root + - DB_PASSWORD=lerd + postgres: + detect: + - key: DB_CONNECTION + value_prefix: pgsql + vars: + - DB_CONNECTION=pgsql + - DB_HOST=lerd-postgres + - DB_PORT=5432 + - DB_DATABASE={{site}} + - DB_USERNAME=postgres + - DB_PASSWORD=lerd + redis: + detect: + - key: REDIS_HOST + vars: + - REDIS_HOST=lerd-redis + - REDIS_PORT=6379 + - REDIS_PASSWORD= + rustfs: + detect: + - key: FILESYSTEM_DISK + value_prefix: s3 + - key: AWS_ENDPOINT + vars: + - AWS_ACCESS_KEY_ID=lerd + - AWS_SECRET_ACCESS_KEY=lerdpassword + - AWS_BUCKET={{site}} + - AWS_ENDPOINT=http://lerd-rustfs:9000 + - AWS_URL=http://localhost:9000/{{site}} + - AWS_USE_PATH_STYLE_ENDPOINT=true + - FILESYSTEM_DISK=s3 + mailpit: + detect: + - key: MAIL_HOST + vars: + - MAIL_MAILER=smtp + - MAIL_HOST=lerd-mailpit + - MAIL_PORT=1025 + - MAIL_USERNAME=null + - MAIL_PASSWORD=null + - MAIL_ENCRYPTION=null + +composer: auto +npm: auto +console: artisan +# Run after a connection change: October caches the compiled config and the CMS +# object cache, and both answer from the old database until they are dropped. +cache_command: cache:clear + +workers: + queue: + label: Queue Worker + icon: queue + command: php artisan queue:work --queue=default --tries=3 --timeout=60 + tune_command: php artisan queue:work --queue={queue} --tries={tries} --timeout={timeout} + restart_command: php artisan queue:restart + requires_service: + name: redis + when_env: QUEUE_CONNECTION=redis + restart: always + schedule: + label: Task Scheduler + icon: clock + command: php artisan schedule:run + schedule: minutely +logs: + - path: storage/logs/*.log + format: monolog + +setup: + # Setup steps run without a shell, and the mirror refuses a folder that is + # not there yet, so creating it is a step of its own. + - label: mkdir -p public + command: mkdir -p public + default: true + check: + missing_file: public + - label: php artisan october:mirror public --relative + command: php artisan october:mirror public --relative + default: true + check: + missing_file: public + - label: php artisan october:migrate + command: php artisan october:migrate + default: true + # Tailor's content tables come from the theme's blueprints and are built by + # their own command; until then any page that reads them fails. + - label: php artisan tailor:migrate + command: php artisan tailor:migrate + default: true + +tinker: + command: ["artisan", "tinker"] + execute_flag: "--execute" + requires_package: laravel/tinker + requires_file: artisan + +commands: + - name: october:migrate + label: Run migrations + command: php artisan october:migrate + description: Apply outstanding module and plugin migrations + output: silent + icon: database + - name: tailor:migrate + label: Migrate Tailor + command: php artisan tailor:migrate + description: Build the content tables the theme's blueprints describe + output: silent + icon: database + - name: cache:clear + label: Clear all caches + command: php artisan cache:clear + description: Drop the application and CMS caches + output: silent + icon: broom + - name: october:mirror + label: Rebuild the public folder + command: mkdir -p public && php artisan october:mirror public --relative + description: Relink public/ to the files October serves, after adding a plugin or theme + output: silent + icon: link + - name: plugin:refresh + label: Refresh a plugin + command: php artisan plugin:refresh + description: Roll a plugin's tables back and migrate them again + output: text + icon: refresh + confirm: true + +doctor: + migrate_command: october:migrate + checks: + - name: app_debug + type: env_combo + when: + APP_ENV: production + warn_if: + APP_DEBUG: "true" + detail: "APP_DEBUG is on while APP_ENV=production, so stack traces and config will leak. Turn debug off." + - name: public_mirror + type: command + command: test -d public + fix: october:mirror + detail: "public/ is missing, so nothing is served: October builds it with `october:mirror public`, and serving the project root instead would put .env and vendor/ on the web." diff --git a/frameworks/sculpin.svg b/frameworks/sculpin.svg new file mode 100644 index 0000000..b47d54e --- /dev/null +++ b/frameworks/sculpin.svg @@ -0,0 +1 @@ + diff --git a/frameworks/sculpin/3.yaml b/frameworks/sculpin/3.yaml new file mode 100644 index 0000000..cd78c34 --- /dev/null +++ b/frameworks/sculpin/3.yaml @@ -0,0 +1,40 @@ +name: sculpin +version: "3" +label: Sculpin +color: "#84a4b4" +# Sculpin is a static site generator: the dev environment writes to output_dev, +# and that folder is the whole site. +public_dir: output_dev +php: + min: "7.4" + max: "8.4" + +detect: + - composer: sculpin/sculpin + +env: + file: "" + format: none + +composer: auto +npm: auto + +workers: + watch: + label: Watch & rebuild + icon: refresh + command: vendor/bin/sculpin generate --watch + restart: always + +setup: + - label: Generate the site + command: vendor/bin/sculpin generate + default: true + +commands: + - name: generate + label: Generate the site + command: vendor/bin/sculpin generate + description: Regenerate output_dev from the source folder + output: text + icon: refresh diff --git a/frameworks/slim.svg b/frameworks/slim.svg new file mode 100644 index 0000000..387f317 --- /dev/null +++ b/frameworks/slim.svg @@ -0,0 +1 @@ + diff --git a/frameworks/slim/4.yaml b/frameworks/slim/4.yaml new file mode 100644 index 0000000..7983f04 --- /dev/null +++ b/frameworks/slim/4.yaml @@ -0,0 +1,25 @@ +name: slim +version: "4" +label: Slim +color: "#749c44" +public_dir: public +create: composer create-project slim/slim-skeleton:^4.0 +php: + min: "7.4" + max: "8.5" + +detect: + - composer: slim/slim + +# The skeleton keeps its settings in app/settings.php and reads no dotenv, so +# there is no file for lerd to write connection values into. +env: + file: "" + format: none + +composer: auto +npm: auto + +logs: + - path: logs/*.log + format: monolog