tech blog

Engineering a Winning Pitch: Building an Interactive Deck with Next.js 16

Beauty Insight Editor

🇰🇷 Key Takeaways (요약)

현대적인 피칭을 위한 기술적 도전과 성취:

  1. Web-based Interactive Deck: 정적인 PDF를 넘어, URL 공유만으로 즉시 접근 가능한 반응형 웹 슬라이드를 구축했습니다. (Next.js 16 + Embla Carousel)
  2. Context-Aware Mobile UX: 데스크탑에서는 가로형 캐러셀, 모바일에서는 "랜딩 페이지" 스타일의 세로 스크롤로 자동 전환되는 적응형 UI를 구현했습니다.
  3. Data Storytelling: Recharts를 활용해 복잡한 K-Beauty 시장 데이터를 직관적인 애니메이션 차트로 시각화했습니다.
  4. Detail-Oriented Engineering: 'Soft Break' 문제 해결부터 SEO 최적화, 다크 모드 툴팁까지, 디테일한 사용자 경험(UX)을 놓치지 않았습니다.

1. Introduction: Beyond the PDF

In the fast-paced world of startup pitching, the medium is often as important as the message. We faced a critical question: "How can we effectively communicate our data-driven K-Beauty solution to global partners like L'Oréal?"

Traditional PDFs are static and lifeless. They fail to convey the dynamic nature of our AI-powered insights.

We decided to build a "Living Pitch Deck"—a web application that feels like a premium presentation but behaves like a modern app. This post details how we engineered this experience using the latest web technologies.

2. Why we chose Next.js 16 for our Pitch Deck?

The choice of technology was strategic. We needed speed, SEO visibility, and seamless interactivity.

FeaturePDF / PPTNext.js 16 Web Deck
AccessibilityRequires downloadInstant Link Access
ResponsivenessStatic (Pinch to zoom)100% Mobile Optimized
UpdatesResend fileReal-time Deploy
AnalyticsNoneFull GA4 Tracking

Using Next.js 16 (App Router) allowed us to leverage Server Components for initial load speed while using Client Components for rich interactions like charts and carousels.

3. Solving the "Mobile Context" Problem

Pitch decks are often reviewed on the go—in taxis, waiting rooms, or between meetings. A horizontal slide layout works on a laptop but is a nightmare on a phone.

We implemented a "Hybrid Layout Strategy":

  • Desktop (>768px): Horizontal Carousel (Embla) with keyboard & mouse wheel navigation.
  • Mobile (<768px): Vertical "Landing Page" Scroll for natural reading flow.
// components/pitch-deck/PitchDeckContainer.tsx
export default function PitchDeckContainer() {
    const isMobile = useMediaQuery('(max-width: 768px)');
 
    if (isMobile) {
        // Render as a vertical scrollable list
        return (
            <div className="flex flex-col w-full min-h-screen bg-white">
                {SLIDE_DATA.map((slide) => (
                    <SlideComponent key={slide.id} data={slide} />
                ))}
            </div>
        );
    }
 
    // Render as an interactive carousel for desktop
    return (
        <div className="embla" ref={emblaRef}>
            {/* Carousel Logic */}
        </div>
    );
}

This ensures that no matter where the investor is, they get the best possible reading experience.

4. How to make data memorable with Recharts?

"Data is boring unless it tells a story."

For 'Beauty Insight Lab', our core value is data. We needed to show, not just tell, how much time and money our AI saves. We used Recharts to bring static numbers to life.

Dynamic Interaction

We added entry animations (animationDuration={2000}) and custom tooltips that react to user hover. This makes the data feel "alive."

// components/pitch-deck/slides/Slide5_Traction.tsx
<BarChart data={data} layout="vertical">
    <Tooltip 
        cursor={{ fill: 'transparent' }} 
        contentStyle={{ borderRadius: '10px', borderColor: '#eee' }}
        formatter={(value: any) => [`${value} Days`, 'Duration']}
    />
    <Bar 
        dataKey="time" 
        data={data}
        isAnimationActive={true}
        animationDuration={2000} // Smooth entry animation
    >
        {data.map((entry, index) => (
             <Cell key={`cell-${index}`} fill={entry.fill} />
        ))}
    </Bar>
</BarChart>

The result? A chart that visually demonstrates reducing a process from 30 days to 1 day in a way that sticks in the viewer's mind.

5. Overcoming Technical Hurdles (Q&A)

Q: "Markdown text was merging into one line. How did you fix it?"

We encountered an issue where Markdown "Soft Breaks" (single newlines) were being ignored by the browser, rendering distinct lines as a single paragraph.

Solution:
We utilized Tailwind CSS's whitespace-pre-wrap class on the container to force the browser to respect newline characters from the source. We also ensured the remark-breaks plugin was correctly configured in our MDX pipeline.

Q: "We saw 'Duplicate Key' errors in the Table of Contents. Why?"

Our extractHeadings helper was generating IDs simply by slugifying text. When multiple headers had the same text (e.g., "Overview"), it created duplicate IDs, causing React reconciliation errors.

Fix:
We implemented a frequency map to append a counter to duplicate IDs (e.g., overview, overview-1), ensuring every DOM element has a unique identity.

// Helper logic in page.tsx
if (idMap.has(id)) {
    const count = idMap.get(id)! + 1;
    idMap.set(id, count);
    id = `${id}-${count}`; // Make unique
}

6. Refactoring for "Beauty Insight Lab"

Branding consistency is key. We performed a comprehensive codebase refactor to remove legacy benchmarking references and unify everything under our own identity, Beauty Insight Lab.

This wasn't just a find-and-replace job; it involved updating asset paths, UI badges, and even PDF filename logic to ensure a seamless, professional brand experience.


This project is part of our journey to expand K-Beauty globally using AI.

We are building more than just a deck; we are building the infrastructure for the future of beauty exports.

Interested in our technology? Check out our Technical Blog.