Skip to main content

Landing Page Redesign Implementation Plan

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: Redesign docs.volr.io landing page with a prominent npx volr command, Claude Code skills showcase, and terminal typing animation demo.

Architecture: Three new React components (NpxCommand, SkillsSection, TerminalDemo) added to the existing Docusaurus homepage. All use Framer Motion (already installed) for animations and CSS Modules for styling. The existing hero is restructured with new copy and the npx command box. Existing doc cards section is preserved at the bottom.

Tech Stack: React 18, Docusaurus 3, Framer Motion 11, lucide-react, CSS Modules, Tailwind CSS v4


Task 1: Create NpxCommand component

Files:

  • Create: src/components/NpxCommand/NpxCommand.tsx
  • Create: src/components/NpxCommand/NpxCommand.module.css

Step 1: Create the NpxCommand component

// src/components/NpxCommand/NpxCommand.tsx
import { useState, useCallback } from 'react';
import { Copy, Check } from 'lucide-react';
import styles from './NpxCommand.module.css';

const COMMAND = 'npx volr';

export default function NpxCommand() {
const [copied, setCopied] = useState(false);

const handleCopy = useCallback(async () => {
try {
await navigator.clipboard.writeText(COMMAND);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} catch {
// Fallback for older browsers
const textarea = document.createElement('textarea');
textarea.value = COMMAND;
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}
}, []);

return (
<button className={styles.container} onClick={handleCopy} type="button" aria-label="Copy npx volr command">
<span className={styles.prompt}>$</span>
<span className={styles.command}>{COMMAND}</span>
<span className={styles.copyIcon}>
{copied ? <Check size={16} /> : <Copy size={16} />}
</span>
</button>
);
}

Step 2: Create NpxCommand styles

/* src/components/NpxCommand/NpxCommand.module.css */
.container {
display: inline-flex;
align-items: center;
gap: 0.75rem;
padding: 0.875rem 1.25rem;
background-color: #111827;
border: 1px solid #374151;
border-radius: 0.5rem;
cursor: pointer;
transition: all 0.2s ease;
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;
font-size: 1rem;
line-height: 1;
}

.container:hover {
border-color: #4b5563;
background-color: #1f2937;
}

[data-theme='dark'] .container {
background-color: #0d1117;
border-color: #30363d;
}

[data-theme='dark'] .container:hover {
border-color: #484f58;
background-color: #161b22;
}

.prompt {
color: #6b7280;
user-select: none;
}

.command {
color: #f9fafb;
font-weight: 500;
}

.copyIcon {
display: flex;
align-items: center;
color: #6b7280;
transition: color 0.2s ease;
margin-left: 0.5rem;
}

.container:hover .copyIcon {
color: #9ca3af;
}

Step 3: Verify the component renders

Run: cd /Users/danny/strartups/volr/volr-project/volr-docs && yarn start Expected: Dev server starts without errors

Step 4: Commit

git add src/components/NpxCommand/
git commit -m "feat: add NpxCommand copy-to-clipboard component"

Task 2: Create SkillsSection component

Files:

  • Create: src/components/SkillsSection/SkillsSection.tsx
  • Create: src/components/SkillsSection/SkillsSection.module.css

Step 1: Create SkillsSection component

The skills data comes from the actual volr-skills repo. Each card shows skill name, description, and a copy button for the skill install command.

// src/components/SkillsSection/SkillsSection.tsx
import { useState, useCallback } from 'react';
import { Copy, Check, ShoppingCart, Music, Store, Hotel, Palette } from 'lucide-react';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import styles from './SkillsSection.module.css';

interface Skill {
id: string;
icon: typeof ShoppingCart;
name: { en: string; ko: string };
description: { en: string; ko: string };
}

const skills: Skill[] = [
{
id: 'volr-checkout-base',
icon: ShoppingCart,
name: { en: 'Checkout Base', ko: 'Checkout Base' },
description: {
en: 'Stablecoin payment API setup and integration',
ko: '스테이블코인 결제 API 설정 및 연동',
},
},
{
id: 'volr-fandom',
icon: Music,
name: { en: 'Fandom & K-Culture', ko: 'Fandom & K-Culture' },
description: {
en: 'Fan commerce, tickets, merch, and event payments',
ko: '팬 커머스, 티켓, 굿즈, 이벤트 결제',
},
},
{
id: 'volr-sellers',
icon: Store,
name: { en: 'Global Sellers', ko: 'Global Sellers' },
description: {
en: 'E-commerce and marketplace seller integrations',
ko: '이커머스 및 마켓플레이스 셀러 연동',
},
},
{
id: 'volr-accommodation',
icon: Hotel,
name: { en: 'Accommodation', ko: 'Accommodation' },
description: {
en: 'Hotel, booking, and vacation rental payments',
ko: '호텔, 예약, 숙소 결제',
},
},
{
id: 'volr-creators',
icon: Palette,
name: { en: 'Creator Economy', ko: 'Creator Economy' },
description: {
en: 'Tips, subscriptions, and digital goods payments',
ko: '팁, 구독, 디지털 상품 결제',
},
},
];

