테마와 블록 작성에 필요한 스킬

Discourse 테마와 블록 컴포넌트를 구축하기 위한 Claude Code 스킬 저장소입니다:

:toolbox: 포함 내용

테마 작성 스킬 — Discourse 테마 구축의 포괄적인 범위를 다룹니다: discourse_theme CLI를 이용한 스캐폴딩, SCSS 아키텍처, 뷰포트 라이브러리, 로컬라이제이션, 설정, 수정자(modifiers), 값 변환기(value transformers), 아이콘, CSS 변수. 아이콘, 변수, 변환기에 대한 상세 참조 파일은 별도로 포함되며 필요 시 로드할 수 있습니다. SKILL.md

블록 작성 스킬 — Blocks API의 테마 측을 다룹니다: @block 데코레이터를 사용한 블록 컴포넌트 작성, args 스키마 정의, 사용 가능한 코어 아웃렛(outlet)으로 블록 렌더링, 조건부, 컨테이너 블록 및 레이아웃 그룹화, 그리고 블록 args에 테마 번역 및 설정 통합. SKILL.md

예제 테마 — 블록으로 구축된 사용자 정의 홈페이를 갖춘 작동하는 테마로, 아웃렛, 조건부, 레이아웃 구성에 대한 실제 패턴을 보여줍니다.


:jigsaw: Blocks API 소개

Blocks API는 Discourse의 테마와 플러그인에서 모듈형이고 조합 가능한 UI 컴포넌트를 구축하기 위한 새로운 프레임워크입니다. 블록은 homepage-blocks, hero-blocks, sidebar-discovery와 같은 이름이 지정된 아웃렛에 등록되는 Glimmer 컴포넌트이며, 라우트, 사용자, 뷰포트, 사이트 설정 또는 플러그인 가용성에 따라 조건부로 표시될 수 있습니다.

이 시스템의 주요 강점은 블록이 작고 집중된 범위와 일관된 패턴을 가진다는 것입니다. 이는 AI 지원 개발에 적합하게 만듭니다: 블록 스킬을 가진 모델은 작동하는 블록 컴포넌트를 스캐폴딩하고, 아웃렛에 등록하며, 조건부를 연결하는 작업을 한 번에 수행할 수 있습니다.

이 저장소의 예제 테마는 사용 가능한 플러그인과 콘텐츠에 따라 적응하는 홈페이를 보여줍니다. 히어로 블록과 추천 주제 목록이 포함된 기본 홈페이의 모습은 다음과 같습니다:

추가 조건이 충족되면(추천 태그가 구성되고, Discourse Events 플러그인이 활성화되며, Discourse Leaderboard 플러그인이 사용 가능한 경우) 추가 블록이 레이아웃에 조건부로 렌더링됩니다:

블록은 홈페이지로 제한되지 않습니다. 예제 테마는 또한 sidebar-blocks 아웃렛을 사용하여 링크를 추가하고, sidebar-discovery 아웃렛을 사용하여 카테고리별 사이드바 콘텐츠를 추가하며, 카테고리 페이지 상단에 category-banner 블록을 사용합니다:

DevTools의 블록 검사기(inspector)는 페이지 위에 아웃렛 라벨과 블록 식별자를 겹쳐 표시합니다. 이를 통해 레이아웃 구조를 이해하고 어디서 무엇을 렌더링하는지 디버깅하기가 쉽습니다:


:art: 디자인 플랫폼 MCP와 함께 사용하기

이 스킬들은 디자인 플랫폼 MCP(Penpot 또는 Figma MCP 등)와 잘 궁합이 맞습니다. 하나만 연결하면 Claude가 디자인 파일에서 컴포넌트 사양과 디자인 토큰을 직접 읽고 스킬의 관례를 사용하여 구현할 수 있습니다. 구조화된 디자인 시스템을 기반으로 작업할 때 특히 디자인과 코드 사이의 루프가 더 조밀해집니다.


:fork_and_knife: 포크 및 조정

스킬의 일부 관례는 관습보다는 선호도에 가깝습니다. 예를 들어 SCSS 폴더 아키텍처가 그렇습니다. 저장소를 포크하여 스킬을 자신의 워크플로와 관례에 맞게 조정할 수 있습니다.


:speech_balloon: 만든 것을 공유하기

한 번 시도해 보고 어떻게 되었는지 알려주세요! 스킬을 어떻게 사용 중인지, 무엇으로 구축했는지, 그리고 어디에서 한계를 느꼈는지를 듣고 싶습니다. 피드백, 수정, 포크 모두 환영합니다.

Blocks에 대한 전용 토픽이 따로 있는지, 아니면 여기가 그 토픽인가요?

후자라면 코드 스니펫이 도움이 될 수 있을까요? 아니면 plugin-api.gjs 파일에 있는 것이 현재 문서인가요?

감사합니다.

코어와 플러그인 구현을 포함하여 전체 Blocks API를 다루는 문서가 여전히 존재합니다. Blocks를 활용한 테마 작업에 대해서는 SKILL.md에 이미 모든 관련 사항이 다루어져 있습니다. 내용은 간결하고 매우 읽기 쉽습니다.

