Skip to main content
Version: v1

Architecture

This page describes how the Vortex template is structured and how its components work together in your project.

Design principles​

Vortex follows these principles:

  • Simple is better than complex: The template encourages clarity, even in customizations.
  • Use standard tools: Wherever possible, Vortex follows upstream conventions and avoids reinvention.
  • Avoid silent errors: Misconfigurations should fail loudly.
  • Readability counts: Code and configuration are meant to be understood.
  • Explicit logging helps: Scripts log every major step, so you can follow what's going on.

Code lifecycle​

Vortex follows the same code lifecycle in local, CI, and hosting environments, which reduces the chance of errors.

The lifecycle below covers the whole system, and each section of this page describes one of its stages:

Local Development
═════════════════════════════════════════════════════════════════════════════════════════
Developer writes code ──► Build and test locally ──► Commit changes
│
▼
Git Repository
═════════════════════════════════════════════════════════════════════════════════════════
Push to remote branch ──► Open/Update Pull Request
│
▼
┌─ CI Pipeline ────────────────────────────────────────────────────────────────────────────┐
│ │
│ ┌─ Database Job (Nightly) ───────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Scheduled ──► Download production ──► Sanitize database ──► Store database cache │ │
│ │ trigger database Remove sensitive data │ │
│ │ │ │
│ └─────────────────────────────────────┬──────────────────────────────────────────────┘ │
│ │ Provides cached database │
│ ▼ │
│ ┌─ Lint Job ────────────┐ ┌─ Database Job ────────────────┐ ┌─ Audit Job ──────────┐ │
│ │ │ │ ◆ Nightly cache exists? │ │ Composer audit │ │
│ │ Build CLI container │ │ Yes ──► job succeeds │ │ (advisories) │ │
│ │ ▼ │ │ No ──► download, sanitize, │ │ ▼ │ │
│ │ Composer validate │ │ store cache │ │ Gitleaks │ │
│ │ ▼ │ └───────────────┬───────────────┘ │ (committed secrets) │ │
│ │ Composer normalize │ ▼ │ │ │
│ │ ▼ │ ┌─ Build Job ───────────────────┐ │ │ │
│ │ Hadolint │ │ Code assembly │ │ │ │
│ │ ▼ │ │ Docker, Composer deps, │ │ │ │
│ │ DCLint │ │ NPM deps, assets │ │ │ │
│ │ ▼ │ │ ▼ │ │ │ │
│ │ PHPCS │ │ Website setup │ │ │ │
│ │ ▼ │ │ Import cached DB, drush │ │ │ │
│ │ PHPStan │ │ deploy, custom scripts │ │ │ │
│ │ ▼ │ │ ▼ │ │ │ │
│ │ Rector │ │ Testing │ │ │ │
│ │ ▼ │ │ PHPUnit tests ──► Behat tests │ │ │ │
│ │ Twig CS Fixer │ └───────────────┬───────────────┘ │ │ │
│ │ ▼ │ │ │ │ │
│ │ Gherkin Lint │ │ │ │ │
│ │ ▼ │ │ │ │ │
│ │ ESLint / Stylelint │ │ │ │ │
│ │ │ │ │ │ │
│ └──────────┬────────────┘ │ │ │ │
│ │ │ │ │ │
│ ▼ ▼ │ │ │
│ ┌─ Deployment Job ─────────────────────────────────────────┐ │ │ │
│ │ │ │ │ │
│ │ Webhook Artifact Lagoon │ │ Does not gate │ │
│ │ Call URL Package artifact Run Lagoon CLI deploy │ │ deployment │ │
│ │ │ │ │ │
│ └──────────────────────────────────────────────────────────┘ └──────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────┘
│
▼
Hosting Platform
═════════════════════════════════════════════════════════════════════════════════════════
◆ Environment ──No──► Sync DB from production ───┐
exists? │
│ Yes ▼
└──────────────────────────────────► drush deploy ──► Custom scripts ──► Notifications


Available Environments
═════════════════════════════════════════════════════════════════════════════════════════
┊ PR Environment ┊ Dev Staging Production
┊ (auto-removed) ┊ develop branch main branch production branch or tag

Local development environment​

Your project includes a containerized local environment that uses Docker Compose and production-grade Lagoon images, so local, CI, and hosting environments stay consistent.

Ahoy wraps complex tasks like provisioning, testing, or database imports in short, memorable commands.

Planned features

Support for DDEV and Lando is on our roadmap for local development environments.

➡️ See Development > Environment

Automation scripts​

Vortex uses POSIX-compliant Bash scripts shipped via the drevops/vortex-tooling Composer package (installed to vendor/drevops/vortex-tooling/src/) to automate common tasks and connect components together.

These scripts:

  • Run identically across local, CI, and hosting
  • Support environment variables to adapt behavior
  • Are modular and extensible

The scripts aren't part of the template's own files: they're a dependency. Your project's composer.json requires drevops/vortex-tooling with a tilde constraint (~1.4.0 in the shipped template), which accepts patch releases but holds the minor version. As a result, a new minor release can't reach your deployments until you raise the constraint yourself. Once installed, every script is available as a Composer binary at vendor/bin/vortex-<script> (for example vendor/bin/vortex-provision or vendor/bin/vortex-deploy), and the Ahoy commands wrap those binaries.

