Files
ghost.sori.studio/docs/spec.md
2026-04-27 18:15:15 +09:00

9.7 KiB

기술 명세

현재 버전

  • v1.0.5

테마 개요

  • 테마명: Zenless Column Flow (slug: zenless-column-flow)
  • Ghost v5 대응 커스텀 테마
  • 참고 사이트 https://thred.brightthemes.com/ 기반의 3열 에디토리얼 레이아웃
  • 좌측 탐색, 중앙 콘텐츠, 우측 구독/추천/작성자 패널 구조

구현 범위

  • default.hbs 기반 공통 셸
  • home, index, tag, author, post, page 템플릿
  • 검색 오버레이, 탭 전환, 다크모드 토글용 프런트 스크립트
  • Ghost navigation, get, subscribe_form, comments, pagination 헬퍼 사용
  • @site.accent_color가 설정된 경우 default.hbs의 body 인라인 변수로 전역 --accent/--accent-strong를 덮어써 테마 포인트 색상을 동기화함
  • topbar 브랜드는 모바일 화면에서만 노출하며, @site.logo를 우선 렌더링하고 로고 미설정 시 @site.title 텍스트를 fallback으로 사용함
  • 데스크톱 topbar__innervar(--sidebar-left) minmax(0, var(--content-column)) var(--sidebar-right) 3열 그리드이며, 1024px 이상에서만 검색 셀(.topbar__search)에 min-width: min(--topbar-search-min, 100%)를 적용해 중앙 검색 최소 폭을 완만히 보장함. 검색 트리거는 라벨(.search-trigger__label) 말줄임·단축키 flex-shrink: 0 유지. 브랜드 텍스트는 말줄임, 로고 이미지는 max-width: 100%로 축소
  • 1023px 이하에서는 topbar__innerminmax(0, 1fr) auto 2열로 바꾸고 검색 열을 숨긴 뒤, 브랜드·액션을 각각 1·2열에 배치함(헤더가 3열 정의만 남는 문제 방지)
  • home Hero는 @site.cover_image가 있을 때 배경 이미지로 적용하며 오버레이와 텍스트 대비를 함께 조정함
  • 좌측 사이드바 menu-groups: Primary는 @site.navigation 항목이 있을 때만 아코디언과 {{navigation}}를 렌더하고, Secondary도 @site.secondary_navigation이 있을 때만 아코디언과 {{navigation type="secondary"}}를 동일 마크업(ul.nav)으로 노출함. 각 라벨은 @custom.primary_nav_label, @custom.secondary_nav_label(미입력 시 Primary/Secondary fallback)로 어드민에서 변경 가능함
  • 상단 사용자 메뉴는 멤버 로그인 시에만 드롭다운 상단에 이름/아바타 행을 노출하며, 서버 렌더링 값으로 초기 표시한 뒤 /members/api/member/ 재조회로 실시간 동기화하고 아바타 미등록 시 fallback 문자(이름/이메일 첫 글자)를 사용함. 비로그인 시 해당 행은 렌더하지 않음
  • Tailwind CSS 빌드 결과물(assets/built/tailwind.css)을 기존 screen.css와 함께 로드
  • Tailwind 기본 초기화(preflight)를 활성화해 브라우저 기본 마진과 폼 스타일을 리셋
  • Alpine.js 로컬 자산(assets/built/alpine.js)을 전역 로드
  • npm run dev:watch는 초기 dev:prepare 실행 후 Tailwind --watch와 파일 변경 감지 기반 dev:sync를 함께 실행함
  • 로컬 Docker 구성은 Mailpit SMTP(mailpit:1025)를 사용하도록 설정되어 멤버/댓글 알림 메일을 로컬 수신함
  • npm run zip:version은 현재 package.json 버전명을 기준으로 업로드용 zip을 생성함
  • 좌측 카테고리 영역은 Alpine.js로 제어되며 1024px 이상에서 기본 열림, 미만에서 기본 닫힘
  • 좌측 카테고리 목록은 data-category-priority-order에 지정한 태그 slug를 우선순위로 먼저 배치하고, 나머지는 count.posts desc 기본 순서를 유지한 뒤 제한 개수만 노출함
  • 좌측 네비게이션 마커와 카테고리 마커는 동일한 세로 바 → 원형 hover 패턴 사용
  • 상단 사용자 버튼/메뉴 아바타는 로그인 멤버일 때 댓글 UI와 유사한 형태(이니셜 배경 + 이미지 오버레이)로 표시하며, 이니셜과 배경색은 멤버 이름/이메일 기반으로 동기화함. 비로그인 상태는 icon-user-circle 아이콘을 사용함
  • 로그인 상태 사용자 버튼/메뉴 아바타의 배경색은 투명으로 유지하며, 비로그인 상태 아이콘은 32px 버튼 영역에 맞는 크기로 렌더링함
  • 상단 사용자 메뉴의 멤버 동기화는 /members/api/member/ 재조회(cache: no-store)로 수행하며 member/members[0] 응답 형태를 모두 처리함
  • 검색 모달은 partials/site/topbar.hbsdata-search-source(posts/tags/authors) 데이터를 사용하고, 결과를 Authors, Tags, Posts 섹션으로 분리해 렌더링함
  • 검색 모달 입력 왼쪽 X 버튼은 입력값 초기화 용도이며, 모달 닫기는 배경 클릭/ESC로 처리함
  • 검색 모달 입력의 브라우저 기본 우측 cancel 버튼은 숨김 처리하고, search-result__excerpt는 한 줄 말줄임으로 고정함
  • 전역 ol, ul, menu 기본 패딩과 리스트 스타일 리셋 적용
  • author.hbs는 페이지 컨텍스트의 작성자 데이터를 직접 사용
  • 작성자 프로필 이미지는 우측 사이드바, 좌측 작성자 목록, 작성자 아카이브, 검색 데이터 소스에서 img_url ... absolute="true" 기준으로 렌더링해 포스트 상세처럼 경로가 깊은 URL에서도 동일한 이미지 주소를 사용함
  • page-tags.hbsslug=tags 페이지에 연결 가능
  • 태그/작성자 디렉터리 목록은 현재 limit="100" 기준
  • tags-index.hbs는 Ghost routes.yaml 커스텀 라우트로 /tags/에 연결됨
  • 로컬 개발 환경의 실제 라우트 설정은 .docker/ghost/content/settings/routes.yaml을 기준으로 사용함
  • 홈 메인 피드는 히어로, Featured 수평 슬라이드, Latest 리스트 구성을 사용함
  • 홈 Hero는 @site.cover_image가 있을 때만 커버 이미지 영역으로 노출하며, 텍스트/구독 폼은 렌더링하지 않음
  • 홈 Hero 커버는 이미지 로딩 완료 전까지 스켈레톤(shimmer) 애니메이션을 표시하고, 로드 후 실제 이미지로 페이드 전환함
  • 홈 Latest 블록 아래에는 home-categories partial로 태그별 섹션을 두며, 좌측 사이드바와 동일한 data-category-priority-order·data-category-priority-limit(10)로 정렬·개수 제한 후 태그당 최신 글 최대 5개를 번호 링크로만 표시함. 세로 액센트는 태그 accent_color--color-accent에 넣고 assets/styles/tailwind.css.home-categories__row에서 border-left: 3px solid var(--color-accent)로 표시한다(미설정 시 중립색). 설명이 없으면 빈 칸으로 두며, 좌·우 열은 minmax(0,2fr)/minmax(0,3fr) 그리드로 고정한다
  • 태그·작성자 아카이브(tag.hbs, author.hbs)는 홈과 동일한 post-feed를 쓰지 않고, post-feed-archive로 글 목록과 페이지네이션만 노출함
  • 우측 사이드바 Recommended 섹션은 Ghost recommendations 데이터를 우선 사용하며, 항목별 외부 링크와 favicon 표시를 지원함
  • 포스트 상세 우측 Read nextprimary_tag 기준 관련 글을 우선 노출하고, 관련 글이 없으면 최신 글(현재 글 제외)로 대체함
  • Recommendations Portal 모달의 제목/설명은 트리거 버튼의 data-portal-title, data-portal-description 값으로 오픈 시점에 동기화함
  • 리스트형 post-card는 Tailwind 유틸리티 중심 마크업으로 구성되며, 썸네일은 aspect-square sm:aspect-video 비율을 사용
  • post-items 카드 본문(post-card-content)은 요약 문단이 실제 텍스트 높이만 차지하며(flex-1·고정 min-h 없음), 요약이 있을 때만 메타 줄에 mt-auto를 주어 이미지와 높이를 맞출 때 생기던 요약 블록 내부 빈 여백을 줄임. 요약이 없으면 요약 노드를 렌더하지 않음
  • 각 카드 항목은 border-b border-brd 구분선을 유지하고, 콘텐츠 래퍼는 min-w-0 기준으로 줄바꿈 폭을 제어
  • 포스트 상세 헤더는 제목, 메타, 공유 버튼, 대표 이미지를 Tailwind 유틸리티 중심 마크업으로 구성하고 상단 단일 태그 라벨은 표시하지 않음
  • 포스트 상세/목록 공유 버튼(data-post-share-toggle)은 각 글의 data-share-title/description/image/url 메타데이터를 공통 공유 모달(data-share-modal)에 전달해 프리뷰 카드와 공유 액션(X, 주소 복사)을 렌더링함. 모달 닫기(배경/버튼/ESC)와 body scroll lock을 지원하며, 주소 복사 성공 시 버튼은 잠깐 검정 배경/흰 텍스트 상태로 바뀜
  • 포스트 본문은 prose prose-theme 클래스를 사용하며, Typography 플러그인 대신 Tailwind 입력 파일에서 원본 기준 타이포그래피 규칙을 직접 제공함
  • 포스트 댓글 영역은 comments 활성 여부를 우선 기준으로 노출하며, 활성 시 로그인 멤버는 댓글 0개 상태에서도 {{comments}} 입력 UI를 사용함
  • 본문 ul, ol은 전역 리스트 리셋과 별개로 prose 범위 안에서 실제 마커와 들여쓰기를 다시 적용함
  • 태그 배지는 --color-accent 기반 배경 혼합색(bg-accent/10, hover:bg-accent/5)을 사용함
  • 홈 Latest, 기본 index, 태그 아카이브, 작성자 아카이브의 목록 영역은 Load More 버튼 기반 확장형 페이지네이션을 사용함
  • bodytag-hash-ld가 있는 페이지는 좌/우 사이드바를 숨기고, .site-shell을 단일 블록(최대 폭 720px)으로 전환함
  • tag-hash-ld 페이지에서는 topbar도 숨겨 랜딩 본문만 노출함
  • tag-hash-ld 페이지에서는 .post-header를 숨기고 페이지 본문만 노출함

주요 스타일 방향

  • 밝은 크림톤 배경 + 오렌지 포인트
  • 테두리 중심의 미니멀 편집형 UI
  • 데스크톱 3열, 태블릿 2열, 모바일 1열 반응형
  • Tailwind는 점진적으로 도입하고, 기존 구조 클래스와 병행 사용