Integration of html templates with MODX

Integration of html templates Website development practice
MODX is a popular content management system that allows you to create websites of any complexity. One of its advantages is the ability to integrate with various templates, which allows you to create a unique design for your site. In this lesson, I will tell you how to correctly integrate html templates with MODX.

Transfer of finished layout (template)

Each html template consists of a certain set of files, usually html, css, js files and images. There may also be fonts, scss files, php handlers, etc.

Eterna template files

You can download the template used in this tutorial here: Templates for MODX.

To integrate the design, we usually need to transfer all files except html and php to the hosting. In this case, everything we need is in the assets folder:

Contents of the assets folder

Let’s upload all the files from the assets folder to the assets directory. You can do this using the hosting file manager or via ftp/sftp. In the end we get the following:

Template files uploaded to the MODX website

Now you can edit the basic template, to do this, in the resource tree, go to the “Elements” – “Templates” tab and edit the “Initial template”.

Editing the initial template

As you can see, the initial template contains the MODX syntax: [[*name]] – resource and TV fields, [[++name]] – system settings. We will study all of this as we develop the site, but for now you can delete all of the template code.

To highlight the code of MODX templates, install the Ace add-on.

Now open the code of the main page html template – usually this is the index.html file (it is better to do this using code editors) copy and paste it in place of the standard code of the initial template. Then save the template.

inserted code

Open the main page, it should be the same as the template.

Main page of the site

If your entire code is crooked, then you haven’t uploaded something.

Integration of HTML layout with CMS

Integration of HTML layout with CMS is the process of combining the design and layout of a website (html, CSS, JavaScript) with a content management system (CMS), in our case with MODX. This allows you to manage the content of the site through the CMS interface, without having to manually change the site code.

In other words, we need to turn static code into dynamic to significantly simplify the process of content management and updating the site, as well as, if necessary, create more complex and functional sites.

Integration of layout into MODX often begins with determining which elements of the site are usually repeated from page to page. If you open all our html template files and look at them, you will see that they all have repeating elements: a header with navigation, breadcrumbs (on all pages except the main one), a footer.

Cross-cutting elements in the template

These are all so to speak cross-cutting elements, they can be taken out to separate chunks.

Using chunks

Chunks are a way to offer management of repeating content in one place. In the example template above, there is static navigation in the header and footer, this can become a problem if there is a need to change the text for one of these links. Instead of changing the text in each template and risking desynchronization, it would be preferable to update it once, and this change will be reflected in all templates. We can do this using chunks.

Let’s make a clever chunk system: create a chunk tpl and move all the code from the initial template to it, and output the created chunk instead.

Next, we cut out from the chunk tpl everything except the through elements (in this case, everything that is between <main class="main"> ... </main>) create a chunk tpl.1 place the cut code there and save it. And in place of the cut code, we connect our newly created chunk.

connect the chunk

If you open the main page now, it should not change (it should remain exactly the same as before using chunks).

Main page of the site

Using standard resource fields

Open a chunk with through elements and register resource fields. For example, change:

 <title>Eterna Bootstrap Template - Index</title>
<meta content="" name="description">

to

 <title>[[*longtitle]]</title>
<meta content="[[*description]]" name="description">

Well, let’s call the [[*content]] field somewhere in the tpl.1 chunk.

The standard fields are not enough, you can create your own TV.

Using system settings

Let’s call the most common system settings:

[[++site_url]] – base URL (see CNC settings)

[[++modx_charset]] – site encoding

[[++site_name]] – site name

[[++cultureKey]] – site language

Our template start will look like this:

<!DOCTYPE html>
<html lang="[[++cultureKey]]"> 
<head>
  <base href="[[++site_url]]">
  <meta charset="[[++modx_charset]]">
  <meta content="width=device-width, initial-scale=1.0" name="viewport">
  <title>[[*longtitle]] | [[++site_name]]</title>
  <meta name="description" content="[[*description]]">

We can also create our own system settings, the easiest way to do this is with the ClientConfig add-on, install it and create settings there: phone, email, address, social networks, etc.

Then display them in the necessary parts of the template.

Using filters and modifiers

Let’s complicate the logic of displaying chunks and standard fields, system settings using filters and modifiers.

Let’s complicate the output of title a little, make it like this:

[[*longtitle:default=`[[*pagetitle]]`]] – if the extended title is filled in, then we output it, otherwise we output the title.

Let’s add meta robots:

<meta name="robots" content="[[*searchable:is=`1`:then=`index, follow`:else=`noindex, nofollow`]]">

Modify the call to chunk tpl.1:

[[$tpl.[[*template]]]]

In this case, depending on the template, we connect the tpl.id template – you will learn why below.

Ultimately, the code of our chunk (tpl) with cross-cutting elements should take approximately the following code:

<!DOCTYPE html>
<html lang="[[++cultureKey]]"> 
<head>
  <base href="[[++site_url]]">
  <meta charset="[[++modx_charset]]">
  <meta name="robots" content="[[*searchable:is=`1`:then=`index, follow`:else=`noindex, nofollow`]]">
  <meta content="width=device-width, initial-scale=1.0" name="viewport">
  <title>[[*longtitle]] | [[++site_name]]</title>
  <meta name="description" content="[[*description]]">
  <meta name="keywords" content="">
  <!-- Favicons -->
  <link href="assets/img/favicon.png" rel="icon">
  <link href="assets/img/apple-touch-icon.png" rel="apple-touch-icon">
  <!-- Fonts -->
  <link href="https://fonts.googleapis.com" rel="preconnect">
  <link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,300;1,400;1,500;1,600;1,700;1,800&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Raleway:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
  <!-- Vendor CSS Files -->
  <link href="assets/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
  <link href="assets/vendor/bootstrap-icons/bootstrap-icons.css" rel="stylesheet">
  <link href="assets/vendor/aos/aos.css" rel="stylesheet">
  <link href="assets/vendor/swiper/swiper-bundle.min.css" rel="stylesheet">
  <link href="assets/vendor/glightbox/css/glightbox.min.css" rel="stylesheet">
  <!-- Main CSS File -->
  <link href="assets/css/main.css" rel="stylesheet">
