Our delivery loop is the same every time.
1. Scope a skeleton. Start from
drupal-skeleton (or rust-skeleton for desktop apps).
Inherit DDEV, PHP 8.3, MariaDB 11.4, Composer + Node 20, and a green smoke test on day
one. No "let's set up the local dev environment" sprint.
2. Model the content first, the UI second. Content types, fields, taxonomies, and view modes get sketched as YAML before a single template is drawn. The content model survives template rewrites; the templates don't survive content model changes.
3. Seed from CSV, validate from CSV. Real content arrives as
spreadsheets. A four-command Drush surface — import, export,
diff, commit — gives operators a flat, diff-able, comment-able
working surface, and gives developers the guarantee that the site reconstructs
verbatim from those files.
4. Deploy from GHCR. GitHub Actions builds an OCI image on every
push; SSH-keyed deploys to a single Traefik-fronted VPS pull and recreate.
Schema-changing deploys destroy and reinstall — no orphaned hook_update_N
drift.
5. Retrofit forward. When the project ships, every lesson worth keeping moves back to the skeleton. The next project starts with all of this one's hard-won defaults.
We've used this loop on a bilingual Drupal Commerce property (Mon Petit Café, Bogotá), on a contrib-grade three.js Drupal theme, on a Windows desktop app for matrices, on an ElevenLabs voice-agent integration. The constants travel; the specifics don't.