const translations = {
en: {
title: 'Built-in AI Skills',
subtitle: 'Install Volr skills in your AI coding agent to accelerate integration',
copied: 'Copied!',
copy: 'Copy install command',
},
ko: {
title: 'Built-in AI Skills',
subtitle: 'AI 코딩 에이전트에 Volr skill을 설치하여 통합을 가속화하세요',
copied: '복사됨!',
copy: '설치 명령어 복사',
},
};

function SkillCard({ skill, locale }: { skill: Skill; locale: 'en' | 'ko' }) {
const [copied, setCopied] = useState(false);
const t = translations[locale];
const Icon = skill.icon;

const handleCopy = useCallback(async () => {
const command = `npx volr skill install ${skill.id}`;
try {
await navigator.clipboard.writeText(command);
} catch {
const textarea = document.createElement('textarea');
textarea.value = command;
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
}
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}, [skill.id]);

return (
<div className={styles.card}>
<div className={styles.cardHeader}>
<div className={styles.iconBox}>
<Icon size={20} />
</div>
<h3 className={styles.cardTitle}>{skill.name[locale]}</h3>
</div>
<p className={styles.cardDescription}>{skill.description[locale]}</p>
<button className={styles.copyButton} onClick={handleCopy} type="button" aria-label={t.copy}>
<code className={styles.commandText}>npx volr skill install {skill.id}</code>
<span className={styles.copyIconWrapper}>
{copied ? <Check size={14} /> : <Copy size={14} />}
</span>
</button>
</div>
);
}

export default function SkillsSection() {
const { i18n } = useDocusaurusContext();
const locale = (i18n.currentLocale as 'en' | 'ko') || 'en';
const t = translations[locale];

return (
<section className={styles.section}>
<h2 className={styles.title}>{t.title}</h2>
<p className={styles.subtitle}>{t.subtitle}</p>
<div className={styles.grid}>
{skills.map((skill) => (
<SkillCard key={skill.id} skill={skill} locale={locale} />
))}
</div>
</section>
);
}

Step 2: Create SkillsSection styles

/* src/components/SkillsSection/SkillsSection.module.css */
.section {
margin-top: 5rem;
margin-bottom: 5rem;
}

.title {
font-size: 1.75rem;
font-weight: 600;
color: var(--ifm-font-color-base);
margin: 0 0 0.75rem 0;
text-align: center;
letter-spacing: -0.01em;
}

@media (min-width: 768px) {
.title {
font-size: 2rem;
}
}

.subtitle {
font-size: 1rem;
color: #6b7280;
text-align: center;
margin: 0 auto 2.5rem;
max-width: 500px;
line-height: 1.6;
}

[data-theme='dark'] .subtitle {
color: #9ca3af;
}

.grid {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
}

@media (min-width: 640px) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
}

@media (min-width: 1024px) {
.grid {
grid-template-columns: repeat(3, 1fr);
}
}

.card {
display: flex;
flex-direction: column;
padding: 1.5rem;
background-color: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 0.75rem;
transition: all 0.2s ease;
}

.card:hover {
border-color: #d1d5db;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
transform: translateY(-2px);
}

[data-theme='dark'] .card {
background-color: #1f2937;
border-color: #374151;
}

[data-theme='dark'] .card:hover {
border-color: #4b5563;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3);
}

.cardHeader {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 0.75rem;
}

.iconBox {
display: flex;
align-items: center;
justify-content: center;
width: 2.5rem;
height: 2.5rem;
color: #276AFF;
background-color: #EDF2FF;
border-radius: 0.5rem;
flex-shrink: 0;
}

[data-theme='dark'] .iconBox {
color: #82A8FF;
background-color: #1A3A6B;
}