</head>
<body class="index-page">
  <header id="header" class="header sticky-top">
    <div class="topbar d-flex align-items-center dark-background">
      <div class="container d-flex justify-content-center justify-content-md-between">
        <div class="contact-info d-flex align-items-center">
          <i class="bi bi-envelope d-flex align-items-center"><a href="mailto:[[++email]]">[[++email]]</a></i>
          <i class="bi bi-phone d-flex align-items-center ms-4"><span>[[++phone]]</span></i>
        </div>
        <div class="social-links d-none d-md-flex align-items-center">
          [[++twitter:!empty=`<a href="[[++twitter]]" class="twitter"><i class="bi bi-twitter-x"></i></a>`]] 
          [[++facebook:!empty=`<a href="[[++facebook]]" class="facebook"><i class="bi bi-facebook"></i></a>`]] 
          [[++instagram:!empty=`<a href="[[++instagram]]" class="instagram"><i class="bi bi-instagram"></i></a>`]] 
          [[++linkedin:!empty=`<a href="[[++linkedin]]" class="linkedin"><i class="bi bi-linkedin"></i></a>`]] 
        </div>
      </div>
    </div><!-- End Top Bar -->
    <div class="branding">
      <div class="container position-relative d-flex align-items-center justify-content-between">
        <a href="/" class="logo d-flex align-items-center">
          <!-- Uncomment the line below if you also wish to use an image logo -->
          <!-- <img src="assets/img/logo.png" alt=""> -->
          <h1 class="sitename">[[++site_name]]<br></h1>
        </a>
        <nav id="navmenu" class="navmenu">
          <ul>
            <li><a href="index.html" class="active">Home</a></li>
            <li><a href="about.html">About</a></li>
            <li><a href="services.html">Services</a></li>
            <li><a href="portfolio.html">Portfolio</a></li>
            <li><a href="team.html">Team</a></li>
            <li><a href="pricing.html">Pricing</a></li>
            <li><a href="blog.html">Blog</a></li>
            <li class="dropdown"><a href="#"><span>Dropdown</span> <i class="bi bi-chevron-down toggle-dropdown"></i></a>
              <ul>
                <li><a href="#">Dropdown 1</a></li>
                <li class="dropdown"><a href="#"><span>Deep Dropdown</span> <i class="bi bi-chevron-down toggle-dropdown"></i></a>
                  <ul>
                    <li><a href="#">Deep Dropdown 1</a></li>
                    <li><a href="#">Deep Dropdown 2</a></li>
                    <li><a href="#">Deep Dropdown 3</a></li>
                    <li><a href="#">Deep Dropdown 4</a></li>
                    <li><a href="#">Deep Dropdown 5</a></li>
                  </ul>
                </li>
                <li><a href="#">Dropdown 2</a></li>
                <li><a href="#">Dropdown 3</a></li>
                <li><a href="#">Dropdown 4</a></li>
              </ul>
            </li>
            <li><a href="contact.html">Contact</a></li>
          </ul>
          <i class="mobile-nav-toggle d-xl-none bi bi-list"></i>
        </nav>
      </div>
    </div>
  </header>
  <main class="main">
    [[$tpl.[[*template]]]]
  </main>
  <footer id="footer" class="footer position-relative dark-background">
    <div class="footer-newsletter">
      <div class="container">
        <div class="row justify-content-center text-center">
          <div class="col-lg-6">
            <h4>Join Our Newsletter</h4>
            <p>Subscribe to our newsletter and receive the latest news about our products and services!</p>
            <form action="forms/newsletter.php" method="post" class="php-email-form">
              <div class="newsletter-form"><input type="email" name="email"><input type="submit" value="Subscribe"></div>
              <div class="loading">Loading</div>
              <div class="error-message"></div>
              <div class="sent-message">Your subscription request has been sent. Thank you!</div>
            </form>
          </div>
        </div>
      </div>
    </div>
    <div class="container footer-top">
      <div class="row gy-4">
        <div class="col-lg-4 col-md-6 footer-about">
          <a href="/" class="d-flex align-items-center">
            <span class="sitename">[[++site_name]]</span>
          </a>
          <div class="footer-contact pt-3">
            <p>A108 Adam Street</p>
            <p>New York, NY 535022</p>
            <p class="mt-3"><strong>Phone:</strong> <span>[[++phone]]</span></p>
            <p><strong>Email:</strong> <span>[[++email]]</span></p>
          </div>
        </div>
        <div class="col-lg-2 col-md-3 footer-links">
          <h4>Useful Links</h4>
          <ul>
            <li><i class="bi bi-chevron-right"></i> <a href="#">Home</a></li>
            <li><i class="bi bi-chevron-right"></i> <a href="#">About us</a></li>
            <li><i class="bi bi-chevron-right"></i> <a href="#">Services</a></li>
            <li><i class="bi bi-chevron-right"></i> <a href="#">Terms of service</a></li>
          </ul>
        </div>
        <div class="col-lg-2 col-md-3 footer-links">
          <h4>Our Services</h4>
          <ul>
            <li><i class="bi bi-chevron-right"></i> <a href="#">Web Design</a></li>
            <li><i class="bi bi-chevron-right"></i> <a href="#">Web Development</a></li>
            <li><i class="bi bi-chevron-right"></i> <a href="#">Product Management</a></li>
            <li><i class="bi bi-chevron-right"></i> <a href="#">Marketing</a></li>
          </ul>
        </div>
        <div class="col-lg-4 col-md-12">
          <h4>Follow Us</h4>
          <p>Cras fermentum odio eu feugiat lide par naso tierra videa magna derita valies</p>
          <div class="social-links d-flex">
            [[++twitter:!empty=`<a href="[[++twitter]]"><i class="bi bi-twitter-x"></i></a>`]] 
            [[++facebook:!empty=`<a href="[[++facebook]]"><i class="bi bi-facebook"></i></a>`]] 
            [[++instagram:!empty=`<a href="[[++instagram]]"><i class="bi bi-instagram"></i></a>`]] 
            [[++linkedin:!empty=`<a href="[[++linkedin]]"><i class="bi bi-linkedin"></i></a>`]] 
          </div>
        </div>
      </div>
    </div>
    <div class="container copyright text-center mt-4">
      <p>© <span>Copyright</span> <strong class="px-1 sitename">[[++site_name]]</strong> <span>All Rights Reserved</span></p>
    </div>
  </footer>
  <!-- Scroll Top -->
  <a href="#" id="scroll-top" class="scroll-top d-flex align-items-center justify-content-center"><i class="bi bi-arrow-up-short"></i></a>
  <!-- Preloader -->
  <div id="preloader"></div>
  <!-- Vendor JS Files -->
  <script src="assets/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
  <script src="assets/vendor/php-email-form/validate.js"></script>
  <script src="assets/vendor/aos/aos.js"></script>
  <script src="assets/vendor/swiper/swiper-bundle.min.js"></script>
  <script src="assets/vendor/purecounter/purecounter_vanilla.js"></script>
  <script src="assets/vendor/waypoints/noframework.waypoints.js"></script>
  <script src="assets/vendor/glightbox/js/glightbox.min.js"></script>
  <script src="assets/vendor/imagesloaded/imagesloaded.pkgd.min.js"></script>
  <script src="assets/vendor/isotope-layout/isotope.pkgd.min.js"></script>
  <!-- Main JS File -->
  <script src="assets/js/main.js"></script>
