@antigenic-oss/paint 0.2.9 → 0.3.1
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/bin/paint.js +32 -0
- package/next.config.mjs +8 -0
- package/package.json +1 -1
- package/public/dev-editor-inspector.js +14 -0
- package/public/sw-proxy/sw.js +886 -0
- 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 +112 -405
- 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/hooks/usePostMessage.ts +7 -1
- package/src/lib/serviceWorkerRegistration.ts +163 -0
- package/src/store/treeSlice.ts +29 -17
- package/src/store/uiSlice.ts +6 -0
package/src/app/docs/page.tsx
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
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
|
|
|
@@ -35,9 +32,6 @@ export const metadata: Metadata = {
|
|
|
35
32
|
},
|
|
36
33
|
}
|
|
37
34
|
|
|
38
|
-
const SCRIPT_TAG =
|
|
39
|
-
'<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>'
|
|
40
|
-
|
|
41
35
|
export default function DocsPage() {
|
|
42
36
|
return (
|
|
43
37
|
<div
|
|
@@ -92,11 +86,17 @@ export default function DocsPage() {
|
|
|
92
86
|
</strong>
|
|
93
87
|
, the editor loads your page through a{' '}
|
|
94
88
|
<strong style={{ color: 'var(--text-primary)' }}>
|
|
95
|
-
|
|
89
|
+
Service Worker proxy
|
|
96
90
|
</strong>
|
|
97
|
-
. The proxy
|
|
98
|
-
|
|
99
|
-
|
|
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{' '}
|
|
100
100
|
<code style={inlineCodeStyle}>postMessage</code> — reporting
|
|
101
101
|
element metadata when you hover or click, and applying style
|
|
102
102
|
previews in real time.
|
|
@@ -109,10 +109,11 @@ export default function DocsPage() {
|
|
|
109
109
|
actual source files.
|
|
110
110
|
</p>
|
|
111
111
|
<p style={{ ...bodyText, marginTop: '0.75rem' }}>
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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.
|
|
116
117
|
</p>
|
|
117
118
|
</Section>
|
|
118
119
|
|
|
@@ -207,402 +208,78 @@ export default function DocsPage() {
|
|
|
207
208
|
</Section>
|
|
208
209
|
|
|
209
210
|
{/* Framework Guides */}
|
|
210
|
-
<Section id="framework-guides" title="Framework
|
|
211
|
-
<p style={
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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.
|
|
215
216
|
</p>
|
|
216
|
-
<
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
<
|
|
225
|
-
<
|
|
226
|
-
|
|
227
|
-
locally, replace{' '}
|
|
228
|
-
<code style={{ ...inlineCodeStyle, fontSize: '0.8em' }}>
|
|
229
|
-
https://dev-editor-flow.vercel.app
|
|
230
|
-
</code>{' '}
|
|
231
|
-
with{' '}
|
|
232
|
-
<code style={{ ...inlineCodeStyle, fontSize: '0.8em' }}>
|
|
233
|
-
http://localhost:4000
|
|
234
|
-
</code>{' '}
|
|
235
|
-
(or your custom port).
|
|
236
|
-
</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" />
|
|
237
228
|
</div>
|
|
238
|
-
<
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
Add to <code style={inlineCodeStyle}>app/layout.tsx</code>
|
|
250
|
-
</p>
|
|
251
|
-
<CodeBlock
|
|
252
|
-
language="tsx"
|
|
253
|
-
copyText={SCRIPT_TAG}
|
|
254
|
-
code={`// app/layout.tsx
|
|
255
|
-
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
256
|
-
return (
|
|
257
|
-
<html lang="en">
|
|
258
|
-
<body>
|
|
259
|
-
{children}
|
|
260
|
-
<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>
|
|
261
|
-
</body>
|
|
262
|
-
</html>
|
|
263
|
-
);
|
|
264
|
-
}`}
|
|
265
|
-
/>
|
|
266
|
-
</div>
|
|
267
|
-
<div>
|
|
268
|
-
<h4
|
|
269
|
-
className="text-base font-medium mb-1"
|
|
270
|
-
style={{ color: 'var(--text-primary)' }}
|
|
271
|
-
>
|
|
272
|
-
Pages Router
|
|
273
|
-
</h4>
|
|
274
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
275
|
-
Add to{' '}
|
|
276
|
-
<code style={inlineCodeStyle}>pages/_document.tsx</code>
|
|
277
|
-
</p>
|
|
278
|
-
<CodeBlock
|
|
279
|
-
language="tsx"
|
|
280
|
-
copyText={SCRIPT_TAG}
|
|
281
|
-
code={`// pages/_document.tsx
|
|
282
|
-
import { Html, Head, Main, NextScript } from 'next/document';
|
|
283
|
-
|
|
284
|
-
export default function Document() {
|
|
285
|
-
return (
|
|
286
|
-
<Html>
|
|
287
|
-
<Head />
|
|
288
|
-
<body>
|
|
289
|
-
<Main />
|
|
290
|
-
<NextScript />
|
|
291
|
-
<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>
|
|
292
|
-
</body>
|
|
293
|
-
</Html>
|
|
294
|
-
);
|
|
295
|
-
}`}
|
|
296
|
-
/>
|
|
297
|
-
</div>
|
|
298
|
-
</FrameworkSection>
|
|
299
|
-
|
|
300
|
-
{/* Vite + React */}
|
|
301
|
-
<FrameworkSection
|
|
302
|
-
id="vite-react"
|
|
303
|
-
title="Vite + React"
|
|
304
|
-
icon="⚡"
|
|
305
|
-
>
|
|
306
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
307
|
-
Add to <code style={inlineCodeStyle}>index.html</code>{' '}
|
|
308
|
-
(project root)
|
|
309
|
-
</p>
|
|
310
|
-
<CodeBlock
|
|
311
|
-
language="html"
|
|
312
|
-
copyText={SCRIPT_TAG}
|
|
313
|
-
code={`<!-- index.html -->
|
|
314
|
-
<!DOCTYPE html>
|
|
315
|
-
<html lang="en">
|
|
316
|
-
<head>
|
|
317
|
-
<meta charset="UTF-8" />
|
|
318
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
319
|
-
<title>My App</title>
|
|
320
|
-
</head>
|
|
321
|
-
<body>
|
|
322
|
-
<div id="root"></div>
|
|
323
|
-
<script type="module" src="/src/main.tsx"></script>
|
|
324
|
-
<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>
|
|
325
|
-
</body>
|
|
326
|
-
</html>`}
|
|
327
|
-
/>
|
|
328
|
-
</FrameworkSection>
|
|
329
|
-
|
|
330
|
-
{/* Create React App */}
|
|
331
|
-
<FrameworkSection
|
|
332
|
-
id="create-react-app"
|
|
333
|
-
title="Create React App"
|
|
334
|
-
icon="⚛"
|
|
335
|
-
>
|
|
336
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
337
|
-
Add to{' '}
|
|
338
|
-
<code style={inlineCodeStyle}>public/index.html</code>
|
|
339
|
-
</p>
|
|
340
|
-
<CodeBlock
|
|
341
|
-
language="html"
|
|
342
|
-
copyText={SCRIPT_TAG}
|
|
343
|
-
code={`<!-- public/index.html -->
|
|
344
|
-
<!DOCTYPE html>
|
|
345
|
-
<html lang="en">
|
|
346
|
-
<head>
|
|
347
|
-
<meta charset="utf-8" />
|
|
348
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
349
|
-
<title>My App</title>
|
|
350
|
-
</head>
|
|
351
|
-
<body>
|
|
352
|
-
<div id="root"></div>
|
|
353
|
-
<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>
|
|
354
|
-
</body>
|
|
355
|
-
</html>`}
|
|
356
|
-
/>
|
|
357
|
-
</FrameworkSection>
|
|
358
|
-
|
|
359
|
-
{/* Plain HTML */}
|
|
360
|
-
<FrameworkSection
|
|
361
|
-
id="plain-html"
|
|
362
|
-
title="Plain HTML"
|
|
363
|
-
icon="📄"
|
|
364
|
-
>
|
|
365
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
366
|
-
Add before{' '}
|
|
367
|
-
<code style={inlineCodeStyle}></body></code> in any{' '}
|
|
368
|
-
<code style={inlineCodeStyle}>.html</code> file
|
|
369
|
-
</p>
|
|
370
|
-
<CodeBlock
|
|
371
|
-
language="html"
|
|
372
|
-
copyText={SCRIPT_TAG}
|
|
373
|
-
code={`<!DOCTYPE html>
|
|
374
|
-
<html>
|
|
375
|
-
<head>
|
|
376
|
-
<title>My Page</title>
|
|
377
|
-
</head>
|
|
378
|
-
<body>
|
|
379
|
-
<h1>Hello</h1>
|
|
380
|
-
<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>
|
|
381
|
-
</body>
|
|
382
|
-
</html>`}
|
|
383
|
-
/>
|
|
384
|
-
</FrameworkSection>
|
|
385
|
-
|
|
386
|
-
{/* React Native / Expo Web */}
|
|
387
|
-
<FrameworkSection
|
|
388
|
-
id="react-native-expo"
|
|
389
|
-
title="React Native / Expo Web"
|
|
390
|
-
icon="📱"
|
|
391
|
-
>
|
|
392
|
-
<div>
|
|
393
|
-
<h4
|
|
394
|
-
className="text-base font-medium mb-1"
|
|
395
|
-
style={{ color: 'var(--text-primary)' }}
|
|
396
|
-
>
|
|
397
|
-
Expo Router
|
|
398
|
-
</h4>
|
|
399
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
400
|
-
Add to{' '}
|
|
401
|
-
<code style={inlineCodeStyle}>app/_layout.tsx</code> using{' '}
|
|
402
|
-
a <code style={inlineCodeStyle}><Script></code>{' '}
|
|
403
|
-
component or the web{' '}
|
|
404
|
-
<code style={inlineCodeStyle}>index.html</code>
|
|
405
|
-
</p>
|
|
406
|
-
<CodeBlock
|
|
407
|
-
language="tsx"
|
|
408
|
-
copyText={SCRIPT_TAG}
|
|
409
|
-
code={`// app/_layout.tsx
|
|
410
|
-
import { Slot } from 'expo-router';
|
|
411
|
-
import { Platform } from 'react-native';
|
|
412
|
-
import { useEffect } from 'react';
|
|
413
|
-
|
|
414
|
-
export default function RootLayout() {
|
|
415
|
-
useEffect(() => {
|
|
416
|
-
if (Platform.OS === 'web') {
|
|
417
|
-
const script = document.createElement('script');
|
|
418
|
-
script.src = 'https://dev-editor-flow.vercel.app/dev-editor-inspector.js';
|
|
419
|
-
document.body.appendChild(script);
|
|
420
|
-
}
|
|
421
|
-
}, []);
|
|
422
|
-
|
|
423
|
-
return <Slot />;
|
|
424
|
-
}`}
|
|
425
|
-
/>
|
|
426
|
-
</div>
|
|
427
|
-
<div>
|
|
428
|
-
<h4
|
|
429
|
-
className="text-base font-medium mb-1"
|
|
430
|
-
style={{ color: 'var(--text-primary)' }}
|
|
431
|
-
>
|
|
432
|
-
Custom <code style={inlineCodeStyle}>web/index.html</code>
|
|
433
|
-
</h4>
|
|
434
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
435
|
-
If your Expo project has a custom web entry point
|
|
436
|
-
</p>
|
|
437
|
-
<CodeBlock
|
|
438
|
-
language="html"
|
|
439
|
-
copyText={SCRIPT_TAG}
|
|
440
|
-
code={`<!-- web/index.html -->
|
|
441
|
-
<!DOCTYPE html>
|
|
442
|
-
<html>
|
|
443
|
-
<head>
|
|
444
|
-
<meta charset="utf-8" />
|
|
445
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
446
|
-
</head>
|
|
447
|
-
<body>
|
|
448
|
-
<div id="root"></div>
|
|
449
|
-
<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>
|
|
450
|
-
</body>
|
|
451
|
-
</html>`}
|
|
452
|
-
/>
|
|
453
|
-
</div>
|
|
454
|
-
</FrameworkSection>
|
|
455
|
-
|
|
456
|
-
{/* Vue / Nuxt */}
|
|
457
|
-
<FrameworkSection
|
|
458
|
-
id="vue-nuxt"
|
|
459
|
-
title="Vue / Nuxt"
|
|
460
|
-
icon="⚫"
|
|
461
|
-
>
|
|
462
|
-
<div>
|
|
463
|
-
<h4
|
|
464
|
-
className="text-base font-medium mb-1"
|
|
465
|
-
style={{ color: 'var(--text-primary)' }}
|
|
466
|
-
>
|
|
467
|
-
Vue (Vite)
|
|
468
|
-
</h4>
|
|
469
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
470
|
-
Add to <code style={inlineCodeStyle}>index.html</code>{' '}
|
|
471
|
-
(project root)
|
|
472
|
-
</p>
|
|
473
|
-
<CodeBlock
|
|
474
|
-
language="html"
|
|
475
|
-
copyText={SCRIPT_TAG}
|
|
476
|
-
code={`<!-- index.html -->
|
|
477
|
-
<!DOCTYPE html>
|
|
478
|
-
<html lang="en">
|
|
479
|
-
<head>
|
|
480
|
-
<meta charset="UTF-8" />
|
|
481
|
-
<title>My Vue App</title>
|
|
482
|
-
</head>
|
|
483
|
-
<body>
|
|
484
|
-
<div id="app"></div>
|
|
485
|
-
<script type="module" src="/src/main.ts"></script>
|
|
486
|
-
<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>
|
|
487
|
-
</body>
|
|
488
|
-
</html>`}
|
|
489
|
-
/>
|
|
490
|
-
</div>
|
|
491
|
-
<div>
|
|
492
|
-
<h4
|
|
493
|
-
className="text-base font-medium mb-1"
|
|
494
|
-
style={{ color: 'var(--text-primary)' }}
|
|
495
|
-
>
|
|
496
|
-
Nuxt 3
|
|
497
|
-
</h4>
|
|
498
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
499
|
-
Add via{' '}
|
|
500
|
-
<code style={inlineCodeStyle}>nuxt.config.ts</code> or{' '}
|
|
501
|
-
<code style={inlineCodeStyle}>app.html</code>
|
|
502
|
-
</p>
|
|
503
|
-
<CodeBlock
|
|
504
|
-
language="ts"
|
|
505
|
-
copyText={`app: {\n head: {\n script: [{ src: 'https://dev-editor-flow.vercel.app/dev-editor-inspector.js' }]\n }\n}`}
|
|
506
|
-
code={`// nuxt.config.ts
|
|
507
|
-
export default defineNuxtConfig({
|
|
508
|
-
app: {
|
|
509
|
-
head: {
|
|
510
|
-
script: [
|
|
511
|
-
{ src: 'https://dev-editor-flow.vercel.app/dev-editor-inspector.js' }
|
|
512
|
-
]
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
});`}
|
|
516
|
-
/>
|
|
517
|
-
</div>
|
|
518
|
-
</FrameworkSection>
|
|
519
|
-
|
|
520
|
-
{/* Svelte / SvelteKit */}
|
|
521
|
-
<FrameworkSection
|
|
522
|
-
id="svelte-sveltekit"
|
|
523
|
-
title="Svelte / SvelteKit"
|
|
524
|
-
icon="🌱"
|
|
525
|
-
>
|
|
526
|
-
<p style={{ ...mutedText, marginBottom: '0.5rem' }}>
|
|
527
|
-
Add to <code style={inlineCodeStyle}>src/app.html</code>
|
|
528
|
-
</p>
|
|
529
|
-
<CodeBlock
|
|
530
|
-
language="html"
|
|
531
|
-
copyText={SCRIPT_TAG}
|
|
532
|
-
code={`<!-- src/app.html -->
|
|
533
|
-
<!DOCTYPE html>
|
|
534
|
-
<html lang="en">
|
|
535
|
-
<head>
|
|
536
|
-
<meta charset="utf-8" />
|
|
537
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
538
|
-
%sveltekit.head%
|
|
539
|
-
</head>
|
|
540
|
-
<body data-sveltekit-preload-data="hover">
|
|
541
|
-
<div style="display: contents">%sveltekit.body%</div>
|
|
542
|
-
<script src="https://dev-editor-flow.vercel.app/dev-editor-inspector.js"></script>
|
|
543
|
-
</body>
|
|
544
|
-
</html>`}
|
|
545
|
-
/>
|
|
546
|
-
</FrameworkSection>
|
|
547
|
-
</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>
|
|
548
240
|
</Section>
|
|
549
241
|
|
|
550
242
|
{/* Troubleshooting */}
|
|
551
243
|
<Section id="troubleshooting" title="Troubleshooting">
|
|
552
244
|
<div className="flex flex-col gap-4">
|
|
553
|
-
<TroubleshootItem title="
|
|
245
|
+
<TroubleshootItem title="Stuck on "Connecting"">
|
|
554
246
|
<p>
|
|
555
|
-
If the
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
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).
|
|
559
252
|
</p>
|
|
560
253
|
</TroubleshootItem>
|
|
561
254
|
|
|
562
255
|
<TroubleshootItem title="CORS or Cross-Origin errors">
|
|
563
256
|
<p>
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
<code style={inlineCodeStyle}>localhost:4000</code>.
|
|
570
|
-
</p>
|
|
571
|
-
</TroubleshootItem>
|
|
572
|
-
|
|
573
|
-
<TroubleshootItem title="COEP / COOP headers blocking the iframe">
|
|
574
|
-
<p>
|
|
575
|
-
Some frameworks set{' '}
|
|
576
|
-
<code style={inlineCodeStyle}>
|
|
577
|
-
Cross-Origin-Embedder-Policy
|
|
578
|
-
</code>{' '}
|
|
579
|
-
or{' '}
|
|
580
|
-
<code style={inlineCodeStyle}>
|
|
581
|
-
Cross-Origin-Opener-Policy
|
|
582
|
-
</code>{' '}
|
|
583
|
-
headers that prevent loading in an iframe. Check your server
|
|
584
|
-
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.
|
|
585
262
|
</p>
|
|
586
263
|
</TroubleshootItem>
|
|
587
264
|
|
|
588
|
-
<TroubleshootItem title="
|
|
265
|
+
<TroubleshootItem title="Page looks different or broken">
|
|
589
266
|
<p>
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
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.
|
|
596
273
|
</p>
|
|
597
274
|
</TroubleshootItem>
|
|
598
275
|
|
|
599
|
-
<TroubleshootItem title="
|
|
276
|
+
<TroubleshootItem title="Target dev server not reachable">
|
|
600
277
|
<p>
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
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.
|
|
606
283
|
</p>
|
|
607
284
|
</TroubleshootItem>
|
|
608
285
|
</div>
|
|
@@ -612,17 +289,13 @@ export default defineNuxtConfig({
|
|
|
612
289
|
<Section id="faq" title="FAQ">
|
|
613
290
|
<FaqAccordion>
|
|
614
291
|
<FaqSection
|
|
615
|
-
id="faq-
|
|
616
|
-
question="
|
|
292
|
+
id="faq-no-setup"
|
|
293
|
+
question="Do I need to add any script tags to my project?"
|
|
617
294
|
>
|
|
618
295
|
<p>
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
pAInt via <code style={inlineCodeStyle}>postMessage</code>.
|
|
623
|
-
It does not modify your source code, send data to external
|
|
624
|
-
servers, or execute arbitrary code. It only communicates
|
|
625
|
-
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.
|
|
626
299
|
</p>
|
|
627
300
|
</FaqSection>
|
|
628
301
|
|
|
@@ -662,15 +335,13 @@ export default defineNuxtConfig({
|
|
|
662
335
|
|
|
663
336
|
<FaqSection
|
|
664
337
|
id="faq-production"
|
|
665
|
-
question="
|
|
338
|
+
question="Does pAInt affect my production build?"
|
|
666
339
|
>
|
|
667
340
|
<p>
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
users — but it's best practice to keep it out of
|
|
673
|
-
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.
|
|
674
345
|
</p>
|
|
675
346
|
</FaqSection>
|
|
676
347
|
|
|
@@ -818,6 +489,42 @@ function TroubleshootItem({
|
|
|
818
489
|
)
|
|
819
490
|
}
|
|
820
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
|
+
|
|
821
528
|
function UseCaseItem({
|
|
822
529
|
title,
|
|
823
530
|
description,
|
package/src/app/page.tsx
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { useEffect, useState } from 'react'
|
|
4
4
|
import { Editor } from '@/components/Editor'
|
|
5
5
|
import { useEditorStore } from '@/store'
|
|
6
|
+
import { registerSwProxy } from '@/lib/serviceWorkerRegistration'
|
|
6
7
|
|
|
7
8
|
export default function Home() {
|
|
8
9
|
const loadPersistedUI = useEditorStore((s) => s.loadPersistedUI)
|
|
@@ -26,6 +27,7 @@ export default function Home() {
|
|
|
26
27
|
|
|
27
28
|
loadPersistedUI()
|
|
28
29
|
loadPersistedClaude()
|
|
30
|
+
registerSwProxy()
|
|
29
31
|
|
|
30
32
|
// Suppress HMR errors caused by proxied routes leaking into the
|
|
31
33
|
// editor's route tree (e.g. "unrecognized HMR message").
|