designpaca 초기 구현 — 스킬 · 설치 CLI · 배포 파이프라인

웹 디자인 파이프라인 스킬과 이를 5개 에이전트에 설치하는 CLI 를 담은 모노레포.

스킬 (packages/skill)
- SKILL.md 261줄 + 참조 문서 16개 3,349줄. progressive disclosure 로
  본문은 절차와 인덱스만, 지식은 references/ 로 분리
- 0~6단계 파이프라인. 규모에 따라 전체·연장·국소 세 경로로 분기
- 하드 게이트 12개는 grep·카운트로 검증 가능한 것만. 취향 판단은 제외
- 미학 프리셋 5종, AI 슬롭 지문 목록, 한글 조판 규칙,
  SVG 필터·three.js·인터랙티브 모션·HTML-in-Canvas 실전 지침

설치 CLI (packages/cli, packages/core)
- npx designpaca 온보딩 TUI. Claude Code · Codex · Cursor · Windsurf · AGENTS.md
- 매니페스트에 설치 시점 해시를 기록해 사용자가 고친 파일은 update 가 건너뛴다
- 타깃별로 본문의 references/ 경로를 실제 설치 위치로 재작성
- AGENTS.md 는 항상 로드되므로 본문 대신 303자 포인터만 주입
- Windsurf 는 12,000자 상한 초과 시 설치를 차단

배포 (build/ci, .forgejo/workflows)
- 태그 v* → 검사·테스트·빌드 → npmjs 배포 + Forgejo 레지스트리 미러
  → draft 릴리스 → Cloudflare Pages. 재실행 멱등

근거 (research/)
- 약 250개 웹 소스 조사 결과와 도그푸딩 검증 2건. 스킬의 모든 수치는 여기서 나온다

테스트 22개 통과 (core 16 · cli 6)
This commit is contained in:
Yun Chan 2026-08-20 10:48:00 +09:00
commit 8808c672dc
135 changed files with 38838 additions and 0 deletions

View file

@ -0,0 +1,216 @@
/* 히어로. 값은 전부 tokens.css 에서 온다. */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
margin: 0;
background: var(--surface);
color: var(--ink);
font-family: var(--font-body);
font-size: var(--step-0);
line-height: var(--leading-normal);
letter-spacing: var(--tracking-body);
font-variant-numeric: tabular-nums; /* dark-instrument: 수치가 흔들리면 계기판이 아니다 */
}
/* layout.md §1 — 하나의 그리드에서 전부 나온다 */
.page {
display: grid;
grid-template-columns:
[full-start] minmax(var(--gutter), 1fr)
[main-start] minmax(0, var(--container)) [main-end]
minmax(var(--gutter), 1fr) [full-end];
}
.page > * { grid-column: main; }
.page > .full { grid-column: full; }
/* ---------------------------------------------------------------- 내비 */
.nav {
display: flex;
flex-wrap: wrap; /* 320px 에서 밀려 가로 스크롤이 생겼다 */
align-items: center;
gap: var(--space-2) var(--space-4);
padding-block: var(--space-4);
}
.nav__mark {
font-family: var(--font-display);
font-size: var(--step-2);
letter-spacing: var(--tracking-display);
margin: 0;
margin-inline-end: auto;
}
.nav__link {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 44px; /* 터치 타깃 44×44 */
min-width: 44px;
color: var(--ink-muted);
font-size: var(--step--1);
text-decoration: none;
border-bottom: 1px solid transparent;
}
.nav__link:hover { color: var(--ink); border-bottom-color: var(--line); }
/* ---------------------------------------------------------------- 히어로 */
.hero {
/* 100vh 금지(하드게이트 #9). dvh 를 쓰고 min-height 로만 잡는다 */
min-height: min(84dvh, 46rem);
display: grid;
/* 비대칭 7:5. layout.md — 중앙 정렬 히어로는 쓰지 않는다 */
grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
gap: var(--space-6) var(--space-7);
align-items: start;
padding-block: var(--space-7) var(--space-8);
}
.hero__headline {
font-family: var(--font-display);
font-size: var(--display-1);
line-height: var(--leading-tight);
letter-spacing: var(--tracking-display);
font-weight: 400;
margin: 0 0 var(--space-4);
text-wrap: balance;
}
.hero__sub {
max-width: var(--measure);
color: var(--ink-muted);
font-size: var(--step-1);
margin: 0 0 var(--space-5);
}
.hero__actions {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--space-4);
}
/* 주 CTA — 감수한 리스크: 강조색을 쓰지 않고 잉크 반전으로만 만든다 */
.cta {
display: inline-block;
background: var(--cta-bg);
color: var(--cta-ink);
font-size: var(--step-0);
font-weight: 600;
line-height: 1.2;
text-decoration: none;
padding: var(--space-3) var(--space-5);
border: 0;
border-radius: var(--radius-md);
white-space: nowrap; /* 하드게이트 #6 — 라벨이 2줄로 접히지 않는다 */
/* 하드게이트 #8 — transform/opacity 만 트랜지션한다 */
transition: transform var(--dur-instant) var(--ease-out);
}
.cta:hover { transform: translateY(-1px); }
.cta:active { transform: translateY(0); }
.link-quiet {
display: inline-flex;
align-items: center;
min-height: 44px; /* 터치 타깃 */
color: var(--accent); /* 강조색은 오직 글자에만 */
font-size: var(--step-0);
text-decoration: underline; /* 색만으로 구분하지 않는다 */
text-underline-offset: 0.25em;
}
/* ---------------------------------------------------------------- 제품 화면
* 하드게이트 #12 div 만든 가짜 스크린샷 금지.
* 브리프가 실제 스크린샷을 제공하므로 <img> 쓴다.
* aspect-ratio 자리를 미리 잡아 CLS 막는다.
*/
.shot {
display: block;
width: 100%;
height: auto;
aspect-ratio: 4 / 3;
object-fit: cover;
object-position: left top;
background: var(--surface-raised); /* 로드 전/실패 시의 자리 */
border-radius: var(--radius-md);
}
.shot-caption {
display: block;
margin-top: var(--space-2);
color: var(--ink-muted);
font-size: var(--step--1);
font-family: var(--font-mono);
}
/* ---------------------------------------------------------------- 설치 명령 */
.install {
grid-column: main;
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--space-3);
background: var(--surface-raised);
border-radius: var(--radius-md);
padding: var(--space-3) var(--space-4);
font-family: var(--font-mono);
font-size: var(--step-0);
}
.install__prompt { color: var(--ink-muted); user-select: none; }
.install__cmd { color: var(--ink); }
.install__copy {
margin-inline-start: auto;
min-height: 44px;
min-width: 44px;
background: transparent;
color: var(--ink-muted);
border: 1px solid var(--line);
border-radius: var(--radius-sm);
font: inherit;
font-size: var(--step--1);
padding: var(--space-1) var(--space-3);
cursor: pointer;
transition: transform var(--dur-instant) var(--ease-out);
}
.install__copy:hover { color: var(--ink); transform: translateY(-1px); }
/* ---------------------------------------------------------------- 테마 토글 */
.theme-toggle {
min-height: 44px;
min-width: 44px;
background: transparent;
color: var(--ink-muted);
border: 1px solid var(--line);
border-radius: var(--radius-sm);
font: inherit;
font-size: var(--step--1);
padding: var(--space-1) var(--space-3);
cursor: pointer;
}
.theme-toggle:hover { color: var(--ink); }
.visually-hidden {
position: absolute;
width: 1px; height: 1px;
padding: 0; margin: -1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
border: 0;
}
/* ---------------------------------------------------------------- 포커스 */
:where(a, button):focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
border-radius: var(--radius-sm);
}
/* ---------------------------------------------------------------- 반응형 */
/* 콘텐츠가 깨지는 지점에서만. 기기 크기를 가정하지 않는다 */
@media (max-width: 54rem) {
.hero { grid-template-columns: minmax(0, 1fr); }
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { transition-duration: 1ms !important; animation-duration: 1ms !important; }
}