</body>
</html>

Creating additional templates

For now, we will create only 1 template, for regular static pages: about the company, privacy policy, contacts, etc. We will take the team.html file as a basis.

Create a new template named Static and call the tpl chunk in it (which stores cross-cutting elements) and save it.

Create a new template

Now create a chunk named tpl.2 (where 2 is the id of the newly created template) and place the code in it that is located between the main block.

Create a new chunk

Now we modernize the breadcrumbs section, it will look like this:

    <!-- Page Title -->
    <div class="page-title" data-aos="fade">
      <div class="container">
        <nav class="breadcrumbs">
          <ol>
            <li><a href="/">Главная</a></li>
            <li class="current">[[*pagetitle]]</li>
          </ol>
        </nav>
        <h1>[[*pagetitle]]</h1>
      </div>
    </div><!-- End Page Title -->

In principle, it can be sent to a separate chunk: breadcrumbs. And call the chunk with cross-cutting elements (tpl), with this construction: [[*id:is=`1`:else=`[[$breadcrumbs]]`]] – we display the chunk on all pages except the main one.

We display the chunk on all pages except the main one

Now we will throw out all the unnecessary (in this case, blocks with the command) from the next section with content and display the content field, in the end we will get the following chunk code (tpl.2):

<section id="team" class="team section">
    <div class="container">
        [[*content]]
    </div>
</section>

Using Snippets

MODX offers a lot of dynamics out of the box, and Snippets are a way to extend this dynamics. We can write them ourselves, even if you don’t know PHP, you can use, for example, the gpt chat and ask it to write the necessary code, for example, here is what it gave:

<?php
// Get the current year
$currentYear = date("Y");

// Specify the year from which copywriting begins
$startYear = 2010;

// If the current year coincides with the starting year, output only one year
if ($currentYear == $startYear) {
echo $currentYear;
} else {
// Otherwise, output years in the format "2010 - 2021"
echo $startYear . " - " . $currentYear;
}
?>

It may not be perfect, but it looks working. Let’s try to output it, create a snippet named year and the code above. And we call it in copywriting:

Calling a snippet in copywriting

We go to the site and check:

It works

Everything works, the only thing I don’t really like is that the year of creation (of the company or site) needs to be changed directly in the snippet code, we modify it so that we can set this parameter when calling the snippet:

<?php
$currentYear = date("Y");
if($currentYear == $startYear) {
	return $currentYear;
} else {
return ''.$startYear.' – '.$currentYear.'';
}

Now it can be called like this: [[year? &startYear=`2022`]].

Have you exhausted all the basic functionality, what’s next?

In fact, we haven’t exhausted everything, and have only considered the basic principles of integration. Using snippets or plugins, you can program a lot of things in PHP. But we will follow the path of ready-made solutions – we will install add-ons (many of which include ready-made snippets) and put the rest of the code on them.

You can put complex elements on MIGX: sliders, similar blocks consisting of many fields, in general, everything that the main page has in non-through elements.

But for many other things, you need to create resources, from which the menu will be built, some blocks will be collected (for example, the display of services or articles on the main page), and so on. In general, create empty static pages of the site for now (about the company, services, portfolio, contacts, etc.) with the new Static template.

Create a new resource

And move on to the next lesson: creating contact forms using the Formit + FetchIt component bundle.

Rate article
MODX 3
Add a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.