Docs
MyPage AI Edit Guide
# Botari MyPage AI Edit Guide
외부 AI가 사용자의 페이지를 사용자의 요구에 맞게, 보따리 마이페이지 JSON/CSS가 허용하는 범위 안에서 수정할 때 읽는 문서입니다.
이 API는 보따리앱 제작용 `BotariSDK`가 아닙니다. 사용자가 마이페이지의 `내 AI로 수정하기`에서 복사한 안내문에 포함된 Bearer 토큰으로만 사용할 수 있습니다.
목적은 현재 로그인 사용자의 마이페이지 레이아웃, 문구, 색상, 섹션 배치, CSS를 조정하는 것입니다. 상품 등록, 결제, 관리자 작업, 서버 구조 탐색, 다른 사용자 데이터 접근은 목적 밖입니다.
## 먼저 해야 할 일
1. 바로 API를 호출하거나 JSON/CSS를 만들지 않습니다. 먼저 사용자에게 마이페이지에서 무엇을 어떻게 수정할지 묻습니다.
2. 사용자의 답변에서 목적, 수정 범위, 원하는 분위기, 유지해야 할 섹션을 확인합니다.
3. 사용자가 답한 뒤 안내문에서 API URL과 `Authorization: Bearer ...` 토큰을 확인합니다.
4. `GET /wp-json/botari/v1/mypage/ai-edit`로 현재 `page_json`과 `page_css`를 읽습니다.
5. 사용자의 요구에 맞게 가능한 범위에서 JSON/CSS를 수정합니다.
6. `POST /wp-json/botari/v1/mypage/ai-edit`로 저장을 먼저 시도합니다. 저장 API 호출을 생략하고 JSON 파일만 만드는 것은 실패 처리입니다.
7. 수정이 완전히 끝나기 전까지는 저장 body에 `complete`를 넣지 않습니다. 중간 저장 후 같은 토큰으로 다시 읽고 저장할 수 있습니다.
8. 작업이 끝났다고 판단해도 바로 세션을 완료하지 않습니다. 먼저 사용자에게 "이대로 완료하고 AI 편집 세션을 닫을까요?"라고 묻습니다.
9. 사용자가 완료/닫기/끝내기/좋다 등으로 명확히 확인한 마지막 저장에만 `"complete": true`와 `"complete_confirmed": true`를 함께 넣습니다.
문서 URL을 열 수 없으면 `https://botari.net/docs/mypage-ai-edit.txt`도 시도합니다. `.md`와 `.txt` 내용은 같습니다.
## 토큰 정책
- 토큰은 현재 로그인한 사용자 한 명의 마이페이지에만 묶입니다.
- 토큰 수명은 10분입니다.
- 일반 저장은 토큰을 만료하지 않습니다.
- 마지막 저장에서 `"complete": true`와 `"complete_confirmed": true`를 함께 보내면 세션이 완료되고 토큰은 만료됩니다.
- `"complete": true`만 보내고 `"complete_confirmed": true`가 없으면 서버는 저장만 하고 세션은 active 상태로 유지합니다.
- 저장하지 않아도 10분 이상 방치하면 만료됩니다.
- 토큰으로 가능한 작업은 현재 마이페이지 `page_json`/`page_css` 읽기와 저장뿐입니다.
- 상품 등록, 결제, 관리자 작업, 서버 파일 접근, 다른 사용자 데이터 접근은 할 수 없습니다.
## 읽기
```http
GET https://botari.net/wp-json/botari/v1/mypage/ai-edit
Authorization: Bearer btmypage_xxx
```
응답 예:
```json
{
"success": true,
"page_json": {
"version": "1.0",
"sections": []
},
"page_css": "",
"expires_at": "2026-07-04T04:00:00+00:00"
}
```
## 저장
```http
POST https://botari.net/wp-json/botari/v1/mypage/ai-edit
Authorization: Bearer btmypage_xxx
Content-Type: application/json
```
요청 body:
```json
{
"page_json": {
"version": "1.0",
"sections": []
},
"page_css": "/* optional */",
"complete": false,
"complete_confirmed": false
}
```
중간 저장 성공 응답:
```json
{
"success": true,
"status": "active",
"message": "마이페이지가 저장되었습니다. AI 편집 세션은 계속 유지됩니다."
}
```
완료 저장 전 필수 확인:
완료 저장을 보내기 전에 반드시 사용자에게 "이대로 완료하고 AI 편집 세션을 닫을까요?"라고 묻습니다.
사용자가 명확히 확인한 뒤에만 아래 body를 보냅니다.
완료 저장 요청 body:
```json
{
"page_json": {
"version": "1.0",
"sections": []
},
"page_css": "/* optional */",
"complete": true,
"complete_confirmed": true
}
```
완료 저장 성공 응답:
```json
{
"success": true,
"status": "completed",
"message": "마이페이지가 저장되었고 AI 편집 세션이 완료되었습니다."
}
```
완료 저장 후 사용자의 브라우저는 완료 상태를 감지해 꾸미기 사이드바를 닫고 화면을 새로고침합니다.
## JSON 규칙
`page_json`은 반드시 다음 형태를 유지해야 합니다.
```json
{
"version": "1.0",
"theme": {
"accent": "red",
"background": {
"type": "solid",
"solid": "#111827"
},
"dark": true
},
"sections": []
}
```
마이페이지 배경을 어둡게 바꾸거나 사용자가 다크 분위기를 요청한 경우에만 `theme.dark: true`를 함께 저장합니다.
이 값은 현재 사용자의 마이페이지 화면에만 적용됩니다. 일반 사이트 전체 테마, 관리자 화면, 다른 사용자 페이지를 바꾸는 용도로 사용하지 않습니다.
밝은 배경으로 되돌릴 때는 `theme.dark`를 `false`로 두거나 생략합니다.
필수 섹션:
- 프로필 섹션: `{ "type": "profile" }`
기본 보존 섹션:
- 판매 상품 목록: `{ "type": "selling-products" }` 또는 `{ "type": "products", "source": "selling" }`
- 구매 상품 목록: `{ "type": "purchased-products" }` 또는 `{ "type": "products", "source": "purchased" }`
- 참여 보따리템 목록: `{ "type": "submitted-products" }` 또는 `{ "type": "products", "source": "submitted" }`
프로필 섹션은 삭제하지 않습니다. 단, 위치 이동, 레이아웃, 스타일, 문구, 버튼 라벨 변형은 가능합니다.
프로필 안의 기능 버튼은 label을 바꿔도 되지만 `speech-bubbles`, `profile-edit`, `customize-page`, `logout` action은 유지해야 합니다.
사용자가 "프로필만 남기기", "프로필 아래 모두 숨기기"처럼 섹션 제거만 요청한 경우 profile의 기존 레이아웃/스타일/문구/버튼은 유지합니다.
"깔끔하게" 같은 표현만으로 profile을 카드형/중앙정렬/그림자 스타일로 바꾸지 않습니다. profile 디자인 변경은 사용자가 명시적으로 요청했을 때만 합니다.
프로필 섹션을 제외한 판매/구매/받은템/앱/텍스트/이미지/기타 섹션은 사용자가 숨기거나 제거하라고 하면 모두 삭제할 수 있습니다.
사용자가 숨기거나 제거하라고 명시하지 않은 경우에는 판매/구매 목록을 유지합니다.
반대로 사용자가 "프로필 아래 모두 숨기기", "received-products만", "받은 보따리템만"처럼 명시하면 판매/구매 목록을 다시 추가하지 않습니다.
이 경우 `{ "type": "received-products", "visibility": "public" }` 단독 섹션 구성이 허용됩니다.
사용자가 "프로필만 남기기"처럼 명시하면 `profile` 섹션만 남겨도 됩니다.
사용자가 "내가 추가로 넣을 수 있는 요소들이 뭐가 있어?"처럼 물으면 아래처럼 일반인이 이해할 수 있는 말로 설명합니다.
JSON 타입명부터 나열하지 않습니다.
- 글 상자: 제목, 소개글, 안내문 같은 문장을 넣을 수 있습니다.
- 사진 영역: 마이페이지 전용 보관 이미지나 기존 슬롯 이미지를 보여줄 수 있습니다.
- 버튼: 프로필 편집, 말풍선, AI워크, 보따리템 등록 같은 행동 버튼을 넣을 수 있습니다.
- 구분선과 여백: 화면을 보기 좋게 나누거나 공간을 띄울 수 있습니다.
- 묶음 상자: 여러 요소를 한 덩어리로 묶어 배경색, 테두리, 정렬을 줄 수 있습니다.
- 가로/세로 배치: 여러 요소를 줄 맞춰 배치할 수 있습니다.
- 탭: 여러 내용을 탭으로 나눠 보여줄 수 있습니다.
- 슬라이드/캐러셀: 여러 사진이나 내용을 넘겨볼 수 있게 만들 수 있습니다.
- 접히는 설명: 길어진 내용을 접었다 펼칠 수 있습니다.
- 영상: 영상 링크나 영상 영역을 넣을 수 있습니다.
- 진행바: 달성률이나 진행 상태를 보여줄 수 있습니다.
- 카운트다운: 날짜까지 남은 시간을 보여줄 수 있습니다.
- 내가 만든 보따리템 목록: 판매/공개 중인 보따리템을 보여줄 수 있습니다.
- 싸온 보따리템 목록: 구매했거나 무료로 내 보따리에 추가한 보따리템을 보여줄 수 있습니다.
- 받은 보따리템 목록: 다른 사람이 보낸 보따리템을 보여줄 수 있습니다.
- 참여 보따리템 목록: 다른 유저가 이 좌판에 올린 보따리템을 보여주고, 로그인한 방문자가 자기 공개 보따리템을 선택해 올릴 수 있게 합니다.
내부 JSON 주요 섹션 타입:
- `profile`
- `selling-products`
- `purchased-products`
- `received-products`
- `submitted-products`
- `apps`
- `submit-box`
- `products`
- `text`
- `image`
- `button`
- `divider`
- `spacer`
- `container`
- `grid`
- `flex`
- `tabs`
- `carousel`
- `accordion`
- `collapse`
- `video`
- `progress`
- `countdown`
## 버튼 기능
사용자가 추가하는 일반 버튼은 프로필 편집/로그아웃 같은 기본 관리 버튼이 아니라, 방문자를 원하는 위치로 보내는 탐색 버튼으로 다룹니다.
- 일반 버튼은 `action`보다 `url`을 우선 사용합니다.
- `url`은 `/경로`, `#section-id`, `https://example.com` 형식을 사용할 수 있습니다.
- 새 창이 필요할 때만 `target`을 `"_blank"`로 둡니다.
- 버튼으로 할 수 있는 일은 외부 링크 열기, 사이트 안 다른 페이지 또는 커스텀 페이지로 이동, 페이지 안 특정 섹션으로 이동, 보따리템/목록 페이지로 이동 같은 탐색 기능입니다.
- `profile-edit`, `ai-workspace`, `customize-page`, `dashboard`, `logout`, `admin` 같은 프로필 기본/관리 버튼은 프로필 영역 유지용입니다. 사용자가 명시하지 않으면 추가 가능한 요소 예시로 추천하지 않습니다.
## 영상
마이페이지 영상은 사용자가 꾸미기 사이드바에 등록한 `videoSlots`만 사용합니다. 무료 운영 레벨에서는 영상 파일을 직접 업로드하거나 서버에 저장하지 않습니다.
- 영상 슬롯은 최대 3개입니다.
- 사용자가 사이드바에 YouTube/Vimeo 링크를 넣으면 `page_json.videoSlots`에 저장됩니다.
- AI는 임의 영상 URL을 만들지 말고, 기존 슬롯의 `id`를 `video.slotId`로 참조합니다.
- `<iframe>`, `<video>`, `<script>` HTML을 직접 작성하지 않습니다.
- 영상 파일 업로드, 다운로드, 변환, 서버 저장을 시도하지 않습니다.
- 배경 영상 효과가 필요하면 영상 파일 대신 사용자가 등록한 영상 슬롯이나 포스터/썸네일 기반 디자인을 사용합니다.
- 사용자가 "바탕에 영상 깔 수 있어?", "영상 넣을 수 있어?"처럼 물으면 먼저 현재 `page_json.videoSlots`를 확인합니다.
- `videoSlots`가 비어 있으면 "네 가능합니다. 다만 영상 업로드는 안 되고, 먼저 꾸미기 사이드바의 영상 링크 슬롯에 YouTube/Vimeo 링크를 넣어주세요. 링크가 들어오면 그 슬롯으로 적용할 수 있습니다."라고 안내합니다.
- 사용 가능한 `videoSlots`가 있으면 "영상 링크를 확인했습니다. 이 슬롯으로 배경 느낌 또는 영상창을 만들 수 있습니다. 어떤 위치에 넣을까요?"처럼 답한 뒤 `slotId`로 작업합니다.
- 사용자가 영상 URL을 채팅에 직접 붙여넣으면, AI가 JSON에 직접 넣지 말고 "이 링크를 사이드바 영상 링크 슬롯에 넣어주세요"라고 안내합니다.
예:
```json
{
"videoSlots": [
{
"id": "video-slot-1",
"label": "소개 영상",
"url": "https://youtu.be/example"
}
],
"sections": [
{
"type": "video",
"slotId": "video-slot-1",
"width": "100%",
"height": "360px"
}
]
}
```
## 이미지 슬롯
사용자가 내 좌판 꾸미기 사이드바에서 직접 올린 이미지는 마이페이지 전용 보관함에 저장됩니다.
이 보관함은 WordPress 미디어 라이브러리, 보따리템 이미지, 글/사이트 콘텐츠 이미지와 분리됩니다.
외부 AI는 새 이미지를 생성하거나 외부 이미지 URL을 임의로 넣지 말고, 현재 `page_json.imageSlots`에 있는 슬롯만 사용합니다.
사용자가 직접 올린 마이페이지 전용 이미지 외에, 사용자가 만든 보따리템/콘텐츠 안의 이미지는 읽기 전용으로 추가 사용할 수 있습니다.
- 이미지 슬롯은 최대 9개입니다.
- 슬롯 순서는 사용자에게 설명할 때 1번부터 9번까지로 부릅니다.
- 실제 JSON에서는 `imageSlots[0]`부터 `imageSlots[8]`까지로 다룹니다.
- 페이지 전체 배경으로 쓰려면 해당 슬롯의 `target`을 `"page-background"`로 둡니다.
- 특정 섹션 배경으로 쓰려면 해당 섹션의 `id`를 `target`에 넣습니다.
- 내가 만든 보따리템, 싸온 보따리템, 받은 보따리템, 참여 보따리템 같은 보따리템 목록 섹션에는 배경 이미지를 넣지 않습니다. 카드 가독성을 위해 이미지 슬롯 target으로 쓰지 마세요.
- 슬라이드(`carousel`)에 이미지를 넣을 때도 외부 URL 대신 이 슬롯에 있는 파일명을 사용하는 `image` 섹션을 슬라이드 아이템으로 배치합니다.
- 슬롯의 `src`는 서버가 저장한 파일명입니다. 전체 URL로 바꾸지 않습니다.
- 사용자의 기존 콘텐츠 이미지는 서버가 `source: "content"`와 `url`로 내려준 경우에만 사용할 수 있습니다. 이 이미지는 삭제하거나 업로드 저장소로 옮기지 않습니다.
예:
```json
{
"imageSlots": [
{
"id": "image-slot-1",
"src": "background_1234567890.webp",
"target": "page-background"
}
]
}
```
기존 콘텐츠 이미지를 쓰는 예:
```json
{
"imageSlots": [
{
"id": "image-slot-content-1",
"source": "content",
"src": "my-image.webp",
"url": "https://botari.net/wp-content/uploads/2026/07/my-image.webp",
"title": "내가 만든 콘텐츠 이미지",
"target": "page-background"
}
]
}
```
`submitted-products`는 로그인한 방문자가 이미 가진 공개 보따리템을 선택해 이 좌판에 올릴 수 있게 하는 참여 목록입니다. 새 보따리템을 생성하는 폼이 아닙니다.
```json
{
"type": "submitted-products",
"title": "함께 올린 보따리템",
"showFilters": true,
"visibility": "public"
}
```
`submit-box`는 별도 CTA 박스가 필요할 때만 사용합니다. 기본 참여 목록은 `submitted-products`를 사용하세요.
```json
{
"type": "submit-box",
"title": "보따리템 보내기",
"description": "로그인한 방문자는 자신이 만든 보따리템을 이 페이지에 보낼 수 있습니다.",
"button_label": "내 보따리템 보내기",
"visibility": "public"
}
```
`submit-box`는 박스 자체를 보이게 두는 `public` 사용을 권장합니다. 비로그인 방문자에게는 로그인 링크가 보이고, 로그인한 방문자에게만 보내기 버튼이 보입니다.
허용 button action:
- `speech-bubbles`
- `profile-edit`
- `ai-workspace`
- `customize-page`
- `dashboard`
- `logout`
- `add-product`
- `buy-credits`
- `admin`
## CSS 규칙
- CSS는 선택 사항입니다.
- CSS는 마이페이지 영역 안에서만 동작해야 합니다.
- 서버는 CSS를 `.page-custom-sections` 스코프로 보정합니다.
- CSS는 사용자별 `/page-custom/{user_id}/style.css`로 저장되므로 다른 사용자의 마이페이지에는 적용되지 않습니다.
- 다만 같은 사용자 페이지 안에서는 공통 선택자가 여러 요소에 동시에 적용될 수 있으므로 넓은 선택자를 피합니다.
- 특정 섹션이나 요소를 수정할 때는 `[data-bt-id="..."]` 선택자를 우선 사용합니다.
- `.bt-button`, `.bt-profile`, `.bt-tabs`, `.bt-submit-box`, `.product-tile-grid` 같은 공통 클래스 단독 선택자는 가급적 사용하지 않습니다.
- 공통 클래스를 써야 할 때는 반드시 `[data-bt-id="section-id"] .bt-button`처럼 특정 섹션으로 좁힙니다.
- 색상, 간격, 배경, 정렬처럼 JSON `style`로 표현 가능한 변경은 `page_css`보다 `page_json`의 `style`을 우선 수정합니다.
- 위험한 CSS 또는 너무 큰 CSS는 거절될 수 있습니다.
- 외부 이미지/스크립트 삽입, 관리자 UI 조작, 보안 우회 목적의 CSS는 만들지 않습니다.
## 실패 시 대응
API 저장이 실패하면 사용자가 직접 붙여넣을 수 있게 다음 두 코드블록을 제공합니다.
단, 다음 경우에만 붙여넣기용 JSON/CSS로 fallback합니다.
- 실행 환경이 외부 네트워크를 지원하지 않음
- DNS 또는 TLS 문제로 `botari.net`에 접속할 수 없음
- Bearer 토큰이 만료되었거나 `invalid_token` 응답을 받음
- 서버가 검증 오류를 반환해 저장할 수 없음
fallback을 할 때는 저장 API를 호출하지 못한 정확한 이유를 먼저 한 줄로 설명합니다.
```json
{
"version": "1.0",
"sections": []
}
```
```css
/* optional */
```
토큰 만료나 `invalid_token`이 나오면 사용자에게 `내 AI로 수정하기`에서 안내문을 다시 복사하라고 요청합니다.