How to Fix Drupal 10 / 11 Sites Without a $90/hr Acquia Specialist
Drupal is the most architecturally serious open-source CMS — it's also the most expensive to maintain. A senior Drupal dev bills $80–150/hr. Yet most "Drupal site is broken" tickets fall into a few buckets: a stuck cache_* table, a missing config import after deploy, a dead module after a security update, or a WSOD (white screen of death) from a contrib module. SimpleReview's Drupal-aware agent knows the module/theme override system (themes/custom/[theme]/, modules/custom/[module]/, config sync) and can edit the right file the first time and open a PR.
web/modules/custom/, finds the file, opens a PR. Fix ships within an hour.
Key Takeaways
- Drupal customization lives in
web/modules/custom/,web/themes/custom/, plus contrib inweb/modules/contrib/. Never editcore/orvendor/. - WSOD usually = a fatal in a custom module's
.moduleor.installfile. Symfony exception trail insites/default/files/php/twig/. - Drupal 10 → 11 upgrade requires PHP 8.3+, removes
pathandaggregatorfrom core, expects all modules updated. - Drupal.org Project pages at
drupal.org/project/— we publishsimplereviewmodule. Install:composer require drupal/simplereviewor admin → Extend → Install new module → URL → enable. - For Composer dependency hell, multi-site Drupal, custom Views handlers, GraphQL/JSON:API customization → Vibers human review.
Drupal File Layout in 60 Seconds (Drupal 10/11)
Modern Drupal (10/11) ships with a Composer-managed web/ docroot. Knowing which folder owns what is the difference between a 10-minute fix and a 4-hour quote.
| Path | What lives there | Edit? |
|---|---|---|
/web/modules/contrib/ | Community modules from drupal.org (CAPTCHA, Webform, Pathauto…) | No — managed by Composer |
/web/modules/custom/[name]/ | Your custom modules — .info.yml, .module, .install, src/ | Yes — this is your code |
/web/themes/contrib/ | Contrib themes (Bootstrap, Gin, Radix) | No — override in custom subtheme |
/web/themes/custom/[theme]/ | Your theme — templates/, css/, js/, [theme].info.yml | Yes |
/web/sites/default/settings.php | Site-specific settings — DB creds, hash salt, trusted hosts, error verbosity | Yes (carefully) |
/config/sync/ | Exported config (Configuration Management) — *.yml per entity/view/field | Yes — commit changes through drush cex / drush cim |
/vendor/ | Composer dependencies (Symfony, Twig, Guzzle…) | Never — regenerated on composer install |
Three-Click Workflow with SimpleReview
- Install the SimpleReview Chrome extension from the Chrome Web Store. Free with your own AI key (Claude Code or Codex), built-in mode otherwise.
- Connect your Drupal repo. Paste a GitHub / GitLab / Gitea URL. If your site isn't on Git yet, give SFTP credentials and the agent will work from a private working tree. Composer-managed sites are auto-detected via
composer.jsonat the project root. - Open your Drupal site, click the SimpleReview icon, click the broken element or the area to change. Type plain English: "remove Powered by Drupal", "fix WSOD on /node/42", "add reCAPTCHA to the contact webform". Click Fix it. The agent reads the right override file (or opens the right config YAML) and ships a PR.
Common Drupal Fixes
WSOD (White Screen of Death) after a deploy
First step: enable verbose errors in sites/default/settings.php:
// sites/default/settings.php
$config['system.logging']['error_level'] = 'verbose';
Then check Recent log messages at /admin/reports/dblog, or tail the Twig debug log:
tail -f sites/default/files/php/twig/*.log
Common cause: a custom module references a removed deprecated API. The classic offender is drupal_set_message() — removed in Drupal 9. Replace with the modern messenger service:
// before — fatal in Drupal 9/10/11
drupal_set_message(t('Saved.'));
// after
\Drupal::messenger()->addMessage(t('Saved.'));
The agent finds the call site in web/modules/custom/[name]/[name].module, swaps it, runs drush cr in the PR description, and ships the patch.
Add reCAPTCHA to a webform / user register
Install the captcha + recaptcha modules:
composer require drupal/captcha drupal/recaptcha
drush en captcha recaptcha -y
drush cr
Configure: admin → Configuration → People → CAPTCHA → reCAPTCHA → enter site key + secret. Then admin → Configuration → People → CAPTCHA settings, set the form ID (e.g., user_register_form) and challenge type to reCAPTCHA. The agent generates the PR with the composer require command and the corresponding config/sync/captcha.settings.yml diff.
Hide "Powered by Drupal" from footer
Two valid paths. The simpler one is to disable the block from the UI: admin → Structure → Block layout → disable the Powered by Drupal block in the footer region. Do not comment out core templates.
The Twig override path (works even when block placement is theme-driven):
{# web/themes/custom/[theme]/templates/block--system-powered-by-block.html.twig #}
{# Empty override — suppresses the block markup #}
Then drush cr to clear the theme registry. The agent picks the override path automatically when the block is placed via the theme's [theme].info.yml regions rather than block layout.
Module conflict / module disappeared after update
Symptom: a module you used yesterday is gone from the Extend page, or shows "missing schema". Composer-based fix:
composer update drupal/[module] --with-dependencies
drush updb -y
drush cr
If still broken, check core compatibility in the module's .info.yml:
# web/modules/contrib/[module]/[module].info.yml
core_version_requirement: ^10 || ^11
A module pinned to ^9 won't load on Drupal 10. Either bump the constraint upstream (PR to drupal.org) or pick a maintained fork.
Slow admin / storefront after Drupal 10 upgrade
Enable BigPipe (drupal/bigpipe — already in core, just enable). Internal Page Cache + Dynamic Page Cache modules cover anonymous + authenticated traffic respectively. Then rebuild:
drush en big_pipe page_cache dynamic_page_cache -y
drush cr
For massive sites (10k+ nodes, complex Views): enable Redis adapter via drupal/redis module — moves cache + lock + queue out of MySQL.
Config import fails: 'Site UUID mismatch'
Classic symptom when importing config from a different environment. Drupal refuses to import config exported from a different site UUID. Fix: align the running site UUID with the one in your exported config:
# grab the UUID from the config to be imported
grep '^uuid:' config/sync/system.site.yml
# set the running site to that UUID
drush sset system.site.uuid 'NEW-UUID-HERE'
# now config import works
drush cim -y
Alternative path: import config first into a fresh install, then run drush cim. The agent picks the right path depending on whether you're rehydrating a clone or pushing dev → prod.
Drupal.org Projects — Our Module
drupal.org/project/[name] is THE marketplace — every Drupal module/theme is hosted there (16,000+ projects). We publish simplereview module (in approval — usual cycle 4–12 weeks for new modules due to security review).
Install once approved:
composer require drupal/simplereview
drush en simplereview -y
drush cr
Or via UI: admin → Extend → Install new module → paste drupal.org/project/simplereview → enable.
Until the module lands: SimpleReview Chrome Extension auto-detects Drupal via the <meta name="generator" content="Drupal X (https://www.drupal.org)"> tag plus the drupalSettings JS handle. Routes via Git or SFTP — no module install required.
Comparison Table — Drupal Specialist vs SimpleReview
| Step | Drupal Specialist | SimpleReview agent |
|---|---|---|
| Brief / Zoom | 30–60 min discovery call | One sentence in the popup |
| DDEV/Lando setup | 30–60 min per environment | Once, then cached |
| Locate the override file | 15–90 min depending on theme/module familiarity | Instant — already indexed |
| Make the edit | 5–30 min | 5–30 seconds |
Run drush cim / cr / updb | Manual + verify | Included in PR description |
| Open a PR | If they use Git | Always |
| Cost for a 1-line WSOD fix | $80–300 (1–2 hour minimum) | $0 (BYO key) or pennies of API usage |
When You Want a Senior Drupal Developer
This isn't anti-developer — it's anti-paying-an-hour-for-five-minutes. Pay for human expertise when:
- Composer + Drush + Drupal Console dependency hell — version conflicts that won't resolve, broken patches in
composer.json'sextra.patches. - Multi-site Drupal —
sites.phprouting, shared modules, per-site config sync directories. - Custom Views handlers / Field formatters — writing
HandlerBasesubclasses, customFieldFormatterplugins, exposed filters with custom widgets. - GraphQL / JSON:API customization — schema overrides, normalizers, write-mode permissions.
- Migration Drupal 7 → 9 → 10 — huge undertaking; many sites are still stuck on D7 EOL (January 2025) and need a real migration plan, not an automated patch.
- Performance audit — Apache Solr / Search API tuning, Redis sharding, Varnish vs Nginx FastCGI cache, MySQL slow query log.
Vibers handles exactly this slice — a real human reviews any PR you flag, sends a fix-up if needed, and approves before merge. Use the agent for the 80%, use a human for the 20% that earns its hourly rate.
Stop Paying $90/hr for One-File Drupal Edits
SimpleReview's Drupal-aware agent reads web/modules/custom/, finds the override file, and opens a PR for the fix you described.
D7→D10 migration, multi-site, custom Views handlers? Get a human review →
FAQ
web/modules/custom/ and web/themes/custom/[theme]/, edits the right file, and opens a pull request you can merge.sites/default/settings.php with $config['system.logging']['error_level'] = 'verbose'; then reload. Drupal will show the Symfony exception trail. Most WSODs are a fatal in a custom .module/.install file calling a deprecated API (drupal_set_message() removed in D9 — use \Drupal::messenger()->addMessage()). Tail sites/default/files/php/twig/*.log for the full stack trace.web/ docroot, Composer-managed structure, and config sync. Drupal 9 — limited (works for theme/module edits, but config schema diffs vary). Drupal 7 — EOL since January 2025; very limited support — best path is migration to Drupal 10/11 with a human Drupal developer.info.yml and templates/ folder on first connection. Olivero (default frontend), Claro (admin), and contrib themes like Bootstrap, Gin, and Radix all follow the same Twig override pattern. Custom subthemes that override base themes are auto-detected — the agent edits the override file, not the base.captcha + recaptcha), the PR includes the composer require command in the description so you (or your CI) can run it before merge.