- FacebookAudit: 'facebook.com/...' 형식 데이터에 'https://www.facebook.com/' 가
중복 prepend 되어 'https://www.facebook.com/facebook.com/...' 깨진 URL 생성
- YouTubeAudit: linkedUrls 의 url 이 protocol 없이 그대로 href 에 들어가
상대 경로로 인식되던 버그
- 6개 병원 (view/banobagi/grand/wonjin/ts/irum) 모두 영향
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
profileLink (병원 홈페이지 도메인) 이 우선되어 핸들 클릭 시
인스타그램이 아닌 홈페이지로 이동하던 버그 수정.
5개 병원 (banobagi/grand/wonjin/ts/irum) 모두 영향.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
각 mockPlan_{clinic}.ts에서 ...mockPlan (뷰성형외과) 스프레드를 완전 제거하고,
각 병원의 mockReport_{clinic}.ts 실측 데이터를 근거로 전 섹션 재구성:
- mockPlan_banobagi: 26년·6,853 리뷰·Black+Gold, 8개 채널전략
- mockPlan_grand: 이세환 원장·안면거상 전문·Navy Blue, 6개 채널전략
- mockPlan_wonjin: 35년·코성형·글로벌 3계정·Deep Purple, 6개 채널전략
- mockPlan_ts: 리얼모델·12,509 리뷰·Dark Navy+Crimson, 7개 채널전략
- mockPlan_irum: 다국어 KR/TH/JP·LINE 신규·Forest Green, 8개 채널전략
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- KPIDashboard의 CTA 버튼이 /plan/:id 로만 이동 → 스크롤 위치 불확정
- 수정: /plan/:id#branding-guide 로 해시 포함 이동
- MarketingPlanPage에 useEffect 추가: location.hash 감지 시
sticky Navbar(80px) + ReportNav(48px) = 128px 오프셋 적용하여
해당 섹션 상단이 nav 바로 아래에 정렬되도록 scrollTo
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
세션 내내 추적하던 'opacity 20-30% 흐림' 인상의 진짜 원인:
const isDragging = draggedEntry?.entry.id === entry.id;
→ mock entry에 id가 없어 undefined === undefined → true
→ 모든 entry에 opacity-40 상시 적용됨
수정:
- isDragging: 오브젝트 참조 비교로 전환 (id 의존 제거)
- entry 배경/border: 더 진한 파스텔로 대비 강화
(#F3F0FF → #EDE5FF, border #D5CDF5 → #B8A8E8 등)
- entry 제목: text-slate-700 → font-medium text-[#0A1128]
- 아이콘 opacity-60 제거 (100% 불투명)
- shadow-sm + hover:shadow-lg
- 섹션 dark 테마 복원 (Dark/White 섹션 교차 규칙 유지)
- 일자 셀 bg-slate-50/50 제거, 빈 셀 border 불투명화
6개 병원 데모(view-clinic/banobagi/grand/wonjin/ts/irum) 모두
ContentCalendar 컴포넌트를 공유하므로 한 번에 반영.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 일자 셀 bg-slate-50/50(50% 투명) 제거 → entry 카드가 주간 카드 위 직접 노출
- 빈 셀 border-slate-200/60 → border-slate-200 (불투명)
- entry 카드에 contentTypeColors.shadow 추가 → 색상별 soft glow로 떠있는 느낌
- dark 테마 유지 (ChannelStrategy와 동일한 dark 섹션 + 흰 카드 패턴)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Navbar/ReportNav의 backdrop-blur-lg가 스크롤 시 섹션을 덮는
GPU 합성 블러 레이어를 만들어 콘텐츠 캘린더가 흐려 보임
- bg-white/95 단색으로 교체 (시각적 차이 미미, 블러 부작용 제거)
- 이전 커밋(5f7d58c, aac1367)의 motion/whileInView 제거는
원인이 아니었음 — 조상 nav의 backdrop-filter가 진범
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
framer-motion animate가 프로덕션 빌드에서 완료되지 않는 문제로
SectionWrapper/ContentCalendar의 opacity:0 initial 상태가 유지됨.
motion.div/motion.button/motion.section을 일반 태그로 교체하고
모든 opacity 진입 애니메이션 제거.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SectionWrapper의 motion.section이 opacity:0 initial 상태에서
framer-motion animate가 발동하지 않아 전체 섹션이 투명하게 보이는
문제를 수정. SectionWrapper를 일반 <section>으로 교체하고,
plan 컴포넌트들의 whileInView/viewport 애니메이션 제거.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
전역 CSS h1~h6 { text-primary-900 } 규칙이 부모의 text-white 상속을
덮어쓰는 문제 수정. .text-white 컨테이너 내 모든 heading에
text-white 강제 적용 (통합 권장 사항 등 퍼플 배경 섹션 전체 적용).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
id === 'view-clinic' 체크를 useEffect 최상단으로 이동.
기존에는 location.state에 이전 분석 데이터가 남아있으면
transformApiReport를 통해 엉뚱한 병원 데이터가 렌더링되는 버그 수정.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- otherChannels 모든 URL에 https:// prefix 추가 (카카오톡, 네이버 블로그/플레이스, 강남언니, 네이버 카페, Threads, Facebook TH)
- 강남언니 URL https://www.gangnamunni.com/hospitals/189 로 수정
- 닥터나우 URL https://www.doctornow.co.kr 추가
- Playwright로 7개 채널 실제 스크린샷 캡처 (YouTube, Instagram KR/EN, Facebook KR, 강남언니, 웹사이트, 네이버 블로그)
- screenshots 배열 SVG placeholder → 실제 PNG 파일 경로로 업데이트
- capturedAt 날짜 2026-04-13으로 업데이트
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- websiteAudit: snsLinksOnSite false→true, Footer SNS 5개 링크 상세 추가
(Blog, Facebook, Instagram, YouTube, Naver Cafe)
- Website 점수 52→65 상향, tracking 6개로 보강
- 네이버 카페 "뷰성형외과 성형의 모든것" 회원 5,984명 otherChannels 추가
- mockPlan: Naver Cafe 채널 전략 추가 (20개 게시판 구조 기반)
- WebsiteAudit 타입에 snsLinksDetail 옵셔널 필드 추가
- problemDiagnosis SNS 단절 진단 수정 (Footer 있으나 Header에는 없음)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 9개 채널 실제 데이터 수집 (Firecrawl + Chrome MCP)
- mockReport.ts: 강남언니 9.5점/19,030리뷰 (TODO 해결), 채널 점수 갱신,
Instagram 70K/14K 실제 수치, Facebook TH 페이지 발견, Naver Blog 활성화
- mockPlan.ts: Naver Blog 미확인→활성 550개, YouTube 104K 반영
- useReport: id='view-clinic' demo fallback 추가
- useMarketingPlan: id='view-clinic' demo fallback 추가
- Viewclinic Plan.md: 수집 데이터 전체 기록
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- planning 단계 'AI 콘텐츠 전략 생성 중...' → 'Generating AI content strategy...'
- labelDone '콘텐츠 플랜 생성 완료' → 'Content plan generated'
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- collect-channel-data: naverBlog 실시간 검색 제거 → verified handle 기반 RSS 직접 fetch
- collect-channel-data: naverPlace DB-first 패턴 (verified_channels에 저장된 데이터 우선 사용, 없을 때만 URL도메인 매칭 검색 후 DB에 저장)
- transformReport: ch.issues 배열 항목이 {issue, severity} 객체일 때 JSON.stringify 대신 .issue 문자열 추출
- ProblemDiagnosis: Lucide 아이콘 제거 → FilledIcons(ShieldFilled, FileTextFilled, LinkExternalFilled), 항목 구분자 ' ' → ' — '
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ContentCalendar: 드래그앤드롭(주차 내 요일 간 이동) + 엔트리 추가 버튼 + iCal Export
- BrandingGuide: 색상 팔레트 인라인 편집(스와치 클릭 → hex 팝오버) + DO/DON'T 2컬럼
- WorkflowTracker: 콘텐츠 제작 파이프라인(기획→AI초안→검토→승인→배포), 동영상/이미지+텍스트 분류
- RepurposingProposal: YouTube 인기 영상 리퍼포징 제안 아코디언 섹션
- AssetDetailModal: 에셋 카드 클릭 시 상세 모달
- 디자인 시스템 감사: Lucide 라인 아이콘 제거, 원색(pink/indigo/purple) 제거, 이모지 UI 제거
- "My Assets" → "나의 소재" 일관성 변경
- FilledIcons: DownloadFilled, RocketFilled 추가
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- collect-channel-data: gangnamUnni scraping no longer requires
verified=true. Fallback: Firecrawl search for gangnamunni.com URL
when discover-channels failed to verify. Solves empty ratings/reviews.
- generate-report: Perplexity prompt now explicitly requests leadDoctor
(name, specialty, rating, reviewCount) and staffCount in clinicInfo.
- transformReport: clinicInfo type extended with leadDoctor + staffCount;
transformation prefers clinic.leadDoctor over doctors[0] fallback.
Root cause: clinic_registry table not yet in DB → discover-channels
always falls back to API search → gangnamUnni URL not found →
collect-channel-data skips gangnamUnni → all clinic metrics empty.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each analysis run now creates a dedicated folder in Supabase Storage:
clinics/{domain}/{reportId}/
├── scrape_data.json (discover-channels: website scrape + Perplexity)
├── channel_data.json (collect-channel-data: all channel API results)
└── report.json (generate-report: final AI-generated report)
Screenshots also moved from {reportId}/{id}.png to:
clinics/{domain}/{reportId}/screenshots/{id}.png
Migration: 20260407_clinic_data_storage.sql creates 'clinic-data' bucket
(private, 10MB/file, JSON only). All writes are non-fatal — pipeline
continues even if Storage upload fails.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Hero button: gray when empty, accent gradient when URL entered
- generate-report: force-inject gangnamUnniStats from Vision Analysis
into channelAnalysis (score, rating, reviews, doctors)
- Add gangnamunni Vision data to prompt context
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- All fetch calls to Supabase Edge Functions now include
Authorization: Bearer <anon_key> (was missing → 401 errors)
- Fix Firecrawl screenshot API: remove invalid screenshotOptions,
use "screenshot@fullPage" format (v2 API compatibility)
- Fix screenshot response handling: v2 returns URL not base64,
now downloads and converts to base64 for Gemini Vision
- Add about page to Vision Analysis capture targets
- Add retry utility, channel error tracking, pipeline resume,
enrichment retry, EmptyState improvements (Sprint 2-3)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
WP-1: YouTube channel ID regex {20,} → {22} (exactly 24 chars)
WP-2: Naver Place category filtering in enrich-channels (성형/피부)
WP-3: Google Maps stores mapsUrl separately from clinicWebsite
WP-4: Naver Blog separates officialBlogUrl from search results
WP-5: 강남언니 rawRating + normalized rating (≤5 → ×2), Firecrawl
prompt explicitly states "out of 10, NOT out of 5"
WP-6: Perplexity model centralized in _shared/config.ts (env override)
WP-7: Apify Instagram timeout 30s → 45s
Frontend: transformReport uses mapsUrl and officialBlogUrl when available
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Google Maps: was using gm.website (clinic's own site) → now always
generates maps.google.com/search URL
Naver Blog: was linking to first search result post (random personal
blog) → now links to Naver blog search results page
Naver Place: np.link was the clinic's own website, not Naver Place →
now generates map.naver.com search URL. Also fixed collect-channel-data
to search with "성형외과" suffix and match by category (성형/피부) to
avoid same-name dental clinics.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Facebook pageName now links to facebook.com/{url} with ExternalLink icon.
OtherChannels: moved ExternalLink from right-end to inline with channel
name, matching the Instagram/YouTube pattern.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
staffCount is the number of registered doctors from 강남언니, not total
staff. Label changed from 의료진(medical staff) to 전문의(specialists)
to accurately reflect the data source. Diagnosis message also updated.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
YouTubeAudit: handle links to youtube.com/@{handle} with ExternalLink icon
InstagramAudit: handle links to instagram.com/{handle} with ExternalLink icon
ClinicSnapshot: domain is now clickable link, phone is tel: link
OtherChannels: Google Maps generates search URL, Naver Blog links to
first blog post or search results (previously empty string)
transformReport: fills missing URL fields for Google Maps and Naver Blog
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Halved blob movement (30px→15px, 8vw→4vw) and reduced scale
(1.1→1.05). Using translate3d forces GPU compositing layer,
preventing main-thread layout recalculation that causes jitter.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Added will-change:transform, contain:layout style, and
backface-visibility:hidden to all blob animations. This promotes
blobs to their own GPU compositing layer, preventing them from
triggering main-thread reflow/repaint that causes page shaking.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Animated blobs with translate+scale overflow their containers,
causing horizontal scrollbar to flicker and page to jitter.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Uses scrollbar-width:thin + 6px webkit scrollbar to minimize
layout shift from the default ~15px scrollbar. Keeps original
design intact while reducing visual asymmetry.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reverts to the original design with full-color button (no disabled
opacity), original background gradients, and original blob decorations.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All layout changes (blob modifications, overflow-x/clip, scrollbar-gutter)
reverted to the original version that was working correctly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Removes scrollbar-gutter:stable which pushed content left.
overlay scrollbar floats over content with zero layout impact.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Modules.tsx: wrap blobs in overflow-clip container, use max-w instead
of min-w to prevent viewport overflow
- index.css: add #root { overflow-x:clip; max-width:100vw } as final
safety net — no child element can expand beyond viewport
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>