SuperAPI AI Directory

web-frontend-build

Frontend & websites

View repository

Updated 10-16 07:58

About this skill

Web Frontend Build Skill

web/_design/*as input, take web/index.html, web/styles/*.css, web/scripts/main.jsa workflow that builds. Operates as static files without build tools.

Workflow

Step 1: Entry point HTML structure (web/index.html)

<!DOCTYPE html>
<html lang="ko" data-theme="dark">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
  <title>SK하이닉스 다각도 분석 보고서 — 2026-05-12</title>
  <meta name="description" content="..." />
  <meta name="theme-color" content="#0a0e1a" />
<section id="summary" class="section">
  <h2>Executive Summary</h2>
  <p class="tldr">현재가 약 1,861,000원 · 시가총액 1,319조원 · 1Y +871% ...</p>
  <div class="summary-grid">
    <div class="summary-card strength">
      <h3>핵심 강점 3</h3>
      <ul>...</ul>
    </div>
    <div class="summary-card concern">
      <h3>핵심 우려 3</h3>
      <ul>...</ul>
    </div>
  </div>
</section>

<section id="analysis" class="section">
  <h2>5개 분석 영역</h2>
  <!-- 5개 sub-section: 시세/펀더/산업/심리/리스크 -->
  <article class="analysis-block" id="analysis-market">
    <header><h3>1. 시장 데이터</h3></header>
    <div class="chart-container" data-chart>
      <canvas id="chart-price"></canvas>
    </div>
    <p class="analysis-body">...</p>
  </article>
  <!-- ... -->
</section>

<section id="scenarios" class="section">
  <h2>시나리오 분석</h2>
  <!-- 3 ScenarioCard + Fan chart -->
</section>

<section id="monitoring" class="section">
  <h2>모니터링 타임라인</h2>
  <!-- 향후 90일 이벤트 -->
</section>

<section id="appendix" class="section">
  <h2>부록</h2>
  <details>
    <summary>데이터 출처</summary>
    <!-- ... -->
  </details>
  <details>
    <summary>분석 한계 (Caveats)</summary>
    <!-- ... -->
  </details>
</section>

Step 2: CSS design system (web/styles/main.css)

:root[data-theme="dark"] {
  --bg-primary: #0a0e1a;
  --bg-secondary: #111827;
  --bg-elevated: #1f2937;
  --text-primary: #f8fafc;
  --text-secondary: #cbd5e1;
  --text-tertiary: #94a3b8;
  --accent-primary: #06b6d4;
  /* ... 모든 토큰 */
}

:root[data-theme="light"] {
  --bg-primary: #ffffff;
  --bg-secondary: #f8fafc;
  /* ... */
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; }

body {
  font-family: 'Inter', 'Pretendard', sans-serif;
  background: var(--bg-primary);
  color: var(--text-primary);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Typography scale */
.display-1 { font-size: clamp(48px, 8vw, 96px); font-weight: 700; line-height: 1.05; letter-spacing: -0.02em; }
.display-2 { font-size: clamp(36px, 6vw, 72px); font-weight: 600; line-height: 1.1; }
h1 { font-size: clamp(32px, 4vw, 48px); font-weight: 600; }
h2 { font-size: clamp(24px, 3vw, 36px); font-weight: 600; margin-bottom: 24px; }
h3 { font-size: 20px; font-weight: 500; }

/* Layout grid */
main { max-width: 1280px; margin: 0 auto; padding: 0 24px; }
.section { padding: 96px 0; }

/* Sticky header with glassmorphism */
.site-header {
  position: sticky; top: 0; z-index: 100;
  backdrop-filter: blur(16px);
  background: color-mix(in srgb, var(--bg-primary) 70%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--text-tertiary) 20%, transparent);
}

/* 배경 캔버스 */
#bg-canvas {
  position: fixed; inset: 0; z-index: -1;
  pointer-events: none;
}

/* Reduced motion fallback */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

Step 3: Component CSS (web/styles/components.css)

/* Metric Card with glow on hover */
.metric-card {
  padding: 24px;
  background: color-mix(in srgb, var(--bg-secondary) 60%, transparent);
  backdrop-filter: blur(8px);
  border: 1px solid color-mix(in srgb, var(--text-tertiary) 15%, transparent);
  border-radius: 20px;
  transition: transform 300ms cubic-bezier(0.2, 0, 0, 1), box-shadow 300ms;
}
.metric-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 16px 48px rgba(0,0,0,0.4), 0 0 32px rgba(6, 182, 212, 0.15);
}

