홈페이지에서만 표시되는 커스텀 콘텐츠 추가하기

테마 개발자로서 자주 마주치는 상황 중 하나는 커뮤니티의 홈페이지에서만 표시되는 콘텐츠를 만드는 것입니다.

테마의 “헤더 이후” 섹션에 HTML을 추가하면 해당 콘텐츠가 모든 페이지에 표시됩니다. CSS를 활용하여 홈페이지를 제외한 모든 곳에서 이를 숨기는 방법이 있지만, 대신 Discourse 테마를 사용하여 홈페이지에서만 표시되는 콘텐츠가 포함된 컴포넌트를 만들어 보겠습니다.

Discourse 테마에 익숙하지 않다면 Beginner's guide to using Discourse ThemesStructure of themes and theme components 을 확인해 보세요.

Discourse 테마에서 다음 디렉터리 구조를 설정해야 합니다:

:file_folder: javascripts/discourse/components/
:file_folder: javascripts/discourse/connectors/

이제 Ember 컴포넌트를 생성하겠습니다. Ember 컴포넌트에 대한 자세한 내용은 공식 문서에서 확인할 수 있습니다: Ember.js Guides - Guides and Tutorials - Ember Guides

하지만 지금은 로직과 템플릿이 모두 포함된 단일 .gjs 파일로 작성된 간단한 컴포넌트가 될 것입니다.

:page_facing_up: javascripts/discourse/components/custom-homepage-content.gjs

import Component from "@glimmer/component";
import { service } from "@ember/service";
import { defaultHomepage } from "discourse/lib/utilities";

export default class CustomHomepageContent extends Component {
  @service router;

  get isHomepage() {
    const { currentRouteName } = this.router;
    return currentRouteName === `discovery.${defaultHomepage()}`;
  }

  <template>
    {{#if this.isHomepage}}
      <h1>This is my homepage HTML content</h1>
    {{/if}}
  </template>
}

이것은 isHomepage getter를 생성하며, 라우터 서비스의 currentRouteName을 확인합니다. 라우트 이름이 홈페이지(사이트 설정에 의해 결정됨)와 일치하면 true를 반환합니다. <template>...</template> 내부의 템플릿은 해당 getter를 확인하여 true일 때만 콘텐츠를 표시합니다. {{#if}} 블록 사이에 원하는 HTML을 자유롭게 추가할 수 있습니다.

컴포넌트가 생성되었으니 이제 이를 Discourse 어딘가에 추가해야 합니다. 이 단계에서는 어떤 플러그인 아웃렛을 사용할지 결정해야 합니다. 플러그인 아웃렛은 Discourse 전체에 걸쳐 개발자가 코드에 연결할 수 있도록 추가된 영역입니다. Github에서 Discourse를 검색하여 이를 찾을 수 있습니다 또는 (deprecated) Plugin outlet locations theme component 에서 찾아볼 수 있습니다.

사용자 정의 홈페이지의 경우 above-main-container가 일반적인 선택이므로, 이를 사용하겠습니다.

정확한 디렉터리에 커넥터 파일을 생성해야 합니다:

:page_facing_up: javascripts/discourse/connectors/above-main-container/custom-homepage-connector.gjs

import CustomHomepageContent from "../../components/custom-homepage-content";

<template><CustomHomepageContent /></template>

:point_up: 그리고 그것이 전부입니다. 컴포넌트를 호출하는 한 줄만 필요합니다 :tada:


이 문서는 버전 관리됩니다 - 변경 사항을 github에서 제안해 주세요.

47개의 좋아요

Hi @awesomerobot,

Thanks for the explanation. I tried the steps you suggested but the after_header I implemented is still showing in the post detail pages. Can you recommend how I can fix this to show only on my home page?

1개의 좋아요

Hi @Cornelius, is it alright to view your code?

2개의 좋아요

It would be great to rewrite this for modern use of the filesystem rather than sticking everything in the header tags.

Most of these old guides for themes are out of date with your things are done now.

7개의 좋아요

Yes, this was fairly outdated! I’ve updated it to reflect the structure of remote themes and our modern Ember components.

6개의 좋아요

That’s awesome!

And that getter is the same thing as this http://ember-cli-page-object.js.org/docs/v1.11.x/api/getter.html? I know just enough to be dangerous. If it is the same, then I’ll edit the OP to link to it.

3개의 좋아요

@awesomerobot Hi kris, I have installed discourse locally on my system. What is the right path to add these files in my local instance of discourse. I wanted to add a new theme-component in my local instance of discourse.

1개의 좋아요

You would create your theme component and install it through the ux.

Install a theme or theme component

Install the Discourse Theme CLI console app to help you build themes

4개의 좋아요

If I build my homepage on top of the category view, I am consequentially still getting my custom content even if I go to /categories which is not the home URL. I want to limit this to just the root URL / which I believe is what the previous code was doing, but I wonder if defaultHomepage() should do that.

3개의 좋아요

discovery.${defaultHomepage()} will match the route that is set as the landing route by the top-menu setting. It will match both the root URL / AND the specific route, like /categories.

In my experience there’s two complications when building a custom homepage based on defaultHomepage():

  • the route that it is build on is not available as a plain list view any longer
  • members can set their own default homepage in their interface settings. So one either needs to disable that feature or actually have a homepage concept that works on any of the top-menu routes

To only build a custom homepage on the root URL one can check for router.currentURL === '/'. By default, this only matches the root URL / and not the landing route set by the top-menu setting. However, there is logic now on the sidebar links that additionally aims to match a given URL to a route. So it won’t work on sidebar links by default. I just posted a topic on this: Can I have sidebar links that don’t resolve an url to a route?

In my understanding there’s currently no default way to build a custom homepage on the root URL without either targeting a route from the top-menu as well or running into issues with the sidebar. It would be great to have that option.

4개의 좋아요

Right, it’s kind of a long-standing hack that / and the corresponding /route can render different content. We have a todo to

  1. Allow the homepage to be set independently of the top_menu setting
  2. Add a new stand-alone homepage template that can be customized without taking over an existing route

Custom homepages are a very common request at this point, so we could certainly use more flexibility here.

6개의 좋아요