Skip to content
intermediate Phase 22 · Module Directories Deep Dive

View Directory - Module Directories Deep Dive

Understanding the Magento 2 View directory: frontend layout, templates, web assets, adminhtml structure, and area-specific organization

45m
0 problems
Topic Progress 0%

View Directory Structure

Complete View Layout

Vendor/Module/view/
├── frontend/
│   ├── layout/
│   │   ├── default.xml              (all frontend pages)
│   │   ├── catalog_product_view.xml  (product page only)
│   │   ├── catalog_category_view.xml (category page only)
│   │   └── vendor_module_index.xml   (custom route)
│   ├── templates/
│   │   ├── product/
│   │   │   ├── view.phtml
│   │   │   └── list.phtml
│   │   └── widget/
│   │       └── custom.phtml
│   ├── web/
│   │   ├── css/
│   │   │   └── source/
│   │   │       └── _module.less
│   │   ├── js/
│   │   │   └── component.js
│   │   ├── images/
│   │   │   └── logo.png
│   │   └── fonts/
│   └── requirejs-config.js
├── adminhtml/
│   ├── layout/
│   │   ├── default.xml
│   │   └── vendor_module_index.xml
│   ├── templates/
│   │   └── widget/
│   │       └── form.phtml
│   └── web/
│       ├── css/
│       ├── js/
│       └── images/
└── base/
    └── web/
        └── images/
            └── shared-image.png

Area Separation

Magento loads view files based on the current area:

  • frontend: Customer-facing storefront
  • adminhtml: Admin panel
  • base: Shared across all areas

Each area has its own layout handles, templates, and assets.

Frontend Layout and Templates

Layout Files

Layout XML files control page structure:

<!-- default.xml: applies to ALL frontend pages -->
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
            <block class="Vendor\Module\Block\Banner"
                   name="vendor.banner"
                   template="Vendor_Module::banner.phtml"/>
        </referenceContainer>
    </body>
</page>

Template Files (.phtml)

<!-- vendor_module::product/view.phtml -->
<?php
/** @var Vendor\Module\Block\Product\View $block */
$product = $block->getProduct();
?>
<div class="product-view">
    <h1><?= $block->escapeHtml($product->getName()) ?></h1>
    <div class="price">
        <?= $block->getFormattedPrice($product->getPrice()) ?>
    </div>
    <div class="description">
        <?= $block->escapeHtml($product->getDescription()) ?>
    </div>
</div>

Escaping Output

Always escape output to prevent XSS:

// Text escaping
echo $block->escapeHtml($text);
echo $block->escapeHtml($text, ['b', 'i', 'em', 'strong']); // allow some HTML

// URL escaping
echo $block->escapeUrl($url);

// CSS escaping
echo $block->escapeCss($css);

// JS escaping
echo $block->escapeJs($js);

// Attribute escaping
echo $block->escapeHtmlAttr($attribute);

Template Inheritance

Templates can extend other templates:

<!-- parent.phtml -->
<div class="wrapper">
    <?= $this->getChildHtml('content') ?>
</div>

<!-- child.phtml (extends parent) -->
<?php $this->extend('parent.phtml') ?>
<?php $this->blockContent('content') ?>
    <p>My content here</p>
<?php $this->blockContent() ?>

Web Assets Directory

CSS/LESS Files

Place stylesheets in view/frontend/web/css/source/:

// _module.less
& when (@media-common = true) {
    .vendor-banner {
        background-color: @color-blue;
        padding: 20px;
        text-align: center;

        &__title {
            font-size: 24px;
            color: @color-white;
        }

        &__subtitle {
            font-size: 16px;
            margin-top: 10px;
        }
    }
}

// Responsive styles
.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) {
    .vendor-banner {
        padding: 10px;

        &__title {
            font-size: 18px;
        }
    }
}

JavaScript Files

Place JS in view/frontend/web/js/:

// component.js
define([
    'jquery',
    'uiComponent'
], function ($, Component) {
    'use strict';

    return Component.extend({
        defaults: {
            template: 'Vendor_Module/component'
        },

        initialize: function () {
            this._super();
            console.log('Component initialized');
            return this;
        },

        customMethod: function () {
            // Custom logic
        }
    });
});

requirejs-config.js

Configure module dependencies and aliases:

// view/frontend/requirejs-config.js
var config = {
    map: {
        '*': {
            'customComponent': 'Vendor_Module/js/component'
        }
    },
    paths: {
        'vendorModule': 'Vendor_Module/js'
    },
    shim: {
        'vendorModule/legacy': {
            'deps': ['jquery']
        }
    }
};

