Using the new custom-homepage feature

Trying out the new custom-homepage feature: DEV: allow themes to render their own custom homepage by pmusaraj · Pull Request #26291 · discourse/discourse · GitHub :tada:

@pmusaraj I wonder what’s the best approach to add components?

  1. So adding the custom-homepage modifier enables the discovery.custom route and shows a default info alert, rendered on the custom-homepage outlet:

  2. I add a component to the outlet and it renders instead:

  3. However, when I add more than one component, I get an error:

    image

  4. I can add more components to other outlets though. Here’s a view with plugin outlets visible:

    image

So I wonder how the new outlet should work:

  • In a way, I wouldn’t need the outlet. I can just use the other available ones and limit components to the discovery.custom route
  • Though it seems I need to put at least one component on the outlet, otherwise the default alert is rendered? Putting an empty template there doesn’t work.
  • On the other hand, if I could add multiple components to the outlet, I wouldn’t need to have a route logic at all. Components would only show on the homepage because the outlet will not be available on other routes?
4 Likes

That’s not surprising?

Put a single template file here and use it to reference your Components in the Components folder (of which you can then have many)

<MyFirstComponent />
<MySecondComponent />
<MyThirdComponent />

Or whatever you want … just stick with one template in this folder?

1 Like

I thought it is because it works with other outlets? As on the screenshot above…

Oh sorry, you are right, it seems legal on Outlets (usually) to publish more than one template file in a single Theme Component (I was aware it handled clashes across Theme Components and plugins so they all get to render). Curious.

I guess though: why would you want to do that? You will have less control over the layout?

One template forces you to compose the entire layout in one go with however many sub-components you want?

The behaviour does appear to be inconsistent though …

If I build a custom homepage, I’d want to be able to render multiple existing components on it. And as mentioned, this already works when using other available outlets and limiting the components to the custom homepage route.

If I can only add one component to the particular custom-homepage outlet, and also need to add one to disable the default yield, then this actually restricts my layout control.

But why can’t you reference all those components in one template?

Oh because they are coming from different Theme Components?

I think we were talking at cross-purposes here.

When I say put all your (Ember) Components in the Components folder, I mean exactly that but in one Theme Component.

I think the crux of this is simply: “why does this outlet behave differently?” I get that you are trying to combine different Theme Components.

Yes, that’s the idea. I just used the plain text templates above as an illustration. E.g. I use Featured Lists. And I can render it on the outlet with these settings:

image

But when I want to render another one the same way I get the multiple connector error.

:+1:t4:

2 Likes

Thanks for testing this out @nolo and for the questions.

I didn’t know the answer to this either, but I looked and figured out roughly why. We recently introduced a distinction between classic plugin outlets and wrapper plugin outlets, in this PR from last year: DEV: Allow PluginOutlets to 'wrap' a core implementation by davidtaylorhq · Pull Request #23110 · discourse/discourse · GitHub

The wrapper plugin outlets are the ones that allow only one connector, the rest allow multiples. To illustrate, the current core plugin outlet code is this:

<PluginOutlet @name="custom-homepage">
  {{#if this.currentUser.admin}}
    <p class="alert alert-info">
      {{i18n "custom_homepage.admin_message"}}
    </p>
  {{/if}}
</PluginOutlet>

and it allows only one connector. But if I change the core outlet code to:

<PluginOutlet @name="custom-homepage" />

It will allow multiple connector templates just fine. We could make this change in core for this particular outlet, but this difference is more general. It does feel a bit opaque to developers, though, I see your point there.

Note also that multiple connectors have an ordering problem, afaik we don’t have a mechanism to decide on ordering.

I think the best approach here, regardless, is what @merefield suggested: use one template and then reference Ember components from it.

Default alert is only shown to admins, FYI.

5 Likes

Thank you for the explanations!

Playing more with this… it’s really fresh and a joy to use!

I used three existing components for that layout and that’s what I’d expect to be a common approach when building a custom homepage. I could only add one of these to the wrapper outlet, that’s why I think having a plain outlet here would be more helpful.

6 Likes

Another observation: I put a link on the sidebar using the /custom url:

image

It’s not highlighted when on the custom route.

If I understand the logic with the sidebar highlights correctly, it should also be highlighted when on the root url /.

3 Likes

I see your issue more clearly after having a quick look at the Featured Lists component. One option is to refactor that component and have it output all of the lists into one Ember component. Then you could add that component to a plugin wrapper outlet.

Another option is to add a second plugin outlet to the custom homepage template, something like <PluginOutlet @name="below-custom-homepage"/>.

I may be hanging on to this custom-homepage outlet with a message for admins for not much good reason, to be honest. That warning is not all that useful…

Yeah, that can be tricky. In my local test just now, /custom there doesn’t work properly. It’s better to use /, that routes correctly. But it still doesn’t highlight.

2 Likes

That seems to be a common issue. If I use /it also doesn’t highlight other routes set as the landing page.

Yes, I could also imagine the warning just being displayed differently. The main advantage of wrapper outlets seems to be that I can conditionally yield core code or render custom one. But that would likely never be a case for that info message.

There must be a misunderstanding. The component already wraps all lists in one wrapping component and renders it on any given outlet:

image

So I can add the component without issues to the current wrapper outlet on the custom homepage.
What I can’t do is use that outlet to render more than one standalone component on the custom homepage. Components I would have installed as theme components, like these three:

image

My assumption is that making such use of several standalone theme components to build a custom homepage would be the common approach. Rather than building it all from scratch in one theme.

If you consider adding another outlet or changing the outlet setup, I could give some more feedback from using it so far. Though I’ll wrap that rabbit hole in details :smile:

So I realized that the outlet is rendered within the main-outlet element. The overall structure of these elements then is:

  • main-outlet wrapper
    • sidebar-wrapper
    • main-outlet
      • custom-homepage outlet

As a designer I’m actually not that flexible arranging items on a custom homepage using this outlet. For the design shared above I rather used the before-main-outlet outlet, not only because I can put more than one component, but also because it doesn’t nest components within the main-outlet element.

The structure as shared on the screenshot above looks like this:

  • main-outlet wrapper
    • sidebar-wrapper
    • component: search banner
    • component: featured topics
    • component: featured lists
    • main-outlet

The advantage is that I can arrange elements across the width of the entire main-outlet wrapper and not just within the main-outlet element. To illustrate the point, if I’d render one of the components on the current custom-homepage outlet, it would render nested within the main-outlet element like this:

The most flexibility for custom designs in my view would be offered by a plugin outlet that is placed

  • as a direct child of the main-outlet wrapper (similar to the before-main-outlet outlet)
  • within a wrapping div

That wrapping div would bundle all components added to it and allow for easy ordering. Such a structure would then look like:

  • main-outlet wrapper
    • sidebar-wrapper
    • custom-homepage-wrapper
      • component: search banner
      • component: featured topics
      • component: featured lists
    • main-outlet

So that’s my feedback as a designer. Guess it’s for you to decide how much that aligns with what you’d consider a common application for the custom homepage feature.

3 Likes

Presumably this page is “superficial” in that it will appear for the user but not for “Googlebot” and so won’t be indexed?

Correct, yes, for the crawler view I have opted to outputting just the top menu. Can’t really know from the Rails app what a theme will output in this route.

I am thinking about the suggestions here @nolo, will make some time shortly to test out some changes. Please :bear: with me.

5 Likes

I’ve added support for this feature into Discourse Bars 🍻 🍸 (a sidebar framework) - #43 by merefield

4 Likes

An issue I came across: I wanted to display the Homepage Feature component on the custom homepage. But then topics are not filtered on this route. The component just shows any recent topic that has an image.

The code on the component is:

    const topicList = await this.store.findFiltered("topicList", {
      filter: "latest",
      params: {
        tags: [`${settings.featured_tag}`],
        order: sortOrder,
      }

And it seems the params are not applied on the custom homepage. It works fine otherwise. Not sure why this happens?

Edit: I use the same method on the Featured Lists component. When using this component on the custom homepage, the filter is also not applied. But only on the first list… when there’s more, the following lists are all filtered correctly.

3 Likes

Interesting, I’m not sure why that is, maybe there’s some logic in the topicList store that is tied to the discovery routes? The custom homepage is not a discovery route.

I’m curious, does that same component with the params work fine in say an admin route? Or user profile route? Any chance you can check?

@tynaut ran into a similar issue, so there’s likely something to be addressed here.

1 Like

I tried with the Featured Lists component, it already has a setting to show the component everywhere. This doesn’t include admin routes, but I tried on all others (static pages, user profiles,…) and it seems to work everywhere expect the custom homepage.

The other weird thing is, as mentioned, that it only doesn’t filter the first list. E.g. here I filter two lists, one for tag featured, one for General category, and that’s how the lists show on all other routes:

Just on the custom homepage route, they show like this:

So the first list doesn’t filter for the tag any more, but the second list does filter for the category. And when I switch the order of the lists, the first list doesn’t filter for category, but the second does filter for the tag:

2 Likes

I found a little tricky to reproduce this properly with the Featured Homepage component, it mixes in too many other conditions.

I can easily reproduce with a stripped down component though. I pushed this into a sample repo here: GitHub - pmusaraj/discourse-sample-custom-homepage

The sample-list component there should pull in only topics with the featured tag, but it doesn’t (it pulls in the first 3 topics for me). If I remove the custom_homepage modifier from that theme’s about.json file, then the right topics are pulled in.

I’ll find someone more familiar with the store service to have a look. Thanks!

1 Like

Hi

can you please explain how to add a component( search banner or a custom component already installed on forum) inside the home.hbs file to make it show on new custom homepage

thanks