C.W.K.
Stream
Lesson 06 of 08 · published

Anchor 6 — Viewport context payload shape

~11 min · payload, schema, context, case-study

Level 0Extension 입덕
0 XP0/54 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete
"Lesson 6 가 ChromeEmbed 의 모든 부분 흐르는 JSON object zoom in: host-context payload. 모든 field 정당화, 모든 field 가 panel iframe 이 의존하는 계약."

Full shape

Content script 의 extractContext() 가 반환:

{
  type: 'pippa:host-context',
  payload: {
    host_kind: 'web-page',
    snapshot_at: '2026-05-16T01:23:45.000Z',
    host_id: chrome.runtime.id,
    source: location.href,
    human_label: document.title || location.hostname,
    favicon: faviconHref(),
    selection,
    viewportText,
    readableText: viewportText, // compat alias
    wordCount,
    viewport: { width, height, scrollX, scrollY, devicePixelRatio },
    scrollPosition: { y: scrollY, ofPageHeight: pageHeight },
    language: document.documentElement?.lang || navigator.language || '',
    frameUrl: location.href,
    isTopFrame: window.top === window
  }
}

Identity field

  • host_kind — ChromeEmbed 엔 항상 'web-page'. PIPPA-EMBEDS framework 가 이거 기대; Adobe-embed 가 'adobe-app', Calendar 가 'gcal-event' 등. Downstream 렌더링 위한 discriminator.
  • host_id — extension 의 runtime id. cwkPippa 가 다른 installed instance (multi-Chrome-profile setup) 의 메시지 구별하게.
  • source — user 가 있는 canonical URL. cwkPippa 가 이걸 'capturing from example.com/article' 로 surface.
  • human_label — fallback-chained title. Chat thread label 로 사용.
  • favicon — UI affordance 위해.

Content field

  • selection — 현재 highlighted 텍스트 (또는 최대 5 분 전의 cached selection).
  • viewportText — user 의 현재 viewport 안 텍스트, walker-추출 spatially sorted (Lesson 3).
  • readableText — viewportText 의 alias. 옛 cwkPippa 코드 경로가 'readableText' read; alias 가 ChromeEmbed 가 그것들 안 깨뜨림. 계획: cwkPippa 가 'viewportText' 로 완전 migrate 할 때 deprecate.
  • wordCount — cwkPippa UI 위한 quick metric ('1,247 words in view').

Viewport field

  • viewport: { width, height, scrollX, scrollY, devicePixelRatio } — user window 의 physical-pixel 측정. cwkPippa 가 작은 viewport 나 hi-DPI display 에 UI 적응 가능.
  • scrollPosition: { y, ofPageHeight } — user 가 page 의 어디 수직 위치, plus 총 page height. cwkPippa 가 'you are 60% through this article' 표시 가능.

Metadata

  • snapshot_at — ISO timestamp. cwkPippa 가 'context from 5 seconds ago' 표시 가능.
  • language — cwkPippa 가 매칭 locale 로 응답 format 에 유용.
  • frameUrl, isTopFrame — SW (Lesson 2) 의 merge logic 위해. Sub-frame push 가 이거 carry, SW 가 top-frame snapshot override 할지 결정 가능.

왜 schema, '그냥 DOM 보내기' 아님

Fixed payload shape 의 규율이 이럴 때 payback:

  • 다른 embed 가 compose. PIPPA-EMBEDS framework 가 모든 embed (Chrome, Adobe, Mail, Calendar) 가 같은 field 이름의 host-context 생산 기대. cwkPippa 가 uniformly 렌더.
  • Versioning. Payload v1 → v2 bump 필요하면, 오늘 version: 1 field 추가하고 내일 확인.
  • Compatibility. readableText alias 가 정확히 fixed schema 가 enable 하는 종류의 migration aid. Schema 없이는 모든 consumer 가 추측해야.
  • Observability. cwkPippa 의 log 가 context payload 보일 때, 어떤 field 존재하는지 추측 안 하고 structured record 처럼 read 가능.

Payload 에 없는 것

일부러 부재:

  • Full document HTML — 훨씬 너무 크고 viewport semantic 잃음.
  • Screenshot — storage 비용, screenshot crop 이 future field 가능.
  • Tab history — ChromeEmbed 의 scope 밖; cwkPippa 가 이미 자체 conversation history 가짐.
  • User identity — Pippa 가 cwkPippa session 에서 누군지 앎, extension context 에서 아님.

Field 추가가 feature 로 정당화될 때 저렴; speculatively 추가는 schema 시끄럽고 bridge 느리게 만듬.

한 payload shape, 모든 field 정당화, 모든 field 가 계약. Schema 가 ChromeEmbed 를 다른 embed 와 composable 하게 만드는 것; 그것 없이는 각 embed 가 'context' 재발명 하고 cwkPippa 가 다 special-case 해야.
PIPPA-EMBEDS framework 각도. ChromeEmbed v0.1 이 첫 PIPPA embed. Ship 하는 host-context schema 가 future embed (Adobe, Mail, Calendar, IDE) 위한 제안된 계약. cwkPippa 가 uniformly 렌더; embed 의 유일한 job 이 native host 가 제공하는 어떤 것이든 schema field 채우기. 그게 win — 각 새 embed 가 from-scratch UI 가 아닌 한 payload format 가진 content-script-and-bus shape.

Code

content-script.js — schema, prototype 가 write 한 정확히 그대로·javascript
// embeds/chrome/content-script.js — extractContext 의 shape 된 output
function extractContext() {
  const viewportText = collectViewportText();
  const selection = currentSelectionText();
  const pageHeight = Math.max(
    document.documentElement?.scrollHeight || 0,
    document.body?.scrollHeight || 0,
    window.innerHeight || 0
  );
  return {
    type: 'pippa:host-context',
    payload: {
      host_kind: 'web-page',
      snapshot_at: new Date().toISOString(),
      host_id: chrome.runtime.id,
      source: location.href,
      human_label: document.title || location.hostname,
      favicon: faviconHref(),
      selection,
      viewportText,
      readableText: viewportText, // back-compat alias
      wordCount: viewportText ? viewportText.split(/\s+/).filter(Boolean).length : 0,
      viewport: {
        width: Math.round(window.innerWidth || 0),
        height: Math.round(window.innerHeight || 0),
        scrollX: Math.round(window.scrollX || 0),
        scrollY: Math.round(window.scrollY || 0),
        devicePixelRatio: Number((window.devicePixelRatio || 1).toFixed(2))
      },
      scrollPosition: { y: window.scrollY || 0, ofPageHeight: pageHeight },
      language: document.documentElement?.lang || navigator.language || '',
      frameUrl: location.href,
      isTopFrame: window.top === window
    }
  };
}

Exercise

Payload shape 보고 각 field 가 design 에 contribute 한 Track label: host_kind (embed framework, Track 9), source/human_label/favicon (chrome.tabs, Track 2 + 4), selection/viewportText (Track 3 + Track 7 Lesson 3), viewport/scrollPosition (Track 7 Lesson 3 의 rect math), snapshot_at (Track 5 의 timestamp), frameUrl/isTopFrame (Track 3 의 all_frames). 모든 field 가 concrete 이유로 trace back 되는 거 주목 — 'maybe useful' speculative field 없음. 규율이 panel 이 의존할 수 있는 계약 만드는 것.
Hint
Field 추가 원하면 — 예 meta 태그에서 documentDescription — 멈추고 물어 봐: cwkPippa 의 어느 feature 가 consume 할까? Queued consumer 없으면 defer. Field 추가가 앞엔 저렴하지만 영원히 비쌈 (모든 나중 embed 가 그것들 채워야, 또는 cwkPippa 가 missing value 처리해야). 첫 feature 지원하는 가장 작은 schema 로 시작, feature 도착 시 field 추가.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.