Images and Fonts

view/frontend/web/
├── images/
│   ├── logo.png
│   ├── icons/
│   │   └── sprite.svg
│   └── banners/
│       └── hero.jpg
└── fonts/
    └── custom-font.woff2

Reference in templates:

<img src="<?= $block->getViewFileUrl('Vendor_Module::images/logo.png') ?>" alt="Logo">

Adminhtml View Directory

Admin View Structure

Admin templates and layouts mirror the frontend structure but are scoped to the admin area:

Vendor/Module/view/adminhtml/
├── layout/
│   ├── default.xml              (all admin pages)
│   ├── vendor_module_index.xml  (custom admin page)
│   └── catalog_product_edit.xml (extend product edit)
├── templates/
│   ├── widget/
│   │   └── form.phtml
│   └── warranty/
│       └── grid.phtml
└── web/
    ├── css/
    │   └── source/
    │       └── _module.less
    ├── js/
    │   └── grid.js
    └── images/

Admin Layout XML

<!-- vendor_module_index.xml -->
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"
      layout="admin-2columns-left">
    <update handle="formkey"/>
    <body>
        <referenceContainer name="content">
            <block class="Vendor\Module\Block\Adminhtml\Warranty\Grid"
                   name="vendor.warranty.grid"
                   template="Vendor_Module::warranty/grid.phtml"/>
        </referenceContainer>
    </body>
</page>

Admin Templates

<!-- warranty/grid.phtml -->
<?php
/** @var Vendor\Module\Block\Adminhtml\Warranty\Grid $block */
$grid = $block->getGrid();
?>
<div class="warranty-grid">
    <table class="data-grid">
        <thead>
            <tr>
                <th><?= __('ID') ?></th>
                <th><?= __('Name') ?></th>
                <th><?= __('Duration') ?></th>
                <th><?= __('Actions') ?></th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($grid->getItems() as $item): ?>
            <tr>
                <td><?= $item->getId() ?></td>
                <td><?= $block->escapeHtml($item->getName()) ?></td>
                <td><?= $item->getDuration() ?> months</td>
                <td>
                    <a href="<?= $block->getUrl('vendor_warranty/edit', ['id' => $item->getId()]) ?>">
                        <?= __('Edit') ?>
                    </a>
                </td>
            </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
</div>

Static Content Deployment

When adding new view files, deploy static content:

# Development
bin/magento setup:static-content:deploy -f

# Clear specific area
bin/magento cache:clean

# Remove old static files
rm -rf pub/static/frontend/Vendor/Module/
bin/magento setup:static-content:deploy -f

Quiz

1. Which directory contains files shared across all areas?

Question 1 options

2. How do you reference a template file in layout XML?

Question 2 options

3. Where should LESS files be placed in a module?

Question 3 options

Flashcards

Question

What are the three view areas in Magento?

Answer

frontend (storefront), adminhtml (admin panel), base (shared)

Question

What is the file extension for Magento templates?

Answer

.phtml

Question

How do you reference a module's static assets?

Answer

Vendor_Module::images/logo.png or $block->getViewFileUrl('Vendor_Module::...')

Question

Where does requirejs-config.js go?

Answer

view/frontend/requirejs-config.js

Question

What escaping function prevents XSS in templates?

Answer

$block->escapeHtml($text)

Revision Notes

Key Takeaways

  • 1. View directory is organized by area: frontend, adminhtml, base
  • 2. Layout XML controls page structure; templates render HTML
  • 3. Web assets (CSS, JS, images) live in view/{area}/web/
  • 4. Always escape output in templates with escapeHtml()
  • 5. Run static content deploy after adding new view files

Interview Tips

  • Explain the area separation (frontend, adminhtml, base)
  • Know how templates reference blocks and access data
  • Discuss the web asset pipeline (LESS → CSS, RequireJS)
  • Be ready to explain how to add custom CSS/JS to a module

Cheat Sheet

view/
├── frontend/     (storefront)
│   ├── layout/   (XML page configs)
│   ├── templates/ (.phtml files)
│   ├── web/      (CSS, JS, images)
│   └── requirejs-config.js
├── adminhtml/    (admin panel)
└── base/         (shared assets)

Template: Vendor_Module::path/file.phtml
Asset URL: $block->getViewFileUrl('Vendor_Module::images/logo.png')