Compare commits

...

6 commits

Author SHA1 Message Date
Charles
aabce2732a
Merge b85f2889b0 into df1535b7fd 2026-05-30 22:05:14 +08:00
Charles
b85f2889b0 fix(i18n): point Korean license-exception link to design-templates/guizang-ppt
The bundled MIT-licensed guizang-ppt files live under design-templates/guizang-ppt/, not skills/guizang-ppt/. Correct the Korean CONTRIBUTING license-exception reference so readers reach a valid path.
2026-05-30 10:12:36 +09:00
Charles
e091d1790f docs(i18n): link Korean core docs from README switcher and mark ko Core Docs complete 2026-05-30 09:55:17 +09:00
Charles
a4d63edecd feat(i18n): add Korean translation for MAINTAINERS 2026-05-30 09:55:17 +09:00
Charles
4024b8dd98 feat(i18n): add Korean translation for CONTRIBUTING 2026-05-30 09:55:17 +09:00
Charles
766a680a34 feat(i18n): add Korean translation for QUICKSTART 2026-05-30 09:55:17 +09:00
5 changed files with 903 additions and 5 deletions

316
CONTRIBUTING.ko.md Normal file
View file

@ -0,0 +1,316 @@
# Open Design 기여 가이드
기여를 고민하고 있다니 고맙습니다. OD는 일부러 작게 유지합니다. 대부분의 가치는 프레임워크 코드가 아니라 **파일**(skill, design system, 프롬프트 조각)에 담겨 있습니다. 그래서 가장 효과가 큰 기여는 대개 폴더 하나, Markdown 파일 하나, 또는 PR 한 건 크기의 adapter입니다.
이 문서는 어떤 종류의 기여를 어디서 시작해야 하는지, 그리고 PR이 머지되려면 어떤 기준을 넘어야 하는지 정확히 알려줍니다.
<p align="center"><a href="CONTRIBUTING.md">English</a> · <a href="CONTRIBUTING.pt-BR.md">Português (Brasil)</a> · <a href="CONTRIBUTING.de.md">Deutsch</a> · <a href="CONTRIBUTING.fr.md">Français</a> · <a href="CONTRIBUTING.zh-CN.md">简体中文</a> · <a href="CONTRIBUTING.ja-JP.md">日本語</a> · <b>한국어</b></p>
---
## 오후 한나절이면 끝나는 세 가지 기여
| 하고 싶은 일 | 실제로 추가하는 것 | 위치 | 규모 |
|---|---|---|---|
| OD가 새로운 종류의 artifact를 렌더링하게 만들기 (청구서, iOS 설정 화면, 한 장짜리 문서 등) | **Skill** | [`skills/<your-skill>/`](skills/) | 폴더 하나, 파일 약 2개 |
| OD가 새 브랜드의 비주얼 언어를 구사하게 만들기 | **Design System** | [`design-systems/<brand>/DESIGN.md`](design-systems/) | Markdown 파일 하나 |
| 새 coding-agent CLI 연결하기 | **Agent adapter** | [`apps/daemon/src/agents.ts`](apps/daemon/src/agents.ts) | 배열 하나에 약 10줄 |
| 기능 추가, 버그 수정, [`open-codesign`][ocod]에서 UX 패턴 가져오기 | 코드 | `apps/web/src/`, `apps/daemon/` | 일반 PR |
| 문서 개선, 일부 섹션을 Français / Deutsch / 中文로 번역, 오타 수정 | 문서 | `README.md`, `README.fr.md`, `README.de.md`, `README.zh-CN.md`, `docs/`, `QUICKSTART.md` | PR 한 건 |
어느 쪽에 해당하는지 모르겠다면 [먼저 discussion이나 issue를 열어주세요](https://github.com/nexu-io/open-design/issues/new). 적절한 위치를 안내해 드리겠습니다.
---
## 로컬 환경 설정
한 페이지짜리 전체 설정 안내는 [`QUICKSTART.ko.md`](QUICKSTART.ko.md)에 있습니다. 기여자를 위한 요약은 다음과 같습니다.
```bash
git clone https://github.com/nexu-io/open-design.git
cd open-design
corepack enable # packageManager에 고정된 pnpm을 선택합니다
pnpm install
pnpm tools-dev run web # daemon + web 포그라운드 루프
pnpm typecheck # tsc -b --noEmit
pnpm --filter @open-design/web build # 필요할 때 web 패키지 빌드
```
Node `~24`와 pnpm `10.33.x`가 필요합니다. `nvm`이나 `fnm`은 선택 사항입니다. Node를 그렇게 관리하는 게 편하다면 `nvm install 24 && nvm use 24` 또는 `fnm install 24 && fnm use 24`를 실행하세요. macOS, Linux, WSL2가 주요 지원 환경입니다. Windows 네이티브도 지원합니다. 흔히 겪는 설정 문제는 [`docs/windows-troubleshooting.md`](docs/windows-troubleshooting.md)를 참고하세요.
## Docker 설정
Node.js나 pnpm을 설치하지 않고도 Open Design을 실행할 수 있습니다.
### 사전 준비
Compose v2가 포함된 Docker Desktop이 설치되어 있는지 확인하세요.
```bash
docker compose version
```
### Open Design 실행
```bash
cd deploy
docker compose up -d
```
브라우저에서 다음 주소를 엽니다.
```text
http://localhost:7456
```
### 자주 쓰는 명령어
```bash
# 로그 보기
docker compose logs -f
# 컨테이너 재시작
docker compose restart
# 컨테이너 중지
docker compose down
# 최신 이미지 받기
docker compose pull
docker compose up -d
```
### 선택적 환경 변수 재정의
`deploy/.env` 파일을 만듭니다.
```env
OPEN_DESIGN_PORT=7456
OPEN_DESIGN_MEM_LIMIT=384m
OPEN_DESIGN_ALLOWED_ORIGINS=https://yourdomain.com
OPEN_DESIGN_IMAGE=docker.io/vanjayak/open-design:latest
```
> 프로젝트와 데이터베이스 데이터는 Docker 볼륨에 자동으로 보존됩니다.
전체 Docker 가이드와 고급 설정은 [`QUICKSTART.ko.md`](QUICKSTART.ko.md)를 참고하세요.
---
## 새 Skill 추가하기
skill은 [`skills/`](skills/) 아래에 두는 폴더로, 루트에 `SKILL.md`를 두고 Claude Code의 [`SKILL.md` 규약][skill]에 우리의 선택적 `od:` 확장을 더한 형태입니다. **등록 절차는 없습니다.** 폴더를 넣고 daemon을 재시작하면 picker에 바로 나타납니다.
### → 전체 가이드는 [`docs/skills-contributing.md`](docs/skills-contributing.md)를 보세요
이 문서가 다음 내용을 단계별로 안내합니다.
- **빠른 시작** — 저장소 클론 → 가장 비슷한 기존 skill 복사 → `pnpm tools-dev run web` 실행 → picker 확인 → PR 열기.
- **skill이란 무엇이고 무엇이 아닌가** — 당신의 아이디어가 사실은 기능이나 vendor 연동이었다면, 일주일을 아껴줍니다.
- **skill 구조** — 최소한의 폴더 구성과 `SKILL.md` frontmatter 치트시트.
- **로컬 실행** — 실제로 중요한 네 가지 명령어.
- **머지 기준** — 리뷰어가 확인할 항목을 그대로 복사해 쓸 수 있는 체크리스트.
- **PR 설명 템플릿** — PR 본문에 붙여넣고 채우면 됩니다.
- **자주 거절되는 패턴** — 최근 실제로 사용한 거절 사유와 구체적인 예시.
프로토콜 명세(전체 frontmatter 문법 — 타입이 지정된 입력, 슬라이더 파라미터, craft 참조, 테스트 프리미티브)는 [`docs/skills-protocol.md`](docs/skills-protocol.md)에 별도로 정리되어 있습니다.
---
## 새 Design System 추가하기
design system은 `design-systems/<slug>/` 아래에 두는 [`DESIGN.md`](design-systems/README.md) 파일 하나입니다. **파일 하나뿐, 코드는 없습니다.** 넣고 daemon을 재시작하면 picker에 카테고리별로 묶여 나타납니다.
### design system 폴더 구성
```text
design-systems/your-brand/
└── DESIGN.md
```
### `DESIGN.md` 형식
```markdown
# Design System Inspired by YourBrand
> Category: Developer Tools
> One-line summary that shows in the picker preview.
## 1. Visual Theme & Atmosphere
## 2. Color
- Primary: `#hex` / `oklch(...)`
- …
## 3. Typography
## 4. Spacing & Grid
## 5. Layout & Composition
## 6. Components
## 7. Motion & Interaction
## 8. Voice & Brand
## 9. Anti-patterns
```
9개 섹션 구조는 고정입니다. skill 본문이 이 구조를 grep으로 찾기 때문입니다. 첫 H1이 picker 라벨이 되고(`Design System Inspired by` 접두사는 자동으로 제거됩니다), `> Category: …` 줄이 어느 그룹에 들어갈지 결정합니다. 기존 카테고리는 [`design-systems/README.md`](design-systems/README.md)에 정리되어 있습니다. 브랜드가 정말 어디에도 안 맞으면 새 카테고리를 만들 수 있지만, **먼저 기존 카테고리부터 검토하세요**.
### 새 design system 머지 기준
1. **9개 섹션이 모두 있어야 합니다.** 찾기 어려운 데이터(예: motion 토큰)는 섹션 본문이 비어 있어도 괜찮지만, 제목은 반드시 있어야 합니다. 없으면 프롬프트의 grep이 깨집니다.
2. **hex 코드는 실제 값이어야 합니다.** 기억이나 AI 추측이 아니라 브랜드의 사이트나 제품에서 직접 추출하세요. README의 "brand-spec extraction" 5단계 프로토콜은 maintainer에게도 똑같이 적용됩니다.
3. **강조 색상의 OKLch 값**은 있으면 좋습니다. 라이트/다크 모드에서 팔레트가 예측 가능하게 보간됩니다.
4. **마케팅 문구는 빼세요.** 브랜드 슬로건은 design 토큰이 아닙니다. 잘라내세요.
5. **slug는 ASCII로 작성하세요.** `linear.app``linear-app`이 되고 `x.ai``x-ai`가 됩니다. 이미 가져온 69개 시스템이 이 규칙을 따르니 그대로 맞추세요.
우리가 제공하는 69개 제품 시스템은 [`scripts/sync-design-systems.ts`](scripts/sync-design-systems.ts)를 통해 [`VoltAgent/awesome-design-md`][acd2]에서 가져온 것입니다. 브랜드가 그 upstream에 속한다면 **그쪽에 먼저 PR을 보내세요.** 다음 동기화 때 자동으로 반영됩니다. `design-systems/` 폴더는 upstream에 맞지 않는 시스템과, 우리가 직접 작성한 스타터 2개를 위한 곳입니다.
---
## 새 coding-agent CLI 추가하기
새 agent(예: 어느 신생 업체의 `foo-coder` CLI)를 연결하는 일은 [`apps/daemon/src/agents.ts`](apps/daemon/src/agents.ts)에 항목 하나를 추가하는 것입니다.
```javascript
{
id: 'foo',
name: 'Foo Coder',
bin: 'foo',
versionArgs: ['--version'],
buildArgs: (prompt) => ['exec', '-p', prompt],
streamFormat: 'plain', // 또는 해당 형식을 지원하면 'claude-stream-json'
}
```
이게 전부입니다. daemon이 `PATH`에서 감지하고, picker에 나타나며, 채팅 경로가 동작합니다. CLI가 (Claude Code의 `--output-format stream-json`처럼) **타입이 지정된 이벤트**를 내보낸다면 [`apps/daemon/src/claude-stream.ts`](apps/daemon/src/claude-stream.ts)에 파서를 연결하고 `streamFormat: 'claude-stream-json'`으로 설정하세요.
머지 기준:
1. 새 agent로 **실제 세션이 처음부터 끝까지 동작**해야 합니다. artifact가 스트리밍으로 통과한 것을 보여주는 daemon 로그를 PR 설명에 붙여넣으세요.
2. CLI의 특이사항을 **`docs/agent-adapters.md`**에 정리하세요(키 파일이 필요한가? 이미지 입력을 지원하는가? 비대화형 플래그는 무엇인가?).
3. **README의 "Supported coding agents" 표**에 한 줄을 추가하세요.
---
## 모델 `max_tokens` 메타데이터 갱신하기
API 모드 채팅은 매 요청마다 upstream provider에 `max_tokens`를 보냅니다. web 클라이언트는 [`apps/web/src/state/maxTokens.ts`](apps/web/src/state/maxTokens.ts)의 3단계 조회로 이 값을 정합니다.
1. 설정에서 사용자가 직접 지정한 값(있는 경우).
2. 없으면 [`apps/web/src/state/litellm-models.json`](apps/web/src/state/litellm-models.json)의 모델별 기본값. 이는 [BerriAI/litellm][litellm]의 `model_prices_and_context_window.json`(MIT)에서 잘라온 vendored 데이터로, Anthropic, OpenAI, DeepSeek, Groq, Together, Mistral, Gemini, Bedrock, Vertex, OpenRouter 등 약 2천 개의 채팅 모델을 포함합니다.
3. 그래도 없으면 `FALLBACK_MAX_TOKENS = 8192`.
새로 출시된 모델을 반영하려면 vendored JSON을 다시 생성하세요.
```bash
node --experimental-strip-types scripts/sync-litellm-models.ts
```
이 스크립트는 LiteLLM의 카탈로그를 가져와 `mode: 'chat'` 항목만 걸러내고, 각 항목을 `max_output_tokens`(없으면 `max_tokens`)로 매핑한 뒤 정렬된 스냅샷을 씁니다. 갱신을 유발한 PR과 함께 다시 생성된 `litellm-models.json`을 커밋하세요.
`maxTokens.ts`의 OVERRIDES 표는 실제로 쓰는 모델 id에 대해 LiteLLM에 값이 없거나 틀린 드문 경우를 위한 것입니다. 예를 들어 `mimo-v2.5-pro`가 그렇습니다(LiteLLM은 MiMo를 `openrouter/xiaomi/...``novita/xiaomimimo/...` 별칭으로만 제공하는데, 둘 다 Xiaomi 직접 API가 쓰는 정식 id와 맞지 않습니다). 이 표는 작게 유지하세요. LiteLLM이 제대로 다루는 것은 모두 upstream에 두는 게 맞습니다.
[litellm]: https://github.com/BerriAI/litellm
---
## 현지화 유지보수
독일어는 격식 있는 `Sie`를 씁니다. OD는 1인 창작자, 에이전시, 엔지니어링 팀이 뒤섞인 사용자층에 말을 걸기 때문입니다. 비격식 `du` 어조가 더 잘 맞는다는 프로젝트 피드백이 나오기 전까지는, 격식 독일어가 가장 무난한 기본값입니다. 로케일 PR은 UI 요소, 핵심 문서, 그리고 `apps/web/src/i18n/content.ts`의 표시 전용 갤러리 메타데이터를 번역해야 하지만, `skills/``design-systems/`, 또는 agent가 실행하는 프롬프트 본문은 번역하면 안 됩니다. 이런 원본 프롬프트는 워크플로우 입력으로 관리되며, 원본 언어를 하나로 유지해야 로케일마다 프롬프트 QA가 늘어나는 일을 막을 수 있습니다. skill, design system, 프롬프트 템플릿을 추가하거나 이름을 바꿀 때는 독일어 표시 메타데이터를 갱신하고 `pnpm --filter @open-design/web test`를 실행하세요. 독일어 표시 항목이 누락되면 `content.test.ts`가 실패합니다. daemon 오류, export 파일명, agent가 생성한 artifact 텍스트는 PR이 명시적으로 범위에 넣지 않는 한 알려진 한계로 둡니다.
새 로케일을 추가하는 단계별 안내(UI 사전, README, 언어 전환기, 지역별 용어)는 [`TRANSLATIONS.md`](TRANSLATIONS.md)를 참고하세요.
---
## 코드 스타일
포매팅에 까다롭게 굴지는 않지만(저장 시 Prettier로 충분합니다), 두 가지 규칙은 양보할 수 없습니다. 프롬프트 스택과 사용자에게 노출되는 API에 그대로 드러나기 때문입니다.
1. **JS/TS는 작은따옴표.** escape 때문에 보기 흉해지는 경우가 아니라면 문자열은 작은따옴표로 감쌉니다. 코드베이스는 이미 일관되니 맞춰주세요.
2. **주석은 영어로.** PR이 Deutsch나 中文로 번역하는 작업이더라도 코드 주석은 영어로 둡니다. grep으로 찾을 수 있는 참조를 한 벌로 유지하기 위해서입니다.
그 외에:
- **설명조 주석은 쓰지 마세요.** `// import the module`이나 `// loop through items` 같은 것 말입니다. 코드만 봐도 명백하다면 그 주석은 잡음입니다. 주석은 코드로 표현할 수 없는 의도나 제약에만 쓰세요.
- **`apps/web/src/`는 TypeScript를 씁니다.** daemon(`apps/daemon/`)은 타입이 중요한 곳에 JSDoc을 붙인 순수 ESM JavaScript입니다. 그대로 유지하세요.
- **새 최상위 의존성을 추가하지 마세요.** 추가한다면 얻는 것과 늘어나는 번들 크기를 PR 설명에 한 단락으로 적으세요. [`package.json`](package.json)의 의존성 목록은 일부러 작게 둡니다.
- **푸시 전에 `pnpm typecheck`를 실행하세요.** CI에서도 돌립니다. 실패하면 "고쳐주세요" 코멘트를 받게 됩니다.
---
## 커밋과 pull request
- **PR 하나에 관심사 하나.** skill 추가 + 파서 리팩터링 + 의존성 버전 업은 PR 세 개입니다.
- **제목은 명령형 + 범위.** `add dating-web skill`, `fix daemon SSE backpressure when CLI hangs`, `docs: clarify .od layout`처럼 씁니다.
- **PR 템플릿을 사용하세요.** [`.github/pull_request_template.md`](.github/pull_request_template.md)의 모든 섹션(Why, What users will see, Surface area, Screenshots(UI인 경우), Bug fix verification(버그 수정인 경우), Validation)을 채우세요. 빈 섹션에는 "채워주세요" 답변이 달립니다.
- **본문에는 이유를 적으세요.** "이게 뭘 하는지"는 보통 diff만 봐도 알 수 있습니다. 정작 드러나지 않는 것은 "이게 왜 있어야 하는지"입니다.
- **issue가 있다면 연결하세요.** issue가 없고 PR이 사소하지 않다면 먼저 issue를 열어주세요. 시간을 쏟기 전에 그 변경을 원하는지 합의할 수 있습니다.
- **리뷰 중에는 squash하지 마세요.** fixup 커밋을 푸시하면 머지할 때 우리가 squash합니다.
- **공유 브랜치에 force-push하지 마세요.** 리뷰어가 요청한 경우는 예외입니다.
CLA는 요구하지 않습니다. Apache-2.0으로 충분하며, 당신의 기여도 같은 라이선스를 따릅니다.
---
## 버그 신고하기
다음 내용을 담아 issue를 열어주세요.
- 무엇을 실행했는지(정확한 `pnpm tools-dev ...` 호출).
- 어떤 agent CLI를 선택했는지(또는 BYOK 경로였는지).
- 이를 유발한 skill + design system 조합.
- 관련된 **daemon stderr 끝부분**. "artifact가 렌더링되지 않았다"는 신고 대부분은 `spawn ENOENT`나 CLI의 실제 오류가 보이면 30초 만에 원인이 잡힙니다.
- UI 문제라면 스크린샷.
프롬프트 스택 버그("agent가 보라색 그라데이션 hero를 내보냈는데, slop 블랙리스트가 그걸 막았어야 했다")라면 **assistant 메시지 전문**을 함께 넣어주세요. 위반이 모델 탓인지 프롬프트 탓인지 볼 수 있습니다.
---
## 질문하기
- 아키텍처 질문, 설계 질문, "이게 버그인지 오용인지" → [GitHub Discussions](https://github.com/nexu-io/open-design/discussions) (권장 — 다음 사람이 검색할 수 있습니다).
- "X를 하는 skill을 어떻게 작성하나요" → discussion을 열어주세요. 답해드리고, 빠져 있던 패턴이라면 그 답을 [`docs/skills-protocol.md`](docs/skills-protocol.md)에 정리합니다.
---
## 받지 않는 것
프로젝트의 초점을 유지하기 위해, 다음과 같은 PR은 열지 말아주세요.
- **모델 런타임을 vendor로 포함.** OD의 핵심 베팅은 "이미 쓰고 있는 CLI면 충분하다"입니다. `pi-ai`나 OpenAI 키, 모델 로더를 제공하지 않습니다.
- **사전 논의 없이 현재 스택에서 벗어나는 프론트엔드 재작성.** Next.js 16 App Router + React 18 + TS가 기준선입니다. maintainer가 명시적으로 그 마이그레이션을 원하지 않는 한 Astro, Solid, Svelte 같은 다른 프레임워크로의 재작성은 받지 않습니다.
- **daemon을 serverless 함수로 대체.** daemon의 존재 이유는 실제 `cwd`를 소유하고 실제 CLI를 spawn하는 것입니다. SPA를 Vercel에 배포하는 것은 괜찮지만, daemon은 daemon으로 남습니다.
- **텔레메트리 / 분석 / phone-home 추가.** OD는 local-first입니다. 외부로 나가는 호출은 사용자가 명시적으로 설정한 provider로 향하는 것뿐입니다.
- **바이너리 번들링** 시 라이선스 파일과 저작자 표기를 옆에 두지 않는 경우.
아이디어가 적합한지 모르겠다면 코드를 작성하기 전에 discussion을 열어주세요.
---
## Maintainer 되기
꾸준히 기여해 왔고 Maintainer가 되는 길이 궁금하다면, 규칙은 **[`MAINTAINERS.ko.md`](MAINTAINERS.ko.md)**에 있습니다. 요약하면 이렇습니다.
- Maintainer는 issue를 리뷰하고 승인하고 닫을 수 있습니다. 머지 버튼은 Core Team이 쥐고 있지만, 당신의 승인은 머지에 필요한 승인으로 그대로 인정됩니다.
- 기준은 **머지된 PR 20건 이상**에 더해, 공개된 계정 품질 검증(봇 방지, sock-puppet 방지)과 기여 품질에 대한 Core Team의 판단입니다. 지원서 양식은 없습니다. Core Team이 내부적으로 후보를 올리고 직접 연락합니다.
- **할당량도, SLA도, 정해진 임기도 없습니다.** 물러나는 일은 쉽고 되돌릴 수 있습니다(Emeritus → 여유가 생기면 복귀).
- 모든 기준, 추천 절차, 물러나는 규칙, 초기 프로젝트 면제 조항은 [`MAINTAINERS.ko.md`](MAINTAINERS.ko.md)에 있습니다. 위 내용 중 관심 가는 게 있다면 그 문서를 읽어보세요.
요컨대 좋은 PR을 내고, 사려 깊게 리뷰하고, [Discussions][discussions]와 [Discord][discord]에서 어울리다 보면 나머지는 알아서 따라옵니다.
[discussions]: https://github.com/nexu-io/open-design/discussions
[discord]: https://discord.gg/qhbcCH8Am4
---
## 라이선스
기여하면, 당신의 기여가 이 저장소의 [Apache-2.0 License](LICENSE)를 따른다는 데 동의하는 것입니다. 단 [`design-templates/guizang-ppt/`](design-templates/guizang-ppt/) 안의 파일은 예외로, 원래의 MIT 라이선스와 [op7418](https://github.com/op7418)에 대한 저작자 표기를 그대로 유지합니다.
[skill]: https://docs.anthropic.com/en/docs/claude-code/skills
[guizang]: https://github.com/op7418/guizang-ppt-skill
[acd2]: https://github.com/VoltAgent/awesome-design-md
[ocod]: https://github.com/OpenCoworkAI/open-codesign

191
MAINTAINERS.ko.md Normal file
View file

@ -0,0 +1,191 @@
# Maintainers
<p align="center"><a href="MAINTAINERS.md">English</a> · <a href="MAINTAINERS.pt-BR.md">Português (Brasil)</a> · <a href="MAINTAINERS.de.md">Deutsch</a> · <a href="MAINTAINERS.fr.md">Français</a> · <a href="MAINTAINERS.zh-CN.md">简体中文</a> · <a href="MAINTAINERS.ja-JP.md">日本語</a> · <b>한국어</b></p>
이 문서는 `nexu-io/open-design`의 Maintainer가 되고, 그 역할을 맡고, 물러나는 규칙을 정합니다. Core Team의 개별 명단은 내부에서 관리하므로 여기에 적지 않습니다. 공개적으로 중요한 건 모두가 따르는 규칙 그 자체입니다.
> **상태**: v1, 2026-05-11 초안 작성. [`CONTRIBUTING.ko.md`](CONTRIBUTING.ko.md#maintainer-되기)와 짝을 이루는 문서입니다. CONTRIBUTING.ko.md는 전체 규칙을 확인하려는 기여자를 이 문서로 안내합니다.
---
## 역할
| 역할 | 권한 |
|---|---|
| **Contributor** | 머지된 PR이 1건 이상인 모든 사람. 특별한 권한은 없습니다. |
| **External Maintainer** | 아래 규칙에 따라 승격된 커뮤니티 기여자. 리뷰, 승인, issue 닫기/다시 열기, issue 셀프 배정을 할 수 있습니다. **머지 버튼은 누를 수 없습니다** — 이 권한은 Core Team이 갖습니다. |
| **Core Team** | Open Design의 내부 팀. 저장소 전체 쓰기 권한을 갖고, 거버넌스 결정의 최종 권한을 가집니다. 명단은 내부에서 관리합니다. |
별도 언급이 없으면 이 문서의 나머지는 모두 **External Maintainer**에 관한 내용입니다.
---
## Maintainer만 할 수 있고 Contributor는 할 수 없는 것
| 동작 | Contributor | Maintainer |
|---|:---:|:---:|
| PR 승인 | ⚠️ 단순 코멘트로 처리되며, 머지에 필요한 승인으로 **인정되지 않음** | ✓ 머지에 필요한 승인으로 인정됨 |
| issue 닫기 / 다시 열기 | 본인이 연 issue만 | ✓ 모든 issue |
| 열려 있고 배정되지 않은 issue 셀프 배정(P0 우선) | ✗ | ✓ |
### 머지 조건
PR은 누가 작성했든 다음 **세 가지를 모두** 만족해야 합니다.
1. 코드 충돌이 없을 것.
2. CI가 완전히 통과(green)할 것.
3. Maintainer 또는 Core Team 멤버의 승인이 최소 1건 있을 것.
대부분의 PR은 Maintainer의 승인을 거쳐 머지됩니다. Maintainer의 신뢰가 프로젝트의 일상에 가장 직접적으로 드러나는 방식입니다.
---
## Maintainer가 되는 방법
진입 조건은 **세 가지**이며, 모두 충족해야 합니다.
### 1. 기여량
- `nexu-io/open-design`에 머지된 PR **20건 이상**.
이 수치는 자동 통과 기준이 아니라 최소선입니다. PR 20건을 넘기면 검토 대상에 오를 뿐, 역할이 보장되지는 않습니다.
### 2. 계정 신뢰도(다중 계정·봇 방지)
후보의 GitHub 프로필을 일곱 가지 항목으로 점검합니다. **7개 중 5개 이상의 통과 기준을 만족하고, 거부 기준은 하나도 건드리지 않아야 합니다.**
| # | 항목 | 통과 기준 | 거부 기준 |
|---|---|---|---|
| 1 | GitHub 계정 나이 | 1년 이상 | 90일 미만 |
| 2 | 공개 저장소 | 3개 이상 | 0개 |
| 3 | 팔로워 | 10명 이상 | 3명 미만 |
| 4 | 팔로워 / 팔로잉 비율 | 0.30 초과 | 0.05 미만(전형적인 팔로우 농장 패턴) |
| 5 | 프로필 완성도 | 커스텀 아바타 **그리고** bio / company / blog / twitter 중 하나 이상 | 기본 아바타 **그리고** bio·company·blog가 모두 비어 있음 |
| 6 | 다른 프로젝트 활동 | **다른** 공개 저장소에 머지된 PR이 하나 이상 있거나, issue/star 활동이 꾸준함 | 머지된 PR이 이 저장소에만 있음 |
| 7 | 계정 상태 | GitHub 플랫폼 제재 이력 없음(스팸/차단/복구) | 위 항목 중 하나라도 해당 |
#### 초기 프로젝트 면제(저장소가 6개월이 되면 자동 만료)
`nexu-io/open-design`이 최초 커밋으로부터 6개월 미만인 동안에는, 다음 조건에서 **다른 프로젝트 활동**(#6) 거부 기준을 Core Team 합의로 면제할 수 있습니다.
- 항목 1, 2, 3, 5가 통과 기준을 명확히 넘을 것, **그리고**
- 이 저장소에서의 PR 품질이 Core Team의 직접 리뷰로 높게 평가될 것.
면제할 때는 후보 이름과 날짜를 Core Team 내부 기록에 함께 남깁니다. 저장소가 6개월에 도달하면 이 면제 조항은 더 이상 적용되지 않습니다.
### 3. 기여 품질(Core Team 판단)
정성적인 평가이며 공식에 따르지 않습니다. Core Team은 다음을 봅니다.
- 머지된 PR의 **코드 품질**(정확성, 작업 범위 준수, 저장소 경계 존중).
- 다른 사람의 PR에 남긴 리뷰 코멘트의 **리뷰 품질**.
- **커뮤니티 참여** — Discussions, issue 분류, Discord 활동.
- **협업 신호** — 피드백에 대한 반응, 기꺼이 수정하려는 자세.
앞의 두 조건을 통과하면 후보군에 들어갑니다. 이 세 번째 기준을 넘어서야 지명을 받습니다.
### 선정 절차
1. Core Team 멤버가 내부에서 후보를 제안합니다.
2. Core Team이 합의에 이릅니다.
3. Core Team 멤버가 비공개로 연락해 후보의 의사를 확인합니다.
4. 온보딩.
5. 공개 발표.
지명 PR도, 공개 투표도, 정해진 임기도 없습니다. 이는 의도적으로 **K8s/Apache의 승인자 투표 모델을 뒤집은** 방식입니다. 프로젝트 초기에는 가벼운 Core Team 합의가 더 빠르게 움직이면서도 같은 수준의 결과를 냅니다. Maintainer 인원이 External Maintainer 다섯 명을 넘어 늘어나면 이 부분을 다시 검토합니다.
---
## 책임과 기대
**엄격한 할당량은 없습니다.** 주간 PR 리뷰 횟수도, 최소 issue 분류 비율도, 응답 시간 SLA도 없습니다. Maintainer는 신뢰의 인정이지, 보수 없는 업무가 아닙니다.
다만 원칙적으로 부탁드리는 것은 다음과 같습니다.
- 맥락을 아는 PR은 승인하고, 모르는 PR은 판단을 보류하세요.
- 머지 조건(§"머지 조건")을 지키세요. 당신의 승인은 형식적인 도장이 아니라 실질적인 신호입니다.
- 오랜 기간 자리를 비울 때는 `#maintainers`에 알려 주세요.
- `#maintainers`에서 공유되는 미공개 로드맵은 기밀로 다뤄 주세요.
Core Team이 나쁜 행태(형식적 승인, 악의적 issue 닫기, 미공개 로드맵 유출 등)의 패턴을 확인하면, §"사유 기반 사임"에 따라 권한을 회수합니다.
---
## Maintainer 전용 접근 권한
위에 적은 저장소 권한 외에도, Maintainer는 일반 커뮤니티가 받지 못하는 몇 가지를 받습니다.
- **Discord `#maintainers` 채널** — Core Team과 공유하는 비공개 작업 공간. 디자인 미리보기, RFC 초안, 그리고 아직 공개되지 않은 로드맵에 대한 내부 조율에 씁니다.
- **기밀 로드맵** — 아직 발표되지 않은 작업을 미리 볼 수 있습니다. Maintainer는 Core Team 멤버가 공개로 발표하기 전까지 그 내용을 기밀로 다루기로 합의합니다.
- **Core Team과의 직통 라인**`#maintainers` 메시지는 공개 Discussions보다 더 빠르고 충실한 답을 받습니다. Core Team은 아키텍처와 로드맵 결정에 Maintainer의 의견을 진심으로 구합니다.
- **Maintainer 배지** — GitHub 프로필과 MAINTAINERS 관련 저장소 화면에 표시되는 공개 신뢰 표식(GitHub 배지 기능이 준비되는 대로 적용).
- **승격 시 공개 인정** — 합류할 때 Twitter, GitHub Discussions, Discord에서 발표합니다.
---
## 사임
Maintainer는 종신직이 아닙니다. 세 가지 퇴장 경로가 있습니다.
### 자발적 사임(스스로)
- Maintainer가 Core Team에 메시지를 보내거나 `#maintainers`에 글을 올립니다.
- 권한은 24시간 안에 회수됩니다.
- 해당 Maintainer는 **Emeritus** 상태로 전환됩니다.
- 공개적인 사유는 필요 없습니다.
### 비활동 전환
다음 중 **하나라도** 해당하면 비활동 전환 대상으로 검토합니다.
- 활동 신호(머지된 PR, 리뷰 코멘트, issue 분류, 비중 있는 Discussion이나 Discord 참여)가 90일 연속 없거나, **또는**
- @ 멘션(PR 리뷰 요청, issue 배정)에 60일 연속 응답이 없음.
절차:
1. Core Team이 `#maintainers`에서 해당 Maintainer를 비공개로 @ 멘션하고, **14일의 응답 기간**을 줍니다.
2. 14일 안에 의미 있는 응답이 없으면 Emeritus로 전환되고 권한이 회수됩니다.
3. GitHub Discussions에 짧고 따뜻한 공개 안내를 올립니다: "그동안의 기여에 감사합니다. Emeritus로 전환되었으며, 언제든 다시 돌아오셔도 좋습니다."
4. 복귀는 쉽습니다 — 아래 "Emeritus"를 참고하세요.
### 사유 기반 사임
다음에 의해 발동됩니다.
- 반복되는 나쁜 행태(예: 함량 미달 PR에 대한 형식적 승인, 악의적 issue 닫기, 권한 남용).
- 프로젝트 [행동 강령][coc] 위반.
- 보안 등급의 사고(계정 탈취를 즉시 보고하지 않음, 미공개 로드맵 고의 유출 등).
절차:
1. Core Team 멤버는 누구나 논의를 시작할 수 있습니다.
2. 조치를 취하기 전에 **Core Team 멤버 3명 이상**이 동의해야 합니다(Core Team 전원 합의까지는 필요하지 않습니다).
3. 결정 후 24시간 안에: 권한 회수, `#maintainers`에서 제외, 모든 Maintainer 명단에서 제거(Emeritus로 전환되지 **않습니다**).
4. 당사자에게 결정과 사유를 알리며, 한 차례 이의를 제기할 수 있습니다.
원칙은 **Maintainer를 가급적 유지하는 쪽**입니다. 작은 실수 한 번은 강제 사임의 사유가 되지 않습니다. 사유 기반 경로는 반복되는 패턴이나 심각한 일회성 사고에만 적용합니다.
[coc]: https://www.contributor-covenant.org/
---
## Emeritus
자발적으로 사임하거나 비활동으로 전환된 Maintainer는 **Emeritus**가 됩니다. Emeritus 상태는 다음과 같습니다.
- 쓰기/승인/닫기 권한을 회수합니다.
- (내부) 명단의 Emeritus 항목에 이름을 남겨 공로를 기립니다.
- Discord `#maintainers` 접근 권한을 유지합니다(읽기든 글쓰기든 Maintainer가 선택).
- 이어지는 책임은 없습니다.
### Emeritus에서 복귀
가장 간단한 복귀 경로: 최근 30일 안에 머지된 PR 3건. 그러면 Core Team이 권한을 복원합니다. 다시 지명받을 필요는 없습니다.
Emeritus의 취지는 인생에는 늘 일이 생긴다는 점을 인정하는 것입니다. 안식년, 이직, 육아 같은 일을 양쪽 모두에게 아무런 부담이나 사회적 비용 없이 받아들이려는 것입니다.
---
## 이 문서의 변경
이 문서의 규칙은 Core Team 합의로 개정할 수 있습니다. 중대한 변경(진입 조건, 사임 기준)은 활동 중인 후보에게 적용되기 전에 GitHub Discussions에 발표합니다. 편집상의 명확화는 곧바로 반영할 수 있습니다.

391
QUICKSTART.ko.md Normal file
View file

@ -0,0 +1,391 @@
# 빠른 시작
<p align="center"><a href="QUICKSTART.md">English</a> · <a href="QUICKSTART.pt-BR.md">Português (Brasil)</a> · <a href="QUICKSTART.de.md">Deutsch</a> · <a href="QUICKSTART.fr.md">Français</a> · <a href="QUICKSTART.ja-JP.md">日本語</a> · <a href="QUICKSTART.zh-CN.md">简体中文</a> · <a href="QUICKSTART.zh-TW.md">繁體中文</a> · <b>한국어</b></p>
제품 전체를 로컬에서 실행해 보세요.
## 환경 요구사항
- **Node.js:** `~24`(Node 24.x). `package.json#engines`로 버전을 강제합니다.
- **pnpm:** `10.33.x`. `packageManager``pnpm@10.33.2`를 고정해 두었으니, Corepack을 쓰면 고정된 버전이 자동으로 선택됩니다.
- **OS:** macOS, Linux, WSL2가 주요 지원 환경입니다. Windows 네이티브도 지원합니다. 자주 겪는 설치 문제는 [`docs/windows-troubleshooting.md`](docs/windows-troubleshooting.md)를 참고하세요.
- **선택: 로컬 에이전트 CLI:** Claude Code, Codex, Devin for Terminal, Gemini CLI, OpenCode, Cursor Agent, Qwen, Qoder CLI, GitHub Copilot CLI 등. 설치된 CLI가 없으면 Settings에서 BYOK API 모드를 쓰면 됩니다.
### 로컬 에이전트 CLI와 PATH
daemon은 **`PATH`**(여기에 더해 자주 쓰이는 사용자 툴체인 디렉터리)를 스캔합니다. **`npm install -g`**나 **Homebrew**로 CLI를 설치했는데도 Open Design이 *not installed*로 표시한다면, GUI가 최소한의 `PATH`로 시작하면서 전역 npm이나 Homebrew의 `bin` 디렉터리를 포함하지 못한 경우입니다(앱이 전체 로그인 셸에서 실행되지 않은 macOS에서 흔히 발생). daemon을 실행하는 프로세스의 `PATH`에 실행 파일 디렉터리가 들어 있는지 확인한 뒤, **Settings → Execution mode**에서 **Rescan**을 누르세요.
[`nvm`](https://github.com/nvm-sh/nvm) / [`fnm`](https://github.com/Schniz/fnm)은 편의를 위한 선택 도구일 뿐, 프로젝트 설정에 꼭 필요한 것은 아닙니다. 둘 중 하나를 쓴다면 pnpm을 실행하기 전에 Node 24를 설치하고 선택하세요.
```bash
# nvm
nvm install 24
nvm use 24
# fnm
fnm install 24
fnm use 24
```
그다음 Corepack을 켜고 리포지토리가 pnpm을 선택하도록 합니다.
```bash
corepack enable
corepack pnpm --version # 10.33.2가 출력되어야 합니다
```
## Docker 설정
Node.js나 pnpm을 로컬에 설치하지 않고도, 완전히 컨테이너화된 환경에서 Open Design을 실행할 수 있습니다.
### 요구사항
* Docker Desktop
* Docker Compose v2
Docker가 제대로 설치됐는지 확인하세요.
```bash
docker compose version
```
---
## Open Design 시작하기
리포지토리 루트에서 진행합니다.
1. deploy 디렉터리로 이동한 뒤 환경 변수 템플릿을 복사합니다.
```bash
cd deploy
cp .env.example .env
```
2. 안전한 토큰을 생성합니다.
```bash
openssl rand -hex 32
```
3. 에디터에서 `.env`를 열고 `OD_API_TOKEN=`을 찾아, 방금 생성한 토큰을 붙여 넣습니다.
이제 서비스를 시작합니다.
```bash
docker compose up -d
```
브라우저에서 앱을 엽니다.
```text
http://localhost:7456
```
처음 시작할 때는 Docker가 최신 이미지를 받아오느라 몇 초 걸릴 수 있습니다.
---
## 자주 쓰는 Docker 명령어
### 로그 보기
```bash
docker compose logs -f
```
### 컨테이너 재시작
```bash
docker compose restart
```
### 컨테이너 중지
```bash
docker compose down
```
### 최신 이미지 받아오기
```bash
docker compose pull
docker compose up -d
```
### 로컬 앱 데이터 전부 삭제
```bash
docker compose down -v
```
---
## 환경 설정
기본 설정을 덮어쓰려면 `deploy/.env` 파일을 만드세요. 제공된 예시에서 시작하면 됩니다.
```bash
cp deploy/.env.example deploy/.env
```
`deploy/.env`를 편집해 직접 만든 토큰을 넣고, 나머지 값도 필요에 맞게 조정합니다.
```env
# 호스트에 노출할 포트
OPEN_DESIGN_PORT=7456
# 컨테이너 메모리 제한
OPEN_DESIGN_MEM_LIMIT=384m
# 허용할 CORS origin
OPEN_DESIGN_ALLOWED_ORIGINS=https://yourdomain.com
# Docker 이미지 태그
OPEN_DESIGN_IMAGE=docker.io/vanjayak/open-design:latest
# daemon 보안에 필요한 API 토큰
# 생성 방법: openssl rand -hex 32
OD_API_TOKEN=
```
---
## 영구 저장소
Open Design은 프로젝트와 SQLite 데이터를 Docker 볼륨 안에 저장합니다.
```text
open_design_data
```
이 볼륨은 다음 경로에 마운트됩니다.
```text
/app/.od
```
데이터는 컨테이너를 재시작하거나 이미지를 업데이트해도 그대로 유지됩니다.
볼륨을 확인하려면:
```bash
docker volume inspect open-design_open_design_data
```
---
## 참고
* Docker 모드는 로컬에 Node.js나 pnpm을 설치하고 싶지 않은 기여자에게 적합합니다.
* 컨테이너는 프로덕션 daemon 빌드를 `7456` 포트에 직접 노출합니다.
* 개발 워크플로우와 더 깊은 로컬 설정은 이 빠른 시작 가이드의 나머지 부분을 참고하세요.
---
## 한 번에 실행하기 (dev 모드)
```bash
corepack enable
pnpm install
pnpm tools-dev run web # daemon + web을 포그라운드로 시작합니다
# tools-dev가 출력한 web URL을 엽니다
```
데스크톱 셸과 관리 대상 sidecar 전부를 백그라운드로 실행하려면:
```bash
pnpm tools-dev # daemon + web + desktop을 백그라운드로 시작합니다
```
처음 로드하면 앱은 설치된 코드 에이전트 CLI(Claude Code / Codex / Devin for Terminal / Gemini / OpenCode / Cursor Agent / Qwen / Qoder CLI)를 감지해 자동으로 선택하고, 기본값으로 `web-prototype` skill과 `Neutral Modern` 디자인 시스템을 씁니다. 프롬프트를 입력하고 **Send**를 누르세요. 에이전트가 왼쪽 패널에 스트리밍되고, `<artifact>` 태그가 파싱되면서 HTML이 오른쪽에 실시간으로 렌더링됩니다. 작업이 끝나면 **Save to disk**를 눌러 artifact를 `./.od/artifacts/<timestamp>-<slug>/index.html`에 저장하세요.
**Design system** 드롭다운에는 71개의 내장 시스템이 들어 있습니다. 직접 작성한 스타터 2개(Neutral Modern, Warm Editorial)와 [`awesome-design-md`](https://github.com/VoltAgent/awesome-design-md)에서 가져온 69개의 제품 시스템으로, 카테고리별(AI & LLM, Developer Tools, Productivity, Backend, Design Tools, Fintech, E-Commerce, Media, Automotive)로 묶여 있습니다. 하나를 고르면 모든 프로토타입이 그 브랜드의 미감으로 입혀집니다. 여기에 [`awesome-design-skills`](https://github.com/bergside/awesome-design-skills)에서 가져온 57개의 디자인 skill도 함께 제공됩니다.
**Skill** 드롭다운은 모드별(Prototype / Deck / Template / Design system)로 묶이며, 각 모드의 기본 skill에는 `· default` 접미사가 붙습니다. 함께 제공되는 skill은 다음과 같습니다.
- **Prototype**`web-prototype`(범용), `saas-landing`, `dashboard`, `pricing-page`, `docs-page`, `blog-post`, `mobile-app`.
- **Deck / PPT**`simple-deck`(단일 파일 가로 스와이프)과 `magazine-web-ppt`([`op7418/guizang-ppt-skill`](https://github.com/op7418/guizang-ppt-skill)에서 가져온 `guizang-ppt` 번들. deck 모드의 기본값이며, 자체 에셋/템플릿과 레퍼런스 4개를 함께 제공). 사이드 파일이 있는 skill에는 "Skill root (absolute)" 머리말이 자동으로 붙어, 에이전트가 `assets/template.html`이나 `references/*.md`를 CWD가 아니라 실제 디스크 경로 기준으로 해석할 수 있습니다.
skill과 디자인 시스템을 짝지으면, 프롬프트 하나로 선택한 시각 언어에 맞는 프로토타입이나 deck이 레이아웃에 맞게 생성됩니다.
## 그 밖의 스크립트
```bash
pnpm tools-dev # daemon + web + desktop을 백그라운드로
pnpm tools-dev start web # daemon + web을 백그라운드로
pnpm tools-dev run web # daemon + web을 포그라운드로 (e2e/dev 서버)
pnpm tools-dev restart # daemon + web + desktop 재시작
pnpm tools-dev restart --daemon-port 7457 --web-port 5175
pnpm tools-dev status # 관리 중인 런타임 확인
pnpm tools-dev logs # daemon/web/desktop 로그 보기
pnpm tools-dev check # 상태 + 최근 로그 + 일반 진단
pnpm tools-dev stop # 관리 중인 런타임 중지
pnpm --filter @open-design/daemon build # `od`용 apps/daemon/dist/cli.js 빌드
pnpm --filter @open-design/web build # 필요할 때 web 패키지 빌드
pnpm typecheck # 워크스페이스 타입 체크
```
로컬 라이프사이클의 진입점은 `pnpm tools-dev` 하나뿐입니다. 삭제된 옛 루트 alias(`pnpm dev`, `pnpm dev:all`, `pnpm daemon`, `pnpm preview`, `pnpm start`)는 쓰지 마세요.
로컬 개발 중에는 `tools-dev`가 daemon을 먼저 띄우고 그 포트를 `apps/web`에 넘깁니다. `apps/web/next.config.ts``/api/*`, `/artifacts/*`, `/frames/*`를 그 daemon 포트로 다시 매핑하므로, App Router 앱이 CORS 설정 없이도 옆에서 도는 Express 프로세스와 통신할 수 있습니다.
## 미디어 생성 / 에이전트 dispatcher 점검
이미지, 비디오, 오디오, HyperFrames skill은 daemon이 에이전트를 spawn할 때 주입하는 환경 변수를 통해 로컬 `od` CLI를 호출합니다.
- `OD_BIN``apps/daemon/dist/cli.js`의 절대 경로.
- `OD_DAEMON_URL` — 실행 중인 daemon URL.
- `OD_PROJECT_ID` — 활성 프로젝트 id.
- `OD_PROJECT_DIR` — 활성 프로젝트의 파일 디렉터리.
미디어 생성이 `OD_BIN: parameter not set`, `apps/daemon/dist/cli.js` 누락, `failed to reach daemon at http://127.0.0.1:0` 같은 메시지로 실패하면, daemon CLI를 다시 빌드하고 관리 중인 런타임을 재시작하세요.
```bash
pnpm --filter @open-design/daemon build
pnpm tools-dev restart --daemon-port 7457 --web-port 5175
ls -la apps/daemon/dist/cli.js
curl -s http://127.0.0.1:7457/api/health
```
그다음 오래된 터미널 에이전트 세션을 이어 가지 말고, Open Design 앱에서 프로젝트를 다시 여세요. daemon이 spawn한 에이전트라면 다음과 같은 값이 보여야 합니다.
```bash
echo "OD_BIN=$OD_BIN"
echo "OD_PROJECT_ID=$OD_PROJECT_ID"
echo "OD_PROJECT_DIR=$OD_PROJECT_DIR"
echo "OD_DAEMON_URL=$OD_DAEMON_URL"
ls -la "$OD_BIN"
```
`OD_DAEMON_URL``http://127.0.0.1:7457`처럼 실제 daemon 포트여야 하며, `http://127.0.0.1:0`이어서는 안 됩니다. `:0` 값은 "빈 포트를 골라라"라는 내부 실행 힌트일 뿐이라, 에이전트 세션으로 새어 나가면 안 됩니다.
daemon 단독 프로덕션 모드에서는 daemon이 정적 Next.js export를 `http://localhost:7456`에서 직접 서빙하므로, reverse proxy가 끼어들지 않습니다.
daemon 앞에 nginx를 둔다면, SSE 경로는 버퍼링과 압축을 끄세요. 흔한 실패는 80~90초 뒤 브라우저 콘솔에 `net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK)`가 뜨는 경우입니다. daemon이 `X-Accel-Buffering: no`를 보내도 nginx의 `gzip on`이 청크 SSE 응답을 버퍼링하기 때문입니다.
```nginx
location /api/ {
proxy_pass http://127.0.0.1:7456;
proxy_buffering off;
gzip off;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
```
## 두 가지 실행 모드
| 모드 | 선택값 | 요청이 흐르는 경로 |
|---|---|---|
| **Local CLI** (daemon이 에이전트를 감지하면 기본값) | "Local CLI" | 프론트엔드 → daemon `/api/chat``spawn(<agent>, ...)` → stdout → SSE → artifact 파서 → 미리보기 |
| **API 모드** (대체 수단 / CLI 없음) | "Anthropic API" / "OpenAI API" / "Azure OpenAI" / "Google Gemini" | 프론트엔드 → daemon `/api/proxy/{provider}/stream` → 프로바이더 SSE를 `delta/end/error`로 정규화 → artifact 파서 → 미리보기 |
두 모드 모두 **같은** `<artifact>` 파서와 **같은** 샌드박스 iframe으로 들어갑니다. 다른 점은 전송 방식과 시스템 프롬프트 전달 방식뿐입니다(로컬 CLI는 별도의 시스템 채널이 없어서, 조합된 프롬프트를 사용자 메시지 안에 접어 넣습니다).
## 프롬프트 구성
전송할 때마다 앱은 세 개의 레이어로 시스템 프롬프트를 만들어 프로바이더에 보냅니다.
```
BASE_SYSTEM_PROMPT (출력 규약: <artifact>로 감싸고, 코드 펜스는 쓰지 않는다)
+ 활성 디자인 시스템 본문 (DESIGN.md — 팔레트/타입/레이아웃)
+ 활성 skill 본문 (SKILL.md — 워크플로우와 출력 규칙)
```
상단 바에서 skill이나 디자인 시스템을 바꾸면, 다음 전송부터 새 조합이 적용됩니다. 본문은 세션별로 메모리에 캐시되므로, 한 번 선택할 때 daemon에 한 번만 요청합니다.
## 파일 맵
```
open-design/
├── apps/
│ ├── daemon/ # Node/Express — 로컬 에이전트 spawn + API 서빙
│ │ └── src/
│ │ ├── cli.ts # `od` bin 진입점
│ │ ├── server.ts # /api/* + 정적 서빙
│ │ ├── agents.ts # claude/codex/devin/gemini/opencode/cursor-agent/qwen/qoder/copilot용 PATH 스캐너
│ │ ├── skills.ts # SKILL.md 로더 (frontmatter 파서)
│ │ └── design-systems.ts # DESIGN.md 로더
│ │ ├── sidecar/ # tools-dev daemon sidecar 래퍼
│ │ └── tests/ # daemon 패키지 테스트
│ ├── web/ # Next.js 16 App Router + React 클라이언트
│ ├── app/ # App Router 진입점
│ ├── src/ # React + TypeScript 클라이언트/런타임 모듈
│ │ ├── App.tsx # 모드 / skill / DS 선택기 + 전송 조율
│ │ ├── providers/ # daemon + BYOK API 전송 계층
│ │ ├── prompts/ # system, discovery, directions, deck framework
│ │ ├── artifacts/ # 스트리밍 <artifact> 파서 + manifest
│ │ ├── runtime/ # iframe srcdoc, markdown, export 헬퍼
│ │ └── state/ # localStorage + daemon 기반 프로젝트 상태
│ ├── sidecar/ # tools-dev web sidecar 래퍼
│ └── next.config.ts # tools-dev rewrite + prod apps/web/out export 설정
│ └── desktop/ # tools-dev가 실행/점검하는 Electron 런타임
├── packages/
│ ├── contracts/ # 공유 web/daemon 앱 contract
│ ├── sidecar-proto/ # Open Design sidecar 프로토콜 contract
│ ├── sidecar/ # 범용 sidecar 런타임 프리미티브
│ └── platform/ # 범용 process/platform 프리미티브
├── tools/dev/ # `pnpm tools-dev` 라이프사이클 및 inspect CLI
├── e2e/ # Playwright UI + 외부 통합/Vitest 하네스
├── skills/ # SKILL.md — 어떤 Claude Code skill 리포지토리에서든 그대로 넣을 수 있음
│ ├── web-prototype/ # 범용 단일 화면 프로토타입 (prototype 모드 기본값)
│ ├── saas-landing/ # 마케팅 페이지 (hero / features / pricing / CTA)
│ ├── dashboard/ # 관리자 / 분석 대시보드
│ ├── pricing-page/ # 단독 가격 + 비교
│ ├── docs-page/ # 3단 문서 레이아웃
│ ├── blog-post/ # 에디토리얼 롱폼
│ ├── mobile-app/ # 휴대폰 프레임 단일 화면
│ ├── simple-deck/ # 미니멀 가로 스와이프 deck
│ └── guizang-ppt/ # magazine-web-ppt — 번들된 deck/PPT 기본값
│ ├── SKILL.md
│ ├── assets/template.html
│ └── references/{themes,layouts,components,checklist}.md
├── design-systems/ # DESIGN.md — 9개 섹션 스키마 (awesome-claude-design)
│ ├── default/ # Neutral Modern (스타터)
│ ├── warm-editorial/ # Warm Editorial (스타터)
│ ├── README.md # 카탈로그 개요
│ └── …129개 시스템 # 스타터 2개 · 제품 시스템 70개 · 디자인 skill 57개
├── scripts/sync-design-systems.ts # 업스트림 getdesign tarball에서 다시 import
├── docs/ # 제품 비전 + 스펙
├── .od/ # 런타임 데이터 (gitignore 처리, 자동 생성)
│ ├── app.sqlite # 프로젝트 / 대화 / 메시지 / 탭
│ ├── artifacts/ # 일회성 "Save to disk" 렌더링
│ └── projects/<id>/ # 프로젝트별 작업 디렉터리 + 에이전트 cwd
├── pnpm-workspace.yaml # apps/* + packages/* + tools/* + e2e
└── package.json # 루트 품질 스크립트 + `od` bin
```
## 문제 해결
- **Node.js 버전을 바꾼 뒤 `better-sqlite3`가 로드되지 않거나 ABI가 맞지 않을 때**`pnpm install``postinstall`을 자동으로 다시 돌려 현재 Node.js에 맞게 네이티브 애드온을 리빌드합니다. 직접 리빌드하거나 수정을 확인하려면 `pnpm --filter @open-design/daemon rebuild better-sqlite3`를 실행한 뒤 `pnpm --filter @open-design/daemon exec node -e "require('better-sqlite3')"`를 돌리세요. 빌드 도구 `python3`, `make`, `g++`(또는 `clang++`)가 필요합니다. `.npmrc``ignore-scripts=true`가 있다면, `pnpm install``node scripts/postinstall.mjs`를 실행하세요.
- **"no agents found on PATH"** — `claude`, `codex`, `devin`, `gemini`, `opencode`, `cursor-agent`, `qwen`, `qodercli`, `copilot` 중 하나를 설치하세요. 아니면 Settings에서 API 모드로 바꾸고 프로바이더 키를 붙여 넣으세요.
- **Claude Code가 코드 1로 종료될 때** — Open Design이 `claude`를 시작하긴 했지만, spawn된 비대화형 실행이 응답을 내기 전에 실패한 경우입니다. Open Design을 시작하는 셸이나 앱 환경과 같은 곳에서 다음을 확인하세요.
```bash
claude --version
claude auth status --text
printf 'hello' | claude -p --output-format stream-json --verbose --permission-mode bypassPermissions
```
스모크 테스트가 커스텀 엔드포인트 없이 `401`, `apiKeySource: "none"`, 또는 다른 인증 오류를 낸다면, `claude`를 실행해 `/login`한 뒤 Claude를 종료하고 Open Design을 다시 시도하세요. Claude 프로필을 여러 개 쓴다면 **Settings -> Execution mode -> Claude Code config directory**를 `~/.claude-2` 같은 프로필 경로로 지정하세요. `ANTHROPIC_BASE_URL`이나 프록시가 설정돼 있다면 엔드포인트 URL, 프록시 자격 증명, 엔드포인트 인증 환경, 모델 접근 권한을 확인하세요. 표준 Claude Code 인증으로 다시 시도하려는 게 아니라면 커스텀 엔드포인트는 그대로 두세요. Windows에서는 네이티브 PowerShell과 WSL이 서로 다른 Claude 설치본과 자격 증명 저장소를 쓰므로, Open Design이 쓰는 것과 같은 환경에서 다시 인증하고, `/login`으로도 네이티브 Windows 자격 증명이 복구되지 않으면 Windows 자격 증명 관리자를 확인하세요.
- **`/api/chat`에서 daemon 500** — daemon 터미널의 stderr 끝부분을 확인하세요. 대개 CLI가 자신의 인자를 거부한 경우입니다. CLI마다 받는 argv 형태가 다릅니다. 손봐야 한다면 `apps/daemon/src/agents.ts``buildArgs`를 보세요.
- **미디어 생성이 `OD_BIN` 누락 또는 daemon URL이 `:0`이라고 할 때** — 위의 미디어 dispatcher 점검을 실행하세요. 옛 CLI 세션을 이어 가지 말고, Open Design 앱에서 프로젝트를 다시 열어 daemon이 새 `OD_*` 변수를 주입하게 하세요.
- **Codex가 플러그인 컨텍스트를 너무 많이 로드할 때**`OD_CODEX_DISABLE_PLUGINS=1 pnpm tools-dev`로 Open Design을 시작하면, daemon이 spawn하는 Codex 프로세스가 `--disable plugins`로 실행됩니다.
- **artifact가 끝내 렌더링되지 않을 때** — 모델이 `<artifact>`로 감싸지 않은 텍스트를 만든 경우입니다. 시스템 프롬프트가 제대로 전달되는지 확인하고(daemon 로그 확인), 더 강력한 모델이나 더 엄격한 skill로 바꿔 보세요.
## 비전과 다시 잇기
이 빠른 시작은 [`docs/`](docs/)에 담긴 스펙을 실제로 돌릴 수 있게 만든 씨앗입니다. 스펙은 이것이 어디로 자라날지 설명합니다([`docs/roadmap.md`](docs/roadmap.md) 참고). 핵심만 짚으면 다음과 같습니다.
- `docs/architecture.md`는 출시된 스택을 설명합니다. 앞단의 Next.js 16 App Router, 그 뒤의 로컬 daemon, 그리고 dev에서 `apps/web/next.config.ts`의 rewrite가 브라우저를 같은 `/api` 표면과 계속 통신하게 유지하는 구조입니다.
- `docs/skills-protocol.md``od:` frontmatter 전체(타입 입력, 슬라이더, 기능 게이팅)를 설명합니다. 이 MVP는 `name` / `description` / `triggers` / `od.mode` / `od.design_system.requires`만 읽습니다. 나머지를 추가하려면 `apps/daemon/src/skills.ts`를 확장하세요.
- `docs/agent-adapters.md`는 더 풍부한 dispatch(기능 감지, 스트리밍 tool-call)를 내다봅니다. 우리의 `apps/daemon/src/agents.ts`는 배선을 증명할 만큼만 갖춘 최소 dispatcher입니다.
- `docs/modes.md`는 네 가지 모드를 나열합니다. prototype / deck / template / design-system. 우리는 앞의 두 가지를 위한 skill을 제공하며, 선택기는 이미 `mode`로 필터링합니다.

View file

@ -33,7 +33,7 @@
<a href="#디자인-시스템"><img alt="Design systems" src="https://img.shields.io/badge/design%20systems-149-orange?style=flat-square" /></a>
<a href="#내장-skills"><img alt="Skills" src="https://img.shields.io/badge/skills-131-teal?style=flat-square" /></a>
<a href="https://discord.gg/qhbcCH8Am4"><img alt="Discord" src="https://img.shields.io/badge/discord-join-5865F2?style=flat-square&logo=discord&logoColor=white" /></a>
<a href="QUICKSTART.md"><img alt="Quickstart" src="https://img.shields.io/badge/quickstart-3%20commands-green?style=flat-square" /></a>
<a href="QUICKSTART.ko.md"><img alt="Quickstart" src="https://img.shields.io/badge/quickstart-3%20commands-green?style=flat-square" /></a>
</p>
<p align="center"><a href="README.md">English</a> · <a href="README.es.md">Español</a> · <a href="README.pt-BR.md">Português (Brasil)</a> · <a href="README.de.md">Deutsch</a> · <a href="README.fr.md">Français</a> · <a href="README.zh-CN.md">简体中文</a> · <a href="README.zh-TW.md">繁體中文</a> · <b>한국어</b> · <a href="README.ja-JP.md">日本語</a> · <a href="README.ar.md">العربية</a> · <a href="README.ru.md">Русский</a> · <a href="README.uk.md">Українська</a> · <a href="README.tr.md">Türkçe</a></p>
@ -332,7 +332,7 @@ pnpm tools-dev run web
Windows 사용자는 네이티브 설치 경로와 작은 더블 클릭 런처에 대해서는 [`docs/windows-troubleshooting.md`](docs/windows-troubleshooting.md)를 참고하세요.
데스크톱/백그라운드 시작, 고정 포트 재시작, 미디어 생성 dispatcher 확인(`OD_BIN`, `OD_DAEMON_URL`, `apps/daemon/dist/cli.js`)은 [`QUICKSTART.md`](QUICKSTART.md)를 참고하세요.
데스크톱/백그라운드 시작, 고정 포트 재시작, 미디어 생성 dispatcher 확인(`OD_BIN`, `OD_DAEMON_URL`, `apps/daemon/dist/cli.js`)은 [`QUICKSTART.ko.md`](QUICKSTART.ko.md)를 참고하세요.
첫 번째 로드 시:
@ -360,7 +360,7 @@ Daemon은 저장소 루트에 하나의 숨겨진 폴더를 소유합니다. 그
| 초기 상태로 재설정 | `pnpm tools-dev stop`, `rm -rf .od`, `pnpm tools-dev run web` 재실행 |
| 다른 위치로 이동 | 아직 지원되지 않음 — 경로가 저장소 상대 경로로 하드코딩됨 |
전체 파일 맵, 스크립트, 트러블슈팅 → [`QUICKSTART.md`](QUICKSTART.md).
전체 파일 맵, 스크립트, 트러블슈팅 → [`QUICKSTART.ko.md`](QUICKSTART.ko.md).
## 저장소 구조
@ -719,7 +719,7 @@ daemon 부팅 시 `PATH`에서 자동 감지됩니다. 설정 필요 없음. 스
- **디자인 시스템 추가** — 9섹션 스키마를 사용하여 [`design-systems/<brand>/`](design-systems/)에 `DESIGN.md`를 드롭하세요.
- **새 코딩 에이전트 CLI 연결** — [`apps/daemon/src/agents.ts`](apps/daemon/src/agents.ts)에 항목 하나 추가.
전체 설명, 병합 기준, 코드 스타일, 받지 않는 것 → [`CONTRIBUTING.md`](CONTRIBUTING.md) ([Deutsch](CONTRIBUTING.de.md), [Français](CONTRIBUTING.fr.md), [简体中文](CONTRIBUTING.zh-CN.md)).
전체 설명, 병합 기준, 코드 스타일, 받지 않는 것 → [`CONTRIBUTING.ko.md`](CONTRIBUTING.ko.md) ([English](CONTRIBUTING.md), [Deutsch](CONTRIBUTING.de.md), [Français](CONTRIBUTING.fr.md), [简体中文](CONTRIBUTING.zh-CN.md)).
## 컨트리뷰터

View file

@ -118,7 +118,7 @@ Open Design currently supports **19 languages** across different surfaces:
| Bahasa Indonesia | `id` | — | ✅ | — | active |
| Italiano | `it` | — | ✅ | — | active |
| 日本語 (Japanese) | `ja` | ✅ | ✅ | ✅ | active |
| 한국어 (Korean) | `ko` | ✅ | ✅ | | active |
| 한국어 (Korean) | `ko` | ✅ | ✅ | | active |
| Polski (Polish) | `pl` | — | ✅ | — | active |
| Português (Brasil) | `pt-BR` | ✅ | ✅ | ✅ | active |
| Русский (Russian) | `ru` | ✅ | ✅ | — | active |