.cardTitle {
font-size: 1rem;
font-weight: 600;
color: var(--ifm-font-color-base);
margin: 0;
line-height: 1.4;
}

.cardDescription {
font-size: 0.875rem;
color: #6b7280;
margin: 0 0 1rem 0;
line-height: 1.5;
flex: 1;
}

[data-theme='dark'] .cardDescription {
color: #9ca3af;
}

.copyButton {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 0.75rem;
background-color: #f3f4f6;
border: 1px solid #e5e7eb;
border-radius: 0.375rem;
cursor: pointer;
transition: all 0.15s ease;
width: 100%;
}

.copyButton:hover {
background-color: #e5e7eb;
border-color: #d1d5db;
}

[data-theme='dark'] .copyButton {
background-color: #111827;
border-color: #374151;
}

[data-theme='dark'] .copyButton:hover {
background-color: #1f2937;
border-color: #4b5563;
}

.commandText {
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;
font-size: 0.75rem;
color: #6b7280;
flex: 1;
text-align: left;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
background: none;
border: none;
padding: 0;
}

[data-theme='dark'] .commandText {
color: #9ca3af;
}

.copyIconWrapper {
display: flex;
align-items: center;
color: #9ca3af;
flex-shrink: 0;
}

Step 3: Verify dev server still works

Run: cd /Users/danny/strartups/volr/volr-project/volr-docs && yarn start Expected: No errors

Step 4: Commit

git add src/components/SkillsSection/
git commit -m "feat: add SkillsSection component with copy-to-clipboard commands"

Task 3: Create TerminalDemo component

Files:

  • Create: src/components/TerminalDemo/TerminalDemo.tsx
  • Create: src/components/TerminalDemo/TerminalDemo.module.css

Step 1: Create TerminalDemo component

Uses Framer Motion for typing animation and sequential step reveal. Loops infinitely.

// src/components/TerminalDemo/TerminalDemo.tsx
import { useEffect, useState, useRef } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import styles from './TerminalDemo.module.css';

const COMMAND = 'npx volr';
const TYPING_SPEED_MS = 80;
const STEP_DELAY_MS = 600;
const COMPLETION_HOLD_MS = 3000;
const INITIAL_PAUSE_MS = 500;

interface Step {
text: { en: string; ko: string };
}

const steps: Step[] = [
{ text: { en: 'Installing Volr SDK...', ko: 'Volr SDK 설치 중...' } },
{ text: { en: 'Configuring USDC payments...', ko: 'USDC 결제 설정 중...' } },
{ text: { en: 'Setting up webhooks...', ko: '웹훅 설정 중...' } },
{ text: { en: 'Generating API keys...', ko: 'API 키 생성 중...' } },
];

const completionText = {
en: {
line1: 'Stablecoin payments ready!',
line2: 'Run `npm run dev` to test your integration',
},
ko: {
line1: '스테이블코인 결제 준비 완료!',
line2: '`npm run dev`로 통합을 테스트하세요',
},
};

type Phase = 'idle' | 'typing' | 'steps' | 'complete';

