📌 핀노트 (Pinnote)

어떤 웹사이트에든 스크립트 한 줄을 붙이면 됩니다. 사람들이 화면 요소에 핀을 꽂아 의견을 남기고, 여러 사이트의 의견이 한곳에 모입니다.

개발자(사람 또는 AI)는 어느 사이트·화면·요소에 대한 의견인지 정확히 보고 고칩니다. 고친 뒤에는 건마다 완료 응답을 남기고, 의견을 남긴 사람이 확인하거나 다시 엽니다.

설치 한 줄

<script src="https://pinnote.itemview.co.kr/w.js" data-site="pk_사이트키" defer></script>

선택 속성

속성뜻
data-version="1.4.2"앱 버전(의견에 함께 저장)
data-env="staging"환경
data-mode="toggle"toggle(기본, 📌 버튼으로 켜기) · always(항상 켜짐) · off
data-capture="off"요소 주변 캡처 끄기
data-errors="off"최근 JS 오류 수집 끄기
data-lang="ko"언어(지금은 한국어만)
data-position="left"📌 버튼을 왼쪽에 둔다(기본 right)
data-offset-bottom="72"📌 버튼을 바닥에서 이만큼(px) 올린다. 하단 고정 버튼·탭바가 있는 사이트용
data-offset-x="16"📌 버튼과 화면 옆 가장자리 사이(px)
data-name="홍길동"의견 창 이름 칸의 기본값(저장된 이름이 있으면 그것이 우선). 표시용 이름만 넣는다

사이트 코드에서 쓰기

Pinnote.setContext({ screen: 'checkout', journey_id: 'J123' }); // 의견에 함께 저장
Pinnote.setName('홍길동');                   // 이름 칸 기본값 (''이면 지우기, 창이 열려 있으면 바로 반영)
Pinnote.setPosition({ bottom: 72, side: 'right' }); // 하단 바 높이가 바뀔 때마다 알려 주기
Pinnote.open({ page: true });                // 화면 전체 의견 창
Pinnote.open({ selector: '#pay-button' });   // 특정 요소 의견 창
Pinnote.open();                              // 요소 고르기 모드
Pinnote.on('submitted', (d) => console.log('의견', d.id));
document.addEventListener('pinnote:submitted', (e) => console.log(e.detail));

설치 한 줄(defer)이 실행된 뒤의 호출은 위젯 본체가 아직 안 왔어도 로더가 쌓아 두었다가 넘깁니다. 그래서 사이트 코드는 DOMContentLoaded 안에서 부르면 안전합니다.

기능

관리 화면

  1. /admin/에서 관리자 비밀번호와 이름(목록에서 고르거나 새로 입력)으로 들어갑니다.
  2. 사이트 설정 → 새 사이트: 도메인을 넣으면 사이트 키와 설치 한 줄이 나옵니다. 여기서 경로 규칙, 사라짐 기준, 캡처 켜기·끄기를 정합니다.
  3. 받은 의견에서 정리하고, 의견 상세에서 이 요소를 실제 페이지에서 보기로 확인합니다.
  4. 해결할 때는 완료 응답(무엇을 어떻게 고쳤는지)을 적습니다.
  5. API 토큰을 만들어 에이전트나 CI에 넘깁니다. 사용법은 [docs/API.md](docs/API.md)에 있습니다.

API 한눈에

curl -H "Authorization: Bearer $PN_TOKEN" "https://pinnote.itemview.co.kr/api/v1/items?site=1&status=open"
curl -H "Authorization: Bearer $PN_TOKEN" "https://pinnote.itemview.co.kr/api/v1/export?site=1&status=open"   # 마크다운
curl -X POST -H "Authorization: Bearer $PN_TOKEN" -H 'Content-Type: application/json' \
  -d '{"status":"RESOLVED","note":"무엇을 어떻게 고쳤는지","version":"1.4.2"}' https://pinnote.itemview.co.kr/api/v1/items/12/status
php bin/pinnote.php resolve 12 "무엇을 어떻게 고쳤는지" --version=1.4.2

서버 설치·운영

# PHP 8.2 + MariaDB + Apache(AllowOverride All), 웹 루트 = public/
cp config.local.php.example config.local.php   # db, base_url, admin_password, app_secret (웹 루트 밖, git 제외)
php bin/migrate.php      # db/migrations/NNN_*.sql 순서대로 적용 (여러 번 실행해도 안전)
php bin/seed.php         # 기본 워크스페이스·뉴팅 데모·핀노트 데모 사이트와 사이트 키 출력 (중복 없음)

폴더

public/            웹 루트
  w.php            /w.js 로더(캐시 안 함) → widget/pinnote.js?v=버전(길게 캐시)
  widget/          위젯 본체
  vendor/          html2canvas 1.4.1 (MIT, 라이선스 파일 포함)
  api/w/           위젯 API
  api/v1/          REST API v1
  admin/           관리 화면
  demo/            데모 사이트(샘플 페이지 2개)
  docs/            문서 보기
  shot.php         캡처 보기(서명 URL)
lib/               공통 코드(웹 루트 밖)
db/migrations/     스키마
bin/               migrate, seed, pinnote(CLI)
docs/              INSTALL.md, API.md, DESIGN.md
storage/           logs, shots (git 제외)