@designfever/web-review-kit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,241 @@
1
+ # df-web-review-kit
2
+
3
+ Designfever web page review overlay toolkit.
4
+
5
+ `df-web-review-kit`는 프로젝트 안에 `/review` shell을 붙이고, iframe으로 실제 page를 띄운 뒤 QA note/area/DOM marker를 생성하는 검수 도구다. 각 프로젝트는 adapter만 바꿔서 local draft, df-sheet, Supabase 같은 저장소를 선택한다.
6
+
7
+ 현재 Lexus pilot 기준:
8
+
9
+ - package name: `@designfever/web-review-kit`
10
+ - current version: `0.1.0`
11
+ - first route: `/review`
12
+ - primary sources: `local`, `supabase`
13
+ - optional remote direction: `df-sheet`
14
+ - default overlay hotkey: `Shift+Q`
15
+
16
+ ## Docs
17
+
18
+ - [Concept](docs/concept.md): 제품 컨셉, local draft와 remote canonical QA의 역할
19
+ - [Installation](docs/installation.md): package 설치, `/review` mount, Vite/Lexus 예시
20
+ - [Supabase setup](docs/supabase.md): Supabase item/presence 연결 절차
21
+ - [Supabase review item SQL](docs/supabase-review-items.md): table, RPC, RLS, migration SQL
22
+ - [Supabase presence](docs/supabase-presence.md): Realtime Presence adapter 구조
23
+ - [Adapter handoff](docs/adapter-handoff.md): adapter contract와 분리 계획
24
+ - [df-sheet next](docs/df-sheet-next.md): df-sheet를 remote destination으로 쓸 때의 방향
25
+
26
+ `docs/initial-plan.md`는 초기 아이디어 기록이다. 현재 설치/운영 기준은 이 README와 위 문서를 우선한다.
27
+
28
+ ## Quick Start
29
+
30
+ Host project에 package와 React peer dependency를 설치한다.
31
+
32
+ ```bash
33
+ pnpm add @designfever/web-review-kit react react-dom
34
+ ```
35
+
36
+ Supabase를 remote/presence로 쓰면 host project에 Supabase client도 설치한다.
37
+
38
+ ```bash
39
+ pnpm add @supabase/supabase-js
40
+ ```
41
+
42
+ Vite project 예시:
43
+
44
+ ```tsx
45
+ import {
46
+ createFallbackPresenceAdapter,
47
+ createLocalPresenceAdapter,
48
+ createReviewPagesFromGlob,
49
+ createSupabasePresenceAdapter,
50
+ mountReviewShell,
51
+ type ReviewShellAdapter,
52
+ type SupabasePresenceClient,
53
+ } from '@designfever/web-review-kit/react-shell';
54
+ import {
55
+ REVIEW_WORKFLOW_STATUS_OPTIONS,
56
+ localAdapter,
57
+ supabaseAdapter,
58
+ type SupabaseReviewClient,
59
+ } from '@designfever/web-review-kit';
60
+ import { createClient } from '@supabase/supabase-js';
61
+
62
+ const REVIEW_PROJECT_ID = 'lexus-official-v2026';
63
+ const REVIEW_PATH_PREFIX = '/review';
64
+ const pages = createReviewPagesFromGlob(import.meta.glob('/**/index.tsx'), {
65
+ exclude: (href) =>
66
+ href === '/review/' ||
67
+ href === '/guide/' ||
68
+ href.startsWith('/guide/'),
69
+ });
70
+
71
+ const local = localAdapter({
72
+ storageKey: `${REVIEW_PROJECT_ID}-review-items`,
73
+ });
74
+
75
+ const supabaseClient = import.meta.env.VITE_REVIEW_SUPABASE_ANON_KEY
76
+ ? createClient(
77
+ import.meta.env.VITE_REVIEW_SUPABASE_URL,
78
+ import.meta.env.VITE_REVIEW_SUPABASE_ANON_KEY
79
+ )
80
+ : null;
81
+
82
+ const supabase = supabaseClient
83
+ ? supabaseAdapter({
84
+ client: supabaseClient as unknown as SupabaseReviewClient,
85
+ table: import.meta.env.VITE_REVIEW_SUPABASE_TABLE || 'review_items',
86
+ projectId: REVIEW_PROJECT_ID,
87
+ source: 'supabase',
88
+ reviewPathPrefix: REVIEW_PATH_PREFIX,
89
+ })
90
+ : null;
91
+
92
+ const adapters = [
93
+ {
94
+ label: 'local',
95
+ get: (id) => local.get(id),
96
+ list: (query) => local.list(query),
97
+ create: (item) => local.create(item),
98
+ statusOptions: REVIEW_WORKFLOW_STATUS_OPTIONS,
99
+ updateStatus: ({ id, status }) => local.update(id, { status }),
100
+ syncSubmission: ({ id, patch }) => local.update(id, patch),
101
+ remove: (id) => local.remove(id),
102
+ },
103
+ ...(supabase
104
+ ? [
105
+ {
106
+ label: 'supabase',
107
+ get: (id) => supabase.get(id),
108
+ list: (query) => supabase.list(query),
109
+ create: (item) => supabase.create(item),
110
+ statusOptions: REVIEW_WORKFLOW_STATUS_OPTIONS,
111
+ updateStatus: ({ id, status }) => supabase.update(id, { status }),
112
+ remove: (id) => supabase.remove(id),
113
+ } satisfies ReviewShellAdapter,
114
+ ]
115
+ : []),
116
+ ] satisfies ReviewShellAdapter[];
117
+
118
+ const localPresence = createLocalPresenceAdapter({
119
+ channelName: `${REVIEW_PROJECT_ID}:review-presence`,
120
+ });
121
+
122
+ const presence = supabaseClient
123
+ ? createFallbackPresenceAdapter(
124
+ createSupabasePresenceAdapter({
125
+ client: supabaseClient as unknown as SupabasePresenceClient,
126
+ channelPrefix: 'review-presence',
127
+ private: import.meta.env.VITE_REVIEW_SUPABASE_PRESENCE_PRIVATE === 'true',
128
+ }),
129
+ localPresence
130
+ )
131
+ : localPresence;
132
+
133
+ mountReviewShell({
134
+ projectId: REVIEW_PROJECT_ID,
135
+ pages,
136
+ adapters,
137
+ reviewPathPrefix: REVIEW_PATH_PREFIX,
138
+ presence,
139
+ });
140
+ ```
141
+
142
+ ## Package boundary
143
+
144
+ Public imports are limited to the export map:
145
+
146
+ ```ts
147
+ import { createWebReviewKit, localAdapter } from '@designfever/web-review-kit';
148
+ import { mountReviewShell } from '@designfever/web-review-kit/react-shell';
149
+ ```
150
+
151
+ - `@designfever/web-review-kit`: core API, adapters, shared types.
152
+ - `@designfever/web-review-kit/react-shell`: review shell UI, presence adapters, page glob helper.
153
+ - `src/*` is not a public import path.
154
+ - `react` and `react-dom` are peer dependencies.
155
+ - `lucide-react` is currently bundled into the built shell output, not required from the host.
156
+ - Published/packed files are `dist`, `docs`, and `README.md`; the Lexus `/review` page stays as a consumer smoke page outside the package surface.
157
+
158
+ See [Package split checkpoint](docs/package-split-checkpoint.md) for the current split policy.
159
+
160
+ ## Environment
161
+
162
+ ```env
163
+ VITE_REVIEW_SUPABASE_URL=https://your-project.supabase.co
164
+ VITE_REVIEW_SUPABASE_ANON_KEY=
165
+ VITE_REVIEW_SUPABASE_TABLE=review_items
166
+ VITE_REVIEW_SUPABASE_PRESENCE_PRIVATE=false
167
+ ```
168
+
169
+ Browser에는 Supabase `anon` key만 넣는다. `service_role` key는 넣지 않는다.
170
+
171
+ ## Current Lexus Commands
172
+
173
+ Lexus repo 안에서 package를 검증할 때:
174
+
175
+ ```bash
176
+ pnpm dev:review
177
+ pnpm review-kit:typecheck
178
+ pnpm typecheck:review
179
+ pnpm review-kit:build
180
+ pnpm build:review
181
+ ```
182
+
183
+ - `pnpm dev:review`: review-kit build 후 package watch와 Vite dev server 실행
184
+ - `pnpm review-kit:typecheck`: package typecheck
185
+ - `pnpm typecheck:review`: package + Lexus typecheck
186
+ - `pnpm review-kit:build`: package dist build 후 Lexus `node_modules` sync
187
+ - `pnpm build:review`: package dist build 후 Lexus SEO build
188
+
189
+ 이 repo에서는 package를 file dependency로 소비한다.
190
+
191
+ ```json
192
+ "@designfever/web-review-kit": "file:packages/df-web-review-kit"
193
+ ```
194
+
195
+ package source를 바꾸면 commit 전에 `pnpm review-kit:build`로 `dist`도 같이 갱신한다.
196
+
197
+ ## Data Rules
198
+
199
+ - local item `#id`는 개인 draft 번호다.
200
+ - remote source에 등록하면 remote adapter가 새 canonical `reviewNumber`를 발급한다.
201
+ - local에서 remote 등록이 성공하면 local draft는 삭제한다.
202
+ - item model에는 screenshot data URL을 넣지 않는다.
203
+ - deep link restore는 `source`, `target`, `w`, `h`, `item` query를 기준으로 한다.
204
+
205
+ Example:
206
+
207
+ ```txt
208
+ /review?source=supabase&target=/service/&w=540&h=1080&item=<remote-id>
209
+ ```
210
+
211
+ ## Verification
212
+
213
+ Docs-only:
214
+
215
+ ```bash
216
+ git diff --check
217
+ ```
218
+
219
+ Package source:
220
+
221
+ ```bash
222
+ pnpm review-kit:typecheck
223
+ pnpm review-kit:build
224
+ ```
225
+
226
+ Lexus integration:
227
+
228
+ ```bash
229
+ pnpm typecheck:review
230
+ pnpm build:review
231
+ ```
232
+
233
+ Manual smoke:
234
+
235
+ 1. Open `/review`.
236
+ 2. Load a target page.
237
+ 3. Create local note, DOM note, and area item.
238
+ 4. Submit local item to remote.
239
+ 5. Confirm local draft is removed.
240
+ 6. Switch to remote source and open the remote item.
241
+ 7. Confirm route, viewport, scroll, marker, and prompt restore.