export default function TerminalDemo() {
const { i18n } = useDocusaurusContext();
const locale = (i18n.currentLocale as 'en' | 'ko') || 'en';

const [phase, setPhase] = useState<Phase>('idle');
const [typedChars, setTypedChars] = useState(0);
const [visibleSteps, setVisibleSteps] = useState(0);
const timeoutRef = useRef<ReturnType<typeof setTimeout>>();

// Reset and restart loop
const resetAndStart = () => {
setPhase('idle');
setTypedChars(0);
setVisibleSteps(0);
};

// Phase: idle -> typing
useEffect(() => {
if (phase !== 'idle') return;
timeoutRef.current = setTimeout(() => setPhase('typing'), INITIAL_PAUSE_MS);
return () => clearTimeout(timeoutRef.current);
}, [phase]);

// Phase: typing characters
useEffect(() => {
if (phase !== 'typing') return;
if (typedChars >= COMMAND.length) {
timeoutRef.current = setTimeout(() => setPhase('steps'), 300);
return () => clearTimeout(timeoutRef.current);
}
timeoutRef.current = setTimeout(
() => setTypedChars((c) => c + 1),
TYPING_SPEED_MS + Math.random() * 40
);
return () => clearTimeout(timeoutRef.current);
}, [phase, typedChars]);

// Phase: showing steps one by one
useEffect(() => {
if (phase !== 'steps') return;
if (visibleSteps >= steps.length) {
timeoutRef.current = setTimeout(() => setPhase('complete'), STEP_DELAY_MS);
return () => clearTimeout(timeoutRef.current);
}
timeoutRef.current = setTimeout(
() => setVisibleSteps((s) => s + 1),
STEP_DELAY_MS
);
return () => clearTimeout(timeoutRef.current);
}, [phase, visibleSteps]);

// Phase: complete, hold then restart
useEffect(() => {
if (phase !== 'complete') return;
timeoutRef.current = setTimeout(resetAndStart, COMPLETION_HOLD_MS);
return () => clearTimeout(timeoutRef.current);
}, [phase]);

const t = completionText[locale];

return (
<section className={styles.section}>
<h2 className={styles.sectionTitle}>
{locale === 'ko' ? '이렇게 쉽습니다' : 'See How Easy It Is'}
</h2>
<div className={styles.terminalWrapper}>
<div className={styles.terminal}>
{/* Title bar */}
<div className={styles.titleBar}>
<div className={styles.dots}>
<span className={styles.dotRed} />
<span className={styles.dotYellow} />
<span className={styles.dotGreen} />
</div>
<span className={styles.titleText}>Terminal</span>
<div className={styles.dotsPlaceholder} />
</div>

{/* Terminal body */}
<div className={styles.body}>
{/* Command line */}
<div className={styles.line}>
<span className={styles.promptSymbol}>~/my-app $</span>{' '}
<span className={styles.commandText}>
{COMMAND.slice(0, typedChars)}
</span>
{phase === 'idle' || phase === 'typing' ? (
<span className={styles.cursor} />
) : null}
</div>

{/* Steps */}
{phase !== 'idle' && phase !== 'typing' && (
<div className={styles.stepsContainer}>
{steps.slice(0, visibleSteps).map((step, i) => (
<motion.div
key={i}
className={styles.line}
initial={{ opacity: 0, x: -4 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.2 }}
>
<span className={styles.checkmark}></span>{' '}
<span className={styles.stepText}>{step.text[locale]}</span>
</motion.div>
))}
</div>
)}

{/* Completion */}
<AnimatePresence>
{phase === 'complete' && (
<motion.div
className={styles.completion}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.3 }}
>
<div className={styles.line}>
<span className={styles.completionEmoji}>🎉</span>{' '}
<span className={styles.completionText}>{t.line1}</span>
</div>
<div className={styles.line}>
<span className={styles.hintText}>{t.line2}</span>
</div>
</motion.div>
)}
</AnimatePresence>
</div>
</div>
</div>
</section>
);
}

Step 2: Create TerminalDemo styles

/* src/components/TerminalDemo/TerminalDemo.module.css */
.section {
margin-top: 5rem;
margin-bottom: 5rem;
}

.sectionTitle {
font-size: 1.75rem;
font-weight: 600;
color: var(--ifm-font-color-base);
margin: 0 0 2rem 0;
text-align: center;
letter-spacing: -0.01em;
}

@media (min-width: 768px) {
.sectionTitle {
font-size: 2rem;
}
}

.terminalWrapper {
max-width: 640px;
margin: 0 auto;
}

.terminal {
border-radius: 0.75rem;
overflow: hidden;
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.15), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
border: 1px solid #2d333b;
}

[data-theme='dark'] .terminal {
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.4), 0 8px 10px -6px rgba(0, 0, 0, 0.3);
border-color: #30363d;
}

.titleBar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.75rem 1rem;
background-color: #1c2028;
}

[data-theme='dark'] .titleBar {
background-color: #161b22;
}

.dots {
display: flex;
gap: 0.5rem;
}

.dotsPlaceholder {
width: 52px;
}

.dotRed,
.dotYellow,
.dotGreen {
width: 12px;
height: 12px;
border-radius: 50%;
}

.dotRed {
background-color: #ff5f57;
}

.dotYellow {
background-color: #febc2e;
}

.dotGreen {
background-color: #28c840;
}

.titleText {
font-size: 0.8125rem;
color: #6b7280;
font-weight: 500;
}

.body {
padding: 1.25rem 1.25rem 1.5rem;
background-color: #0d1117;
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;
font-size: 0.875rem;
line-height: 1.7;
min-height: 220px;
}

[data-theme='dark'] .body {
background-color: #0d1117;
}

.line {
white-space: nowrap;
}

.promptSymbol {
color: #7ee787;
}

.commandText {
color: #f0f6fc;
}

