Drupal CMS Website Development
Drupal — not the fastest start, but one of the most flexible tools for complex sites: portals, corporate sites with multi-level access, multilingual projects with non-trivial content structure. Modular architecture: core Drupal is a foundation plus contrib modules, custom code is only written where there's no ready-made solution.
Drupal Project Stack
- Drupal 10+ (PHP 8.2+, Symfony components inside)
- Composer — dependency management, the only right way to install Drupal
- Drush — CLI for site management
- DDEV or Docker Compose — local development
- PostgreSQL or MySQL — Drupal works with both
- Redis — cache. Without it Drupal is slow
- Varnish or Nginx FastCGI cache — page cache for anonymous users
Project Initialization
composer create-project drupal/recommended-project my-project
cd my-project
# Development tools
composer require drush/drush drupal/devel drupal/admin_toolbar
# Essential contrib modules
composer require \
drupal/pathauto \ # automatic URLs
drupal/token \ # tokens for pathauto
drupal/metatag \ # SEO meta tags
drupal/redirect \ # redirects
drupal/simple_sitemap \ # sitemap.xml
drupal/paragraphs \ # flexible content
drupal/entity_reference_revisions \
drupal/field_group \ # field grouping in forms
drupal/views_bulk_operations \
drupal/redis \ # Redis cache
drupal/restui # REST API management
# Installation
drush site:install --account-name=admin --account-pass=admin --db-url="pgsql://user:pass@localhost/drupal"
Custom Module Structure
All custom code lives in web/modules/custom/:
web/modules/custom/my_project/
├── my_project.info.yml
├── my_project.module
├── my_project.install # install/update hooks
├── my_project.routing.yml # routes
├── my_project.services.yml # DI container
├── src/
│ ├── Controller/
│ ├── Form/
│ ├── Plugin/
│ ├── EventSubscriber/
│ └── Service/
└── templates/
└── my-template.html.twig
Configuration Workflow
Drupal stores configuration (content types, fields, Views, roles) in YAML files. Key for team work:
# Export current configuration to files
drush config:export
# Import configuration from files (deploy to another environment)
drush config:import
# View diff between active and file configuration
drush config:status
In settings.php:
$settings['config_sync_directory'] = '../config/sync';
All YAML config files are committed to git. Production deployment — git pull + drush config:import + drush updb + drush cr.
Performance
Drupal without cache is slow. Minimum set for production:
// settings.php — Redis for cache
$settings['cache']['default'] = 'cache.backend.redis';
$settings['redis.connection']['host'] = 'redis';
$settings['redis.connection']['port'] = 6379;
// Internal Page Cache + Dynamic Page Cache already in core
// Enable in /admin/config/development/performance
For anonymous traffic — Varnish before Drupal caches pages at millisecond speed — Drupal isn't involved at all.
Timeline
Typical corporate site (homepage, sections, blog, contact form, 2 languages): 4–6 weeks. Portal with personal cabinet, roles, catalog, and REST API: 8–12 weeks.