.metric-value {
  font-family: 'JetBrains Mono', monospace;
  font-size: clamp(36px, 5vw, 64px);
  font-weight: 600;
}
.delta-up { color: var(--bull); }
.delta-down { color: var(--bear); }

/* Summary card glass */
.summary-card {
  padding: 32px;
  background: color-mix(in srgb, var(--bg-elevated) 50%, transparent);
  backdrop-filter: blur(16px);
  border-radius: 24px;
  border: 1px solid color-mix(in srgb, var(--accent-primary) 20%, transparent);
}
.summary-card.strength { border-color: color-mix(in srgb, var(--bull) 30%, transparent); }
.summary-card.concern { border-color: color-mix(in srgb, var(--bear) 30%, transparent); }

/* Chart container */
.chart-container {
  background: var(--bg-secondary);
  border-radius: 20px;
  padding: 32px;
  min-height: 400px;
}

/* Scenario cards */
.scenario-card[data-scenario="bear"] { border-left: 4px solid var(--bear); }
.scenario-card[data-scenario="base"] { border-left: 4px solid var(--accent-primary); }
.scenario-card[data-scenario="bull"] { border-left: 4px solid var(--bull); }

/* Timeline event */
.timeline { display: grid; gap: 16px; }
.timeline-event {
  display: grid;
  grid-template-columns: 120px 1fr auto;
  gap: 16px;
  padding: 16px;
  border-left: 2px solid var(--accent-primary);
}

Step 4: Responsive CSS (web/styles/responsive.css)

/* Mobile-first base in main.css. 여기서는 확장. */

@media (min-width: 768px) {
  .meta-metrics { grid-template-columns: repeat(3, 1fr); }
  .summary-grid { grid-template-columns: 1fr 1fr; }
  .nav-links { display: flex; gap: 32px; }
}

@media (min-width: 1280px) {
  main { padding: 0 48px; }
  .section { padding: 128px 0; }
}

/* Container queries 활용 (지원 브라우저) */
@container (min-width: 600px) {
  .chart-container { padding: 48px; }
}

Step 5: Entry JS (web/scripts/main.js)

// 다크/라이트 모드 토글
const toggle = document.querySelector('.theme-toggle');
const root = document.documentElement;
const stored = localStorage.getItem('theme');
if (stored) root.dataset.theme = stored;
toggle.addEventListener('click', () => {
  const next = root.dataset.theme === 'dark' ? 'light' : 'dark';
  root.dataset.theme = next;
  localStorage.setItem('theme', next);
  toggle.textContent = next === 'dark' ? '🌙' : '☀️';
});

// 스크롤 기반 active 네비
const sections = document.querySelectorAll('section[id]');
const navLinks = document.querySelectorAll('.nav-links a');
const navObserver = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      navLinks.forEach(a => a.classList.toggle('active', a.getAttribute('href') === `#${entry.target.id}`));
    }
  });
}, { threshold: 0.4 });
sections.forEach(s => navObserver.observe(s));

// 데이터 로드 후 차트·동적 콘텐츠 주입
import { initAllCharts } from './charts.js';
import { populateData } from './data-loader.js';
(async () => {
  const data = await fetch('./_design/data.json').then(r => r.json());
  populateData(data);  // 텍스트·리스트 주입
  initAllCharts(data);  // 차트 초기화 (IntersectionObserver lazy)
})();

Step 6: Data loader (web/scripts/data-loader.js)

data.jsoninject text, list, and table data into the DOM. Strengths/concerns/scenarios/timeline, etc.

Working Principles

  • No build step: load directly with ESM modules + CDN libs
  • Semantic markup: <section>, <article>, <nav>, <main> exactly. Heading hierarchy H1→H2→H3 consistency
  • Tokens as CSS Custom Properties: no hardcoded colors or sizes
  • Accessibility: keyboard focus visible, alt text, ARIA labels, prefers-reduced-motion
  • Performance: image lazy loading, font-display: swap, charts lazily initialized with IntersectionObserver
  • Mobile first: based on 320px, breakpoints 768 and 1280

Team Communication

  • Receive tokens, IA, and catalog from design-lead
  • Receive chart container ID specs from visualization-engineer → place them exactly in the HTML
  • Receive background canvas and interaction trigger class specs from motion-designer
  • Receive markup/accessibility/responsive verification results from web-qa → fix

On subsequent runs

Preserve the previous HTML/CSS/JS, and modify only the changed parts. When adding new components, check for component-catalog updates.