.cursor {
display: inline-block;
width: 8px;
height: 1.1em;
background-color: #f0f6fc;
vertical-align: text-bottom;
animation: blink 1s step-end infinite;
}

@keyframes blink {
50% {
opacity: 0;
}
}

.stepsContainer {
margin-top: 0.5rem;
}

.checkmark {
color: #4ade80;
}

.stepText {
color: #c9d1d9;
}

.completion {
margin-top: 0.5rem;
}

.completionEmoji {
/* No special styling needed, inherits line */
}

.completionText {
color: #f0f6fc;
font-weight: 600;
}

.hintText {
color: #6b7280;
font-size: 0.8125rem;
}

Step 3: Verify dev server

Run: cd /Users/danny/strartups/volr/volr-project/volr-docs && yarn start Expected: No errors

Step 4: Commit

git add src/components/TerminalDemo/
git commit -m "feat: add TerminalDemo typing animation component"

Task 4: Rewrite the homepage

Files:

  • Modify: src/pages/index.tsx (full rewrite)
  • Modify: src/pages/index.module.css (update hero styles, keep section card styles)

Step 1: Update index.tsx

Replace the hero section with new headline + npx command, add SkillsSection and TerminalDemo between hero and doc cards.

The key changes to src/pages/index.tsx:

  1. Update translations: new headline "Stablecoin Payments.\nOne Command.", new subtitle "Add stablecoin payments to your app in minutes, not weeks."
  2. Remove the badge element
  3. Replace CTA buttons with NpxCommand component + secondary buttons (Docs, GitHub)
  4. Add SkillsSection component after hero
  5. Add TerminalDemo component after SkillsSection
  6. Keep existing documentation sections grid at bottom
// src/pages/index.tsx — full replacement
import React from 'react';
import Link from '@docusaurus/Link';
import Layout from '@theme/Layout';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import { ArrowRight, BookOpen, CreditCard, Shield, Settings, Zap, Code } from 'lucide-react';
import NpxCommand from '../components/NpxCommand/NpxCommand';
import SkillsSection from '../components/SkillsSection/SkillsSection';
import TerminalDemo from '../components/TerminalDemo/TerminalDemo';
import styles from './index.module.css';

const translations = {
en: {
title: 'Volr — Stablecoin Payments SDK',
description: 'Add stablecoin payments to your app in minutes',
headline: 'Stablecoin Payments.\nOne Command.',
subtitle: 'Add stablecoin payments to your app in minutes, not weeks.',
docs: 'Docs',
github: 'GitHub',
exploreDocs: 'Explore Documentation',
sections: {
gettingStarted: {
title: 'Getting Started',
description: 'Set up your project and integrate Volr SDK',
link: '/docs/quick-start',
},
payment: {
title: 'Payment',
description: 'Learn how to implement Web3 payments',
link: '/docs/payment/intro',
},
authentication: {
title: 'Authentication',
description: 'User authentication and wallet management',
link: '/docs/authentication/intro',
},
configuration: {
title: 'Configuration',
description: 'Customize SDK appearance and behavior',
link: '/docs/configuration/volr-ui-provider',
},
advanced: {
title: 'Advanced',
description: 'Advanced features and customization',
link: '/docs/advanced/transactions',
},
apiReference: {
title: 'API Reference',
description: 'Complete API documentation',
link: '/docs/api-reference/hooks',
},
},
},
ko: {
title: 'Volr — 스테이블코인 결제 SDK',
description: '몇 분 만에 스테이블코인 결제를 앱에 추가하세요',
headline: 'Stablecoin Payments.\nOne Command.',
subtitle: '몇 주가 아닌, 몇 분 만에 스테이블코인 결제를 앱에 추가하세요.',
docs: '문서',
github: 'GitHub',
exploreDocs: '문서 둘러보기',
sections: {
gettingStarted: {
title: '시작하기',
description: '프로젝트 설정 및 Volr SDK 통합',
link: '/docs/quick-start',
},
payment: {
title: '결제',
description: 'Web3 결제 구현 방법',
link: '/docs/payment/intro',
},
authentication: {
title: '인증',
description: '사용자 인증 및 지갑 관리',
link: '/docs/authentication/intro',
},
configuration: {
title: '설정',
description: 'SDK 외관 및 동작 커스터마이징',
link: '/docs/configuration/volr-ui-provider',
},
advanced: {
title: '고급',
description: '고급 기능 및 커스터마이징',
link: '/docs/advanced/transactions',
},
apiReference: {
title: 'API 레퍼런스',
description: '완전한 API 문서',
link: '/docs/api-reference/hooks',
},
},
},
};

