From d5e9b87e3f4a0e800560940f49610c4b6334b548 Mon Sep 17 00:00:00 2001 From: Mina Choi Date: Thu, 3 Sep 2026 10:45:38 +0900 Subject: [PATCH] =?UTF-8?q?[feat]=20solution/frontend:=20=ED=9E=88?= =?UTF-8?q?=EC=96=B4=EB=A1=9C=20=EC=A0=9C=EB=AA=A9=EC=9D=98=20=EC=95=9E?= =?UTF-8?q?=EB=A7=90=EC=9D=B4=20=EB=8F=88=EB=8B=A4=20=E2=80=94=20'?= =?UTF-8?q?=ED=99=88=ED=8E=98=EC=9D=B4=EC=A7=80'=20=EB=8A=94=20=EA=B3=A0?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "SEO · AEO 되는 웹사이트" 는 규격 이름이지 문구가 아니었다. 아임웹처럼 [형용사절] + [명사] 구조로 바꾸고, 명사를 고정한 채 앞말만 갈아 끼운다. - AI가 먼저 찾는 / 챗GPT가 인용하는 / 검색에 바로 걸리는 / 손님이 먼저 만나는 - CSS 만으로 돈다(마퀴와 같은 이유 — 타이머는 백그라운드 탭에서 밀린다) - 문구를 다섯 줄 쌓고 마지막을 첫 줄의 복제로 둔다. -80% 에서 0% 로 되감을 때 글자가 안 튄다 - 줄 높이를 1.25em 으로 못 박는다 — 창 1줄 · 트랙 5줄이라 한 칸이 정확히 20% 여야 한다 - 복제분은 aria-hidden. SEO·AEO 는 제목에서 빼 보조 문구로 내렸다 tsc·eslint·vite build 통과 --- solution/frontend/src/index.css | 28 +++++++++++++++++++++ solution/frontend/src/pages/LandingPage.tsx | 28 +++++++++++++++------ 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/solution/frontend/src/index.css b/solution/frontend/src/index.css index 24e9b47..7409395 100644 --- a/solution/frontend/src/index.css +++ b/solution/frontend/src/index.css @@ -76,6 +76,34 @@ body { } } +/* 히어로 제목의 앞말만 갈아 끼운다 — '홈페이지' 는 고정이고 수식어가 돈다. + ★ CSS 만으로 돈다(마퀴와 같은 이유). 그리고 **문구를 다섯 줄 쌓는다** — 마지막 줄이 + 첫 줄의 복제라 -80% 에서 0% 로 되감을 때 글자가 튀지 않는다. + ★ 줄 높이를 1.25em 으로 못 박는다. 창이 1줄이고 트랙이 5줄이라 한 칸이 정확히 20% 여야 한다. */ +@keyframes o2o-rotate-5 { + 0%, 18% { transform: translateY(0); } + 20%, 38% { transform: translateY(-20%); } + 40%, 58% { transform: translateY(-40%); } + 60%, 78% { transform: translateY(-60%); } + 80%, 100% { transform: translateY(-80%); } +} +.o2o-rotator { + display: block; + height: 1.25em; + overflow: hidden; +} +.o2o-rotator-track { + animation: o2o-rotate-5 11s cubic-bezier(0.65, 0, 0.35, 1) infinite; +} +.o2o-rotator-track > span { + display: block; + height: 1.25em; + line-height: 1.25; +} +@media (prefers-reduced-motion: reduce) { + .o2o-rotator-track { animation: none; } +} + /* 랜딩 히어로의 발행 사이트 마퀴. **CSS 만으로 돈다** — 타이머를 쓰면 탭이 백그라운드일 때 프레임이 밀려 끊긴 것처럼 보인다. 트랙에 같은 목록을 두 벌 넣고 -50% 까지 밀면 이음매가 없다. */ @keyframes o2o-marquee { diff --git a/solution/frontend/src/pages/LandingPage.tsx b/solution/frontend/src/pages/LandingPage.tsx index 2c48bce..806408d 100644 --- a/solution/frontend/src/pages/LandingPage.tsx +++ b/solution/frontend/src/pages/LandingPage.tsx @@ -6,6 +6,12 @@ import {MarketingShell, Section, SectionHead} from '@/components/layout/Marketin import {ShowcaseGrid, ShowcasePeeks} from '@/features/marketing/ShowcaseGrid'; import {Button} from '@/components/ui/button'; +/** + * 히어로 제목의 앞말. '홈페이지' 는 고정이고 이 넷이 돌아간다. + * ★ 넷을 넘기지 않는다 — 다섯째부터는 한 바퀴 도는 데 걸리는 시간이 체류 시간을 넘긴다. + */ +const HEADLINES = ['AI가 먼저 찾는', '챗GPT가 인용하는', '검색에 바로 걸리는', '손님이 먼저 만나는']; + const INDUSTRIES: {id: IndustryType; label: string; icon: typeof Building2}[] = [ {id: 'stay', label: '숙박', icon: Building2}, {id: 'cafe', label: '카페', icon: Coffee}, @@ -43,13 +49,21 @@ export function LandingPage() { {/* ── 상단 ─────────────────────────────────────── */}
-

- SEO · AEO 되는 -
- 웹사이트 +

+ {/* 앞말만 돈다. 마지막 항목은 첫 항목의 복제다 — 되감을 때 글자가 튀지 않게(index.css). */} + + + {[...HEADLINES, HEADLINES[0]].map((line, index) => ( + 0}> + {line} + + ))} + + + 홈페이지

- 가게 이름 한 줄이면 만들어 드립니다 + 가게 이름 한 줄로 시작해 보세요

@@ -87,9 +101,9 @@ export function LandingPage() {
    {[ + 'SEO · AEO 자동 적용', '가입 없이 만들어 봅니다', - '검색엔진에 바로 알립니다', - 'AI가 읽는 형태로 나갑니다', + '5분이면 끝납니다', ].map((line) => (