# Lightsoft Class 템플릿 가이드 ## 1. 소개 Lightsoft Class는 비개발자에게 바이브코딩 학습 과정을 친근한 단계형 카드뉴스로 설명한다. 설치, 터미널, 실습, 링크 모음처럼 순서가 있는 교육 주제에 적합하고, 사진이 주인공인 여행 화보나 실시간 뉴스 요약에는 적합하지 않다. ## 2. 톤 가이드 독자가 바로 행동할 수 있는 짧은 평서문을 쓴다. 생소한 용어는 한 문장 안에서 풀어 쓰고, 단계 제목은 동사형 또는 명사형 중 하나로 통일한다. 과장하거나 질문만 던지고 답을 미루지 않는다. ## 3. 슬라이드 흐름 권장 기본 흐름은 `cover → content/content-list → step1-terminal → step2-benefits → step3-setup/step3-practice/step3-setup-detail/step3-usage → step4-links → step5-summary → cta`다. `cover`와 `cta`는 각각 정확히 1장이고, 나머지 타입은 주제에 맞게 골라 조합한다. ## 4. 슬롯별 작성 요령 아래 슬롯 한계는 등록 시 manifest에서 자동 생성했다. design_max는 디자인 권장 상한이며 초과해도 렌더는 성공하지만 `design_max_exceeded` 경고가 발생한다. max_chars는 실측 하드 상한이며 초과하면 422 `max_chars_exceeded`가 발생한다. 다만 max_chars는 레이아웃 안전을 보장하는 값이 아니라, 같은 글자 수라도 글자 폭이나 줄바꿈에 따라 max_chars 이내에서 렌더 영역을 넘을 수 있다. 이 경우 렌더는 성공하고 결과 이미지와 함께 `text_overflow` 등의 warning을 반환하므로, 경고가 발생한 슬롯의 문구를 더 줄여 다시 렌더한다. 이 수치는 손으로 쓴 것이 아니라 manifest가 원본이다 — 본 가이드와 manifest는 영구히 일치한다. - 요청 크기: `POST /v1/renders`의 전체 JSON 요청 본문 상한은 1,048,576바이트(1MB)다. 초과하면 HTTP 413 `payload_too_large`가 발생한다. - 글쓰기 원칙: 한 슬라이드에 한 주장. 좋은 예: `API 문서를 자동으로 검증하는 법`. 나쁜 예: `정말 놀랍고 엄청난 API 문서 자동화에 관하여 알아볼까요?`. - 브랜딩: `brand_logo_url`은 프로젝트 브랜드 자산(`logo_horizontal`)으로 렌더 시 자동 공급된다. 슬롯 값으로 데이터 URI를 직접 넣지 않는다. - 색상: `accent_color`는 manifest 테마 또는 `brand.colors.accent`의 `#RRGGBB`로 자동 공급된다. - 이미지: `image` 타입 슬롯은 공개 HTTPS URL과 `data:image/;base64,...` 데이터 URI를 모두 허용한다. 실사진은 본문 상한을 피하도록 원격 HTTPS URL을 사용하고, 데이터 URI는 로고·아이콘 같은 작은 자산에만 사용한다. 슬라이드 타입별로 아래 소절을 확인한다. 슬롯 이름·필수 여부·한계값은 manifest에서 생성되며, 타입별 작성 요령은 manifest의 `slide_types[].guidance`가 원본이다. ### `cover` (min 1, max 1) 과정의 핵심 주제를 한 문장 제목으로 선언하고 짧은 영문 태그와 호수를 붙인다. | 슬롯 | 필수 | 형식·한계 | | --- | --- | --- | | `tag_text` | 예 | max 10자 | | `serial` | 예 | max 15자 | | `title` | 예 | max 20자 | | `brand_logo_url` | 아니오 | 브랜드 자산(logo_horizontal) | ### `content` (min 0, max 10) 단계 번호와 제목을 먼저 쓰고, 본문은 한 가지 행동이나 개념만 설명한다. | 슬롯 | 필수 | 형식·한계 | | --- | --- | --- | | `step_number` | 예 | max 37자 | | `step_title` | 예 | max 29자 | | `body` | 예 | max 520자 | | `image_url_1` | 예 | 이미지(공개 HTTPS URL 또는 data URI) | ### `content-list` (min 0, max 10) 서로 병렬인 세 항목을 같은 문장 깊이로 쓰고 각 항목에 대응하는 이미지를 제공한다. | 슬롯 | 필수 | 형식·한계 | | --- | --- | --- | | `step_number` | 예 | max 37자 | | `step_title` | 예 | max 29자 | | `desc_1` | 예 | max 312자 | | `desc_2` | 예 | max 208자 | | `desc_3` | 예 | max 104자 | | `image_url_1` | 예 | 이미지(공개 HTTPS URL 또는 data URI) | | `image_url_2` | 예 | 이미지(공개 HTTPS URL 또는 data URI) | | `image_url_3` | 예 | 이미지(공개 HTTPS URL 또는 data URI) | ### `step1-terminal` (min 0, max 10) 터미널 사용의 핵심을 본문으로 설명하고, 실행 순서를 포인트 세 개로 짧게 나눈다. | 슬롯 | 필수 | 형식·한계 | | --- | --- | --- | | `step_number` | 예 | max 999자 | | `step_title` | 예 | max 29자 | | `body` | 예 | max 741자 | | `point_1` | 예 | max 44자 | | `point_2` | 예 | max 44자 | | `point_3` | 예 | max 44자 | | `tag_text` | 예 | max 51자 | ### `step2-benefits` (min 0, max 10) 독자가 가질 질문과 그에 대한 직접적인 답을 한 쌍으로 작성한다. | 슬롯 | 필수 | 형식·한계 | | --- | --- | --- | | `step_number` | 예 | max 37자 | | `step_title` | 예 | max 29자 | | `question` | 예 | max 20자 | | `answer` | 예 | max 20자 | ### `step3-setup` (min 0, max 10) 설치·설정 단계의 목적을 섹션 제목으로, 실제 해야 할 행동을 본문으로 쓴다. | 슬롯 | 필수 | 형식·한계 | | --- | --- | --- | | `step_number` | 예 | max 37자 | | `step_title` | 예 | max 29자 | | `section_title` | 예 | max 11자 | | `body` | 예 | max 144자 | ### `step3-practice` (min 0, max 10) 실습 전환을 알리는 짧은 섹션 제목을 사용하고 세부 설명은 다음 슬라이드로 넘긴다. | 슬롯 | 필수 | 형식·한계 | | --- | --- | --- | | `step_number` | 예 | max 37자 | | `step_title` | 예 | max 29자 | | `section_title` | 예 | max 16자 | ### `step3-setup-detail` (min 0, max 10) 두 설정 화면의 차이를 각각 설명하고 마지막에 한 줄 팁을 덧붙인다. | 슬롯 | 필수 | 형식·한계 | | --- | --- | --- | | `step_number` | 예 | max 37자 | | `step_title` | 예 | max 29자 | | `section_title` | 예 | max 16자 | | `desc_1` | 예 | max 396자 | | `desc_2` | 예 | max 252자 | | `tip` | 예 | max 180자 | | `image_url_1` | 예 | 이미지(공개 HTTPS URL 또는 data URI) | | `image_url_2` | 예 | 이미지(공개 HTTPS URL 또는 data URI) | ### `step3-usage` (min 0, max 10) 좌우 예시의 캡션을 대칭으로 쓰고, 하단 본문은 공통 결론만 설명한다. | 슬롯 | 필수 | 형식·한계 | | --- | --- | --- | | `step_number` | 예 | max 37자 | | `step_title` | 예 | max 29자 | | `caption_left` | 예 | max 36자 | | `caption_right` | 예 | max 17자 | | `body` | 예 | max 250자 | ### `step4-links` (min 0, max 10) 링크 두 개를 같은 형식으로 소개하고 제목·URL·이미지 라벨을 모두 채운다. | 슬롯 | 필수 | 형식·한계 | | --- | --- | --- | | `step_number` | 예 | max 37자 | | `step_title` | 예 | max 29자 | | `item1_title` | 예 | max 35자 | | `item1_link` | 예 | max 41자 | | `item1_label` | 예 | max 29자 | | `item2_title` | 예 | max 35자 | | `item2_link` | 예 | max 41자 | | `item2_label` | 예 | max 29자 | | `image_url_1` | 예 | 이미지(공개 HTTPS URL 또는 data URI) | | `image_url_2` | 예 | 이미지(공개 HTTPS URL 또는 data URI) | ### `step5-summary` (min 0, max 10) 칠판 제목과 본문으로 배운 내용을 압축하고, 하단에는 다음 행동을 한 문장으로 쓴다. | 슬롯 | 필수 | 형식·한계 | | --- | --- | --- | | `step_number` | 예 | max 37자 | | `step_title` | 예 | max 29자 | | `chalk_title` | 예 | max 28자 | | `chalk_body` | 예 | max 1056자 | | `bottom_text` | 예 | max 120자 | ### `cta` (min 1, max 1) 짧은 부제와 행동 문구, 실제 이동할 URL을 제공해 학습 흐름을 닫는다. | 슬롯 | 필수 | 형식·한계 | | --- | --- | --- | | `subtitle` | 예 | max 48자 | | `cta_text` | 예 | max 34자 | | `url` | 예 | max 48자 | | `brand_logo_url` | 아니오 | 브랜드 자산(logo_horizontal) | ## 5. 완성된 slides.json 예시 다음 JSON은 모든 슬라이드 타입을 한 장씩 포함하며 그대로 렌더 요청 본문으로 사용할 수 있다. ```json { "template": "lightsoft-class", "format": "instagram", "slides": [ { "type": "cover", "slots": { "tag_text": "VIBE CODE", "serial": "CLASS 01", "title": "처음 시작하는 바이브코딩" } }, { "type": "content", "slots": { "step_number": "STEP 0", "step_title": "준비하기", "body": "필요한 도구를 한곳에 모아 시작합니다.", "image_url_1": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAF/gL+XwW5WQAAAABJRU5ErkJggg==" } }, { "type": "content-list", "slots": { "step_number": "STEP 0", "step_title": "준비 목록", "desc_1": "목표를 한 줄로 씁니다.", "desc_2": "자료를 한곳에 모읍니다.", "desc_3": "완료 기준을 정합니다.", "image_url_1": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAF/gL+XwW5WQAAAABJRU5ErkJggg==", "image_url_2": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAF/gL+XwW5WQAAAABJRU5ErkJggg==", "image_url_3": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAF/gL+XwW5WQAAAABJRU5ErkJggg==" } }, { "type": "step1-terminal", "slots": { "step_number": "STEP 1", "step_title": "터미널 열기", "body": "명령을 입력해 작업을 시작합니다.", "point_1": "폴더로 이동", "point_2": "명령어 입력", "point_3": "결과 확인", "tag_text": "TERMINAL" } }, { "type": "step2-benefits", "slots": { "step_number": "STEP 2", "step_title": "효과 이해", "question": "코드를 몰라도 시작할 수 있나요?", "answer": "작은 요청부터 확인합니다." } }, { "type": "step3-setup", "slots": { "step_number": "STEP 3", "step_title": "환경 설정", "section_title": "도구 연결", "body": "프로젝트 폴더와 실행 도구를 연결합니다." } }, { "type": "step3-practice", "slots": { "step_number": "STEP 3", "step_title": "첫 실습", "section_title": "작은 화면부터 만들어 봅니다" } }, { "type": "step3-setup-detail", "slots": { "step_number": "STEP 3", "step_title": "설정 확인", "section_title": "두 화면 비교", "desc_1": "왼쪽에서 입력을 확인합니다.", "desc_2": "오른쪽에서 결과를 확인합니다.", "tip": "한 번에 하나씩 바꿉니다.", "image_url_1": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAF/gL+XwW5WQAAAABJRU5ErkJggg==", "image_url_2": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAF/gL+XwW5WQAAAABJRU5ErkJggg==" } }, { "type": "step3-usage", "slots": { "step_number": "STEP 3", "step_title": "요청 작성", "caption_left": "원하는 결과", "caption_right": "확인할 기준", "body": "목표와 완료 기준을 함께 전달합니다." } }, { "type": "step4-links", "slots": { "step_number": "STEP 4", "step_title": "참고 링크", "item1_title": "기초 가이드", "item1_link": "docs.example.com/start", "item1_label": "START", "item2_title": "예제 모음", "item2_link": "docs.example.com/examples", "item2_label": "EXAMPLES", "image_url_1": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAF/gL+XwW5WQAAAABJRU5ErkJggg==", "image_url_2": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAF/gL+XwW5WQAAAABJRU5ErkJggg==" } }, { "type": "step5-summary", "slots": { "step_number": "STEP 5", "step_title": "핵심 정리", "chalk_title": "작게 시작하기", "chalk_body": "요청하고 확인하고 고칩니다.", "bottom_text": "이제 첫 프로젝트를 시작하세요." } }, { "type": "cta", "slots": { "subtitle": "배운 내용을 직접 실행해 보세요", "cta_text": "첫 카드뉴스 만들기", "url": "archive.lightsoft.ai" } } ] } ``` ## 6. curl 호출 예시 ```bash curl -X POST 'https://api.cardnews.example/v1/renders' \ -H 'Authorization: Bearer $CARDNEWS_API_KEY' \ -H 'Content-Type: application/json' \ --data-binary @slides.json ``` ## 7. 검증·경고 대응 가이드 - `slide_count_violation`: `cover`와 `cta`는 각각 1장, 나머지 타입은 manifest 범위에 맞춘다. - `required_slot_missing`: 오류의 `path`가 가리키는 슬롯을 채운다. - `max_chars_exceeded`: 해당 타입 소절의 manifest 기반 한계 이하로 문구를 줄인다. - `text_overflow`: 문장을 짧게 쓰거나 다음 슬라이드로 나눈다. - `invalid_asset_data_uri`: 이미지 값을 공개 HTTPS URL 또는 올바른 `data:image/;base64,...` 형식으로 바꾼다. 실사진은 전체 JSON 본문 1MB 상한을 피하도록 원격 HTTPS URL을 사용한다. - `low_resolution`: 표시 영역보다 큰 원본 이미지로 교체한다.