Example .drupalaibp/ configs
Two complete, runnable configs live in this directory in the repository:
drupal/: a Drupal CMS site with the full provisioning surface, custom questions, and hook scripts. Reach for it as the template for a real Drupal team config.storybook/: a non-Drupal Node/Storybook project built entirely by hooks. Reach for it when you want DDEV plus coding agents around something that is not Drupal.
Running an example
Each example directory is self-contained. Either copy it and let the installer auto-detect the config:
cp -R docs/examples/drupal ~/my-build && cd ~/my-build
bash <(curl -fsSL https://aibp.drupalstarforge.ai/install.sh)
or point the installer at the directory with --config-path (or the
positional source argument):
drupalaibp --config-path path/to/one_line_installer/docs/examples/drupal
A team config repo works the same way with --config-url <git-url>: put the
.drupalaibp/ directory at the repo root (exactly as these examples model
it inside their subdirectories) and the installer clones the repo, builds
from its config, and copies the repo into the project.
How a config works
Drop a .drupalaibp/ directory (containing a config *.json) in the directory
where you launch the installer and it pre-configures the build from that config —
creating the project, installing the coding agents/skills, provisioning, asking
any custom questions, and firing your hook scripts at named build events. Hook
script paths resolve relative to the config file and are copied into the
new project root before they run. Since the config now lives at
.drupalaibp/config.json, a script that sits beside it is referenced as
./seed-content.sh — paths are relative to the .drupalaibp/ directory (the
CONFIG_BASEDIR).
Each example below is a self-contained directory: copy it somewhere, cd into
it, and run the installer. The config and its hook scripts/assets all live
together inside the .drupalaibp/ directory, so a hook script (or a
copy_paths entry) is written relative to that directory.
drupal/ — a Drupal site with provisioning
is_drupal: true, Drupal CMS on Drupal 11. It shows the full Drupal path:
- a private
repositoriesentry registered beforecomposer_projectsare required (soacme/acme_ai_glueresolves); composer_projects(fetch, here withcomposer_with_all_dependencies: true) +install_modules(enable) + arecipesapply. Note the split:recipesonly applies (drush recipe), so thedrupal/drupal_cms_blogrecipe is listed in bothcomposer_projects(to fetch it) andrecipes(to apply it);- Toolbelt expressed as ordinary provisioning —
drupal/tool+drupal/tool_beltincomposer_projectsandtool/tool_belt/tool_belt_*ininstall_modules. There is no dedicatedtoolbeltflag: a built-in handler notices those packages and applies the alpha-stability +tbachert/spiplugin-trust setup they need; - Selenium as a plain
ddev_addonsentry (ddev/ddev-selenium-standalone-chrome) plus a Redis add-on. A built-in handler fires after the add-on is pulled to rewrite its docker-compose/config for headed Chrome watchable over VNC — no dedicatedseleniumflag; questions— apassword(OpenAI key →.ddev/.env, never committed), asingle-select-optionsflavor, and one carrying avalue(SITE_ENV) which pre-answers it so no prompt is shown (distinct fromdefault, which only pre-fills an editable prompt);- an
agents_mdblock whose paragraphs are appended into the installer-managed section ofAGENTS.md— project-specific agent instructions with no hook script; - hooks on
ddev_started(seed content, reading$SITE_FLAVOR) andcoding_agent_added(per-agent notes, receiving the agent name as$1).
AI Best Practices (drupal/ai_best_practices) and drupal/core-dev + phpunit.xml
are not listed here — they are built-in defaults for every is_drupal: true
build.
DTK works the same way as Toolbelt: add drupal/dtk:1.0.x-dev to
composer_projects and dtk to install_modules.
storybook/ — a non-Drupal Node/Storybook project
is_drupal: false, so every Drupal-specific step self-skips (no
composer create-project, no drush, no config export). DDEV + the coding
agents + skills are still set up; the actual project work is driven entirely by
hooks. docroot is set to storybook-static (the directory storybook
build writes to) so DDEV serves the built site directly — a non-Drupal config
has no web/ to fall back on, so docroot must point at wherever the hooks
actually produce output. docroot is also written to .ddev/.env as
$DOCROOT, so build-storybook.sh reads it instead of hardcoding
storybook-static a second time — keep any hook that writes a build output
reading $DOCROOT rather than repeating the directory name:
ddev_startedweight 10 →npm-install.sh(runsnpm init,npx storybook init, installs the selected addons)ddev_startedweight 20 →build-storybook.sh
Both hooks set "where": "web", so they run inside the DDEV web container and
call npm/npx directly (no ddev exec wrapper). A hook's where is host,
web (default), or a ddev service name; a hook on a pre-start event (e.g.
coding_agent_added in the Drupal example) must use where: host because the
container isn't up yet.
If your project has its own hand-authored .storybook/ config (a real
main.ts/preview.tsx/theme.ts, not the placeholder storybook init
scaffolds), keep it next to the config under a non-.storybook name — e.g.
./.drupalaibp/storybook-config/ — and add it to copy_paths
("copy_paths": ["./storybook-config"], relative to .drupalaibp/). That
stages it into the new project root at ./storybook-config (a copy_paths
entry is mirrored to the same relative path in the project). Then have
npm-install.sh copy it over the generic generated .storybook/ after
storybook init:
npx --yes storybook@latest init --type "${framework}" --builder vite --yes
if [ -d storybook-config ]; then
rm -rf .storybook
cp -R storybook-config .storybook
fi
It is stored as storybook-config rather than .storybook directly because a
copy_paths entry is mirrored to the same project-root path — a staged
.storybook/ would be overwritten by storybook init; staging it under a
different name and copying it over after init sidesteps that collision.
It also demonstrates every question type driving those npm commands: a
single-select-options (STORYBOOK_FRAMEWORK → storybook init --type), a
multi-select-options (STORYBOOK_ADDONS → one npm install per selected addon;
the answer arrives comma-joined), a text (STORYBOOK_PORT), and a password
(NPM_REGISTRY_TOKEN). All land in .ddev/.env and reach the hook scripts as
environment variables.
Schema reference
See the schema doc for the full schema and semantics:
docs/drupalaibp-json.md.
Available hook events: before_<step> / <step>_done for every pipeline step,
plus the semantic events before_ddev_start, ddev_started,
coding_agent_added, skill_added, and ask_questions.