Skip to content

feat(examples): download example as a standalone Vite project#8825

Merged
kpal81xd merged 3 commits into
mainfrom
examples-download-vite-project
Jun 3, 2026
Merged

feat(examples): download example as a standalone Vite project#8825
kpal81xd merged 3 commits into
mainfrom
examples-download-vite-project

Conversation

@kpal81xd
Copy link
Copy Markdown
Contributor

@kpal81xd kpal81xd commented Jun 2, 2026

Summary

Adds a Download button to the examples-browser code panel toolbar (next to the refresh/GitHub icons) that exports the currently-viewed example as a runnable, self-contained Vite project — generated entirely in-browser, no server or hosting changes.

The zip is produced client-side with fflate (already bundled). It captures the live Monaco buffers, so any edits the user made in the code panel are included.

Preview

image

What's in the generated project

<category>-<example>/
  package.json      vite.config.mjs    index.html
  README.md
  CREDITS.md        (asset attribution from @credit — only when the example has credits)
  src/
    example.mjs       (@config stripped, imports rewritten)
    context.mjs       (local shim for `examples/context`)
    data.json         (captured control values)
    main.mjs          (imports the example, then replays data.json)
    <shaders / text>  (shipped verbatim, raw imports get `?raw`)
  public/
    assets/… scripts/…        (referenced assets, fetched from /static)
    assets/spine/license.txt  (folder licenses whose terms require shipping the file)
  • Imports rewrittenexamples/context./context.mjs; non-published examples/assets/scripts/** modules are vendored (and their imports recursed); playcanvas / playcanvas/scripts/** left as npm specifiers.
  • Control state — the example's current control values are captured into src/data.json and replayed after the example initialises, mirroring the browser's applyControlState (so values that the example seeds itself aren't clobbered).
  • Assets — source is scanned for ./assets/ & ./scripts/ URLs, fetched from the live /static/…, and shipped under public/ so they resolve unchanged. Dynamic/remote URLs that can't be bundled are noted in the generated README.
  • Attribution — author-written @credit blocks (title / author / source / license) are written to a dedicated CREDITS.md, so asset attribution survives in the download. This covers remote / CDN assets (e.g. gaussian-splatting scenes) that ship no local license file. The credits come from the same parse the in-app credits overlay uses (surfaced via the example snapshot), so there's no guesswork or duplicate parsing. Folder-level license files whose terms require the file to travel with the assets (currently only spine) are co-located under public/ alongside them.
  • Versionspackage.json pins playcanvas: "latest" + @playcanvas/observer; README notes the exact authoring version in case a newer release differs.

Testing

  • Verified end-to-end with Playwright: clicking Download produces misc-hello-world.zip; unzipped → npm i && npm run dev renders the example, with imports rewritten and the @config block stripped.
  • Toolbar styling checked across examples (with/without a controls tab).
  • Attribution verified via the real in-browser buildProjectZip:
    • graphics/shadow-catcherCREDITS.md (Poly Haven, CC BY 4.0), asset still bundled.
    • gaussian-splatting/first-person (remote S3 splat, no local license) → CREDITS.md (Sunnyvale, CC BY 4.0).
    • misc/spineboyCREDITS.md and co-located public/assets/spine/license.txt.
    • Non-attributed examples build with no CREDITS.md and make no extra license fetches.

@mvaligursky
Copy link
Copy Markdown
Contributor

any way we can preserve the CC licenses for assets the example uses?

@kpal81xd
Copy link
Copy Markdown
Contributor Author

kpal81xd commented Jun 2, 2026

any way we can preserve the CC licenses for assets the example uses?

Yep just done

kpal81xd added 3 commits June 3, 2026 09:54
Adds a download icon to the code panel toolbar that exports the current example as a runnable, self-contained Vite project, zipped in-browser with fflate. The generated project includes the example source (config stripped, imports rewritten to a local examples/context shim), the current control values captured to data.json and replayed after the example loads, the referenced assets, and a package.json pinned to the latest published playcanvas + observer.
…project

Replace the sidecar-.txt probing with the authoritative @credit attribution:
the iframe already parses @credit (title/author/source/license) into the example
snapshot, so surface it through the snapshot and write a dedicated CREDITS.md.
This covers remote assets (e.g. gsplat scenes) that ship no local license file,
and removes the per-asset 404 probing. Spine's folder license has redistribution
terms requiring the file to travel with the assets, so co-locate it via an
explicit COLOCATED_LICENSES entry; add a @credit block to the spineboy example.
@kpal81xd kpal81xd force-pushed the examples-download-vite-project branch from 9ac7c07 to b6b7ca4 Compare June 3, 2026 08:54
@kpal81xd kpal81xd merged commit f622cf1 into main Jun 3, 2026
8 checks passed
@kpal81xd kpal81xd deleted the examples-download-vite-project branch June 3, 2026 08:56
kpal81xd added a commit that referenced this pull request Jun 3, 2026
* feat(examples): download example as a standalone Vite project

Adds a download icon to the code panel toolbar that exports the current example as a runnable, self-contained Vite project, zipped in-browser with fflate. The generated project includes the example source (config stripped, imports rewritten to a local examples/context shim), the current control values captured to data.json and replayed after the example loads, the referenced assets, and a package.json pinned to the latest published playcanvas + observer.

* feat(examples): bundle CC license sidecars in the downloaded Vite project

* feat(examples): export asset attribution as CREDITS.md in downloaded project

Replace the sidecar-.txt probing with the authoritative @credit attribution:
the iframe already parses @credit (title/author/source/license) into the example
snapshot, so surface it through the snapshot and write a dedicated CREDITS.md.
This covers remote assets (e.g. gsplat scenes) that ship no local license file,
and removes the per-asset 404 probing. Spine's folder license has redistribution
terms requiring the file to travel with the assets, so co-locate it via an
explicit COLOCATED_LICENSES entry; add a @credit block to the spineboy example.
kpal81xd added a commit that referenced this pull request Jun 3, 2026
* feat(examples): download example as a standalone Vite project

Adds a download icon to the code panel toolbar that exports the current example as a runnable, self-contained Vite project, zipped in-browser with fflate. The generated project includes the example source (config stripped, imports rewritten to a local examples/context shim), the current control values captured to data.json and replayed after the example loads, the referenced assets, and a package.json pinned to the latest published playcanvas + observer.

* feat(examples): bundle CC license sidecars in the downloaded Vite project

* feat(examples): export asset attribution as CREDITS.md in downloaded project

Replace the sidecar-.txt probing with the authoritative @credit attribution:
the iframe already parses @credit (title/author/source/license) into the example
snapshot, so surface it through the snapshot and write a dedicated CREDITS.md.
This covers remote assets (e.g. gsplat scenes) that ship no local license file,
and removes the per-asset 404 probing. Spine's folder license has redistribution
terms requiring the file to travel with the assets, so co-locate it via an
explicit COLOCATED_LICENSES entry; add a @credit block to the spineboy example.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants