@antigenic-oss/paint 0.2.8 → 0.3.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/LICENSE +1 -1
- package/NOTICE +2 -2
- package/README.md +42 -15
- package/bin/paint.js +32 -0
- package/next.config.mjs +8 -0
- package/package.json +10 -8
- package/public/dev-editor-inspector.js +14 -0
- package/public/sw-proxy/sw.js +886 -0
- package/src/app/api/proxy/[[...path]]/route.ts +12 -1
- package/src/app/api/sw-fetch/[[...path]]/route.ts +149 -0
- package/src/app/docs/DocsClient.tsx +1 -1
- package/src/app/docs/page.tsx +134 -407
- package/src/app/layout.tsx +48 -2
- package/src/app/page.tsx +2 -0
- package/src/components/ConnectModal.tsx +98 -181
- package/src/components/PreviewFrame.tsx +91 -0
- package/src/components/TargetSelector.tsx +49 -15
- package/src/components/left-panel/LayerNode.tsx +5 -2
- package/src/components/left-panel/LayersPanel.tsx +10 -1
- package/src/components/right-panel/changes/ChangesPanel.tsx +7 -1
- package/src/hooks/useChangeTracker.ts +34 -26
- package/src/hooks/usePostMessage.ts +27 -1
- package/src/lib/serviceWorkerRegistration.ts +163 -0
- package/src/store/treeSlice.ts +29 -17
- package/src/store/uiSlice.ts +6 -0
- package/src/types/messages.ts +6 -0
package/src/app/docs/page.tsx
CHANGED
|
@@ -1,23 +1,37 @@
|
|
|
1
1
|
import type { Metadata } from 'next'
|
|
2
2
|
import Link from 'next/link'
|
|
3
3
|
import {
|
|
4
|
-
CodeBlock,
|
|
5
4
|
FaqAccordion,
|
|
6
5
|
FaqSection,
|
|
7
|
-
FrameworkAccordion,
|
|
8
|
-
FrameworkSection,
|
|
9
6
|
Sidebar,
|
|
10
7
|
} from './DocsClient'
|
|
11
8
|
|
|
12
9
|
export const metadata: Metadata = {
|
|
13
|
-
title: '
|
|
10
|
+
title: 'Setup Guide',
|
|
14
11
|
description:
|
|
15
|
-
'Framework-specific setup instructions for connecting pAInt to
|
|
12
|
+
'Framework-specific setup instructions for connecting pAInt to localhost projects, including proxy, bridge, and terminal-assisted workflows.',
|
|
13
|
+
keywords: [
|
|
14
|
+
'pAInt setup',
|
|
15
|
+
'localhost visual editor setup',
|
|
16
|
+
'bridge server setup',
|
|
17
|
+
'terminal server setup',
|
|
18
|
+
'Next.js inspector script',
|
|
19
|
+
'Claude Code changelog workflow',
|
|
20
|
+
],
|
|
21
|
+
openGraph: {
|
|
22
|
+
title: 'pAInt Setup Guide',
|
|
23
|
+
description:
|
|
24
|
+
'Connect pAInt to your localhost app with framework-specific instructions and efficient AI handoff workflows.',
|
|
25
|
+
type: 'article',
|
|
26
|
+
},
|
|
27
|
+
twitter: {
|
|
28
|
+
card: 'summary',
|
|
29
|
+
title: 'pAInt Setup Guide',
|
|
30
|
+
description:
|
|
31
|
+
'Configure pAInt quickly for localhost projects and ship cleaner AI-assisted edits.',
|
|
32
|
+
},
|
|
16
33
|
}
|
|
17
34
|
|
|
18
|
-
const SCRIPT_TAG =
|
|
19
|
-
'<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>'
|
|
20
|
-
|
|
21
35
|
export default function DocsPage() {
|
|
22
36
|
return (
|
|
23
37
|
<div
|
|
@@ -72,11 +86,17 @@ export default function DocsPage() {
|
|
|
72
86
|
</strong>
|
|
73
87
|
, the editor loads your page through a{' '}
|
|
74
88
|
<strong style={{ color: 'var(--text-primary)' }}>
|
|
75
|
-
|
|
89
|
+
Service Worker proxy
|
|
76
90
|
</strong>
|
|
77
|
-
. The proxy
|
|
78
|
-
|
|
79
|
-
|
|
91
|
+
. The proxy intercepts requests, fetches your page from
|
|
92
|
+
localhost, injects a lightweight inspector script, and strips
|
|
93
|
+
security headers that would block the iframe — all happening
|
|
94
|
+
in the browser with no server-side proxying needed. Your
|
|
95
|
+
page's scripts and client-side rendering work normally,
|
|
96
|
+
so you see the fully interactive version of your site.
|
|
97
|
+
</p>
|
|
98
|
+
<p style={{ ...bodyText, marginTop: '0.75rem' }}>
|
|
99
|
+
The inspector communicates with the editor via{' '}
|
|
80
100
|
<code style={inlineCodeStyle}>postMessage</code> — reporting
|
|
81
101
|
element metadata when you hover or click, and applying style
|
|
82
102
|
previews in real time.
|
|
@@ -89,10 +109,11 @@ export default function DocsPage() {
|
|
|
89
109
|
actual source files.
|
|
90
110
|
</p>
|
|
91
111
|
<p style={{ ...bodyText, marginTop: '0.75rem' }}>
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
112
|
+
<strong style={{ color: 'var(--success)' }}>
|
|
113
|
+
No script tags needed
|
|
114
|
+
</strong>{' '}
|
|
115
|
+
— the proxy handles everything automatically. Just click
|
|
116
|
+
Connect and start editing.
|
|
96
117
|
</p>
|
|
97
118
|
</Section>
|
|
98
119
|
|
|
@@ -187,402 +208,78 @@ export default function DocsPage() {
|
|
|
187
208
|
</Section>
|
|
188
209
|
|
|
189
210
|
{/* Framework Guides */}
|
|
190
|
-
<Section id="framework-guides" title="Framework
|
|
191
|
-
<p style={
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
211
|
+
<Section id="framework-guides" title="Framework Compatibility">
|
|
212
|
+
<p style={bodyText}>
|
|
213
|
+
pAInt works with any framework out of the box — no script
|
|
214
|
+
tags or configuration needed. The Service Worker proxy
|
|
215
|
+
automatically handles inspector injection for all projects.
|
|
195
216
|
</p>
|
|
196
|
-
<
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
<
|
|
205
|
-
<
|
|
206
|
-
|
|
207
|
-
locally, replace{' '}
|
|
208
|
-
<code style={{ ...inlineCodeStyle, fontSize: '0.8em' }}>
|
|
209
|
-
https://dev-editor-flow.vercel.app
|
|
210
|
-
</code>{' '}
|
|
211
|
-
with{' '}
|
|
212
|
-
<code style={{ ...inlineCodeStyle, fontSize: '0.8em' }}>
|
|
213
|
-
http://localhost:4000
|
|
214
|
-
</code>{' '}
|
|
215
|
-
(or your custom port).
|
|
216
|
-
</span>
|
|
217
|
+
<p style={{ ...bodyText, marginTop: '0.75rem' }}>
|
|
218
|
+
Tested and confirmed working with:
|
|
219
|
+
</p>
|
|
220
|
+
<div className="flex flex-col gap-2 mt-4">
|
|
221
|
+
<CompatItem icon="▲" name="Next.js" detail="App Router & Pages Router" />
|
|
222
|
+
<CompatItem icon="⚡" name="Vite + React" detail="Including React Router, TanStack, etc." />
|
|
223
|
+
<CompatItem icon="⚛" name="Create React App" detail="Standard and ejected setups" />
|
|
224
|
+
<CompatItem icon="📱" name="React Native / Expo Web" detail="Expo Router and custom web entry" />
|
|
225
|
+
<CompatItem icon="⚫" name="Vue / Nuxt" detail="Vue 3 (Vite) and Nuxt 3" />
|
|
226
|
+
<CompatItem icon="🌱" name="Svelte / SvelteKit" detail="SvelteKit and plain Svelte + Vite" />
|
|
227
|
+
<CompatItem icon="📄" name="Plain HTML" detail="Static sites and vanilla JS" />
|
|
217
228
|
</div>
|
|
218
|
-
<
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
Add to <code style={inlineCodeStyle}>app/layout.tsx</code>
|
|
230
|
-
</p>
|
|
231
|
-
<CodeBlock
|
|
232
|
-
language="tsx"
|
|
233
|
-
copyText={SCRIPT_TAG}
|
|
234
|
-
code={`// app/layout.tsx
|
|
235
|
-
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
236
|
-
return (
|
|
237
|
-
<html lang="en">
|
|
238
|
-
<body>
|
|
239
|
-
{children}
|
|
240
|
-
<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>
|
|
241
|
-
</body>
|
|
242
|
-
</html>
|
|
243
|
-
);
|
|
244
|
-
}`}
|
|
245
|
-
/>
|
|
246
|
-
</div>
|
|
247
|
-
<div>
|
|
248
|
-
<h4
|
|
249
|
-
className="text-base font-medium mb-1"
|
|
250
|
-
style={{ color: 'var(--text-primary)' }}
|
|
251
|
-
>
|
|
252
|
-
Pages Router
|
|
253
|
-
</h4>
|
|
254
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
255
|
-
Add to{' '}
|
|
256
|
-
<code style={inlineCodeStyle}>pages/_document.tsx</code>
|
|
257
|
-
</p>
|
|
258
|
-
<CodeBlock
|
|
259
|
-
language="tsx"
|
|
260
|
-
copyText={SCRIPT_TAG}
|
|
261
|
-
code={`// pages/_document.tsx
|
|
262
|
-
import { Html, Head, Main, NextScript } from 'next/document';
|
|
263
|
-
|
|
264
|
-
export default function Document() {
|
|
265
|
-
return (
|
|
266
|
-
<Html>
|
|
267
|
-
<Head />
|
|
268
|
-
<body>
|
|
269
|
-
<Main />
|
|
270
|
-
<NextScript />
|
|
271
|
-
<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>
|
|
272
|
-
</body>
|
|
273
|
-
</Html>
|
|
274
|
-
);
|
|
275
|
-
}`}
|
|
276
|
-
/>
|
|
277
|
-
</div>
|
|
278
|
-
</FrameworkSection>
|
|
279
|
-
|
|
280
|
-
{/* Vite + React */}
|
|
281
|
-
<FrameworkSection
|
|
282
|
-
id="vite-react"
|
|
283
|
-
title="Vite + React"
|
|
284
|
-
icon="⚡"
|
|
285
|
-
>
|
|
286
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
287
|
-
Add to <code style={inlineCodeStyle}>index.html</code>{' '}
|
|
288
|
-
(project root)
|
|
289
|
-
</p>
|
|
290
|
-
<CodeBlock
|
|
291
|
-
language="html"
|
|
292
|
-
copyText={SCRIPT_TAG}
|
|
293
|
-
code={`<!-- index.html -->
|
|
294
|
-
<!DOCTYPE html>
|
|
295
|
-
<html lang="en">
|
|
296
|
-
<head>
|
|
297
|
-
<meta charset="UTF-8" />
|
|
298
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
299
|
-
<title>My App</title>
|
|
300
|
-
</head>
|
|
301
|
-
<body>
|
|
302
|
-
<div id="root"></div>
|
|
303
|
-
<script type="module" src="/src/main.tsx"></script>
|
|
304
|
-
<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>
|
|
305
|
-
</body>
|
|
306
|
-
</html>`}
|
|
307
|
-
/>
|
|
308
|
-
</FrameworkSection>
|
|
309
|
-
|
|
310
|
-
{/* Create React App */}
|
|
311
|
-
<FrameworkSection
|
|
312
|
-
id="create-react-app"
|
|
313
|
-
title="Create React App"
|
|
314
|
-
icon="⚛"
|
|
315
|
-
>
|
|
316
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
317
|
-
Add to{' '}
|
|
318
|
-
<code style={inlineCodeStyle}>public/index.html</code>
|
|
319
|
-
</p>
|
|
320
|
-
<CodeBlock
|
|
321
|
-
language="html"
|
|
322
|
-
copyText={SCRIPT_TAG}
|
|
323
|
-
code={`<!-- public/index.html -->
|
|
324
|
-
<!DOCTYPE html>
|
|
325
|
-
<html lang="en">
|
|
326
|
-
<head>
|
|
327
|
-
<meta charset="utf-8" />
|
|
328
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
329
|
-
<title>My App</title>
|
|
330
|
-
</head>
|
|
331
|
-
<body>
|
|
332
|
-
<div id="root"></div>
|
|
333
|
-
<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>
|
|
334
|
-
</body>
|
|
335
|
-
</html>`}
|
|
336
|
-
/>
|
|
337
|
-
</FrameworkSection>
|
|
338
|
-
|
|
339
|
-
{/* Plain HTML */}
|
|
340
|
-
<FrameworkSection
|
|
341
|
-
id="plain-html"
|
|
342
|
-
title="Plain HTML"
|
|
343
|
-
icon="📄"
|
|
344
|
-
>
|
|
345
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
346
|
-
Add before{' '}
|
|
347
|
-
<code style={inlineCodeStyle}></body></code> in any{' '}
|
|
348
|
-
<code style={inlineCodeStyle}>.html</code> file
|
|
349
|
-
</p>
|
|
350
|
-
<CodeBlock
|
|
351
|
-
language="html"
|
|
352
|
-
copyText={SCRIPT_TAG}
|
|
353
|
-
code={`<!DOCTYPE html>
|
|
354
|
-
<html>
|
|
355
|
-
<head>
|
|
356
|
-
<title>My Page</title>
|
|
357
|
-
</head>
|
|
358
|
-
<body>
|
|
359
|
-
<h1>Hello</h1>
|
|
360
|
-
<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>
|
|
361
|
-
</body>
|
|
362
|
-
</html>`}
|
|
363
|
-
/>
|
|
364
|
-
</FrameworkSection>
|
|
365
|
-
|
|
366
|
-
{/* React Native / Expo Web */}
|
|
367
|
-
<FrameworkSection
|
|
368
|
-
id="react-native-expo"
|
|
369
|
-
title="React Native / Expo Web"
|
|
370
|
-
icon="📱"
|
|
371
|
-
>
|
|
372
|
-
<div>
|
|
373
|
-
<h4
|
|
374
|
-
className="text-base font-medium mb-1"
|
|
375
|
-
style={{ color: 'var(--text-primary)' }}
|
|
376
|
-
>
|
|
377
|
-
Expo Router
|
|
378
|
-
</h4>
|
|
379
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
380
|
-
Add to{' '}
|
|
381
|
-
<code style={inlineCodeStyle}>app/_layout.tsx</code> using{' '}
|
|
382
|
-
a <code style={inlineCodeStyle}><Script></code>{' '}
|
|
383
|
-
component or the web{' '}
|
|
384
|
-
<code style={inlineCodeStyle}>index.html</code>
|
|
385
|
-
</p>
|
|
386
|
-
<CodeBlock
|
|
387
|
-
language="tsx"
|
|
388
|
-
copyText={SCRIPT_TAG}
|
|
389
|
-
code={`// app/_layout.tsx
|
|
390
|
-
import { Slot } from 'expo-router';
|
|
391
|
-
import { Platform } from 'react-native';
|
|
392
|
-
import { useEffect } from 'react';
|
|
393
|
-
|
|
394
|
-
export default function RootLayout() {
|
|
395
|
-
useEffect(() => {
|
|
396
|
-
if (Platform.OS === 'web') {
|
|
397
|
-
const script = document.createElement('script');
|
|
398
|
-
script.src = 'https://dev-editor-flow.vercel.app/dev-editor-inspector.js';
|
|
399
|
-
document.body.appendChild(script);
|
|
400
|
-
}
|
|
401
|
-
}, []);
|
|
402
|
-
|
|
403
|
-
return <Slot />;
|
|
404
|
-
}`}
|
|
405
|
-
/>
|
|
406
|
-
</div>
|
|
407
|
-
<div>
|
|
408
|
-
<h4
|
|
409
|
-
className="text-base font-medium mb-1"
|
|
410
|
-
style={{ color: 'var(--text-primary)' }}
|
|
411
|
-
>
|
|
412
|
-
Custom <code style={inlineCodeStyle}>web/index.html</code>
|
|
413
|
-
</h4>
|
|
414
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
415
|
-
If your Expo project has a custom web entry point
|
|
416
|
-
</p>
|
|
417
|
-
<CodeBlock
|
|
418
|
-
language="html"
|
|
419
|
-
copyText={SCRIPT_TAG}
|
|
420
|
-
code={`<!-- web/index.html -->
|
|
421
|
-
<!DOCTYPE html>
|
|
422
|
-
<html>
|
|
423
|
-
<head>
|
|
424
|
-
<meta charset="utf-8" />
|
|
425
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
426
|
-
</head>
|
|
427
|
-
<body>
|
|
428
|
-
<div id="root"></div>
|
|
429
|
-
<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>
|
|
430
|
-
</body>
|
|
431
|
-
</html>`}
|
|
432
|
-
/>
|
|
433
|
-
</div>
|
|
434
|
-
</FrameworkSection>
|
|
435
|
-
|
|
436
|
-
{/* Vue / Nuxt */}
|
|
437
|
-
<FrameworkSection
|
|
438
|
-
id="vue-nuxt"
|
|
439
|
-
title="Vue / Nuxt"
|
|
440
|
-
icon="⚫"
|
|
441
|
-
>
|
|
442
|
-
<div>
|
|
443
|
-
<h4
|
|
444
|
-
className="text-base font-medium mb-1"
|
|
445
|
-
style={{ color: 'var(--text-primary)' }}
|
|
446
|
-
>
|
|
447
|
-
Vue (Vite)
|
|
448
|
-
</h4>
|
|
449
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
450
|
-
Add to <code style={inlineCodeStyle}>index.html</code>{' '}
|
|
451
|
-
(project root)
|
|
452
|
-
</p>
|
|
453
|
-
<CodeBlock
|
|
454
|
-
language="html"
|
|
455
|
-
copyText={SCRIPT_TAG}
|
|
456
|
-
code={`<!-- index.html -->
|
|
457
|
-
<!DOCTYPE html>
|
|
458
|
-
<html lang="en">
|
|
459
|
-
<head>
|
|
460
|
-
<meta charset="UTF-8" />
|
|
461
|
-
<title>My Vue App</title>
|
|
462
|
-
</head>
|
|
463
|
-
<body>
|
|
464
|
-
<div id="app"></div>
|
|
465
|
-
<script type="module" src="/src/main.ts"></script>
|
|
466
|
-
<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>
|
|
467
|
-
</body>
|
|
468
|
-
</html>`}
|
|
469
|
-
/>
|
|
470
|
-
</div>
|
|
471
|
-
<div>
|
|
472
|
-
<h4
|
|
473
|
-
className="text-base font-medium mb-1"
|
|
474
|
-
style={{ color: 'var(--text-primary)' }}
|
|
475
|
-
>
|
|
476
|
-
Nuxt 3
|
|
477
|
-
</h4>
|
|
478
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
479
|
-
Add via{' '}
|
|
480
|
-
<code style={inlineCodeStyle}>nuxt.config.ts</code> or{' '}
|
|
481
|
-
<code style={inlineCodeStyle}>app.html</code>
|
|
482
|
-
</p>
|
|
483
|
-
<CodeBlock
|
|
484
|
-
language="ts"
|
|
485
|
-
copyText={`app: {\n head: {\n script: [{ src: 'https://dev-editor-flow.vercel.app/dev-editor-inspector.js' }]\n }\n}`}
|
|
486
|
-
code={`// nuxt.config.ts
|
|
487
|
-
export default defineNuxtConfig({
|
|
488
|
-
app: {
|
|
489
|
-
head: {
|
|
490
|
-
script: [
|
|
491
|
-
{ src: 'https://dev-editor-flow.vercel.app/dev-editor-inspector.js' }
|
|
492
|
-
]
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
});`}
|
|
496
|
-
/>
|
|
497
|
-
</div>
|
|
498
|
-
</FrameworkSection>
|
|
499
|
-
|
|
500
|
-
{/* Svelte / SvelteKit */}
|
|
501
|
-
<FrameworkSection
|
|
502
|
-
id="svelte-sveltekit"
|
|
503
|
-
title="Svelte / SvelteKit"
|
|
504
|
-
icon="🌱"
|
|
505
|
-
>
|
|
506
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
507
|
-
Add to <code style={inlineCodeStyle}>src/app.html</code>
|
|
508
|
-
</p>
|
|
509
|
-
<CodeBlock
|
|
510
|
-
language="html"
|
|
511
|
-
copyText={SCRIPT_TAG}
|
|
512
|
-
code={`<!-- src/app.html -->
|
|
513
|
-
<!DOCTYPE html>
|
|
514
|
-
<html lang="en">
|
|
515
|
-
<head>
|
|
516
|
-
<meta charset="utf-8" />
|
|
517
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
518
|
-
%sveltekit.head%
|
|
519
|
-
</head>
|
|
520
|
-
<body data-sveltekit-preload-data="hover">
|
|
521
|
-
<div style="display: contents">%sveltekit.body%</div>
|
|
522
|
-
<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>
|
|
523
|
-
</body>
|
|
524
|
-
</html>`}
|
|
525
|
-
/>
|
|
526
|
-
</FrameworkSection>
|
|
527
|
-
</FrameworkAccordion>
|
|
229
|
+
<p style={{ ...bodyText, marginTop: '1rem' }}>
|
|
230
|
+
Just start your dev server, open pAInt, select the port,
|
|
231
|
+
and click{' '}
|
|
232
|
+
<strong style={{ color: 'var(--text-primary)' }}>
|
|
233
|
+
Connect
|
|
234
|
+
</strong>
|
|
235
|
+
. The proxy preserves your page's scripts and
|
|
236
|
+
client-side rendering, so interactive features like 3D scenes
|
|
237
|
+
(Spline, Three.js), animations (GSAP, Framer Motion), and
|
|
238
|
+
client-side routing all work normally.
|
|
239
|
+
</p>
|
|
528
240
|
</Section>
|
|
529
241
|
|
|
530
242
|
{/* Troubleshooting */}
|
|
531
243
|
<Section id="troubleshooting" title="Troubleshooting">
|
|
532
244
|
<div className="flex flex-col gap-4">
|
|
533
|
-
<TroubleshootItem title="
|
|
245
|
+
<TroubleshootItem title="Stuck on "Connecting"">
|
|
534
246
|
<p>
|
|
535
|
-
If the
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
247
|
+
If the editor stays in "Connecting" state, your
|
|
248
|
+
browser may be caching an old Service Worker. Open DevTools
|
|
249
|
+
→ Application → Service Workers, unregister any
|
|
250
|
+
workers for <code style={inlineCodeStyle}>localhost:4000</code>,
|
|
251
|
+
clear Cache Storage, then hard refresh (Cmd+Shift+R).
|
|
539
252
|
</p>
|
|
540
253
|
</TroubleshootItem>
|
|
541
254
|
|
|
542
255
|
<TroubleshootItem title="CORS or Cross-Origin errors">
|
|
543
256
|
<p>
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
<code style={inlineCodeStyle}>localhost:4000</code>.
|
|
550
|
-
</p>
|
|
551
|
-
</TroubleshootItem>
|
|
552
|
-
|
|
553
|
-
<TroubleshootItem title="COEP / COOP headers blocking the iframe">
|
|
554
|
-
<p>
|
|
555
|
-
Some frameworks set{' '}
|
|
556
|
-
<code style={inlineCodeStyle}>
|
|
557
|
-
Cross-Origin-Embedder-Policy
|
|
558
|
-
</code>{' '}
|
|
559
|
-
or{' '}
|
|
560
|
-
<code style={inlineCodeStyle}>
|
|
561
|
-
Cross-Origin-Opener-Policy
|
|
562
|
-
</code>{' '}
|
|
563
|
-
headers that prevent loading in an iframe. Check your server
|
|
564
|
-
config or middleware and relax these headers in development.
|
|
257
|
+
The Service Worker proxy serves everything from the same
|
|
258
|
+
origin, which handles most CORS issues automatically. If
|
|
259
|
+
your project makes API calls to external services during
|
|
260
|
+
render, those requests are not proxied. This typically
|
|
261
|
+
doesn't affect visual editing.
|
|
565
262
|
</p>
|
|
566
263
|
</TroubleshootItem>
|
|
567
264
|
|
|
568
|
-
<TroubleshootItem title="
|
|
265
|
+
<TroubleshootItem title="Page looks different or broken">
|
|
569
266
|
<p>
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
267
|
+
The proxy preserves all scripts and client-side rendering.
|
|
268
|
+
If something looks off, try a hard refresh to ensure the
|
|
269
|
+
latest Service Worker is active. If the issue persists,
|
|
270
|
+
check the browser console for errors — some pages with
|
|
271
|
+
very strict CSP headers may need those headers relaxed in
|
|
272
|
+
development.
|
|
576
273
|
</p>
|
|
577
274
|
</TroubleshootItem>
|
|
578
275
|
|
|
579
|
-
<TroubleshootItem title="
|
|
276
|
+
<TroubleshootItem title="Target dev server not reachable">
|
|
580
277
|
<p>
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
278
|
+
Make sure your project's dev server is running on the
|
|
279
|
+
port you selected. The proxy connects to{' '}
|
|
280
|
+
<code style={inlineCodeStyle}>localhost:<port></code>{' '}
|
|
281
|
+
from the browser, so the server must be accessible from
|
|
282
|
+
your machine.
|
|
586
283
|
</p>
|
|
587
284
|
</TroubleshootItem>
|
|
588
285
|
</div>
|
|
@@ -592,17 +289,13 @@ export default defineNuxtConfig({
|
|
|
592
289
|
<Section id="faq" title="FAQ">
|
|
593
290
|
<FaqAccordion>
|
|
594
291
|
<FaqSection
|
|
595
|
-
id="faq-
|
|
596
|
-
question="
|
|
292
|
+
id="faq-no-setup"
|
|
293
|
+
question="Do I need to add any script tags to my project?"
|
|
597
294
|
>
|
|
598
295
|
<p>
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
pAInt via <code style={inlineCodeStyle}>postMessage</code>.
|
|
603
|
-
It does not modify your source code, send data to external
|
|
604
|
-
servers, or execute arbitrary code. It only communicates
|
|
605
|
-
with pAInt origin.
|
|
296
|
+
No. pAInt uses a Service Worker proxy that automatically
|
|
297
|
+
injects the inspector script into your page. Just click
|
|
298
|
+
Connect — no modifications to your project needed.
|
|
606
299
|
</p>
|
|
607
300
|
</FaqSection>
|
|
608
301
|
|
|
@@ -642,15 +335,13 @@ export default defineNuxtConfig({
|
|
|
642
335
|
|
|
643
336
|
<FaqSection
|
|
644
337
|
id="faq-production"
|
|
645
|
-
question="
|
|
338
|
+
question="Does pAInt affect my production build?"
|
|
646
339
|
>
|
|
647
340
|
<p>
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
users — but it's best practice to keep it out of
|
|
653
|
-
production builds.
|
|
341
|
+
No. pAInt runs entirely in the browser through a Service
|
|
342
|
+
Worker — nothing is added to your project's source
|
|
343
|
+
code or build output. There's nothing to remove before
|
|
344
|
+
deploying.
|
|
654
345
|
</p>
|
|
655
346
|
</FaqSection>
|
|
656
347
|
|
|
@@ -798,6 +489,42 @@ function TroubleshootItem({
|
|
|
798
489
|
)
|
|
799
490
|
}
|
|
800
491
|
|
|
492
|
+
function CompatItem({
|
|
493
|
+
icon,
|
|
494
|
+
name,
|
|
495
|
+
detail,
|
|
496
|
+
}: {
|
|
497
|
+
icon: string
|
|
498
|
+
name: string
|
|
499
|
+
detail: string
|
|
500
|
+
}) {
|
|
501
|
+
return (
|
|
502
|
+
<div
|
|
503
|
+
className="flex items-center gap-3 rounded-md px-4 py-3"
|
|
504
|
+
style={{
|
|
505
|
+
background: 'var(--bg-secondary)',
|
|
506
|
+
border: '1px solid var(--border)',
|
|
507
|
+
}}
|
|
508
|
+
>
|
|
509
|
+
<span className="text-base">{icon}</span>
|
|
510
|
+
<div>
|
|
511
|
+
<span
|
|
512
|
+
className="text-sm font-medium"
|
|
513
|
+
style={{ color: 'var(--text-primary)' }}
|
|
514
|
+
>
|
|
515
|
+
{name}
|
|
516
|
+
</span>
|
|
517
|
+
<span
|
|
518
|
+
className="text-sm ml-2"
|
|
519
|
+
style={{ color: 'var(--text-muted)' }}
|
|
520
|
+
>
|
|
521
|
+
— {detail}
|
|
522
|
+
</span>
|
|
523
|
+
</div>
|
|
524
|
+
</div>
|
|
525
|
+
)
|
|
526
|
+
}
|
|
527
|
+
|
|
801
528
|
function UseCaseItem({
|
|
802
529
|
title,
|
|
803
530
|
description,
|