I've created a custom route that uses a controller to use a custom template. If I don't mess with base hook my template is rendered somewhere inside page.html.twig as a block and all the variables are accessible. However, I would like to design the page from scratch and be able to override the page.html.twig template. Is this possible?

I'm almost there but I can't access my variables in the template. And the twig dump() returns unstyled sfdump.

Here is the code:



namespace Drupal\te\Controller;

use Drupal\Core\Controller\ControllerBase;

class LangController extends ControllerBase{
  public function langSingle() {
    return [
      '#theme' => 'page__lang_single',
      '#lang_data' => 'testguk'


In the .module file I add more specific suggestions and implement the hook_theme()



 * Implements hook_theme_suggestions_page_alter().
function te_theme_suggestions_page_alter(array &$suggestions, array $variables) {
  if (\Drupal::routeMatch()->getRouteName() == 'te.lang_single') {
    // Suggest a custom template for the page.
    $suggestions[] = 'page__'.'lang_single';


function te_theme($existing, $type, $theme, $path) {

  return [
    'page__lang_single' => [
      'base hook' => 'page',
      'variables' => [
        'lang_data' => NULL,
      'template' => 'page--lang-single',


My template is in the module's templates folder. But if I hit my route I get this unstyled dump() from twig

What is strange the variables like page.navbar are accessible, but my expected lang_data is hardly accessible. Well at least I can't figure out how to render its value without usual dump.

If I search the page the value can be found, but there is definitelt something wrong with my template rendering

enter image description here

  • I think you must not define variables key for a template that use a base hook, because it's inherit of the ones of the base ( see documentation ). Maybe try to take this off, and if you have to add some variable do it with a preprocess hook.
    – TytooF
    Commented Apr 11 at 11:18

1 Answer 1


However, I would like to design the page from scratch ...

The controller is still returning a render array. Then you agree that Drupal is building the page for you, by default using page.html.twig with regions and blocks. Use a different random custom template name, render the build array with renderRoot(), and return it in a response. Drupal won't touch a response with already rendered HTML:

return new Response(\Drupal::service('renderer')->renderRoot($build));

The custom template is then an entire HTML page, for example

<!DOCTYPE html>
    <title>{{ title }}</title>
    <h1>{{ title }}</h1>
    <p>{{ bodytext }}</p> 

where title and bodytext are two template variables passed from the controller.

  • Thanks. But what do I do if I want to use the page.html.twig and still have my variables from the controller? Is this possible?
    – Andrei
    Commented Apr 11 at 11:54
  • I was answering "design the page from scratch". For the controller part, this is not possible. But what is so special about your variables? Controller and page preprocess share the route and its parameters. So you could refactor the code to calculate the variables. Ideally, this is route parameter upcasting stored in the route object.
    – 4uk4
    Commented Apr 11 at 12:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.