<p>You can create a <a href="https://docs.craftcms.com/v3/routing.html#advanced-routing-with-url-rules" rel="nofollow noreferrer">route with a URL rule</a> for these individual pages:</p>

<pre><code>'brands/&lt;firstLetter:\w{1}&gt;' =&gt; ['template' =&gt; 'brands/index'],
</code></pre>

<p>Assuming you URL is something like <code>example.com/brands/a</code> and your template is located at <code>brands/index.twig</code>. This will also pass a <code>firstLetter</code> variable from the URL to the template.</p>

<p>You can use <a href="https://docs.craftcms.com/v3/dev/element-queries/entry-queries.html#parameters" rel="nofollow noreferrer">Craft's search parameter</a> to only search the title field starting with a letter like this:</p>

<p><code>craft.entries.search('title::a*')</code></p>

<p>You can read more about <a href="https://docs.craftcms.com/v3/searching.html" rel="nofollow noreferrer">Craft's search syntax</a> here.</p>

<p>For the number 0-9, combine search queries with an <code>OR</code> string like <code>title::0* OR title::1* OR title::2* OR</code>... etc.</p>

<p>You can't use a URL like <code>example.com/brands/#</code> to show numbers, so I'm just going to use the default <code>example.com/brands</code> to show numbered entries (no <code>firstLetter</code> in the URL).</p>

<p>Putting it all together, we get something like this:</p>

<pre><code>{% if firstLetter is defined %}
  {% set searchQuery = 'title::' ~ firstLetter ~ '*' %}
{% else %}
  {% set searchQuery = '' %}
  {% for num in 0..9 %}
    {% set searchQuery = searchQuery ~ 'title::' ~ num ~ '*' ~ (not loop.last ? ' OR ') %}
  {% endfor %}
{% endif %}

{% for entry in craft.entries.section('brands')
    .search(searchQuery)
    .orderBy('title')
    .all() %}
  {{ entry.title }}
{% endfor %}
</code></pre>

<p>Here's a simple navigation for these pages.</p>

<pre><code>&lt;p&gt;
  &lt;a href="{{ url('brands') }}"&gt;#&lt;/a&gt;
  {% for letter in 'a'..'z' %}
    &lt;a href="{{ url('brands/' ~ letter) }}"&gt;{{ letter|upper }}&lt;/a&gt;
  {% endfor %}
&lt;/p&gt;
</code></pre>

<p>To filter out letters from that list that don't have any entries would be trickier to pull off tho. You could try something like this, but it might not be the most performant.</p>

<pre><code>{% for letter in 'a'..'z' 
    if craft.entries.section('brands')
    .search('title::' ~ letter ~ '*')
    .exists() %}
</code></pre>

<p>Another possible option would be to create a plugin for finding distinct first letter entries like this person did:
<a href="https://craftcms.stackexchange.com/a/10957/273">https://craftcms.stackexchange.com/a/10957/273</a></p>

CC BY-SA 4.0
2018-09-19T09:32:10.047Z
The pages are not setup with that at the moment, so it's a channel with all of them listed, would this work still? https://www.vouchertoday.uk/stores as you can see these need to be split into different pages.
JMKelley
CC BY-SA 4.0
2018-09-19T17:09:10.253Z
Yes, the code above is written to pull all the entries from a "brands" channel. You wouldn't need to split your entries up separately in the Craft control panel. 

