5

As far as I can tell, it's mandatory to have a Single as the site index.

I always use a Structure for organising my pages, and different entry types for different page templates. I intend to use a nav tag to output the menu. However, this time my site nav looks like this:

Homepage         (site.com/)
    Subpage 1    (site.com/subpage-1)
    Subpage 2    (site.com/subpage-2)
    Subpage 3    (site.com/subpage-3)
About            (site.com/about/)
    Subpage 4    (site.com/about/subpage-4)
    Subpage 5    (site.com/about/subpage-5)
Services         (site.com/services/)
    Subpage 6    (site.com/services/subpage-6)
    Subpage 7    (site.com/services/subpage-7)

If I have to use a Single as the home page, how do I put subpages under the home page?

Previously I've used the nav tag, and just hardcoded a link to the home page before the rest of the li's, but that's not going to work this time as the homepage has subpages.

EDIT: I've updated my sitemap to include a URL structure, which is the real challenge here.

3 Answers 3

4

Updated answer to reflect your added uri requirements.

Given your desired uri patterns, I would recommend moving 'subpage-1', 'subpage-2', and 'subpage-3' to the root of your structure which will make all the uri's the way you want without needing to define any custom routes.

For auto-generating the navigation, you can then simply add some logic to either include or exclude those items, depending on how you want your nav to work. You could do this by checking the 'level' and 'hasDescendants()' (if that's consistent) or by entry type (if you want to use something more specific).

For example, if you wanted to exclude subpages-1,-2,-3 in the site nav (using entryType), but include them in the homepage page nav:

{% set pageEntries = craft.entries.section('pages') %}

<ul id="site-nav">
    {# skip entries of type 'homepageSubpage' #}
    {% nav entry in pageEntries if not entry.type == 'homepageSubpage'  %}
        <li>
            <a href="{{ entry.url }}">{{ entry.title }}</a>
            {% ifchildren %}
                <ul>
                    {% children %}
                </ul>
            {% endifchildren %}
        </li>
    {% endnav %}
</ul>

<ul class="homepage-nav">
    {# only show entries of type 'homepageSubpage' #}
    {% for entry in pageEntries if entry.type == 'homepageSubpage' %}
        <li>
            <a href="{{ entry.url }}">{{ entry.title }}</a>
        </li>
    {% endfor %}
</ul>

You could also of course, leave the 'homepage' entry, sitting next to subpage-1,-2,-3, About, and Services and use the technique as described by carlcs.

1
  • Hey - thanks for your answer. It's got me 90% of the way there, I hadn't thought of using the include entry.type for the index page too, thanks. I should have been clearer about URL structure though; I've updated my question. Do you know if there's a way to get that URL structure with the include setup? Feb 22, 2015 at 11:44
7

You can place your homepage entry in a Structure by setting its slug to __home__.

Doing so causes the entry to answer for the / (empty) URI, and it even places the little "home" icon in place of the Entry's slug in the CP.

However, if you do this, its best not to nest pages under the homepage, because then their URIs would be of the form: __home__/subPageSlug

In other words, taking the pages from your example, it's best if your structure can be:

Homepage         (site.com/)
Subpage 1        (site.com/subpage-1)
Subpage 2        (site.com/subpage-2)
Subpage 3        (site.com/subpage-3)
About            (site.com/about/)
    Subpage 4    (site.com/about/subpage-4)
    Subpage 5    (site.com/about/subpage-5)
Services         (site.com/services/)
    Subpage 6    (site.com/services/subpage-6)
    Subpage 7    (site.com/services/subpage-7)

If you want the benefit of placing the homepage in the Structure, but you need to organize some pages as descendants of the homepage, you could, in theory, rig it up... But it'd get pretty janky:

  • Give the homepage the special __home__ slug.
  • Build an index template to answer for the descendant pages by finding the intended entry, setting a entry variable, and extending your regular Page template.
  • Create an .htaccess rule to remove the __home__ segment from a URL if anybody accidentally lands on it, to prevent duplicate content from appearing at multiple URLs.

However, there are major drawbacks to this second approach: First, you won't be able to use your entries' url() method... or, you'll have to somehow filter out the offending __home__/ segment out of the URL any time you loop through entries or use the {% nav %} tag to generate your site nav. Also, this alternative option also foils Craft's built-in slug-uniqueness checking, so if you're not careful you could end up with duplicate slugs for some pages. In general, I don't recommend it... but it's a fun thought exercise.

1
  • Best and simplest answer.
    – kmgdev
    Jan 10, 2016 at 23:49
3

You don't have to use an extra single section for the homepage, see here: "Add home page to a structure?"

Edit: As this question is slightly different to the one I linked to, I will add some more detail on how you can keep your "pages" structure as is. To get the "homepage" entry to load for visits to myexample.com, add a template file with the following code to your webroot.

index.html

{# Get the home page's Entry Model via its slug #}
{% set entry = craft.entries.section('pages').slug('home').first() %}

{# Load the home page's template from the "pages" structure #}
{% include "_pages/_entry" %}

And for the child entries of "homepage" you could do the same.

subpage-1.html

{% set entry = craft.entries.section('pages').slug('subpage-1').first() %}
{% include "_pages/_entry" %}

Or as an alternative solution you could instead add custom routes to config/routes.php
'(?P<slug>subpage-1)' => '_pages/_entry'

And the get the Entry Model in _pages/_entry.html

{% set entry = craft.entries.section('pages').slug(slug).first() %} 

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.