View file

@ -0,0 +1,100 @@
/* 3단계에서 확정한 토큰. 하드코딩된 값은 이 파일 밖에 존재하지 않는다. */
:root {
/* ---- 타입: 본문 스케일 (비율 1.250, 5단계) ---- */
--step--1: 0.8125rem;
--step-0: 1rem;
--step-1: 1.25rem;
--step-2: 1.5625rem;
--step-3: 1.9531rem;
/* ---- 타입: 디스플레이 (스케일 밖. 위계를 만드는 유일한 장치) ---- */
--display-2: clamp(2rem, 1.4rem + 3vw, 2.5rem);
--display-1: clamp(2.75rem, 1.8rem + 4.8vw, 4rem);
--leading-tight: 1.05;
--leading-snug: 1.3;
--leading-normal: 1.55;
--measure: 68ch;
--font-display: 'Newsreader', Georgia, 'Times New Roman', serif;
--font-body: 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
--font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
--tracking-display: -0.025em;
--tracking-body: 0;
/* ---- 간격: 4px 그리드 ---- */
--space-1: 0.25rem;
--space-2: 0.5rem;
--space-3: 1rem;
--space-4: 1.5rem;
--space-5: 2.5rem;
--space-6: 4rem;
--space-7: 6rem;
--space-8: 10rem;
--container: 70rem;
--gutter: clamp(1rem, 4vw, 5rem);
/* ---- 형태: 어휘 2종 ---- */
--radius-sm: 2px;
--radius-md: 4px;
/* ---- 모션 ---- */
--dur-instant: 100ms;
--dur-quick: 200ms;
--dur-normal: 350ms;
--dur-slow: 600ms;
--ease-out: cubic-bezier(0.22, 1, 0.36, 1);
--ease-in: cubic-bezier(0.64, 0, 0.78, 0);
--ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
/* ---- 색: 다크가 저작 기준 (2단계에서 정당화) ---- */
color-scheme: dark light;
--surface: #0D0F12;
--surface-raised: #151A20;
--line: #262E37;
--ink: #E6E8E6;
--ink-muted: #9BA6B2;
--accent: #7FA6FF;
--accent-ink: #0D0F12;
--cta-bg: #E6E8E6;
--cta-ink: #0D0F12;
--ok: #4FA97A;
--warn: #C9A227;
--fail: #D46A55;
}
/* OS가 라이트를 선호하면 라이트. 토글이 명시적으로 다크를 잡으면 무시한다. */
@media (prefers-color-scheme: light) {
:root:not([data-theme='dark']) {
--surface: #F7F5F0;
--surface-raised: #FDFCF9;
--line: #DCD8CF;
--ink: #16181A;
--ink-muted: #5C646E;
--accent: #1B4FD8;
--accent-ink: #FAF9F6;
--cta-bg: #16181A;
--cta-ink: #FAF9F6;
--ok: #2F7D57;
--warn: #8A6D14;
--fail: #A8432E;
}
}
/* 토글이 라이트를 잡으면 OS와 무관하게 라이트 */
:root[data-theme='light'] {
--surface: #F7F5F0;
--surface-raised: #FDFCF9;
--line: #DCD8CF;
--ink: #16181A;
--ink-muted: #5C646E;
--accent: #1B4FD8;
--accent-ink: #FAF9F6;
--cta-bg: #16181A;
--cta-ink: #FAF9F6;
--ok: #2F7D57;
--warn: #8A6D14;
--fail: #A8432E;
}