Add home page to a structure?

20

11

I am using a structure for all of my site's pages (single pages and channel index pages). The structure settings are as follows:

URL for Top-Level Entries:
{slug}

URL for Nested Entries:
{parent.uri}/{slug}

Entry Template:
_pages/_entry.html

Additionally I set up multiple entry types for the structure to relate the pages with individual templates (basically as described in the FAQs). This is my _entry.html:

{% include '_pages/_types/' ~ entry.type %}

This all works great for me [*], but now I'd like to further improve the template setup by adding my site's home page to the structure, too. With a single section I can simply trigger the option "this is the home page" in the section's settings, but how can I tell an entry of my pages structure to be my home page?

[*]: I can generate my site's main navigation from this structure (nice!) and all channels' index pages have entry slugs now, which is incredibly helpful in a multi-lingual Craft setup, if you want to translate your slugs.

carlcs

Posted 2014-07-28T15:53:47.047

Reputation: 31 320

1I think this is a great question, and I'm slightly bummed that it hasn't been answered yet. If it's not possible, perhaps it's worthy of an official feature request. If a single can be set "as the home page", why not a structure page? – Lindsey D – 2014-07-30T02:57:20.700

1Done. Thanks @Lindsey! – carlcs – 2014-07-31T15:17:31.383

Answers

13

The "this is for the homepage" button available on single sections does two things for you, when you navigate to the home page's URL:

  • it populates the entry variable with the single's entry model
  • it loads the template spezified in the single's CP settings

.

Actually nothing you can't do manually with your home page's index.html:

{# Replace the default `entry` variable with the home page's entry model #}
{% set entry = craft.entries.section('pages').id('1').first() %}

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

_pages/_entry.html further includes the template partial designed for the entry type I assigned my home page to:

{# Load the designed template for this entry's entry type #}
{% include '_pages/' ~ entry.type %}

This is all you need to replicate the "this is for the homepage" button behaviour for a structure entry. Additionally you might want to exclude the home page from your navigation menu for example. Again use the id or slug parameter on the ElementCriteriaModel:

{# Get top-level entries in pages structure (exclude home page)  #}
{% set pages = craft.entries.section('pages').id('not 1').level(1) %}

.

Thanks again to Marion, her answer pointed me in the right direction. I added this answer, because her configuration is a bit spezific and rather complicated.

carlcs

Posted 2014-07-28T15:53:47.047

Reputation: 31 320

If you don't want to use and "id" or "slug", but the first element in the structure, it's very easy too. On the index page: {% set entry = craft.entries.section('pages').first() %}. For the navigation: {% set pages = craft.entries.section('pages').offset(1).level(1) %}. Works like a charm. – outline4 – 2015-06-11T06:36:13.980

1This is a great answer, but wouldn't '/homepage/{slug}' now be part of the uri for all subpages? I would think you would also need to add a custom route that re-maps uris to remove the 'homepage' segment. – Douglas McDonald – 2015-02-22T19:42:01.340

Nope @Douglas, "Home" could go anywhere in my structure, as it is excluded from the nav loop. So pages like "About" and "Contact" are still first level entries in my "Pages" structure, peacfully located besides "Home" (one could say this is not consistent, but I think it's good enough having it at the top). – carlcs – 2015-02-22T20:35:46.920

Got you. I was thinking you were suggesting placing everything under 'home' in the heirarchy (i.e. level 2). That makes more sense. Thanks for clarifying. ;) – Douglas McDonald – 2015-02-22T20:43:40.257

21

This isn't documented, so it's subject to change:

When you set a Single to be the homepage, its slug is automatically set to __home__.

If you want your homepage to be part of a Structure, rather than a separate Single, you can set the slug of a Structure entry to __home__, which makes it act as the site's homepage and gives it that little Home icon in place of its slug in the structure view.

Michael Rog

Posted 2014-07-28T15:53:47.047

Reputation: 2 972

Yep just remember to untick the box on the default single that says "This is for the homepage" – John Macpherson – 2015-05-28T14:26:23.170

Coming across this and checking, the slug for the homepage appears to be homepage currently. – Marty – 2015-08-11T05:26:30.757

3Technically, the actual slug can be whatever you want. The URI must be __home__. But, unless you want to open up the db and edit those values separately, you would probably be editing both together via the slug input. – Michael Rog – 2015-08-11T13:20:57.863

This tip is absolutely brilliant. I just stumbled across it, and it works like a charm! – Lindsey D – 2016-02-02T05:46:28.580

But now every child page have __home__ in the url – JCharette – 2017-03-10T21:23:33.803

1@JCharette In my setup, the homepage is a sibling of the other first-level pages on the site, so it doesn't need to have any children. I recommend this approach. – Michael Rog – 2017-04-12T08:01:05.640

3

I kludged this to work by creating a global whose value was the entry I wanted to use as the home page (everyPage.homePage), and then on _pages/_entry.html using twig to sort things out based on the entry:

  • if no entry: 404 (this should never happen)
  • if entry is everyPage.homePage: 404
  • if entry is the Craft home page single: set entry to everyPage.homePage

Then proceed as normal.

{% if entry is not defined %}
  {% exit 404 %}
{% elseif entry.id == everyPage.homePage.first.id %}
  {% exit 404 %}
{% elseif entry.id == craft.entries.section('homePage').first().id %}
  {% set entry = everyPage.homePage.first %}
{% endif %}

This was using a channel (not a structure) for the pages, and the URL is simply {slug}

Marion Newlevant

Posted 2014-07-28T15:53:47.047

Reputation: 10 149

Whooohoo, Marion! Kinda hacky but really great solution, if this really works. Off for the test... – carlcs – 2014-07-31T17:50:57.517

To be true, I don't really understand it. Let's try: I'd still need a single (the only entry I could route / to), the global is basically not necessary, right? (just for convenience) and then you'd just "import" the content from the select channel- or structure-entry by getting it's entry model... good that's a plan! – carlcs – 2014-07-31T18:05:30.240

Actually... why not simply get the desired entry model (with id or slug) from my public/index.html template!? If that's all I needed, I totally don't know why I didn't come up with that myself. That's all the more reason to thank you, Marion! :D – carlcs – 2014-07-31T18:13:07.380