For each URL/route like `/brands/a` or `/brands/b` it will only display entries where the titles start with the letter in the URLs last segment.
Alex Roper
CC BY-SA 4.0
2018-09-19T19:28:59.403Z
Sorry Alex, How do you go about splitting up entries in the CP?
JMKelley
CC BY-SA 4.0
2018-09-19T22:17:06.873Z
You would NOT have to split them up in the control panel. Do you want to split them up in the control panel for some reason? I thought your question was asking how to display entries from a single channel split up over multiple pages on the front end of the site.
Alex Roper
CC BY-SA 4.0
2018-09-23T10:29:43.303Z
Just tried your method, I'm getting '404 Page not found' on the character URL's e.g. `/brands/m` is there a template I'm needing to create?
JMKelley
CC BY-SA 4.0
2018-09-23T18:18:04.817Z
Yes, you'll need a template file that corresponds to your URL rule in the config/routes.php file. In the example above ('template' => 'brands/index') that would be templates/brands/index.twig (or .html).
Alex Roper
CC BY-SA 4.0
2022-02-04T09:57:48.227Z
Is it possible to use this approach together with sprig (https://putyourlightson.com/plugins/sprig), to load the content on runtime?
buckdanny
CC BY-SA 4.0
2022-02-04T21:07:48.410Z
Yes, I think it's possible to use with Sprig. You could probably move the craft.entries for loop into a Spring component and pass `firstLetter` as a component variable.
Alex Roper
CC BY-SA 4.0
2018-09-18T21:44:57.273Z
2018-09-18T21:44:57.273Z
Alex Roper
<p>You could use <a href="https://docs.craftcms.com/v2/templating/eager-loading-elements.html" rel="nofollow noreferrer">eager loading</a> to speed up things as it is now in your template.</p>

<pre><code>{% set entries = craft.entries({
  section: 'brands',
  with:    ['brandLogo']
}.all() %}
</code></pre>

<p>Another alternative I can think of is using a structure instead of a channel, with 0-9 and A-Z as top level entries and your brands already sorted per character underneath. Than you can just call up the correct letter/branch in your template. Switching from channel to structure won't erase your data either if I'm correct. And the eager loading trick will speed up things too here.</p>

CC BY-SA 4.0
2018-09-17T14:08:15.853Z
2018-09-17T14:15:50.110Z
2018-09-17T14:15:50.110Z
Tom De Smet
<p>I've built a page listing all entries by Character 0-9/A-Z. But unfortunately it's extremely slow loading due to the amount of entries the site has. I'm wondering if I can break out the letters into seperate pages.</p>

<p>Currently everything is on</p>

<pre><code>.../brands/
</code></pre>

<p>What I'm looking to do is create</p>

<pre><code>.../brands/a
.../brands/b
.../brands/c
</code></pre>

<p>I'm unsure if it's code running to create this or something more in the backend of Craft and how I've created the section. The code currently running the A-Z</p>

<pre><code>{% set entries = craft.entries.section('brands') %}
      {% set entriesGrouped = entries|group('title|slice(0, 1)|upper|replace("/[^A-Z]/", "0-9")') %}

      {% for letter, entriesInGroup in entriesGrouped %}
          &lt;h3&gt;{{ letter }}&lt;/h3&gt;
          &lt;ul class="store-list"&gt;
          {% for entry in entriesInGroup %}
            &lt;li&gt;
              {% for asset in entry.brandLogo.all() %}
                &lt;a href="{{ entry.url }}"&gt;
                  &lt;div class="retailer-logo"&gt;
                    &lt;img src="{{ asset.geturl }}" class="img-fluid" alt="{{ entry.title }} Discount Codes &amp; Vouchers"/&gt;
                  &lt;/div&gt;
                &lt;/a&gt;
              {% endfor %}
              &lt;a href="{{ entry.url }}" title="{{ entry.title }} Coupon Codes"&gt;{{ entry.title }} Coupons&lt;/a&gt;
              {% endfor %}
              &lt;/li&gt;
          &lt;/ul&gt;
          &lt;hr&gt;
{% endfor %}
</code></pre>

<templating><entries><sections>
A-Z Separate Pages
# A-Z Separate Pages

(Asked by: username_0 on 2018-09-08)

I've built a page listing all entries by Character 0-9/A-Z. But unfortunately it's extremely slow loading due to the amount of entries the site has. I'm wondering if I can break out the letters into seperate pages.
Currently everything is on
.../brands/

What I'm looking to do is create
.../brands/a
.../brands/b
.../brands/c

I'm unsure if it's code running to create this or something more in the backend of Craft and how I've created the section. The code currently running the A-Z
{% set entries = craft.entries.section('brands') %}
      {% set entriesGrouped = entries|group('title|slice(0, 1)|upper|replace("/[^A-Z]/", "0-9")') %}

      {% for letter, entriesInGroup in entriesGrouped %}
          {{ letter }}
          
          {% for entry in entriesInGroup %}
            
              {% for asset in entry.brandLogo.all() %}
                
                  
                    
                  
                
              {% endfor %}
              {{ entry.title }} Coupons
              {% endfor %}
              
          
          
{% endfor %}

**Tags:** templating, entries, sections


---

## 2 answers

### Answer by username_1 on 2018-09-18. Score: 2 | Accepted answer

You can create a route with a URL rule for these individual pages:
'brands/' => ['template' => 'brands/index'],

Assuming you URL is something like example.com/brands/a and your template is located at brands/index.twig. This will also pass a firstLetter variable from the URL to the template.
You can use Craft's search parameter to only search the title field starting with a letter like this:
craft.entries.search('title::a*')
You can read more about Craft's search syntax here.
For the number 0-9, combine search queries with an OR string like title::0* OR title::1* OR title::2* OR... etc.
You can't use a URL like example.com/brands/# to show numbers, so I'm just going to use the default example.com/brands to show numbered entries (no firstLetter in the URL).
Putting it all together, we get something like this:
{% if firstLetter is defined %}
  {% set searchQuery = 'title::' ~ firstLetter ~ '*' %}
{% else %}
  {% set searchQuery = '' %}
  {% for num in 0..9 %}
    {% set searchQuery = searchQuery ~ 'title::' ~ num ~ '*' ~ (not loop.last ? ' OR ') %}
  {% endfor %}
{% endif %}

{% for entry in craft.entries.section('brands')
    .search(searchQuery)
    .orderBy('title')
    .all() %}
  {{ entry.title }}
{% endfor %}

Here's a simple navigation for these pages.

  #
  {% for letter in 'a'..'z' %}
    {{ letter|upper }}
  {% endfor %}


To filter out letters from that list that don't have any entries would be trickier to pull off tho. You could try something like this, but it might not be the most performant.
{% for letter in 'a'..'z' 
    if craft.entries.section('brands')
    .search('title::' ~ letter ~ '*')
    .exists() %}

Another possible option would be to create a plugin for finding distinct first letter entries like this person did:
https://craftcms.stackexchange.com/a/10957/273

> **Comments:**
> **username_0**: The pages are not setup with that at the moment, so it's a channel with all of them listed, would this work still? https://www.vouchertoday.uk/stores as you can see these need to be split into different pages.  
> **username_1**: Yes, the code above is written to pull all the entries from a "brands" channel. You wouldn't need to split your entries up separately in the Craft control panel.   For each URL/route like `/brands/a` or `/brands/b` it will only display entries where the titles start with the letter in the URLs last segment.  
> **username_0**: Sorry Alex, How do you go about splitting up entries in the CP?  
> **username_1**: You would NOT have to split them up in the control panel. Do you want to split them up in the control panel for some reason? I thought your question was asking how to display entries from a single channel split up over multiple pages on the front end of the site.  
> **username_0**: Just tried your method, I'm getting '404 Page not found' on the character URL's e.g. `/brands/m` is there a template I'm needing to create?  
> **username_1**: Yes, you'll need a template file that corresponds to your URL rule in the config/routes.php file. In the example above ('template' => 'brands/index') that would be templates/brands/index.twig (or .html).  
> **username_2**: Is it possible to use this approach together with sprig (https://putyourlightson.com/plugins/sprig), to load the content on runtime?  
> **username_1**: Yes, I think it's possible to use with Sprig. You could probably move the craft.entries for loop into a Spring component and pass `firstLetter` as a component variable.  

---

### Answer by username_3 on 2018-09-17. Score: 2

You could use eager loading to speed up things as it is now in your template.
{% set entries = craft.entries({
  section: 'brands',
  with:    ['brandLogo']
}.all() %}

Another alternative I can think of is using a structure instead of a channel, with 0-9 and A-Z as top level entries and your brands already sorted per character underneath. Than you can just call up the correct letter/branch in your template. Switching from channel to structure won't erase your data either if I'm correct. And the eager loading trick will speed up things too here.


---