예제 테마에는 초기화 파일(initializer files)과 블록이 모두 포함되어 있습니다. 초기화 파일은 각 BlockOutlet에 대한 레이아웃을 선언합니다: discourse-theme-skills/javascripts/discourse/api-initializers at main · discourse/discourse-theme-skills · GitHub.

테마 작업 시 제가 느끼는 가장 큰 변화는 다음과 같습니다. PluginOutlets처럼 커스텀 컴포넌트를 앱에 직접 주입하지 않고, 이제 몇 가지 전용 레이아웃 프레임이 있습니다. 해당 프레임에 렌더링되어야 하는 모든 블록은 다른 조건으로 표시되더라도 동일한 초기화 파일에 등록됩니다.

이를 통해 커스터마이징과 코어 앱 레이아웃 사이에 깔끔한 인터페이스를 유지할 수 있습니다.

이걸로 진짜 재미있어하고 있어요 :winking_face_with_tongue: … 다른 AI 디자인 도구들처럼, 수작업으로 스케치하는 데 너무 비용이 많이 들었을 아이디어를 빠르게 프로토타입하는 데 정말 효율적이죠.

매우 브루탈리스트 스타일의 에디토리얼 홈페이를 요청했는데, 커뮤니티에서 온 매우 비전통적인 콘텐츠를 강조했습니다. 이 레이아웃을 받았는데, 실제로 추천 블록에 꽤 멋진 아이디어들이 있네요. 가장 재미있는 건, 테마 이름을 Newspaper from Hell이라고 지은 거예요 :grinning_face_with_smiling_eyes:

그다음에는 항상 탐구해 보고 싶었던 일본풍 포털 홈페이를 요청했는데, 밀도 높은 블록, 파스텔 톤, 그리고 수많은 작은 애니메이션들이 들어가야 했습니다. 이 초기 결과물을 정말 좋아해요:

모든 요소가 움직일 때 더 재미있어요 :carp_streamer: Theme Creator

flushy

드디어!!! 서둘러 실험 중인 테마 컴포넌트를 업데이트해 볼게요 :smiley:

Elmo Surrounded by Intense Fire

정말 훌륭하고 창의적인 작업입니다. 이 테마를 포크해서 기반으로 개발할 경우, 시간이 지남에 따라 Discourse 업데이트를 받지 못하는 부모 테마에 대한 고려 사항이 있을까요? 어떻게 접근해야 할지 고민하고 있습니다.

리소스를 공유해 주셔서 감사합니다!

@BrianC님 감사합니다!

부모 테마의 업데이트 유지에 대해 말씀드리자면: 스킬은 Discourse의 테마와 Blocks API를 추적하므로, 우리가 이를 적극적으로 사용하는 한 API가 진화함에 따라 동기화가 유지됩니다. 예제 테마는 패턴을 시연하기 위한 일종의 스냅샷에 가깝습니다. 포크를 생성하면 해당 포크는 사용자가 소유하게 됩니다. 하지만 테마를 업데이트할 때 스킬이나 새로운 예제를 참고할 수 있습니다.

Blocks API 자체의 핵심 목표는 안정적이고 작은 표면 영역(surface area)을 유지하는 것이며, 이는 Discourse 업데이트에 걸쳐 커스터마이징의 회복력을 유지하는 데 도움이 됩니다. 따라서 예제 테마처럼 주로 사용자 정의 블록을 추가하는 경우 이미 안정된 환경 내에서 작업하고 있다고 볼 수 있습니다. 주의해야 할 주요 사항은 아웃렛 이름이나 블록 API 시그니처의 변경 사항입니다. 현재 API는 여전히 실험 단계로 간주되므로 이름 등의 변경이 있을 수 있습니다.

추천하는 접근 방식을 다음과 같이 정리하겠습니다. 테마를 자유롭게 포크하고, 앞으로 어떻게 해야 하는지에 대한 살아있는 참고 자료로 스킬 문서를 활용하세요.

저는 이걸 막 만져 보고 있습니다 (에이전틱 코딩 없이).

사이트의 홈페이지만 제어하는 테마 컴포넌트로 변환하는 데 그리 많은 노력이 들지 않을 것 같은 인상을 받았습니다. 예를 들어, 이미 Horizon 테마를 사용 중인 사이트 같은 경우 말이죠. 그렇게 하면 어리석은 선택일까요?

또한, 몇 가지 문제를 발견했습니다:

다가오는 이벤트 블록이 주제를 정렬하지 않음

그냥 이벤트 주제를 생성일 순서대로 나열할 뿐입니다. 이건 정말 도움이 안 됩니다!!

ask.discourse.com에서는 이 문제를 수정하기 위해 다음과 같은 변경을 제안하고 있으며, 실제로 작동하는 것을 확인했습니다 (비판적인 인간적 사고가 부족함을 용서해 주세요):

