← ClaudeAtlas

authoring-componentslisted

패키지가 다른 패키지의 화면에 컴포넌트를 내주거나, 남의 컴포넌트를 자기 화면에 마운트할 때 읽는다. 자립 번들 저작, mount 계약, import map 소비, 무빌드 화면과 번들형 view 의 차이까지. 화면 조각을 패키지 경계 너머로 재사용해야 하면 만들기 전에 이 문서를 먼저 읽어라.
relayax/relayagent · ★ 17 · Web & Frontend · score 78
Install: claude install-skill relayax/relayagent
# 컴포넌트 수출과 소비 패키지 화면의 한 조각을 다른 패키지가 쓰게 하는 축이다. 결론부터 말하면 **수출물은 자립 ESM 번들 하나이고, 소비자는 프레임워크도 빌드도 필요 없다.** ## 계약 수출은 파일 하나로 좁혀진다. 산출 디렉토리의 `index.js` 가 진입점이고, 수출은 하나다: ```js export function mount(el, props) { // el 안에 그린다 return { unmount() { /* 정리 */ } }; } ``` **스타일도 이 파일 안에 탄다.** 옆에 CSS 를 따로 내지 마라 — 소비자가 그 주소를 알아야 하는데 주소에는 제공자의 설치 이름이 들어간다(`/pkg/<설치이름>/components/index.css`). 같은 패키지가 다른 이름으로 서면 바로 깨진다. 소비자가 아는 것은 이름 하나, 부르는 것은 `mount` 하나다. ## 선언 ```yaml surfaces: components: source: surfaces/components # 저작 트리 out: dist # 빌드 산출. 미선언이면 source/index.js 를 그대로 서빙 ``` `out` 을 선언하면 설치와 발행이 그 자리에서 `npm install` + `npm run build` 를 돈다. 빌드가 실패하면 설치가 실패한다. 손으로 쓴 ESM 한 장이면 `out` 을 빼라 — 그러면 빌드가 아예 없고, 대신 `source/index.js` 가 지금 실재해야 한다(판정이 잡는다). ## React 로 저작하기 써도 된다. **React 는 번들 안에 들어가고 소비자에게는 보이지 않는다.** 채팅 위젯이 이미 그 모양이다. react 를 devDependencies 에 두고 번들러가 안으로 말아 넣게 하라: ```js // build.mjs import * as esbuild from "esbuild"; await esbuild.build({ entryPoints: ["src/index.tsx"], bundle: true, format: "esm", outfile: "dist/index.js", jsx: "automatic", minify: true, loader: { ".css": "text" }, // CSS 를 문자열로 받아 번들 안에 태운다 }); ``` ```jsx // src/index.tsx import { createRoot } from "react-dom/client"; import css from "./panel.css"; import Panel from "./Panel"; let styled = false; function ensureStyle() { if (styled || typeof document === "undefined") return; styled = true; const tag = document.createElement("style"); tag.textCont