This golden sculpture shows a pocket watch connected to some rings

4 time-saving code blocks for effective work with Kirby CMS

| Web Design   Kirby   Code  

For these rather trivial use cases, I had to google the components of my solutions for far too long and read more forum posts than I would have liked. To make your search shorter, I have collected my solutions here.

1. Class names for pre-code blocks in Kirby text fields

Okay, admittedly: This first tip is not a real code block at all, but a hack for Kirby Markdown editor. Nevertheless, very useful: If you don't have markdown.extra enabled and still want to give classes to the pre-code blocks for code examples on your page (e.g. for a syntax highlighter), you can do the following: Instead of beginning and ending the respective block with three apostrophes (`), you can simply use a series of 28 apostrophes and write the desired class name directly after it. To close the code block, you also make another series of 28 apostrophes. So instead of using this:

```

Use the following:
````````````````````````````html to open the code block and
```````````````````````````` to close the code block.

Whatever you write after the "starting row" will be used as the class for the modified pre-code block.

Here are a few examples:

 ````````````````````````````html
<!-- will transform into -->
<pre><code class="language-html">


<!--while the following... -->
 ````````````````````````````javascript
<!--will transform into -->
<pre><code class="language-javascript">

As mentioned: This is particularly handy if you want to assign classes to your <pre><code>blocks in order to style them with a syntax highlighter.

2. breadcrumb navigation that takes URL parameters into account.

If you have a blog that (for example to filter different categories or tags) works with URL parameters (example: tag:gesichtskirmesor ?category=synapsenfasching) , then it is advantageous to consider this also in the breadcrumb navigation of your website. Users are used to returning to the next higher level of your website via the breadcrumb navigation. Example:

You're on a website's blog and you've clicked on the tag "Espresso", so you're only shown articles that have also been tagged with "Espresso". The URL of the page is https://example.com/blog/?tag:espresso, but the breadcrumb navigation only shows Home ➡️ Blog. Now, if the common practice is still followed that the last element in the breadcrumbs should not be linked, there is no way to get back to the unfiltered view of the blog via this navigation. It would be much nicer in that regard if the navigation showed Home ➡️ Blog ➡️ Espresso.

Kirby has a feature built in by design that makes building breadcrumb navigations super easy: $site->breadcrumb() | Kirby. However, this solution doesn't take any URL parameters into account. Here's how we can change that:

First, we take the solution suggested in the link above:

<nav class="breadcrumb" aria-label="breadcrumb">
  <ol>
    <?php foreach($site->breadcrumb() as $crumb): ?>
    <li>
      <a href="<?= $crumb->url() ?>" <?= e($crumb->isActive(), 'aria-current="page"') ?>>
        <?= html($crumb->title()) ?>
      </a>
    </li>
    <?php endforeach ?>
  </ol>
</nav>

Now, using an if statement, we query whether the current entry is active (that is, whether the current entry belongs to the currently displayed page). If it is not, we are just dealing with a parent page, and we can output a linked breadcrumb. We do this in the else statement:

<nav class="breadcrumb" aria-label="breadcrumb">
  <ol>
    <?php foreach($site->breadcrumb() as $crumb): ?>
    <li>
    <?php if($crumb->isActive()): ?>
      //Parameter query 
    <?php else: ?>
       <a href="<?= $crumb->url() ?>">
              <?= html($crumb->title()) ?>
       </a>
    <?php endif; ?>  
    </li>
    <?php endforeach ?>
  </ol>
</nav>

Now we take care of the parameter processing that occurs when the current crumb is active. To achieve this, we first need to check if there even is a parameter with the appropriate name. So inside our <?php if($crumb->isActive()): ?> statement, we make another if statement:
<?php if($breadcrumbtag = param('tag')): ?>
Here we use param('tag') to query whether the current URL has a parameter called "tag" and store the result of this query in the variable $breadcrumbtag. This means that if the URL has a parameter called "tag", its value (in our example above, the value would be "espresso") is stored in $breadcrumbtag. If not, false is stored. For the latter case, we can simply output the title of the breadcrumb, since we are on an active page without a tag. Therefore, in the else statement we simply write <?php echo html($crumb->title());?>.

If, on the other hand, a parameter called "tag" is present and stored in $breadcrumbtag, we first output the link and title of the current page without parameters:

<a href="<?= $crumb->url() ?>">
  <?php echo html($crumb->title()) ?>
</a>

After that, we close the current li element and open a new one. In it, we show $breadcrumbtag as the title of the current page and have reached our goal. Important: It is best not to output $breadcrumbtag unfiltered, but to send it through a urldecode() first, to be sure that there are no mishaps in the display. Our parameter processing looks like this now:

<?php if($breadcrumbtag = param('tag')): ?>
    <a href="<?= $crumb->url() ?>">
      <?php echo html($crumb->title()) ?>
    </a>
  </li>
  <li class="breadcrumb-item">
    <?php echo('' . urldecode($breadcrumbtag)); ?>
<?php else: ?>
  <?php echo html($crumb->title());?>              
<?php endif;?>

And if we now add this code block to the normal breadcrumb block from above, we have a breadcrumb navigation that also includes tags:

<nav aria-label="breadcrumb">
  <ol class="breadcrumb">
  <?php foreach($site->breadcrumb() as $crumb): ?>
    <li class="breadcrumb-item">
      <?php if($crumb->isActive()): ?>

        <?php if($breadcrumbtag = param('tag')): ?>
            <a href="<?= $crumb->url() ?>">
              <?php echo html($crumb->title()) ?>
            </a>
          </li>
          <li class="breadcrumb-item">
            <?php echo('' . urldecode($breadcrumbtag)); ?>
         <?php else: ?>
           <?php echo html($crumb->title());?>              
         <?php endif;?>

       <?php else: ?>
         <a href="<?php echo $crumb->url() ?>">
           <?php echo html($crumb->title()) ?>
         </a>
       <?php endif; ?>
      </li>
    <?php endforeach; ?>  
   </ol>
 </nav>

3. Alternate-language links in the header for multilingual pages

If you have multiple languages on your website, you should indicate in the header where to find the alternate language versions of the page you are calling. This will make it easier for search engines to deliver your content directly to users in the correct language. Here is a good article that explains the basics. In Kirby, you can easily set these links by inserting this code snippet in the header snippet of your page:

  <?php foreach ($kirby->languages() as $language) : ?>
  <link rel="alternate" hreflang="<?php echo strtolower(html($language->code())); ?>" href="<?= $page->url($language->code()); ?>" />
  <?php endforeach; ?>
  <link rel="alternate" hreflang="x-default" href="<?= $page->url($kirby->defaultLanguage()->code()); ?>" />

Kirby then sets based on this loop:

  <?php foreach ($kirby->languages() as $language) : ?>

for each language an alternate link whose hreflang attribute is filled with the language code of the respective language (hreflang="<?php echo strtolower(html($language->code())); ?>"). In addition, the href attribute links directly to the respective language version of the page (href="<?= $page->url($language->code()); ?>"). By the way, this also works if you are routing different languages through different domains and / or have customized the language of the URLs. After setting the links for all languages, outside the foreach loop, a final link is set with the hreflang attribute "x-default", indicating where to find the default version of this page. To accomplish this, Kirby simply outputs the page URL of the default language in the href attribute: <?= $page->url($kirby->defaultLanguage()->code()); ?> . Simple, but effective!

4. Sitemap for Kirby pages with multiple languages

Kirby has a wonderful tutorial in its docs on how to generate a simple xml sitemap automatically: Sitemap for search engines | Kirby. Unfortunately, this tutorial only works for pages that are set up in one language. However, if your site is multilingual, you will have to make a small change to the code to include all language versions of your pages. To save you the work, here is the code snippet for you:

<?= '<?xml version="1.0" encoding="utf-8"?>'; ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<?php foreach (kirby()->languages() as $language) : ?>
    <?php foreach ($pages as $p): ?>
        <?php if (in_array($p->uri(), $ignore)) continue ?>
        <url>
            <loc><?= html($p->url($language->code())) ?></loc>
            <lastmod><?= $p->modified('c', 'date') ?></lastmod>
            <priority><?= ($p->isHomePage()) ? 1 : number_format(0.5 / $p->depth(), 1) ?></priority>
        </url>
    <?php endforeach ?>
<?php endforeach; ?>
</urlset>

I hope these 4 tips were useful and made working with Kirby a little easier for you. If you have any further questions, feel free to ask them in the comments or email me. Also, I highly recommend you to subscribe to my newsletter. I rarely send it out, but when it comes, it's worth it - guaranteed!

Comments

Add a comment

  • Robert

    | Reply

    Mate, it's totally enough to just put the class name after three apostrophes. No need to write 28 of them.

    • Conrad Dreyer

      | Reply

      Yeah, you're right about that. However, if you want to put three apostrophes inside a code block, writing 28 around those is a great fallback. Admittedly, quite a niche scenario, but still useful, I think. But I'll update the article accordingly! Thanks!