@bind
async fetchEvents() {
  const count = this.args.count || 5;
  const results = await ajax("discourse-post-event/events");

  if (!results.events?.length) {
    return null;
  }

  const now = new Date();

  // 과거와 미래의 이벤트를 분리한 후 시작일 기준 오름차순으로 정렬
  const upcoming = results.events
    .filter((e) => new Date(e.starts_at) >= now)
    .sort((a, b) => new Date(a.starts_at) - new Date(b.starts_at));

  return upcoming.slice(0, count);
}

카테고리 배너 블록이 설정을 무시함

모든 카테고리에 표시되며(지정한 카테고리만 표시되지 않음), 내비게이션 시 새로고침되지 않는 것 같습니다(페이지를 새로고침할 때만 새로고침됨).

@nathank님, 시도해 주셔서 감사합니다! 아직 실험 단계로 간주되고 있으며 API가 변경될 예정이므로, 당분간 이를 기반으로 홈페이지 빌더 유형의 테마 컴포넌트를 구축하지 않는 것이 좋습니다.

데모 블록은 기본적인 예시일 뿐입니다. 데이터 로딩 방식을 개선할 예정인 API 변경 사항도 곧 적용될 예정입니다. 해당 기능이 사용 가능해지면 데모 테마의 모든 블록에 대한 변경 사항을 반영하겠습니다.

카테고리 배너 블록은 모든 카테고리에 표시되어야 합니다. 언급하신 카테고리 선택기는 홈페이지의 추천 카테고리 블록을 위한 것으로 보입니다.

드디어 용기를 내어 이것을 조금씩 사용해보았습니다. 공유해 주셔서 정말 감사합니다.

이미 사용자 아바타와 이름(이 부분은 이미 구현했습니다)을 표시하는 커스텀 블록을 생성하는 것은 어떻게 하면 될지 궁금합니다. 여기에 더해, 해당 사용자의 토픽 및 게시물 수, 좋아요 수, 체어 포인트, 그리고 See TL3 Progress 와 유사하지만 특정 배지(그 배지를 기반으로 구축된 커스텀 신뢰 수준)와 관련된 정보도 함께 표시하고 싶습니다.

역할극 게임에서 캐릭터 카드에 경험치(EXP), 기본 정보, 주요 스킬을 볼 수 있는 것처럼요.

블록을 추가하고 싶다면 코어에 PR을 제출해야 할 것 같습니다.

Blocks API에 대해 공부하고 있는데, ask.discourse가 꽤 도움이 되었습니다.

메타 카테고리 배너와 아이콘, 그리고 몇 가지 다른 아이디어를 참고(모방)해서 구현해 보고 싶습니다.

읽어 본 자료 대부분은 자체 호스팅(self-hosted) 사이트에 초점이 맞춰져 있고, 호스팅된 사이트(hosted sites)에 대한 내용은 많지 않습니다.

호스팅된 사이트에는 어떤 제한 사항이 있나요?

이것은 완전히 가능하며, 공유된 테마의 스킬과 예시 블록을 사용하는 에이전트는 이를 코딩하는 데 완전히 능숙할 것입니다.

실제로 저도 얼마 전에 비슷한 블록을 만들었습니다. 아직 새로운 Blocks API를 사용하지는 않지만, Manuel Kostka / Discourse / Blocks / User Profile · GitLab 에서 접근 방식을 살펴볼 수 있습니다. 예를 들어 Canvas Central 테마에서는 다음과 같이 보입니다:

우리는 아직 코어에 블록이 없습니다(아직). 모든 블록은 테마 또는 테마 구성 요소를 사용하여 추가됩니다.

테마와 테마 구성 요소를 사용하여 기존 BlockOutlets에 블록을 추가할 수 있으며, 커스텀 테마를 추가하려면 Pro 플랜 이상이어야 한다고 생각합니다. 그 외에는 제한이 없어야 합니다.

지금 저는 메타에서 아직 실험 단계라 사용하지 말라고 강하게 주장하는, 그리고 ‘도그푸딩’ 중이라고 말하는 AI 봇과 논쟁 중입니다. 더 성숙해지길 기다리려고 포기할 참입니다.

봇은 공식 발표에서 방향성을 얻고 있을 가능성이 높습니다: Creating a 'Blocks' API for injecting content

하지만 동의합니다. 지금은 프로덕션 환경에서 사용하지 않는 것이 좋습니다. 사전 공지 없이 깨지는 변경 사항(breaking changes)이 발생할 가능성이 높기 때문입니다.

스테이징 사이트에서 만지작거리는 거라, 프로덕션 환경에서는 함부로 건드리지 않을 거예요.

그래도 괜찮을 것입니다. 단, 아직 포괄적이지 않다는 것이 아니라, 다른 안정화된 API나 인터페이스와 달리 깨질 수 있는 변경 사항에 대해 헤지하지 않겠다는 점에 주의해야 합니다.

아, 맞다. 내 실수였네. 블록 위치를 추가하는 것에 대한 언급인 줄 알았어.

네, BlockOutlets은 코어에 포함되어 있습니다. 다만 플러그인을 통해서도 추가할 수 있습니다.