Setting up a Local Environment
Do you have a Drupal website you need to style? Or maybe it uses a default layout and the result is not what you want?
Drupal splits the management of content and how it is presented on a page in a very precise way. You can have the same content presented with very different layouts.
The layer of Drupal that manages layout and style is called a theme. The aim of this book is to teach you what the theme layer is, how it works, and how to leverage it to style content the way you want.
To get started, you need an environment where you can do your work. You can choose between your local machine or some remote service; in both cases, you will need a way to run a PHP interpreter, a web server, and a database server.
You will also need a code editor that supports working on different kinds of files—such as PHP, CSS, JavaScript, and YAML—and that is advanced enough to help you navigate through the project, write new code, and debug existing code.
In this chapter, we’ll set up that environment.
We will cover the following topics:
- Installing the required software
- Installing the demo site
- Exploring the demo site
- Disabling production optimization
Technical requirements
Which software to use to run a project locally can be a matter of taste or a best practice enforced by a team (or an organization). In this section, we’re going to install a selection of software that is free (at least for personal use) and, if possible, open source.
The following selection is not mandatory but it will simplify reading the rest of the book because all the screenshots and examples are based on the platforms mentioned.
Git
Git is a distributed version control system that helps developers manage their source code changes over time. It tracks changes in code and allows multiple developers to collaborate on a project simultaneously. Git allows developers to work on their own copy of the code, experiment with different changes, and merge those changes back into the main code base when they're ready. It also allows for backup and recovery of code in case of system crashes or data loss. Git is widely used in software development and other collaborative projects.
The code used in this book is hosted in a Git repository provided by a company called GitHub. From that remote repository, you can obtain (clone) a copy of the code. A Git client is available by default on Linux and macOS systems; on Windows, you must use the WSL 2 subsystem.
You usually interact with Git using the command line, but different tools exist to provide a graphical user interface (one of these is Visual Studio Code, which we’ll install later).
Docker
Docker is a technology used to replicate the same software stack everywhere, independently of the host operating system. This is mandatory to keep consistency between all the developers in a team who may individually use different operating systems. Docker is also useful for replicating as much as possible the configuration of the production environment or having multiple stacks on the same local machine, each one with different software versions and configurations. Maybe you’re working on an old Drupal 7 website that requires PHP 7.*, and a shiny new Drupal 10 website that requires PHP 8.1.
Docker can be installed in different ways, but here we’ll use the simplest one: Docker Desktop.
Docker Desktop is a commercial application developed by the Docker team itself and it’s free for use unless you’re in a large enterprise (more than 250 employees or more than 10 million USD in annual revenue) or some government entity.
Detailed instructions on how to install it can be found at https://docs.docker.com/get-docker/. In the next examples, we’ll use macOS, but the setup and usage are the same on Windows and Linux.
After the installation, you may need to set up Docker Desktop to match your system. Here’s how to do that:
- To run Docker, simply click on its icon in the applications list. Once it's up and running, you'll see the Docker icon appear on the top right of your screen. Clicking on the icon will open a menu where you can easily check if Docker Desktop is running smoothly or if there are any issues to address.

Figure 1.1 – Docker Desktop menu
- Click on the Preferences link to open the Preferences window.
- Click on the Resources | Advanced section to tweak how many of your system resources Docker can consume. On the right pane, you can select how many CPUs and how much memory, swap, and disk size Docker can use:

Figure 1.2 – The Advanced section of Docker Desktop
In this case, I’ve set my system to grant Docker up to 4 CPUs and 12 GB of memory. Usually, you’ll want to choose half of the resources of your system.
- Click on the Resource | File sharing section to configure which directories can be bind-mounted into Docker containers:

Figure 1.3 – The File sharing section of Docker Desktop
In a production environment, you will have a Docker image that contains both the PHP interpreter and the code of the website, but in a local environment, to speed things up, the code stays on the host (your local machine) and is then mounted (made accessible) to the Docker container using a volume. Docker Desktop allows only for a subset of your computer filesystem to be mounted to a Docker container (for security and performance); you can set which directory to include in the File sharing section of the Preferences pane. The /Users
directory is included by default, so you can just clone the demo repository somewhere inside this folder.
To be sure everything is clear, here you can find a list of base Docker concepts as a reference:
- Docker engine: The core system that allows you to build and run containers.
- Image: Contains a list of instructions used to build a container.
- Container: This is the executable image that contains everything needed to run an application.
- Volume: This is the system used by Docker to persist a container’s data between executions. So, container data stored in a volume will be preserved even if the container itself is stopped or removed. Furthermore, the same volume can be attached to multiple containers.
- Compose: This is a tool that allows a set of containers to work together in the same network.
To run a Drupal website, we need at least two containers—one with a web server and one with a database server. Other containers can be useful during development, such as one to explore the database data and one to catch sent emails (for debugging purposes).
Of course, you can set up your stack from scratch, choose which images to use (or build some custom ones), configure them, find a way to orchestrate them, and so on. Because this is a book on Drupal and not Docker, we’ll use a tool that does everything we need for free.
DDEV
DDEV is an open source tool to speed up local PHP development. It uses Docker to configure and run everything that is required to work on a Drupal (or other PHP-based) website. It also provides a lot of commands to interact with the stack.
DDEV configurations can be added to Git and shared with all developers in the team. In this way, whoever clones and spins up the project will have exactly the same environment.
Again, the installation procedure depends on your computer's operating system. You can find all the details on the project website: https://ddev.readthedocs.io.
Note
Pay attention to the installation procedure—one required step is about installing and configuring mkcert
(https://github.com/FiloSottile/mkcert). mkcert
allows you to visit any DDEV-managed website using HTTPS just as it will be in production.
DDEV doesn’t have a graphical interface; everything is managed through the command line. To see a list of all available DDEV commands, you can simply type ddev
on your terminal:
The demo code you’ll download in the next section contains a ready-to-use DDEV setup, located in the .ddev
folder in the root of the repository.
Visual Studio Code
More than just a code editor, we need a full IDE to support our work with different kinds of files. Here, we have a lot of choices, which are mainly driven by personal taste and budget. One IDE that is free but very powerful is Visual Studio Code.
Visual Studio Code is a free application that runs nearly everywhere, from every operating system through the web (it’s the IDE that powers https://github.dev and https://www.gitpod.io, for example).
Note
You can find detailed instructions about how to download and install Visual Studio Code at https://code.visualstudio.com/docs.
Visual Studio Code's features can be enriched by installing extensions; we’ll need some of them to speed up our work, including the following:
- PHP Intelephense
- PHP Debug
- Tailwind CSS IntelliSense
- Twig Language 2
- Prettier (a code formatter)
To install an extension, follow these steps:
- Open Visual Studio Code.
- Click on the View | Extensions menu item to open the extensions view.
- Use the search engine to find the extension to add.
- Click on the Install button under the extension name in the right pane:

Figure 1.4 – PHP Intelephense is one of the most complete plugins for working on PHP with Visual Studio Code
Our local stack is ready to be used. In the next section, we’ll use it to set up and run the demo website.
Installing the demo site
Now that the local environment is ready, we can clone the repository of the demo site.
Cloning and building
The repository has two branches, one with the final website (the same one that you will have at the end of this book) and one with just the CMS configured. We’ll start with the latter, but if you want to see the final result you can switch to the first one.
Start by cloning the repository in a local folder. Remember that Docker Desktop limits the folder that can be mounted in a container, so choose one that is included (usually a subfolder of your home directory is the safer choice):
Then, cd
to that folder and start the DDEV stack:
This command starts the stack but doesn’t build the website; to do that, you must run this command:
build
is a custom command, not part of the original DDEV installation, and it’s available because it has been defined in the .ddev/commands/web
folder of the repository you’ve cloned. In the .ddev/commands
folder, you will find some other custom commands that we have added to DDEV, and you can add your own too. Commands are bash
scripts that run on your host shell or in one of the running containers, depending on which folder contains it:
.ddev/commands/host
: The host computer.ddev/commands/web
: The web container (where the web server and the PHP interpreter run).ddev/commands/db
: The container that runs MySQL
Note
The folder that contains the website is mounted into the web container. The files are exactly the same, but they can be accessed from your local computer and from the web container. Bear in mind that the absolute path may be different between the two systems. On your local computer, it will be something such as /Users/lussoluca/Sites/modern_drupal_themes
, but on the web container, it will always be /var/www/html
. You can connect to a shell that runs in the web container using the ddev ssh
command. To close the web container shell and return to the host shell, just type exit
and hit Return.
Internally, the build
command uses a set of tools to download all the required dependencies and install the website.
Every time you want to reinstall the demo website from scratch, you can execute the build
command again.
DDEV provides some other useful commands, as follows:
stop
: Stop and remove the containers of a project. Does not lose or harm anything.describe
: Get a detailed description of a running DDEV project.delete
: Remove all project information (including the database) for an existing project.
And there are many more—just type ddev
and hit Enter to see them all.
Note
During the start process, DDEV may print a message such as “ssh-agent container is running: If you want to add authentication to the ssh-agent container, run 'ddev auth ssh' to enable your keys.
” You can safely ignore this warning in our context.
Composer
All the external PHP dependencies needed to run the website (such as contrib
modules and development tools) are not versioned in the Git repository. Instead, they’re downloaded from the internet using a tool called Composer. Composer manages packages using a Semantic Versioning approach, where every package has a version in the form of major.minor.patch
(more information at https://semver.org). The application and its dependencies are described in a file called composer.json
, usually located in the root folder of the project. Composer has a lot of commands, but the three most used are shown next.
Here’s the first one:
This updates all the packages to the latest version (always respecting the Semantic Versioning rules). This command also updates (or creates) a composer.lock
file that stores the exact version that has been installed for each package. The composer.lock
file must be added to the Git repository and is mandatory to allow every developer on the team, the CI/CD pipelines, and remote environments to have the same version of every dependency.
The second most used Composer command is this one:
This reads from a composer.lock
file and downloads the exact version of every package.
Finally, when you need a new package (for example, the WebProfiler
contributed module) you can run the following command:
The ddev build
command already executes composer install
for you, and you can see the list of required packages in the composer.json
file in the root folder of the project.
Configuration management
Starting from Drupal 8, the system exports all the configuration needed to recreate the site into a folder, where each configuration is stored as a YAML file. A complex website can have hundreds of such files. Drupal doesn’t use those files directly; they must be imported into the database (this means that if you change one of those files manually, it needs to be imported again to be seen by Drupal). A way to package configurations is to create an installation profile. Drupal core has some ready-to-use installation profiles, such as Standard, Minimal, and Umami (you can see the full list by installing Drupal using the web interface or by looking in the core/profiles
folder). In our demo website, we have defined a new installation profile, called AlpsTrips, in the web/
profiles
folder.
Just about everything in Drupal has a double name—one for humans (such as the profile name, AlpsTrips) and one for machines (that has more restrictive rules, such as no spaces, only some special characters allowed, and so on). The machine name for the AlpsTrips profile is alps
_
trips_profile
.
Drush
One of the packages downloaded by Composer is Drush (https://www.drush.org/latest/). Drush is not a Drupal module and it isn’t used by the website itself; it’s used to automate operations on a Drupal website from the command line. Tasks such as installing Drupal, managing content or users, installing modules, and so on can all be done without even opening a browser instance. To see all the available Drush commands, you can run the following:
DDEV will forward the call to the Drush instance present in the web container.
Default Content
The content of a Drupal website stored in the same database that is used for configurations, but unlike configurations, the core of Drupal doesn’t have any tools for exporting them. To style the website, we need some content to work on (but also for showing the work in progress to the customer, or for writing end-to-end tests). This can be done in a lot of different ways; the community has not yet agreed on the tool to be used by default.
One solution is to use the Default Content contributed module (https://www.drupal.org/project/default_content).
On the demo website repository, we've used Default Content to export a set of dummy contents to a custom module (located on the web/modules/custom/demo
folder). When this module is enabled, the contents are automatically imported into Drupal.
Yarn
The latest tool that is used to build our website is Yarn. Yarn is a package manager for Node.js, and we need it for the same reason we need Composer for PHP packages: we don’t want to save the dependencies in our repository. Similar to Composer, Yarn uses two files—package.json
and yarn.lock
—to describe which packages to download and at which exact version. Yarn can also be used to define and run custom scripts, such as building CSS and JavaScript assets.
All of those tools are used by our build
command to go from a set of files in a repository up to a fully functional Drupal website. The tasks that are executed are set out here:
- Use Composer to download all the required PHP dependencies:
composer
install –prefer-dist.
- Use Drush to install Drupal from a set of configurations.
- Use the Default Content module to import dummy content.
- Use Yarn to download all the required JavaScript dependencies and to build the theme assets.
After the build
command ends, you can open a browser and start navigating. The website URL is printed at the end of the ddev start
command. At any time, you can use the ddev describe
command to print a list of details about the project. The URL you’re looking for is the one for the web
service:

Figure 1.5 – Using ddev describe to list all the available services for a project
In this case (and probably also for you), the URL is https://packt.ddev.site
, and the website should look like this:

Figure 1.6 – The home page of the AlpsTrips website
You’re navigating as an anonymous user; if you want to administer the site, you must log in as a user with some administrative privileges. During the build, one such user has been created for you, with admin
as username and admin
as password. To log in, you can do the following:
- Click on the Log in menu item
- Navigate to https://packt.ddev.site/user/login
After submitting the credentials, you should see some more elements, such as a dark toolbar at the top of every page. From there, you can access every configuration page of Drupal.
Note
The admin
user created during the installation phase of Drupal has too much power. The permissions enforcement and the access checks don’t run for that user. In a real project, we suggest you create a new user, with only the permissions required.
The demo website is packed with everything you will encounter in a standard Drupal website, so let’s explore it and review all the concepts we’ll need to style it.