Files
thePR0M3TH3AN f6007876b7 External embed Phase 1: chromeless read-only viewer
Per docs/EXTERNAL_EMBED_FEATURE.md §18 Phase 1.

- parseEmbedRoute() detects three URL forms so the embed works on
  Vercel-rewrite-friendly hosts AND on plain static servers:
    /embed/<id>       (canonical; needs SPA rewrite)
    #/embed/<id>      (hash; works on any host)
    ?embed=<id>       (query; works on any host)
- Early-return at the top of init() routes embed mode to
  bootEmbedViewer; skips welcome modal, slot/disc/jewel controls,
  attachEvents, walletUI, autosave restore, share-route popstate.
  Editor JS stays loaded (single bundle), but none of its boot
  steps run.
- bootEmbedViewer() decodes the identifier via the existing
  decodeNostrId helper (note / nevent / naddr / hex), races the
  hint relays then user relays + DEFAULT_NOSTR_RELAYS for the
  event, warms linked-design sub-trees in one prefetchBatch
  round-trip, then paints via the existing
  renderDesignPayloadPreview + fitMiniPreview path.
- Premium events refuse with "🔒 Premium design — open in Artstr
  to unlock" placeholder; Phase 2 will render the watermarked
  preview JPEG with an inline CTA.
- Private (encrypted) envelopes refuse with a 🔒 placeholder; no
  decryption attempted.
- body.embed-mode CSS hides every existing top-level element
  (`body.embed-mode > :not(#embedRoot) { display: none !important }`)
  and shows a single #embedRoot with a stage + thin footer (author
  chip + "Open in Artstr ↗"). attr / open / controls query params
  toggle each piece.
- vercel.json gains /embed/:id SPA rewrites and a
  Content-Security-Policy: frame-ancestors * header so the route
  is iframe-able from any origin. Production behavior; dev (python
  http.server) needs no headers — cross-origin framing works by
  default.

Manual smoke-test paths:
  http://localhost:8000/?embed=<naddr>            (query form)
  http://localhost:8000/#/embed/<naddr>           (hash form)
  http://localhost:8001/                          (cross-origin
                                                   iframe host)
2026-06-01 09:01:35 -04:00

20 lines
526 B
JSON

{
"outputDirectory": "src",
"rewrites": [
{ "source": "/share/:id", "destination": "/" },
{ "source": "/share/:id/", "destination": "/" },
{ "source": "/u/:npub", "destination": "/" },
{ "source": "/u/:npub/", "destination": "/" },
{ "source": "/embed/:id", "destination": "/" },
{ "source": "/embed/:id/", "destination": "/" }
],
"headers": [
{
"source": "/embed/:id",
"headers": [
{ "key": "Content-Security-Policy", "value": "frame-ancestors *" }
]
}
]
}