const sectionIcons = {
gettingStarted: BookOpen,
payment: CreditCard,
authentication: Shield,
configuration: Settings,
advanced: Zap,
apiReference: Code,
};

export default function Home(): React.ReactElement {
const { i18n } = useDocusaurusContext();
const locale = i18n.currentLocale as 'en' | 'ko';
const t = translations[locale] || translations.en;

return (
<Layout title={t.title} description={t.description}>
<main className={styles.main}>
{/* Background layers */}
<div className={styles.background}>
<div className={styles.backgroundBase} />
<div className={styles.backgroundPattern} />
<div className={styles.backgroundGradient} />
</div>

<div className={styles.container}>
{/* Hero Section */}
<section className={styles.hero}>
<h1 className={styles.title}>
{t.headline.split('\n').map((line, i) => (
<React.Fragment key={i}>
{i > 0 && <br />}
{line}
</React.Fragment>
))}
</h1>
<p className={styles.subtitle}>{t.subtitle}</p>

<div className={styles.commandRow}>
<NpxCommand />
</div>

<div className={styles.cta}>
{/* @ts-expect-error - Docusaurus Link type compatibility issue */}
<Link to="/docs/quick-start" className={styles.secondaryButton}>
{t.docs}
</Link>
{/* @ts-expect-error - Docusaurus Link type compatibility issue */}
<Link to="https://github.com/volr-io" className={styles.secondaryButton}>
{t.github}
</Link>
</div>
</section>

{/* Terminal Demo */}
<TerminalDemo />

{/* Skills Section */}
<SkillsSection />

{/* Documentation Sections Grid */}
<section className={styles.sections}>
<h2 className={styles.sectionsTitle}>{t.exploreDocs}</h2>
<div className={styles.sectionsGrid}>
{Object.entries(t.sections).map(([key, section]) => {
const Icon = sectionIcons[key as keyof typeof sectionIcons];
return (
/* @ts-expect-error - Docusaurus Link type compatibility issue */
<Link key={key} to={section.link} className={styles.sectionCard}>
<div className={styles.sectionIcon}>
<Icon size={24} />
</div>
<h3 className={styles.sectionTitle}>{section.title}</h3>
<p className={styles.sectionDescription}>{section.description}</p>
<div className={styles.sectionArrow}>
<ArrowRight size={16} />
</div>
</Link>
);
})}
</div>
</section>
</div>
</main>
</Layout>
);
}

Step 2: Update index.module.css

Add .commandRow style and remove .badge style. Remove .primaryButton (no longer used). Keep all section card styles.

Add to src/pages/index.module.css after .subtitle media query block:

.commandRow {
display: flex;
justify-content: center;
margin-bottom: 1.5rem;
}

Remove the .badge and [data-theme='dark'] .badge rules (lines 67-86). Remove the .primaryButton and related rules (lines 142-182) since we no longer use them.

Step 3: Build and verify

Run: cd /Users/danny/strartups/volr/volr-project/volr-docs && yarn build Expected: Build succeeds with no errors

Step 4: Visual check

Run: cd /Users/danny/strartups/volr/volr-project/volr-docs && yarn start Expected: Landing page shows new hero with npx command, terminal demo, skills cards, and doc cards

Step 5: Commit

git add src/pages/index.tsx src/pages/index.module.css
git commit -m "feat: redesign landing page with npx command, terminal demo, and skills section"

Task 5: Final polish and verify

Files:

  • Verify: All modified and created files

Step 1: Run full build

Run: cd /Users/danny/strartups/volr/volr-project/volr-docs && yarn build Expected: Clean build, no TypeScript or CSS errors

Step 2: Test dark mode

Run dev server, toggle dark mode via the theme toggle in the navbar. Verify:

  • NpxCommand box looks good in dark mode
  • Terminal demo has consistent dark styling
  • Skills cards switch properly
  • All text is readable

Step 3: Test responsive design

Check at these widths:

  • 375px (mobile)
  • 768px (tablet)
  • 1280px (desktop)

Verify: All grids collapse properly, text is readable, no overflow

Step 4: Test i18n

Switch to Korean locale and verify all translated strings appear correctly.

Step 5: Commit any fixes

git add -A
git commit -m "fix: polish landing page responsive and dark mode styles"