The package repository on GitHub is a read-only mirror of the .vortex/tooling/ directory of the Vortex repository. Bugs and changes go to the Vortex issue queue, not to the mirror.

Never edit the files under vendor/drevops/vortex-tooling/src/, because the next composer update discards the change. Adapt behavior through environment variables, and add project logic as your own scripts under scripts/ (the provision script discovers and runs scripts/provision-*.sh). Use a cweagans/composer-patches patch only when a shipped script itself must change.

➡️ See Development > Composer > Vortex tooling package for updating the package and Development > Provision > Running custom scripts for extending provisioning.

Customizing scripts​

All scripts read their configuration from environment variables, so you can adapt them to a project or an environment.

During initial project setup, the .env file is updated with project-specific values such as the project name and email. Secrets, tokens, and other environment variables are then set in CI or hosting environments.

➡️ See Development > Variables

Router scripts​

Most Vortex commands are implemented as router script entry points, like vortex-fetch-db or vortex-deploy, that dynamically invoke the more specific logic for your setup, based on configuration or environment variables.

For example:

  • vortex-fetch-db fetches a database from any supported hosting provider or a custom location, so the caller doesn't need to know how each provider works.
  • vortex-deploy deploys code the same way to Acquia, Lagoon, or another hosting provider.
Script architecture diagram
Diagram of scriptsDiagram of scripts

Drupal management​

Provisioning​

The provisioning process is central to how Vortex works. Instead of manually running Drush commands, you run a single provision script. This script handles:

  • Importing a database or initializing a database by installing Drupal from a profile
  • Running updates, config imports, cache rebuilds, and deploy hooks
  • Executing post-provision custom scripts

Because provisioning is centralized, it runs the same way locally, in CI, and in hosting.

You can also add automation around provisioning, such as running migrations conditionally or creating demo content.

➡️ See Development > Provision

Settings management​

Vortex organizes Drupal settings per environment:

  • The environment type (for example, local, CI, stage) is automatically detected based on the environment provider settings located in web/sites/default/includes/providers/.
  • Settings overrides are stored in web/sites/default/includes/modules/ with logic per environment inside each module-specific file.

Keeping each module's settings in its own file avoids config sprawl and lets you remove a module's settings cleanly when you no longer need them.

Vortex also includes tests that check these settings load correctly in each environment.

➡️ See Development > Settings

Module and theme scaffolds​

Vortex includes an example custom module and theme, each with tests. They show how to:

  • Structure custom features
  • Write functional, kernel, and unit tests
  • Connect theme assets to a build pipeline

Use these scaffolds as starting points for your own work.

➡️ See Development > Modules > Module scaffold and Development > Themes

Code quality and testing​

Vortex ships with pre-configured tools for maintaining code quality:

  • PHP CodeSniffer (PHPCS)
  • PHPStan
  • Rector
  • Twig CS Fixer
  • ESLint
  • Stylelint

You'll also find scaffolds for:

  • PHPUnit: Unit and kernel testing
  • Behat: Behavior-driven testing with screenshot capture and extra steps
  • Jest: JavaScript unit testing

➡️ See Development > Code quality and Development > Testing

Automated dependency updates​

Vortex includes configuration for RenovateBot to automate dependency upgrades:

  • Critical updates checked daily
  • Regular updates run weekly
  • Most new releases wait 14 days before they're proposed, so a registry can pull a compromised release first
  • PRs include changelogs and pass through your continuous integration pipeline

You can host RenovateBot yourself or use the cloud version, and you can tweak the schedule as needed.

➡️ See Development > Dependency updates

Environment variables​

Vortex uses environment variables extensively to configure behavior across local, CI, and hosting environments.

These variables are either defined in the .env file or set within CI/hosting environments as secrets.

➡️ See Variables

Continuous integration workflows​

Vortex supports GitHub Actions and CircleCI. You choose which one to use in your project. These pipelines include:

  • Database fetch and caching (for faster builds)
  • Full site provisioning in CI
  • Running code quality checks
  • Running unit, functional, and behavior tests
  • Triggering deploys when tests pass

Each continuous integration configuration mirrors what happens locally and in hosting.

➡️ See Continuous Integration

Hosting integrations​

Vortex has built-in support for Acquia and Lagoon hosting. These integrations:

  • Trigger provisioning with the same steps used locally and in CI
  • Provide deployment pipelines suited to each platform

You can use Vortex with other platforms too, but only Acquia and Lagoon have built-in integrations.

➡️ See Hosting

Documentation & onboarding​

Vortex includes centralized documentation (what you're reading now), as well as a scaffold for adding project-specific docs within your own repository.

Testing the template​

The template and its automation scripts are tested at multiple levels:

  • Unit tests: Shell scripts are tested in isolation using Bats with mocked commands
  • End-to-end tests: Full build pipelines are tested using PHPUnit in real Docker containers
  • Real-world validation: The DrevOps website is a production reference site that receives regular upstream updates

➡️ See Contributing > Maintenance > Template