Repository navigation
Hosting
ModelShot is a static site on GitHub Pages: no server code, no database, no account. The repository is on GitHub, so the host adds no party and needs no secret.
One artifact (tools/deploy, pnpm -r build writes tools/deploy/dist):
| Path in the site | Content | Public URL |
|---|---|---|
/ |
landing page (packages/site) |
https://mrlarkyy.github.io/ModelShot/ |
app/ |
the app (packages/app) |
https://mrlarkyy.github.io/ModelShot/app/ |
embed/v1/ |
embed frame and element script | https://mrlarkyy.github.io/ModelShot/embed/v1/modelshot-embed.js |
Every build uses the relative base ./, so the same files work under /ModelShot/ and, after a custom domain, at the
domain root. The assembly (tools/deploy/src/checkDist.ts) fails the build on a root-absolute URL in an HTML or CSS file (not in JavaScript: the code builds its URLs from
import.meta.url, and the deploy suite loads every worker and chunk under /ModelShot/), a script or stylesheet
from another origin, a missing page policy, or a missing app/sw.js or embed/v1/modelshot-embed.js.
The folder embed/v<n>/ carries the embed contract version (EMBED_PARAMS_VERSION, embed.md); a test
pins the two together. v1 moves with each deploy and stays compatible (parameters are only added). A breaking change
raises the version and needs a new folder; the old one then has to stay in the artifact, which is not done yet.
Pages cannot set headers on GitHub Pages, so each HTML file carries a <meta http-equiv="Content-Security-Policy">
as the first element after the charset, before any script or link:
- app and landing page:
default-src 'self'withscript-src,connect-src,img-src,style-src,font-src'self',object-src 'none',base-uri 'none',form-action 'none';worker-src 'self'in the app,'none'on the landing page. No'unsafe-inline', no wildcard, no host. - embed frame: the same, except
connect-src 'self' https: http:: the frame fetches the model URL its host page names, which is the purpose of the embed. Nothing else may leave it. -
frame-ancestorsis never set (a meta policy ignores it anyway, and the frame must be embeddable), and GitHub Pages sends noX-Frame-Options.
A meta policy does not apply inside workers; the worker code makes no requests (packages/app/test/noNetwork.test.ts).
No SharedArrayBuffer and no WebAssembly are used, so no cross-origin isolation headers are needed.
GitHub, as host, sees the request log of any host: IP address, user agent and the files asked for. Models, skins and state never leave the browser; the deploy suite asserts that every request is a GET without a body to the site's own origin. Network traffic beyond that happens only on an explicit share.
GitHub Pages sends Cache-Control: max-age=600. Built files carry a content hash in their name, so a new deploy
brings new names; index.html, app/sw.js and embed/v1/modelshot-embed.js keep their names and can be up to ten
minutes old. The app's service worker checks sw.js bypassing the HTTP cache and a new version waits until the open
tabs are closed (app.md). An embed frame that a cached page still points at a removed chunk shows a
status or an error and does not hang (deploy.embed.spec.ts).
All project pages of mrlarkyy.github.io share one origin, so IndexedDB and caches are shared with the owner's other
Pages sites. A custom domain isolates them.
The app and the embed frame also share that origin, so the frame can reach the app's IndexedDB. That is safe because
only the site's own scripts run there (script-src 'self', no inline code, pinned by checkDist), and the frame's
connect-src https: http: lets it fetch the model URL only: a response is data, never code. Separating the two would
need another domain.
.github/workflows/pages.yml runs on every push to main and on demand, and does nothing until the repository variable
PAGES_DEPLOY is true. To turn it on:
- Settings, Pages, Source: GitHub Actions.
- Settings, Secrets and variables, Actions, Variables:
PAGES_DEPLOY=true. - Actions,
pages, Run workflow.
Jobs: build installs, builds and uploads the artifact with only contents: read; deploy is the only job with
pages: write and id-token: write and runs nothing but deploy-pages; verify runs the deploy suite against the
live URL once every fixed-name file (the three pages, app/sw.js, embed/v1/modelshot-embed.js) equals the artifact's.
A failed verify does not undo the deploy: the site stays live. Read the uploaded deploy-test-results, then fix
forward or roll back as below.
Rollback: unset PAGES_DEPLOY to stop further deploys; revert the commit and push; or re-run an older successful
pages run (its deploy job), which works only while its artifact is kept (30 days, retention-days in pages.yml).
pnpm --filter @modelshot/deploy run test:browser builds @modelshot/deploy... and the packages it assembles itself, then serves tools/deploy/dist under /ModelShot/ the way
Pages does (e2e/staticServer.ts: MIME types, Access-Control-Allow-Origin: *, max-age=600, no framing headers) and
runs the flow, CSP, offline, embed and header specs. With MS_DEPLOY_URL=https://mrlarkyy.github.io/ModelShot/ it
serves only the host page and tests the live site instead. Unit tests (tools/deploy/test) cover the layout, the assembly, the dist checks and the
server's path handling.
Repository · This wiki is generated from docs/: change the pages there.