MengTo / MengTo/threeui

SylvaLivingWorldScene: bundled font 404s via CORS in its own sandboxed iframe (sourceUrl/assetBaseUrl not exposed)

Open
#39 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
HTML
Stars
6k
Forks
568
Avg merge
1d 6h
Merged PRs (30d)
6

Description

Package version: @designcodeio/threeui@1.1.0 (also reproduces on 1.0.0, 0.3.0)

What's happening

SylvaLivingWorldScene renders its content in a sandboxed iframe: sandbox="allow-scripts", with no allow-same-origin. That makes the iframe a null-origin document.

The scene's own inner-green-3d.html declares:

@font-face{
  font-family:'Lexend';
  src:url('inner-green-assets/lexend-latin.woff2') format('woff2');
  ...
}

a root-relative fetch. From a null-origin iframe, that's a cross-origin request no matter what host actually serves it — and Chrome/WebKit require CORS approval specifically for cross-origin @font-face loads (unlike images or scripts, which can load no-cors). Console:

Access to font at 'https://<host>/inner-green-assets/lexend-latin.woff2' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

The documented workaround doesn't apply to this component

The README says:

Components that render full HTML documents expect their runtime files at the same root-relative URLs used by the ThreeUI preview. Copy the needed files from node_modules/@designcodeio/threeui/lib-dist/assets/ into your app's public directory, or override the component's sourceUrl or assetBaseUrl prop where available.

SylvaLivingWorldSceneProps is exactly:

type SylvaLivingWorldSceneProps = {
  variant?: "living-green";
  className?: string;
  style?: CSSProperties;
};

No sourceUrl, no assetBaseUrl. So the "override the prop" half of the documented fix isn't available for this component — only the "copy the file into your public dir" half is, and even that's insufficient on its own (see below).

Copying the file isn't sufficient either

I copied lexend-latin.woff2 to the exact expected path in my app's public/ dir. The font still failed to load with the same CORS error, because the request's Origin header is null (from the sandbox) and my server (a stock Next.js dev/prod server) doesn't send Access-Control-Allow-Origin for static files by default. The actual fix required adding an explicit CORS header for that path in my app's server config:

// next.config.ts
async headers() {
  return [{
    source: "/inner-green-assets/:path*",
    headers: [{ key: "Access-Control-Allow-Origin", value: "*" }],
  }];
}

That's a non-obvious requirement that follows directly from the allow-scripts-only sandbox choice, and it isn't mentioned anywhere in the README's asset-path guidance.

Ask

Either (or both):

  1. Expose sourceUrl/assetBaseUrl on SylvaLivingWorldScene (and any other "full HTML document" component that's missing it), matching what the README already documents as the intended override.
  2. Document the CORS-header requirement explicitly wherever the "copy the file into public/" guidance appears, since it's not enough by itself given the sandbox.

Note: fixing this did not resolve the branch/foliage geometry never appearing (filed separately as #38) — that reproduces identically with or without this font loading successfully. Filing this as its own issue since it's a real, independent gap.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at SylvaLivingWorldScene and its SylvaLivingWorldSceneProps definition, then inspect the referenced inner-green-3d.html and the README asset-path guidance. Verify the sandboxed font request and compare the documented sourceUrl/assetBaseUrl behavior with this component. Done means the chosen prop or documentation fix covers the font loading path, including the required CORS configuration.

Written by the indexing model from the issue text.

Assessment

Tech stack
nextjs, react, three.js
Domain
documentation, frontend, web-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.