diff --git a/README.md b/README.md index ffaeee4..68c904c 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ Output: Next.js default Optional: ```text -NEXT_PUBLIC_SUME_DOCS_URL=https://docs.sume.so +NEXT_PUBLIC_SUME_DOCS_URL=https://docs.sume.com ``` ## License diff --git a/content/docs-ko/agents.md b/content/docs-ko/agents.md deleted file mode 100644 index 015d489..0000000 --- a/content/docs-ko/agents.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: MCP와 Supercomputer -description: Sume 개발자 도구가 에이전트와 Supercomputer 워크플로에 어떻게 들어가는지 설명합니다. ---- - -Sume 개발자 도구는 한 가지 경계를 중심으로 설계됩니다. Public API가 기준이고, 래퍼는 얇게 유지됩니다. - -## 도구 레이어 - -1. Public API: 워크스페이스 범위 HTTP 엔드포인트입니다. -2. CLI: Public API를 셸에서 쓰기 좋게 감싼 도구입니다. -3. MCP: 같은 Public API를 모델이 쓰기 좋게 감싼 도구입니다. -4. Supercomputer tools: 앱 세션이 주입한 워크스페이스 컨텍스트로 동작하는 앱 내 도구입니다. - -## Asset Library 사용 사례 - -에이전트는 장면을 검색하고, 하나의 에셋을 선택한 뒤, 그 미디어 메타데이터를 다음 생성 또는 분석 단계에서 재사용할 수 있습니다. - -```bash -sume assets search "woman looking at camera hook" --limit 5 --json -sume assets get --json -``` - -Supercomputer는 사용자에게 workspace id를 물어보지 않아야 합니다. 워크스페이스 컨텍스트는 인증된 앱 세션에서 결정됩니다. diff --git a/content/docs-ko/agents/safe-automation.md b/content/docs-ko/agents/safe-automation.md deleted file mode 100644 index c366098..0000000 --- a/content/docs-ko/agents/safe-automation.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: 안전한 자동화 -description: 비밀 유출과 워크스페이스 경계 침범 없이 에이전트에서 Sume API와 도구를 사용하는 기준입니다. ---- - -워크스페이스 격리와 과금 명확성을 지키는 방식으로 Public API와 CLI를 사용하세요. - -## 워크스페이스 격리 - -API 키와 앱 세션이 워크스페이스를 결정합니다. 제품이 명시적으로 워크스페이스 전환을 지원하지 않는 한, 도구는 사용자 입력 workspace id를 받지 않아야 합니다. - -## 크레딧을 쓰는 작업 - -생성과 분석 생성은 크레딧을 사용할 수 있습니다. 에이전트 도구는 그런 작업을 명시적으로 드러내고 읽기 작업과 분리해야 합니다. - -## 로깅 - -안전한 로그: - -- 필요한 경우의 request id, -- 필요한 경우의 job id, -- 높은 수준의 상태, -- 정리된 미디어 메타데이터. - -위험한 로그: - -- API 키, -- signed URL, -- 원본 비공개 미디어 URL, -- 과도한 사용자 콘텐츠나 transcript. diff --git a/content/docs-ko/api/cookbook.md b/content/docs-ko/api/cookbook.md deleted file mode 100644 index e0adfc2..0000000 --- a/content/docs-ko/api/cookbook.md +++ /dev/null @@ -1,210 +0,0 @@ ---- -title: API cookbook -description: 인증, 작업, 생성, 업로드, Asset Library, Reference Analysis를 위한 Sume Public API 예시입니다. ---- - -이 cookbook은 자주 쓰는 Sume API 워크플로를 짧은 예시로 정리합니다. 정확한 -필드와 enum은 [API 레퍼런스](/ko/api/reference)와 -[`/api/openapi.json`](/api/openapi.json)을 사용하세요. - -## Setup - -```bash -export SUME_API_KEY="" -export SUME_API_BASE_URL="https://www.sume.so/api/v1" -``` - -키 확인: - -```bash -curl "$SUME_API_BASE_URL/me" \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -크레딧 확인: - -```bash -curl "$SUME_API_BASE_URL/credits" \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -## 비디오 작업 생성과 폴링 - -작업 생성: - -```bash -curl "$SUME_API_BASE_URL/videos/generations" \ - -H "Authorization: Bearer $SUME_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "prompt": "A creator holds a moisturizer jar in soft morning light.", - "duration": 4, - "aspect_ratio": "9:16", - "resolution": "480p", - "generate_audio": false - }' -``` - -응답의 `job_id`를 저장합니다. - -상태 폴링: - -```bash -curl "$SUME_API_BASE_URL/jobs/job_123" \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -결과 가져오기: - -```bash -curl "$SUME_API_BASE_URL/jobs/job_123/result" \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -## Brand reference로 이미지 생성 - -현재 Brand DNA 프로필 조회: - -```bash -curl "$SUME_API_BASE_URL/brand/current" \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -응답에 `images[].reference_url`이 있으면 이미지 생성 reference로 전달할 수 -있습니다. - -```bash -curl "$SUME_API_BASE_URL/images/generations" \ - -H "Authorization: Bearer $SUME_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "prompt": "Premium skincare product ad using the brand reference.", - "aspect_ratio": "1:1", - "image_count": 1, - "reference_image_urls": [ - "https://media.sume.so/example-reference.jpg" - ] - }' -``` - -워크스페이스에 반환된 reference URL만 사용하고, private 또는 signed URL을 -로그에 남기지 마세요. - -## Asset Library 비디오 업로드 - -업로드 대상 요청: - -```bash -curl "$SUME_API_BASE_URL/uploads/presign" \ - -H "Authorization: Bearer $SUME_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "purpose": "asset_library_video", - "file_name": "source.mp4", - "content_type": "video/mp4", - "size_bytes": 12000000 - }' -``` - -반환된 `upload_url`과 `required_headers`로 파일 바이트를 업로드합니다. Storage -PUT 요청에는 Sume API `Authorization` 헤더를 넣지 마세요. - -업로드 finalize: - -```bash -curl "$SUME_API_BASE_URL/assets" \ - -H "Authorization: Bearer $SUME_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "object_key": "uploads/...", - "file_name": "source.mp4", - "content_type": "video/mp4", - "size_bytes": 12000000 - }' -``` - -## Asset Library 장면 검색 - -```bash -curl "$SUME_API_BASE_URL/assets?q=product%20demo%20hook&limit=5&sort=relevance" \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -하나의 장면 조회: - -```bash -curl "$SUME_API_BASE_URL/assets/asset_123" \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -Scene asset에는 scene-level `media_url`, `thumbnail_url`, `source_video`, -`scene` metadata, search context가 포함될 수 있습니다. - -## Face Swap source video 준비 - -Face Swap은 `face_swap_source_video` purpose로 업로드한 Sume media URL이 -필요합니다. - -```bash -curl "$SUME_API_BASE_URL/uploads/presign" \ - -H "Authorization: Bearer $SUME_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "purpose": "face_swap_source_video", - "file_name": "source.mp4", - "content_type": "video/mp4", - "size_bytes": 12000000 - }' -``` - -바이트 업로드 후 Face Swap 작업 생성: - -```bash -curl "$SUME_API_BASE_URL/face-swap" \ - -H "Authorization: Bearer $SUME_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "source_video_url": "https://media.sume.so/example-source.mp4", - "avatar_ids": ["avatar_123"], - "duration_seconds": 6, - "aspect_ratio": "9:16" - }' -``` - -반환된 각 job id를 `GET /jobs/{jobId}`로 폴링합니다. - -## Reference Analysis - -Reference Analysis는 공개 TikTok 또는 Instagram Reel URL을 받습니다. - -```bash -curl "$SUME_API_BASE_URL/reference-analysis" \ - -H "Authorization: Bearer $SUME_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "url": "https://www.tiktok.com/@example/video/123", - "locale": "ko" - }' -``` - -응답에는 `required_credits`와 `job_id`가 포함됩니다. Jobs endpoint로 폴링하고 -최종 결과를 가져오세요. - -## 실패 처리 - -API 요청 실패 시 `request_id`를 보관합니다. - -```json -{ - "error": { - "code": "invalid_request", - "message": "A human-readable error message.", - "details": {} - }, - "request_id": "req_123" -} -``` - -Job 실패 시 job id, status, 정리된 error code/message만 기록하세요. API 키, -signed URL, storage object key, provider payload, private media URL, 사용자 -이메일, workspace/user id는 로그에 남기지 마세요. diff --git a/content/docs-ko/api/reference.md b/content/docs-ko/api/reference.md deleted file mode 100644 index 2ce6a17..0000000 --- a/content/docs-ko/api/reference.md +++ /dev/null @@ -1,189 +0,0 @@ ---- -title: API 레퍼런스 -description: Sume Public API의 라우트 맵, 요청 메모, 응답 패턴입니다. ---- - -이 페이지는 Sume Public API의 라우트 단위 레퍼런스입니다. 정확한 필드와 -enum은 OpenAPI schema를 source of truth로 사용하세요. - -## OpenAPI 스키마 - -미리보기 스키마: - -```text -/api/openapi.json -``` - -프로덕션 스키마: - -```text -https://www.sume.so/api/v1/openapi.json -``` - -다운로드: - -```bash -curl https://www.sume.so/api/v1/openapi.json \ - -o sume-openapi.json -``` - -## 인증 - -모든 Public API v1 엔드포인트는 워크스페이스 범위 API 키를 사용합니다. - -```bash -curl https://www.sume.so/api/v1/me \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -기존 키는 legacy `X-Api-Key` 헤더도 지원할 수 있지만, -`Authorization: Bearer`를 권장합니다. Sume은 API 키에서 워크스페이스와 -owner 범위를 결정하므로 요청 본문에 `workspace_id`나 `user_id`를 넣지 -마세요. - -## Account와 credits - -| Method | Path | 반환 | 메모 | -|---|---|---|---| -| `GET` | `/me` | `account` | 인증된 사용자, 워크스페이스, API 키 메타데이터. | -| `GET` | `/credits` | `credits` | 플랜, 월간/보너스 크레딧, 남은 크레딧, 활성 생성 용량. | - -## Brand DNA - -| Method | Path | 반환 | 메모 | -|---|---|---|---| -| `GET` | `/brand` | `brand` 목록 | 워크스페이스에서 볼 수 있는 정리된 Brand DNA 프로필. | -| `GET` | `/brand/current` | `brand` | 서버가 선택한 현재 워크스페이스 Brand DNA 프로필. | - -Brand 응답의 `images[].reference_url`은 이미지 생성의 -`reference_image_urls`로 사용할 수 있습니다. - -## Avatars - -| Method | Path | 반환 | 메모 | -|---|---|---|---| -| `GET` | `/avatars` | `avatar` 목록 | API 키로 사용할 수 있는 공개/워크스페이스 아바타. | -| `GET` | `/avatars/{avatarId}` | `avatar` | 하나의 아바타와 media/capability 메타데이터. | - -`capabilities`는 talking-head video, UGC ad video, Face Swap 사용 가능 여부를 -나타냅니다. - -## Jobs - -| Method | Path | 반환 | 메모 | -|---|---|---|---| -| `GET` | `/jobs` | `job` 목록 | `limit`, `cursor`, `type`, `status`를 지원합니다. | -| `GET` | `/jobs/{jobId}` | `job` | 현재 상태와 정리된 error/result URL 필드. | -| `GET` | `/jobs/{jobId}/result` | `job` with `result` | 완료된 작업의 최종 결과. | - -```bash -curl "https://www.sume.so/api/v1/jobs?limit=5&status=completed" \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -Job 객체는 공개 상태와 output 필드만 노출합니다. 내부 provider payload는 -public contract가 아닙니다. - -## 생성 엔드포인트 - -생성 엔드포인트는 크레딧을 예약하거나 사용할 수 있습니다. - -| Method | Path | 반환 | 주요 입력 | -|---|---|---|---| -| `POST` | `/images/generations` | `image_generation` | `prompt`, `aspect_ratio`, `image_count`, `reference_image_urls` | -| `POST` | `/videos/generations` | `video_generation` | `prompt`, `duration`, `aspect_ratio`, `resolution`, `generate_audio` | -| `POST` | `/ads/videos` | `ad_video_generation` | `script`, `ad_format`, `avatar_id` 또는 `avatar_slug` | -| `POST` | `/face-swap` | `face_swap` | `source_video_url`, `avatar_ids`, `duration_seconds` | -| `POST` | `/reference-analysis` | `reference_analysis` | public TikTok 또는 Instagram Reel `url`, `locale` | - -예시: - -```bash -curl https://www.sume.so/api/v1/videos/generations \ - -H "Authorization: Bearer $SUME_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "prompt": "Four-second product demo video on a studio table.", - "duration": 4, - "aspect_ratio": "9:16", - "resolution": "480p", - "generate_audio": false - }' -``` - -## Uploads와 Asset Library - -| Method | Path | 반환 | 메모 | -|---|---|---|---| -| `POST` | `/uploads/presign` | `upload` | 임시 signed upload URL을 만듭니다. | -| `POST` | `/assets` | `asset_upload` | 업로드된 영상을 finalize하고 Asset Library processing을 시작합니다. | -| `GET` | `/assets` | `asset` 목록 | 색인된 scene asset을 나열하거나 검색합니다. | -| `GET` | `/assets/{assetId}` | `asset` | 하나의 scene asset을 읽습니다. | - -업로드 purpose: - -| Purpose | 용도 | -|---|---| -| `asset_library_video` | Asset Library scene search에 ingest할 영상. | -| `face_swap_source_video` | Face Swap source video. | - -```bash -curl https://www.sume.so/api/v1/uploads/presign \ - -H "Authorization: Bearer $SUME_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "purpose": "asset_library_video", - "file_name": "source.mp4", - "content_type": "video/mp4", - "size_bytes": 12000000 - }' -``` - -업로드 응답의 `upload_url`, `object_key`, `media_url`, `required_headers`는 -민감한 operational 값입니다. Storage upload URL에는 Sume API -`Authorization` 헤더를 보내지 마세요. - -## List response - -```json -{ - "object": "list", - "data": [], - "has_more": false, - "next_cursor": null -} -``` - -`limit`로 페이지 크기를 조정하고, `next_cursor`를 `cursor`로 전달해 다음 -페이지를 가져옵니다. - -## Error response - -```json -{ - "error": { - "code": "invalid_request", - "message": "A human-readable error message.", - "details": {} - }, - "request_id": "req_123" -} -``` - -대표 상태 코드: - -| Status | 의미 | -|---|---| -| `400` | 잘못된 요청 본문, 지원하지 않는 입력, validation error. | -| `401` | API 키 누락 또는 invalid key. | -| `402` | 크레딧 부족. | -| `403` | API 키가 요청 리소스나 액션에 접근할 수 없음. | -| `404` | 현재 워크스페이스 범위에서 리소스를 찾을 수 없음. | -| `409` | conflict, duplicate, incompatible state. | -| `413` | 업로드 또는 요청 미디어가 너무 큼. | -| `429` | rate limit 또는 active generation limit. | -| `500`, `502`, `503` | internal, upstream, provider availability failure. | - -문제 제보 시에는 `request_id`와 정리된 endpoint/job id를 포함하세요. API 키, -signed URL, object key, private media URL, provider payload, 사용자 이메일, -workspace/user id는 포함하지 마세요. diff --git a/content/docs-ko/authentication.md b/content/docs-ko/authentication.md deleted file mode 100644 index c9fa695..0000000 --- a/content/docs-ko/authentication.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: 인증 -description: 워크스페이스 범위 API 키로 Sume Public API와 CLI를 인증합니다. ---- - -Sume Public API v1은 API 키를 사용합니다. 신뢰할 수 있는 서버 측 코드에서 Bearer 토큰으로 키를 보내세요. - -```bash -Authorization: Bearer sume_live_... -``` - -이전 대시보드에서 발급된 키는 `X-Api-Key`로도 동작할 수 있지만, 새 연동에서는 Bearer 인증을 권장합니다. - -## 워크스페이스 범위 - -모든 API 키는 하나의 사용자와 워크스페이스 컨텍스트로 해석됩니다. Public API 요청에 identity override를 넣지 마세요. - -```bash -curl https://www.sume.so/api/v1/me \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -`/me`로 다음 정보를 확인할 수 있습니다. - -| 필드 | 의미 | -|---|---| -| `user` | 인증된 Sume 사용자 컨텍스트입니다. | -| `workspace` | 키가 연결된 워크스페이스입니다. | -| `api_key` | prefix, scope 같은 정리된 키 메타데이터입니다. | - -요청 본문에 `workspace_id`, `user_id`, `email`, owner 정보를 보내지 마세요. Sume은 키에서 접근 권한을 계산하고 워크스페이스에 보이는 레코드만 반환합니다. - -## CLI 로그인 - -로컬에서는 CLI가 브라우저 로그인을 통해 범위가 지정된 키를 만들고 저장할 수 있습니다. - -```bash -sume login -sume me -sume auth status -``` - -원격 터미널에서는 다음을 사용합니다. - -```bash -sume login --no-browser -``` - -CLI는 로컬 설정을 `~/.sume/config.json`에 저장하며 파일 권한은 소유자 전용으로 설정합니다. - -## 환경 변수 설정 - -환경 변수는 로컬 설정보다 우선하며 CI와 에이전트에 적합합니다. - -```bash -export SUME_API_KEY="sume_live_..." -export SUME_API_BASE_URL="https://www.sume.so/api/v1" -``` - -수동 설정: - -```bash -sume setup --api-key "$SUME_API_KEY" -sume setup --base-url "https://www.sume.so/api/v1" -``` - -## 시크릿 체크리스트 - -- API 키는 서버 측 시크릿 매니저나 CI 시크릿에 보관합니다. -- 브라우저 코드, 모바일 앱, 스크린샷, 공개 이슈, 로그에 API 키를 넣지 않습니다. -- 노출된 키는 즉시 회전합니다. -- 프로덕션, 스테이징, 로컬 테스트, 자동화에 별도 키를 사용합니다. -- 전체 signed URL, request id, raw auth output, 사용자 이메일, workspace id, API key id는 공유 전에 제거합니다. - -## 권한 오류 - -| 상태 | 의미 | -|---|---| -| `401` | API 키가 없거나, 형식이 잘못되었거나, 폐기되었거나, 알 수 없는 키입니다. | -| `403` | 키는 유효하지만 요청한 기능이나 레코드에 접근할 수 없습니다. | -| `429` | 워크스페이스나 키가 rate limit에 걸렸습니다. | - -Sume 지원팀에 문의할 때는 오류 응답의 `request_id`를 함께 전달하세요. diff --git a/content/docs-ko/cli.md b/content/docs-ko/cli.md deleted file mode 100644 index 9c9c35b..0000000 --- a/content/docs-ko/cli.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: 개요 -description: Sume CLI를 Sume Public API 위의 에이전트 우선 셸 도구로 사용합니다. ---- - -Sume CLI는 Sume Public API 위에 얇게 얹은 래퍼입니다. 터미널에서 사람이 읽기 좋게 사용할 수 있고, 에이전트는 일반 셸 명령과 `--json` 출력으로 사용할 수 있습니다. - -기본 API 주소: - -```text -https://www.sume.so/api/v1 -``` - -## CLI를 쓰는 이유 - -- 사람용 출력이 간결합니다. -- `--json`은 자동화를 위한 구조화된 출력을 반환합니다. -- 명령어가 Public API 엔드포인트와 매핑됩니다. -- Sume 데이터베이스, 큐, provider API, 배포 서비스, 내부 라우트에 직접 연결하지 않습니다. -- Sume이 반환한 안전한 공개 미디어 URL을 다운로드할 수 있습니다. - -## 설치 - -macOS와 Linux: - -```bash -curl https://cli.sume.so/install -fsS | bash -``` - -Windows PowerShell: - -```powershell -irm https://cli.sume.so/install.ps1 | iex -``` - -그 다음 인증합니다. - -```bash -sume login -sume me -sume credits -``` - -## 읽기 명령어 - -```bash -sume auth status -sume me --json -sume credits --json -sume jobs list --limit 5 --json -sume assets search "product demo hook" --limit 5 --json -sume assets get --json -``` - -## 생성 명령어 - -생성 명령은 크레딧을 사용할 수 있습니다. 에이전트가 실행할 때는 사용자 의도를 확인하세요. - -```bash -sume images generate \ - --prompt "Clean product photo on a white bathroom counter." \ - --wait \ - --json - -sume videos generate \ - --prompt "Four-second vertical product demo." \ - --duration 4 \ - --resolution 480p \ - --json -``` - -## 에이전트 모드 - -다른 프로그램이 출력을 파싱할 때는 항상 `--json`을 사용하세요. - -```bash -sume tools list --json -sume tools schema assets.search --json -sume assets search "woman looking at camera hook" --source-type generated --limit 5 --json -``` - -에이전트는 전체 URL, request id, 사용자 이메일, workspace id, API key id, 큰 raw payload를 요약하거나 제거해야 합니다. diff --git a/content/docs-ko/cli/agent-usage.md b/content/docs-ko/cli/agent-usage.md deleted file mode 100644 index e2da929..0000000 --- a/content/docs-ko/cli/agent-usage.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: 에이전트 사용 -description: 코딩 에이전트와 자동화 스크립트에서 Sume CLI를 안전하게 사용합니다. ---- - -에이전트는 명시적인 셸 명령으로 Sume CLI를 사용하고 `--json` 출력을 파싱해야 합니다. - -## JSON 우선 워크플로 - -```bash -sume me --json -sume credits --json -sume jobs list --limit 5 --json -sume assets search "product demo hook" --source-type generated --limit 5 --json -sume images generate --prompt "clean product photo" --wait --json -``` - -## 프로젝트 지침 설치 - -```bash -sume init -sume init --target all -sume init --target claude,cursor,agents-md -``` - -`sume init`은 프로젝트에 Sume 지침을 설치하여 팀원과 에이전트가 같은 워크플로를 사용하도록 합니다. - -## 안전 규칙 - -- API 키를 echo하지 않습니다. -- 비공개 URL이나 signed query string을 프롬프트에 붙여넣지 않습니다. -- 생성 명령 전에 읽기 명령을 먼저 사용합니다. -- 생성은 크레딧 사용 작업으로 취급합니다. -- 검색 결과를 대량으로 출력하기보다 검색 후 한 에셋을 id로 조회합니다. diff --git a/content/docs-ko/cli/commands.md b/content/docs-ko/cli/commands.md deleted file mode 100644 index e9d85ad..0000000 --- a/content/docs-ko/cli/commands.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: 명령어 -description: 인증, 계정, 작업, 에셋, 생성, Reference Analysis, tools, agent setup을 위한 Sume CLI 명령어입니다. ---- - -에이전트나 스크립트가 출력을 파싱한다면 모든 명령에 `--json`을 사용하세요. - -## 인증과 설정 - -```bash -sume login -sume login --no-browser -sume auth status -sume logout -sume setup --api-key "$SUME_API_KEY" -sume setup --base-url "https://www.sume.so/api/v1" -``` - -`sume login`은 Sume 승인 페이지를 열고 범위가 지정된 로컬 API 키를 저장합니다. CI에서는 `SUME_API_KEY`를 선호합니다. - -## 계정과 크레딧 - -```bash -sume me -sume me --json -sume credits -sume credits --json -``` - -생성 전에 CLI가 기대한 계정과 워크스페이스를 바라보는지 확인합니다. - -## 작업 - -```bash -sume jobs list --limit 5 -sume jobs list --status completed --limit 5 -sume jobs get --json -sume jobs result --json -sume jobs result --download ./outputs/ -``` - -| 옵션 | 설명 | -|---|---| -| `--limit ` | 페이지 크기입니다. | -| `--cursor ` | 페이지네이션을 이어갑니다. | -| `--type ` | 작업 유형으로 필터링합니다. | -| `--status ` | 작업 상태로 필터링합니다. | -| `--download [path]` | 안전한 공개 미디어 URL을 파일로 다운로드합니다. | - -## Assets - -```bash -sume assets list --limit 5 --json -sume assets search "mask application" --source-type generated --limit 5 --json -sume assets get --json -sume assets get --download ./assets/ -``` - -| 옵션 | 설명 | -|---|---| -| `--query ` | `assets list`의 검색어입니다. | -| `--source-type ` | 업로드/생성 같은 소스 유형으로 필터링합니다. | -| `--brand ` | 브랜드 언급으로 필터링합니다. | -| `--product ` | 제품 언급으로 필터링합니다. | -| `--tag ` | 재사용 태그로 필터링합니다. | -| `--min-duration` / `--max-duration` | 장면 길이로 필터링합니다. | - -## 생성 - -```bash -sume images generate --prompt "clean product photo" --wait --json -sume videos generate --prompt "short vertical product demo" --duration 4 --json -sume reference-analysis create --url "https://www.tiktok.com/@brand/video/123" --json -``` - -생성 명령은 크레딧을 사용할 수 있으므로 에이전트 실행 전 사용자 확인이 필요합니다. diff --git a/content/docs-ko/cli/install-login.md b/content/docs-ko/cli/install-login.md deleted file mode 100644 index c9c4711..0000000 --- a/content/docs-ko/cli/install-login.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: 설치와 로그인 -description: Sume CLI를 설치하고 브라우저 로그인 또는 API 키로 인증합니다. ---- - -## 설치 - -Linux와 macOS: - -```bash -curl https://cli.sume.so/install -fsS | bash -``` - -Windows PowerShell: - -```powershell -irm https://cli.sume.so/install.ps1 | iex -``` - -시작: - -```bash -sume login -sume me -``` - -## 브라우저 로그인 - -```bash -sume login -``` - -CLI가 브라우저 승인 페이지를 엽니다. 승인 후 범위가 지정된 Sume API 키를 `~/.sume/config.json`에 저장합니다. - -원격 터미널: - -```bash -sume login --no-browser -``` - -## 환경 변수 - -환경 변수는 로컬 설정보다 우선하며 CI에 적합합니다. - -```bash -export SUME_API_KEY="sume_live_..." -export SUME_API_BASE_URL="https://www.sume.so/api/v1" -``` diff --git a/content/docs-ko/public-api.md b/content/docs-ko/public-api.md deleted file mode 100644 index ba761f9..0000000 --- a/content/docs-ko/public-api.md +++ /dev/null @@ -1,161 +0,0 @@ ---- -title: 개요 -description: Sume 생성, 작업, 크레딧, Brand context, 아바타, 업로드, Asset Library 장면에 접근합니다. ---- - -Sume Public API는 서버 연동, CLI 자동화, MCP 래퍼, 에이전트 도구를 위한 -워크스페이스 범위 API입니다. Sume 앱의 핵심 기능인 생성 작업, 작업 -폴링, Brand DNA, 아바타, 업로드, Asset Library 장면 검색을 제공합니다. - -## Base URL - -```text -https://www.sume.so/api/v1 -``` - -이 페이지의 모든 엔드포인트 경로는 위 base URL 기준입니다. - -## 인증 - -서버 환경에서 워크스페이스 API 키를 전달하세요. - -```bash -export SUME_API_KEY="" - -curl https://www.sume.so/api/v1/me \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -Bearer 인증을 권장합니다. 기존 Dashboard 발급 키는 legacy `X-Api-Key` -헤더도 지원할 수 있지만, 새 연동은 `Authorization: Bearer`를 사용하세요. - -요청 본문에 `workspace_id`나 `user_id`를 넣지 마세요. Sume은 API 키에서 -사용자와 워크스페이스 범위를 결정합니다. - -> API 키, signed upload URL, storage object key, private media URL은 모두 -> 민감 정보로 취급하세요. 프롬프트, 로그, 이슈, 공개 지원 채널에 붙여넣지 -> 마세요. - -## 빠른 시작 - -1. API dashboard에서 Sume API 키를 만들거나 복사합니다. -2. `GET /me`로 키가 동작하는지 확인합니다. -3. `GET /credits`로 크레딧 용량을 확인합니다. -4. `POST /videos/generations` 같은 엔드포인트로 비동기 작업을 만듭니다. -5. 종료 상태가 될 때까지 `GET /jobs/{jobId}`를 폴링합니다. -6. `GET /jobs/{jobId}/result`로 생성 미디어나 분석 결과를 가져옵니다. - -```bash -curl https://www.sume.so/api/v1/credits \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -## 엔드포인트 맵 - -| 영역 | 엔드포인트 | 용도 | -|---|---|---| -| Account | `GET /me`, `GET /credits` | 인증, 워크스페이스 범위, 플랜, 크레딧, 활성 생성 용량을 확인합니다. | -| Brand | `GET /brand`, `GET /brand/current` | 정리된 Brand DNA 프로필과 현재 Brand context를 읽습니다. | -| Avatars | `GET /avatars`, `GET /avatars/{avatarId}` | 광고와 Face Swap 워크플로에 사용할 공개/워크스페이스 아바타를 선택합니다. | -| Jobs | `GET /jobs`, `GET /jobs/{jobId}`, `GET /jobs/{jobId}/result` | 작업을 나열하고, 상태를 폴링하고, 생성/분석 결과를 가져옵니다. | -| Generation | `POST /images/generations`, `POST /videos/generations`, `POST /ads/videos`, `POST /face-swap`, `POST /reference-analysis` | 비동기 미디어 또는 분석 작업을 만듭니다. 크레딧을 사용할 수 있습니다. | -| Uploads | `POST /uploads/presign`, `POST /assets` | 영상을 업로드하고 Asset Library ingest 또는 기능별 워크플로로 finalize합니다. | -| Asset Library | `GET /assets`, `GET /assets/{assetId}` | 색인된 장면 에셋을 검색하고 재사용 가능한 클립/소스 메타데이터를 조회합니다. | - -## 비동기 작업 생명주기 - -대부분의 쓰기 엔드포인트는 빠르게 `job_id`를 반환합니다. 해당 id를 저장한 -뒤 작업이 종료 상태가 될 때까지 폴링하세요. - -```text -create endpoint - -> job_id - -> GET /jobs/{jobId} - -> GET /jobs/{jobId}/result -``` - -| 상태 | 연동 동작 | -|---|---| -| `queued`, `processing` 또는 기타 진행 상태 | backoff를 두고 계속 폴링합니다. 비디오 작업은 이미지 작업보다 오래 걸립니다. | -| `completed` | 결과를 가져오고 output URL 또는 구조화된 결과 데이터를 사용합니다. | -| `failed`, `canceled`, `expired` | 폴링을 중단하고 정리된 오류 메시지를 표시합니다. | - -예시 비디오 작업: - -```bash -curl https://www.sume.so/api/v1/videos/generations \ - -H "Authorization: Bearer $SUME_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "prompt": "A creator demonstrates a vitamin serum in a bright studio.", - "aspect_ratio": "9:16", - "duration": 5, - "generate_audio": false - }' -``` - -## 업로드 워크플로 - -사용자 제공 비디오가 필요할 때 업로드를 사용합니다. - -1. `POST /uploads/presign`으로 임시 업로드 대상을 요청합니다. -2. 반환된 `upload_url`에 `required_headers`를 사용해 바이트를 업로드합니다. -3. Asset Library ingest는 `POST /assets`로 finalize합니다. -4. Face Swap은 반환된 `media_url`을 `POST /face-swap`에 전달합니다. - -```bash -curl https://www.sume.so/api/v1/uploads/presign \ - -H "Authorization: Bearer $SUME_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "purpose": "asset_library_video", - "file_name": "reference.mp4", - "content_type": "video/mp4", - "size_bytes": 12000000 - }' -``` - -`purpose`는 `asset_library_video` 또는 `face_swap_source_video`입니다. -`upload_url`, `object_key`, `required_headers`는 업로드 플로우용 민감한 -값이므로 로그에 남기지 마세요. - -## 페이지네이션 - -목록 엔드포인트는 cursor pagination을 사용합니다. - -```json -{ - "object": "list", - "data": [], - "has_more": false, - "next_cursor": null -} -``` - -계속 조회하려면 `next_cursor`를 `cursor`로 전달합니다. - -## 오류 envelope - -```json -{ - "error": { - "code": "invalid_request", - "message": "A human-readable error message.", - "details": {} - }, - "request_id": "req_123" -} -``` - -지원 문의에는 `request_id`를 보관하세요. API 키, signed URL, storage -object key, private media URL, 사용자 이메일, workspace/user id는 외부 로그에서 -제거하세요. - -## 스키마와 예시 - -- [API 레퍼런스](/ko/api/reference)는 현재 엔드포인트를 나열합니다. -- [API cookbook](/ko/api/cookbook)은 복사해 쓸 수 있는 워크플로 예시를 제공합니다. -- 미리보기 OpenAPI 스냅샷은 [`/api/openapi.json`](/api/openapi.json)에 있습니다. -- 프로덕션 live schema는 `https://www.sume.so/api/v1/openapi.json`에서 제공합니다. - -정확한 요청/응답 필드는 OpenAPI schema를 source of truth로 사용하세요. diff --git a/content/docs-ko/quick-start.md b/content/docs-ko/quick-start.md deleted file mode 100644 index 85b13c6..0000000 --- a/content/docs-ko/quick-start.md +++ /dev/null @@ -1,117 +0,0 @@ ---- -title: 빠른 시작 -description: 작업을 만들고, 상태를 폴링하고, 결과를 가져오며 Asset Library를 검색합니다. ---- - -Sume은 워크스페이스 범위의 Public API와 에이전트 친화적인 CLI를 제공합니다. 두 도구는 같은 흐름을 따릅니다. 인증하고, API 키가 연결된 워크스페이스에서 생성 또는 검색을 실행한 뒤, 안정적인 작업과 에셋 엔드포인트로 결과를 읽습니다. - -## Base URL - -```text -https://www.sume.so/api/v1 -``` - -다른 Sume 환경을 의도적으로 테스트하는 경우가 아니라면 이 프로덕션 주소를 사용하세요. - -## 1. 인증 - -Sume에서 API 키를 만들고 서버 측에 안전하게 보관합니다. - -```bash -export SUME_API_KEY="sume_live_..." -``` - -키에 연결된 계정과 워크스페이스를 확인합니다. - -```bash -curl https://www.sume.so/api/v1/me \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -API 키가 워크스페이스 범위를 결정합니다. 요청 본문에 `workspace_id`나 `user_id`를 직접 보내지 마세요. - -## 2. 크레딧 확인 - -생성 엔드포인트는 크레딧을 사용할 수 있습니다. 작업을 만들기 전에 잔액과 동시 실행 상태를 확인하세요. - -```bash -curl https://www.sume.so/api/v1/credits \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -CLI에서는 다음과 같이 확인합니다. - -```bash -sume credits -``` - -## 3. 이미지 작업 만들기 - -```bash -curl https://www.sume.so/api/v1/images/generations \ - -H "Authorization: Bearer $SUME_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "prompt": "Clean skincare product photo on a white bathroom counter.", - "aspect_ratio": "1:1", - "image_count": 1 - }' -``` - -응답은 비동기 작업을 수락했다는 의미이며 작업 id를 포함합니다. - -```json -{ - "object": "image_generation", - "job": { - "id": "job_...", - "status": "queued" - } -} -``` - -CLI 예시는 다음과 같습니다. - -```bash -sume images generate \ - --prompt "Clean skincare product photo on a white bathroom counter." \ - --aspect-ratio 1:1 \ - --wait \ - --json -``` - -## 4. 상태 폴링 - -```bash -curl https://www.sume.so/api/v1/jobs/job_123 \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -일반적인 종료 상태는 `completed`, `failed`, `canceled`, `expired`입니다. 작업이 아직 `queued`, `running`, `processing`이면 잠시 기다린 뒤 다시 조회합니다. - -## 5. 결과 가져오기 - -```bash -curl https://www.sume.so/api/v1/jobs/job_123/result \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -결과에는 안전한 공개 미디어 URL과 메타데이터가 포함될 수 있습니다. 쿼리 문자열이나 비공개 토큰이 들어간 전체 URL은 로그에 남기지 마세요. - -## 6. Asset Library 검색 - -Asset Library는 장면 단위로 색인된 레코드를 반환합니다. 재사용 가능한 클립, 생성 결과, 훅, CTA, 제품 데모, 소스 영상 메타데이터를 찾는 데 사용합니다. - -```bash -sume assets search "product demo hook" \ - --source-type generated \ - --limit 5 \ - --json -``` - -## 다음 단계 - -- [Public API 개요](/ko/public-api)에서 엔드포인트 그룹을 확인하세요. -- [작업과 결과](/ko/workflows/jobs-and-results)에서 폴링과 결과 처리 흐름을 확인하세요. -- [Asset Library](/ko/workflows/asset-library)에서 장면 검색과 필터를 확인하세요. -- [CLI 명령어](/ko/cli/commands)에서 터미널 예시를 확인하세요. diff --git a/content/docs-ko/workflows/asset-library.md b/content/docs-ko/workflows/asset-library.md deleted file mode 100644 index 12ed670..0000000 --- a/content/docs-ko/workflows/asset-library.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: Asset Library -description: 워크스페이스 범위의 장면, 클립, 소스 영상, 생성 비디오 에셋을 검색합니다. ---- - -Asset Library는 업로드 영상, 생성 영상, 소스 미디어에서 색인된 장면 단위 에셋을 노출합니다. 검색 결과는 API 키 워크스페이스 범위로 제한됩니다. - -## Mental model - -| 객체 | 의미 | -|---|---| -| Source video | ingest된 원본 업로드 또는 생성 영상입니다. | -| Scene asset | 해당 영상에서 나온 검색 가능한 클립/세그먼트입니다. | -| Metadata | transcript, visual summary, action labels, 브랜드/제품 언급, 태그, 키워드, CTA, 타이밍입니다. | -| Safe URL | 도구가 재사용할 수 있는 안정적인 미디어 또는 썸네일 URL입니다. 전체 query string URL은 로그에 남기지 마세요. | - -장면 메타데이터가 없는 에셋은 색인이 장면 row를 만들기 전까지 검색 결과에 나타나지 않습니다. - -## 장면 검색 - -```bash -curl "https://www.sume.so/api/v1/assets?q=woman%20camera%20hook&source_type=generated&limit=5&sort=relevance" \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -CLI: - -```bash -sume assets search "woman looking at camera hook" \ - --source-type generated \ - --max-duration 15 \ - --sort relevance \ - --limit 5 \ - --json -``` - -검색어가 있을 때 응답에는 relevance context가 포함됩니다. - -```json -{ - "object": "list", - "data": [ - { - "id": "asset_...", - "object": "asset", - "title": "Scene 1", - "media_url": "https://media.sume.so/...", - "thumbnail_url": "https://media.sume.so/...", - "metadata": { - "visual_summary": "Creator faces camera and introduces the product.", - "cta_present": false - } - } - ], - "has_more": false, - "next_cursor": null -} -``` - -위 형태는 예시입니다. 정확한 필드는 API 레퍼런스를 기준으로 보세요. - -## 필터 - -| Query parameter | CLI flag | 용도 | -|---|---|---| -| `q` | `assets search ""` 또는 `assets list --query` | 자연어 또는 키워드 장면 검색입니다. | -| `search_mode` | `--search-mode auto\|text` | 텍스트/메타데이터 검색 모드입니다. | -| `source_type` | `--source-type` | 업로드, 생성 같은 소스 범주입니다. | -| `segment_type` | `--segment-type` | hook, product demo, CTA 같은 장면 역할입니다. | -| `brand` | `--brand` | 브랜드 언급입니다. | -| `product` | `--product` | 제품 언급입니다. | -| `tag` | `--tag` | 재사용 에셋 태그입니다. | -| `keyword` | `--keyword` | 색인된 키워드입니다. | diff --git a/content/docs-ko/workflows/core-workflow.md b/content/docs-ko/workflows/core-workflow.md deleted file mode 100644 index 2042ffa..0000000 --- a/content/docs-ko/workflows/core-workflow.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: 핵심 워크플로 -description: Sume API와 CLI 호출을 신뢰할 수 있는 미디어 워크플로로 조합합니다. ---- - -Sume 워크플로는 보통 작은 체인으로 구성됩니다. 먼저 읽기 전용 컨텍스트를 확인하고, 명시적으로 크레딧을 쓰는 create 호출을 실행한 뒤, 작업과 결과를 읽어옵니다. - -## 1. 컨텍스트 읽기 - -모든 연동은 계정, 크레딧, 필요한 창작 컨텍스트를 확인하는 것으로 시작합니다. - -```bash -sume me --json -sume credits --json -sume assets search "best product demo hooks" --limit 5 --json -sume tools list --json -``` - -API 대응: - -```text -GET /me -GET /credits -GET /assets?q=best%20product%20demo%20hooks -GET /brand/current -GET /avatars -``` - -## 2. 입력 선택 - -작업을 만들기 전에 필요한 읽기 엔드포인트를 사용합니다. - -| 필요 | 먼저 읽을 것 | -|---|---| -| 브랜드 톤, 제품 claim, 컬러 | `GET /brand/current` 또는 `GET /brand?domain=...` | -| UGC/talking-head 아바타 | `GET /avatars` 또는 `GET /avatars/{avatarId}` | -| 기존 비주얼 레퍼런스 | `GET /assets?q=...` 후 `GET /assets/{assetId}` | -| 이전 출력 | `GET /jobs/{jobId}/result` | -| 업로드된 영상 | `POST /uploads/presign`, 바이트 업로드, 기능별 create/finalize | - -## 3. 명시적으로 작업 만들기 - -생성 엔드포인트는 크레딧을 사용할 수 있으므로 에이전트는 사용자가 명확히 승인하지 않았다면 확인해야 합니다. - -```bash -sume videos generate \ - --prompt "A creator opens with a skincare hook, then shows product texture." \ - --duration 4 \ - --resolution 480p \ - --json -``` - -## 4. 폴링과 결과 - -```bash -sume jobs get --json -sume jobs result --json -``` - -사용자가 파일 저장을 원할 때만 `--download`를 사용합니다. - -```bash -sume jobs result --download ./outputs/ -``` - -## 5. 결과 재사용 - -생성되거나 업로드된 영상은 ingest 후 Asset Library로 다시 들어갈 수 있습니다. 메타데이터로 장면을 검색하고 가장 관련 있는 에셋을 다음 생성이나 분석 단계에서 재사용합니다. diff --git a/content/docs-ko/workflows/errors-and-credits.md b/content/docs-ko/workflows/errors-and-credits.md deleted file mode 100644 index 88bc953..0000000 --- a/content/docs-ko/workflows/errors-and-credits.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: 오류와 크레딧 -description: Sume API 오류, 크레딧 확인, 생성 비용 동작을 이해합니다. ---- - -생성 엔드포인트는 Sume 웹 앱과 같은 billing 경로를 통해 크레딧을 예약하거나 사용할 수 있습니다. - -## 크레딧 확인 - -```bash -sume credits -curl https://www.sume.so/api/v1/credits \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -응답에는 가능한 경우 플랜, 사용 가능한 크레딧, 활성 동시 실행 정보가 포함됩니다. - -## 오류 envelope - -```json -{ - "error": { - "code": "insufficient_credits", - "message": "Not enough credits for this request.", - "details": {} - }, - "request_id": "req_..." -} -``` - -지원 요청을 위해 `request_id`는 기록하되 API 키, signed URL, 원본 비공개 미디어 URL은 로그에 남기지 마세요. - -## 자동화 기준 - -- 읽기 전용 명령은 먼저 실행해도 안전합니다. -- 생성, 분석, 업로드 finalize는 사용자 의도를 확인한 뒤 실행합니다. -- 비용이 발생할 수 있는 도구는 에이전트 UI에서 명확하게 구분합니다. -- 실패 응답은 요약하고 민감한 원문 payload는 공유하지 않습니다. diff --git a/content/docs-ko/workflows/jobs-and-results.md b/content/docs-ko/workflows/jobs-and-results.md deleted file mode 100644 index 1c19bea..0000000 --- a/content/docs-ko/workflows/jobs-and-results.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: 작업과 결과 -description: 작업을 나열하고, 상태를 폴링하고, 결과를 가져오며 비동기 Sume 워크플로를 처리합니다. ---- - -Sume 작업은 이미지 생성, 비디오 생성, AI Ads 비디오, Face Swap, Reference Analysis, 에셋 ingest 같은 비동기 작업을 나타냅니다. - -## 언제 작업을 쓰나 - -create 엔드포인트가 실제 작업 완료 전에 응답할 때 작업을 사용합니다. 초기 응답의 job id를 저장하고 상태를 폴링한 뒤 결과를 가져옵니다. - -```text -create endpoint -> job id -> GET /jobs/{jobId} -> GET /jobs/{jobId}/result -``` - -## 최근 작업 목록 - -```bash -curl "https://www.sume.so/api/v1/jobs?limit=5" \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -CLI: - -```bash -sume jobs list --limit 5 -sume jobs list --status completed --limit 5 -sume jobs list --type video_generation --limit 5 --json -``` - -지원 필터는 `limit`, `cursor`, `type`, `status`입니다. - -## 한 작업 폴링 - -```bash -curl https://www.sume.so/api/v1/jobs/job_123 \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -CLI: - -```bash -sume jobs get job_123 --json -``` - -| 상태 구분 | 할 일 | -|---|---| -| Queued/running/processing | 기다렸다가 다시 폴링합니다. 비디오 작업은 더 긴 간격을 사용합니다. | -| Completed | 결과를 가져옵니다. | -| Failed/canceled/expired | 폴링을 멈추고 정리된 오류/상태를 보여줍니다. | - -## 결과 가져오기 - -```bash -curl https://www.sume.so/api/v1/jobs/job_123/result \ - -H "Authorization: Bearer $SUME_API_KEY" -``` - -CLI: - -```bash -sume jobs result job_123 --json -sume jobs result job_123 --download ./outputs/ -``` - -결과 payload는 작업 유형마다 다릅니다. 생성 미디어, Reference Analysis 출력, provider-safe 메타데이터, Asset Library ingest 참조가 포함될 수 있습니다. diff --git a/next-sitemap.config.js b/next-sitemap.config.js index 50d92b2..9da78b8 100644 --- a/next-sitemap.config.js +++ b/next-sitemap.config.js @@ -1,11 +1,9 @@ module.exports = { - siteUrl: process.env.NEXT_PUBLIC_SUME_DOCS_URL || "https://docs.sume.so", + siteUrl: process.env.NEXT_PUBLIC_SUME_DOCS_URL || "https://docs.sume.com", generateRobotsTxt: true, robotsTxtOptions: { additionalSitemaps: [], - policies: [ - { userAgent: "*", allow: "/" }, - ], + policies: [{ userAgent: "*", allow: "/" }], additionalPaths: async () => [ { route: "/llms.txt", changefreq: "daily", priority: 0.9 }, { route: "/llms-full.txt", changefreq: "daily", priority: 0.9 }, diff --git a/src/components/footer.tsx b/src/components/footer.tsx index 2e73c99..94abe74 100644 --- a/src/components/footer.tsx +++ b/src/components/footer.tsx @@ -2,7 +2,6 @@ import React from "react"; import { Link } from "./link"; import { ThemeSwitcher } from "./theme-switcher"; import { Icon } from "./icon"; -import { LanguageSwitcher } from "./language-switcher"; interface FooterProps { gitHubEditLink?: string; @@ -34,7 +33,6 @@ export const Footer: React.FC = ({ )}
-
diff --git a/src/components/language-switcher.tsx b/src/components/language-switcher.tsx deleted file mode 100644 index 52f4c39..0000000 --- a/src/components/language-switcher.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import React from "react"; -import { useRouter } from "next/router"; -import { cn } from "@/lib/cn"; -import { Link } from "./link"; - -function useLanguageState() { - const router = useRouter(); - const isKorean = router.pathname.startsWith("/ko"); - const [pathAndQuery, ...hashParts] = router.asPath.split("#"); - const [visiblePath = "/", query = ""] = pathAndQuery.split("?"); - const hash = router.asPath.includes("#") - ? `#${hashParts.join("#")}` - : ""; - const queryParams = new URLSearchParams(query); - const englishPath = - visiblePath === "/ko" - ? "/" - : visiblePath.startsWith("/ko/") - ? visiblePath.replace(/^\/ko/, "") - : visiblePath; - const koreanPath = - visiblePath === "/" - ? "/ko" - : visiblePath.startsWith("/ko") - ? visiblePath - : `/ko${visiblePath}`; - - const withLocalePreference = (path: string, locale: "en" | "ko") => { - const nextQuery = new URLSearchParams(queryParams); - nextQuery.set("locale", locale); - const queryString = nextQuery.toString(); - return `${path || "/"}${queryString ? `?${queryString}` : ""}${hash}`; - }; - - return { - isKorean, - englishPath: withLocalePreference(englishPath || "/", "en"), - koreanPath: withLocalePreference(koreanPath, "ko"), - }; -} - -export function LanguageSwitcher() { - const { isKorean, englishPath, koreanPath } = useLanguageState(); - - return ( -
- - EN - - - KO - -
- ); -} diff --git a/src/components/page-actions.tsx b/src/components/page-actions.tsx index c650f8c..8960211 100644 --- a/src/components/page-actions.tsx +++ b/src/components/page-actions.tsx @@ -2,7 +2,6 @@ import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard"; import { useCopyableCode } from "@/contexts/copyable-code-context"; import { reconstructMarkdownWithFrontmatter } from "@/utils/markdown"; import { cn } from "@/lib/cn"; -import { useRouter } from "next/router"; import * as React from "react"; import { Icon } from "./icon"; import type { FrontMatter } from "@/types"; @@ -27,12 +26,10 @@ export function PageActions({ slug, className, }: PageActionsProps) { - const { pathname } = useRouter(); - const isKorean = pathname.startsWith("/ko"); const { copied, copy } = useCopyToClipboard(); const copyableCode = useCopyableCode(); - const rawUrl = `https://docs.sume.so${slug}.md`; + const rawUrl = `https://docs.sume.com${slug}.md`; const handleCopyAsMarkdown = () => { let markdown = rawMarkdown; @@ -57,7 +54,7 @@ export function PageActions({ return (

