Workflow: Where My Files Live
The short answer#
Your files live in your browser, in a folder structure that mirrors your mod's eventual GitHub repository exactly. Nothing you upload, draw, or generate is ever sent to a DiceyTable server for storage — the server only ever sees your files at the moment you explicitly checkpoint or publish to GitHub.
Where, specifically#
Every project's working file tree is written to the Origin Private File System (OPFS), under
drafts/<projectId>/tree/… (draftModFsScope, apps/web/src/storage/draftModFs.ts) — a
real, file-backed filesystem private to the DiceyTable origin, invisible to other sites and not
part of your regular downloads folder. The layout under tree/ is the exact repo-relative path
your mod will have on GitHub (assets/models/…, assets/textures/…, manifest.json, …), so
publishing is a straight upload of what's already there rather than a repacking step.
If your browser doesn't support OPFS, the editor falls back to an equivalent IndexedDB-backed
store (IdbModFs, behind the same LocalModFs interface — apps/web/src/storage/localModFs.ts)
so authoring still works; you won't notice the difference in the editor's behavior.
A sibling, separate scope (drafts/<projectId>/sync/state.json) records GitHub sync bookkeeping
— which file was last synced at which blob sha. It's deliberately outside the tree/ scope
so it's never mistaken for part of your published mod.
Persistence#
The moment you open a draft, the editor asks the browser for persistent storage
(navigator.storage.persist(), called automatically via requestPersistentStorage()) — a
best-effort request that, when granted, tells the browser not to evict your data under ordinary
storage pressure the way it might evict a regular cache. This happens silently in the background;
there's no button to click or setting to check.
What happens if you clear your browser data#
Clearing site data, using a different browser, or the browser evicting storage under real pressure empties your local draft. If your mod is linked to a GitHub repository, this is recoverable: see Opening on another device — the editor re-downloads everything from your repo the next time you open it. If your mod has never been linked to a repository ("No repo yet"), there is no copy anywhere else, and clearing your data loses it — link a repository and checkpoint before you need this safety net, not after.
Clearing the local copy on purpose#
The same recovery works as a deliberate action. Reset local copy from GitHub, in the GitHub
sync dialog behind the status bar's
⇅ indicator, deletes this device's local working copy and re-downloads every file from the
repository. It is the answer to "my local files have drifted and I no longer trust them".
What survives it is the same split this page is about: your manifest and your scene live in the project's draft on the server, not in the local file tree, so Mod Details and the viewport come back exactly as they were. What does not survive is any local file you edited and never published — a texture, a model, a script. The dialog asks you to type the repository name before it will do it, for that reason.
When the same file changed in both places#
If a file changed locally and in the repository since the last sync, the editor does not
pick a winner. It keeps your copy, leaves the repository's alone, and reports a conflict on the
⇅ indicator; the dialog shows both versions side by side and records whichever you choose. Three
files never take part in this: diceytable.mod.json and setup.json are written from the
server draft on every save, and README.md is regenerated from your manifest on every publish,
so there is no local edit to protect and nothing to reconcile.
Which of these files do players download?#
Not all of them. The manifest editor's Files tab (Mod ▸ Mod Details… ▸ Files) lists every file in this tree with what publishing does with it: Pre-loaded (declared in the manifest, downloaded before the table opens), On demand (published, fetched when first used), Entry (the manifest, scene and script) or Editor-only (thumbnails, originals, card source images, photo-mode captures — pushed to your repository, never sent to players). The list maintains itself as you add, move and delete files. The same tab deletes files, and its Cleanup view finds leftovers from deleted decks and thumbnails of files that no longer exist.
Materials, prefabs and table scripts are not in that list because they are not files: they live
inside the scene, setup.json.
Preview and photo-mode captures#
Preview reads this same local tree, but through a
read-only view: it can never write, move or delete a file in your draft. A file missing
locally is fetched from your linked repository's wip branch instead.
Photo-mode captures taken in Preview are the one thing that comes back. The preview tab hands each
capture to the editor tab that holds the project's lease, which writes it into the tree as
screenshots/<yyyymmdd-hhmmss>-<id>.png (or .webp) with a .json sidecar. From then on it is an
ordinary draft file: it syncs, it publishes, and it is removed from the repository only when you
delete it. It is never a declared asset, so players never download it. See
The Screenshots gallery.
If no editor tab answers within 3 seconds, or the editor cannot save it yet (still loading, lost
the lease, or the write failed), the capture is kept in an IndexedDB outbox in this browser
(diceytable-preview-captures) and imported the next time you open the project in the editor. The
status line then reads "N screenshots imported from Preview." The preview also offers a
Download, because an outbox is still only this browser's storage: it keeps entries for at most
30 days and at most 50 across all projects, dropping the oldest first. A capture over 40 MB is
never queued; it is offered as a Download only.
Photo mode on a normal /table writes nothing here at all: a capture there is a browser download
and nothing else.
What eviction actually touches#
Under real storage-quota pressure, the browser (or the editor's own quota-error retry path) only
ever clears the disposable pull-cache for published mods you've merely played, at
cache/<owner>/<repo>/<version> (the commit sha, or the mod's content hash when no sha was
recorded) — content that's trivially re-downloaded from GitHub on demand. Loading a mod that has
been republished since you last played it also prunes your superseded copies of that same mod, so
the cache holds one version per mod rather than one per publish. Your
active draft (drafts/…) is never touched by this eviction path
(OpfsModFs.clearPullCaches, apps/web/src/storage/OpfsModFs.ts) — a write that hits a
quota error retries once after the pull-caches are cleared, specifically so an active draft
write never fails just because you'd previously played a lot of other mods.
See also#
- Opening on another device
- The Status Bar — the sync indicator, the conflict resolver, and the reset
- Connect GitHub
- wip and main
