Skip to content

Commit 71d3bc0

Browse files
authored
Merge pull request #464 from decodedcorp/dev
chore(release): merge dev → main (magazine admin #462)
2 parents bed52cc + 43a2e6a commit 71d3bc0

3 files changed

Lines changed: 73 additions & 33 deletions

File tree

packages/ai-server/src/editorial_article/nodes/generate_thumbnail.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""generate_thumbnail node — gpt-image-2 magazine-style 2:3 thumbnail.
22
3-
source post 1장 + 한글 title overlay → OpenAI gpt-image-1 edit → R2 업로드.
4-
nano-banana 는 한글 text rendering 약해서 이번 노드에서는 OpenAI 사용 (#429).
3+
source post 1장 + English title overlay → OpenAI gpt-image-1 edit → R2 업로드.
4+
nano-banana 는 text rendering 약해서 이번 노드에서는 OpenAI 사용 (#429).
55
66
흐름:
77
1. layout 의 첫 curation_card image_url 다운로드
@@ -34,26 +34,28 @@
3434

3535

3636
def _build_prompt(title: str, subtitle: Optional[str]) -> str: # noqa: ARG001
37-
return f"""Transform this photograph into a Korean fashion magazine Instagram-style thumbnail
37+
return f"""Transform this photograph into an English fashion magazine Instagram-style thumbnail
3838
(2:3 portrait, 1024x1536).
3939
4040
KEEP the subject (person, pose, outfit) recognizable from the source photo.
4141
4242
ADD design treatment over the photograph:
4343
44-
1. KOREAN TITLE TEXT OVERLAY at bottom-left:
44+
1. ENGLISH TITLE TEXT OVERLAY at bottom-left:
4545
"{title}"
4646
4747
Typography:
48-
- Bold sans-serif Korean (Pretendard Bold / Noto Sans CJK Bold style)
48+
- Bold sans-serif English (Inter Bold / Helvetica Neue Bold / Söhne Bold style)
4949
- WHITE color, large readable thumbnail size
50-
- Break into 2-3 lines at natural Korean phrase boundaries (commas, particles)
50+
- Break into 2-3 lines at natural English phrase boundaries
51+
(commas, prepositions, conjunctions)
52+
- Use Title Case or ALL CAPS — pick one and stay consistent
5153
- Position in lower-left third with proper margin from image edge
5254
5355
2. "DECODED MAG" wordmark in TOP-RIGHT corner — REQUIRED:
5456
- Color: bright lime green (#eafd67) — the brand magazine accent color
55-
- Bold sans-serif uppercase (modern editorial typography — think Pretendard /
56-
Inter / Helvetica Bold)
57+
- Bold sans-serif uppercase (modern editorial typography — Inter Bold /
58+
Helvetica Neue Bold)
5759
- Small but readable size — magazine masthead style
5860
- Position: top-right with proper margin (matches title margin on bottom-left)
5961
- Render text PERFECTLY — exactly "DECODED MAG" (uppercase, with single space)
@@ -63,13 +65,13 @@ def _build_prompt(title: str, subtitle: Optional[str]) -> str: # noqa: ARG001
6365
4. If text legibility needs help, add a subtle dark gradient ONLY in the text area (lower-left).
6466
6567
CRITICAL:
66-
- Render the Korean text PERFECTLY — no typos, no character substitutions
68+
- Render the English text PERFECTLY — no typos, no character substitutions
6769
- 2:3 portrait (1024x1536) strictly
6870
- Subject must remain visible behind/around text overlay
6971
70-
Style reference: 053 Magazine, W Korea, Vogue Korea Instagram covers.
72+
Style reference: i-D, Dazed, Highsnobiety, AnOther Magazine Instagram covers.
7173
72-
Output: the photograph with Korean text overlay applied."""
74+
Output: the photograph with English text overlay applied."""
7375

7476

7577
def _pick_source_url(layout: MagazineLayout) -> Optional[str]:

packages/ai-server/src/editorial_article/prompts.py

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -36,38 +36,45 @@ def build_compose_layout_prompt(ctx: RecommendationContext) -> str:
3636
posts_json = json.dumps(posts_payload, ensure_ascii=False, indent=2)
3737
keywords_str = ", ".join(ctx.keywords) if ctx.keywords else ""
3838

39-
return f"""너는 Decoded 매거진의 시니어 에디터다.
40-
아래 angle source posts 를 바탕으로 **Hypebeast TAGGED 스타일** 의
41-
멀티 소스 매거진 기사 layout 을 작성해라.
39+
return f"""You are the senior editor of Decoded magazine.
40+
Based on the angle and source posts below, write a multi-source magazine
41+
article layout in the **Hypebeast TAGGED style** — but in English.
4242
4343
[Angle]
4444
title: {ctx.angle_title}
4545
description: {ctx.angle_description or ''}
4646
rationale: {ctx.rationale or ''}
4747
keywords: {keywords_str}
4848
49-
[Source posts (post_id 와 솔루션)]
49+
[Source posts (post_id and solutions)]
5050
{posts_json}
5151
52-
요구사항:
53-
- title: angle_title 을 다듬은 매거진 제목 (한국어, TAGGED 톤).
54-
- subtitle: 한 문장 부제.
55-
- hero_image_url: null. (#429 — 매거진 본문에 hero banner 안 씀, OG 메타 등은
56-
thumbnail_url 사용. LLM 은 hero_image_url 채우지 마라.)
57-
- sections: 다음 순서로 구성. **hero 섹션 만들지 마라** — title/subtitle 은 layout
58-
의 최상위 필드에서 이미 표시됨.
59-
1. intro (200-300자 도입 카피, 이 angle 이 왜 지금 의미있는지)
60-
2. curation_card N개 — source post 마다 1개. body 에 100-200자 카피, post_id /
61-
image_url / solutions (그 post 의 솔루션 카드들) 포함.
62-
3. (선택) spotlight 1개 — 가장 강조하고 싶은 솔루션 / 브랜드.
63-
4. closing (100-150자 마무리 카피)
64-
- 모든 post_id / solution_id 는 입력에 등장한 것만 사용. 새 id 만들지 마라.
65-
- solutions 배열에는 input solution 의 **original_url / affiliate_url 그대로
66-
복사** (있으면). 사용자가 상품 페이지로 바로 갈 수 있어야 함. URL 변형 X.
67-
- "Hypebeast" / "Tagged" 라는 단어는 출력에 절대 포함 금지. Decoded 로 표기.
68-
- 카피는 한국어, 자연스럽고 트렌디한 매거진 톤.
52+
Requirements:
53+
- title: a refined English magazine headline derived from angle_title (TAGGED
54+
editorial tone — punchy, trend-aware, no clickbait).
55+
- subtitle: one English sentence.
56+
- hero_image_url: null. (#429 — the magazine body does not use a hero banner;
57+
OG/share use thumbnail_url. Do NOT fill hero_image_url.)
58+
- sections: in this order. **Do NOT create a hero section** — title/subtitle
59+
are already rendered from the layout's top-level fields.
60+
1. intro (200-400 chars of opening copy in English — why this angle matters
61+
right now)
62+
2. curation_card × N — one per source post. body is 100-250 chars of English
63+
copy. Include post_id / image_url / solutions (the solution cards for
64+
that post).
65+
3. (optional) spotlight × 1 — the single solution / brand most worth
66+
highlighting.
67+
4. closing (100-200 chars of English closing copy)
68+
- Use only post_id / solution_id values present in the input. Never invent ids.
69+
- In the solutions array, copy the input solution's **original_url /
70+
affiliate_url verbatim** when present, so the reader can jump straight to
71+
the product page. Do not modify URLs.
72+
- The words "Hypebeast" / "Tagged" must NEVER appear in output. Brand as
73+
Decoded.
74+
- All copy in English. Natural, on-trend magazine tone — confident, specific,
75+
no filler.
6976
70-
JSON 출력만. MagazineLayout 스키마:
77+
Output JSON only. MagazineLayout schema:
7178
{{"schema_version": "1.0", "title": "...", "subtitle": "...",
7279
"hero_image_url": "...",
7380
"sections": [{{"type": "intro|curation_card|spotlight|closing",

packages/web/app/admin/editorial/magazine/drafts/[id]/page.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,37 @@ function ArticleDetailContent({ id }: { id: string }) {
9191
</div>
9292

9393
<aside className="space-y-4">
94+
<section className="rounded-lg border border-border p-4 space-y-3">
95+
<h2 className="text-sm font-semibold text-foreground">
96+
Thumbnail preview
97+
</h2>
98+
<div className="relative w-full aspect-[4/5] overflow-hidden rounded-md border border-border bg-muted">
99+
{article.thumbnail_url ? (
100+
// eslint-disable-next-line @next/next/no-img-element
101+
<img
102+
src={article.thumbnail_url}
103+
alt={`${article.title || "Untitled"} thumbnail`}
104+
className="absolute inset-0 h-full w-full object-cover"
105+
/>
106+
) : (
107+
<div className="absolute inset-0 flex items-center justify-center text-xs text-muted-foreground text-center px-3">
108+
Not generated yet
109+
</div>
110+
)}
111+
</div>
112+
{article.thumbnail_url && (
113+
<a
114+
href={article.thumbnail_url}
115+
target="_blank"
116+
rel="noopener noreferrer"
117+
className="block text-[11px] text-muted-foreground hover:text-foreground truncate"
118+
title={article.thumbnail_url}
119+
>
120+
Open original ↗
121+
</a>
122+
)}
123+
</section>
124+
94125
<ChatPanel articleId={article.id} />
95126

96127
<section className="rounded-lg border border-border p-4 space-y-3">

0 commit comments

Comments
 (0)