- {isKorean ? "AI에게 이 페이지 질문하기" : "Ask AI about this page"} + Ask AI about this page

{/* Copy page */} @@ -70,7 +67,7 @@ export function PageActions({ ) : ( <> - {isKorean ? "페이지 복사" : "Copy page"} + Copy page )} @@ -84,7 +81,7 @@ export function PageActions({ > - {isKorean ? "ChatGPT에서 열기" : "Open in ChatGPT"} + Open in ChatGPT - {isKorean ? "Claude에서 열기" : "Open in Claude"} + Open in Claude - {isKorean ? "Cursor에서 열기" : "Open in Cursor"} + Open in Cursor = ({ open, onOpenChange }) => { const router = useRouter(); - const isKorean = router.pathname.startsWith("/ko"); const [inputValue, setInputValue] = useState(""); const { isLoading, results } = useStaticSearch(inputValue, open); @@ -166,7 +165,7 @@ const SearchModal: React.FC = ({ open, onOpenChange }) => { shouldFilter={false} > = ({ open, onOpenChange }) => { {!isLoading && !results && inputValue === "" && (
- {isKorean - ? "검색어를 입력해 문서를 찾아보세요..." - : "Start typing to search the docs..."} + Start typing to search the docs...
)} @@ -246,20 +243,20 @@ const SearchModal: React.FC = ({ open, onOpenChange }) => { - {isKorean ? "이동" : "Navigate"} + Navigate
- {isKorean ? "열기" : "Open"} + Open
esc - {isKorean ? "닫기" : "Close"} + Close @@ -267,29 +264,25 @@ const SearchModal: React.FC = ({ open, onOpenChange }) => { }; const NoResultsContent: React.FC = () => { - const isKorean = useRouter().pathname.startsWith("/ko"); - return (

- {isKorean ? "검색 결과가 없습니다" : "No results found"} + No results found

- {isKorean - ? "다른 검색어를 입력하거나 API 레퍼런스를 열어보세요." - : "Try a different search term or open the API reference."} + Try a different search term or open the API reference.

- {isKorean ? "API 레퍼런스" : "API reference"} + API reference
diff --git a/src/components/search/open-modal-button.tsx b/src/components/search/open-modal-button.tsx index 0076797..58e183e 100644 --- a/src/components/search/open-modal-button.tsx +++ b/src/components/search/open-modal-button.tsx @@ -1,5 +1,4 @@ import React from "react"; -import { useRouter } from "next/router"; import { Icon } from "../icon"; interface OpenModalButtonProps { @@ -11,14 +10,12 @@ const OpenModalButton: React.FC = ({ iconOnly, onOpen, }) => { - const isKorean = useRouter().pathname.startsWith("/ko"); - if (iconOnly) { return ( @@ -32,7 +29,7 @@ const OpenModalButton: React.FC = ({ >
- {isKorean ? "검색..." : "Search..."} + Search...
K diff --git a/src/components/seo.tsx b/src/components/seo.tsx index e94c7ab..056896f 100644 --- a/src/components/seo.tsx +++ b/src/components/seo.tsx @@ -22,7 +22,7 @@ export interface Props extends NextSeoProps { const title = "Sume Developer Docs"; const description = "Documentation for the Sume Public API and CLI"; -export const baseUrl = "https://docs.sume.so"; +export const baseUrl = "https://docs.sume.com"; const image = baseUrl + "/og.png"; const config: DefaultSeoProps = { @@ -56,7 +56,8 @@ export const SEO: React.FC = ({ const title = props.title ?? config.title; const twitterTitle = props.twitterTitle; const description = props.description; - const url = props.url || `${baseUrl}${router.asPath.split("?")[0].split("#")[0]}`; + const url = + props.url || `${baseUrl}${router.asPath.split("?")[0].split("#")[0]}`; // Check if any headers are questions (for FAQPage schema) const hasQuestions = headers.some(h => h.title.trim().endsWith("?")); diff --git a/src/components/sidebar.tsx b/src/components/sidebar.tsx index 068497b..2071d6f 100644 --- a/src/components/sidebar.tsx +++ b/src/components/sidebar.tsx @@ -2,7 +2,6 @@ import { useRouter } from "next/router"; import React, { useMemo, useState, useEffect, useRef } from "react"; import { cn } from "@/lib/cn"; import { sidebarContent } from "../data/sidebar"; -import { koreanSidebarContent } from "../data/sidebar-ko"; import { Link } from "./link"; import { IPage, ISubSection, IExternalLink, ISidebarSection } from "../types"; import SidebarItem from "./sidebar-item"; @@ -80,15 +79,11 @@ const SidebarContent: React.FC = () => { query: { slug }, pathname, } = useRouter(); - const isKorean = pathname.startsWith("/ko"); - const activeSidebarContent = isKorean ? koreanSidebarContent : sidebarContent; + const activeSidebarContent = sidebarContent; const prefixedSlug = useMemo( - () => - slug - ? `${isKorean ? "/ko" : ""}/${(slug as string[] | undefined)?.join("/")}` - : undefined, - [isKorean, slug], + () => (slug ? `/${(slug as string[] | undefined)?.join("/")}` : undefined), + [slug], ); const [expandedSubSections, setExpandedSubSections] = useState([]); diff --git a/src/components/top-nav.tsx b/src/components/top-nav.tsx index e2c639c..d8ee462 100644 --- a/src/components/top-nav.tsx +++ b/src/components/top-nav.tsx @@ -9,28 +9,18 @@ import { IPage, ISubSection, IExternalLink, ISidebarSection } from "../types"; import SidebarItem from "./sidebar-item"; import { Arrow } from "@/components/arrow"; import { OpenSearchModalButton } from "./search"; -import { koreanSidebarContent } from "../data/sidebar-ko"; const navLinks = [ { title: "API", href: "/public-api" }, { title: "CLI", href: "/cli" }, ]; -const koNavLinks = [ - { title: "API", href: "/ko/public-api" }, - { title: "CLI", href: "/ko/cli" }, -]; - type TopNavProps = { onOpenSearch: () => void; }; // Desktop Top Navigation export const TopNav: React.FC = ({ onOpenSearch }) => { - const { pathname } = useRouter(); - const isKorean = pathname.startsWith("/ko"); - const links = isKorean ? koNavLinks : navLinks; - return (
{/* Left - Logo */} @@ -41,9 +31,7 @@ export const TopNav: React.FC = ({ onOpenSearch }) => { > | - - {isKorean ? "문서" : "Docs"} - + Docs @@ -53,7 +41,7 @@ export const TopNav: React.FC = ({ onOpenSearch }) => { {/* Right - Links */} @@ -77,8 +65,6 @@ export const TopNav: React.FC = ({ onOpenSearch }) => { // Mobile Top Navigation with Hamburger Menu export const MobileTopNav: React.FC = ({ onOpenSearch }) => { const router = useRouter(); - const isKorean = router.pathname.startsWith("/ko"); - const links = isKorean ? koNavLinks : navLinks; const [isMenuOpen, setIsMenuOpen] = useState(false); const closeMenu = useCallback(() => { @@ -113,7 +99,7 @@ export const MobileTopNav: React.FC = ({ onOpenSearch }) => { | - {isKorean ? "문서" : "Docs"} + Docs @@ -126,15 +112,7 @@ export const MobileTopNav: React.FC = ({ onOpenSearch }) => {