Webtile stores all user data in Cloud Firestore using a hierarchical collection structure scoped to each authenticated user. Every project, map, tileset image, and sprite lives under theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/johnlobo/webtile/llms.txt
Use this file to discover all available pages before exploring further.
users/{uid} namespace, ensuring that Firestore security rules can trivially restrict access to the document owner. This page documents every collection, document schema, and encoding convention used by the application.
Collection Hierarchy
assets/tileset) beneath each map document, keeping large base64 payloads out of the map document itself and within Firestore’s 1 MiB per-document limit.
Project Document
Path:users/{uid}/projects/{pid}
The project document holds only lightweight metadata. Heavy data such as tile arrays and tileset images are stored in child documents.
Human-readable project name chosen by the user.
Firestore server timestamp set once when the project is first created.
Firestore server timestamp refreshed whenever any map or sprite within the project is saved.
Map Document
Path:users/{uid}/projects/{pid}/maps/{mid}
Each map document describes the tilemap grid dimensions, per-tile pixel dimensions, display options, and the full flat tile array. Maps are ordered by createdAt ascending when listed.
Human-readable map name displayed in the MAPS navigation menu.
Width of a single tile in pixels (e.g.
16).Height of a single tile in pixels (e.g.
16).Map width expressed in tiles (number of columns).
Map height expressed in tiles (number of rows).
When
true, each tile cell is rendered at 2× its natural pixel width. Used to simulate the wide-pixel aspect ratio of CPC Mode 0 graphics.Flat integer array of length
mapW × mapH stored in row-major order. See Tile Encoding below for the encoding rules.true when a tileset image has been uploaded for this map and the assets/tileset sub-document exists.Server timestamp set when the map is first created.
Server timestamp refreshed on every auto-save (debounced 2 seconds after the last tile paint).
Tileset Sub-Document
Path:users/{uid}/projects/{pid}/maps/{mid}/assets/tileset
The tileset image is stored in a dedicated sub-document rather than inline in the map document to avoid exceeding Firestore’s 1 MiB document size limit. It is only written when hasTileset is true on the parent map document.
The tileset PNG encoded as a base64 data URL (e.g.
data:image/png;base64,…). Written by projectService.js after converting any blob URL to base64 before persisting.Natural (intrinsic) pixel width of the tileset image.
Natural (intrinsic) pixel height of the tileset image.
Sprite Document
Path:users/{uid}/projects/{pid}/sprites/{sid}
Sprite documents store CPC-format sprites including palette assignments and multi-frame pixel data. Sprites are loaded in full on demand; listSprites returns summaries (no pixel data) ordered by createdAt ascending.
Human-readable sprite name displayed in the SPRITES navigation menu.
CPC video mode. Controls the number of available ink slots and the hardware byte encoding used during export.
| Value | Mode | Max inks | Pixels per byte |
|---|---|---|---|
0 | Mode 0 | 16 | 2 |
1 | Mode 1 | 4 | 4 |
2 | Mode 2 | 2 | 8 |
Sprite canvas width in pixels.
Sprite canvas height in pixels.
Array of CPC hardware color indices, one entry per ink slot. The length matches the number of available inks for the selected
videoMode (16, 4, or 2). CPC color indices are integers in the range 0–26.Array of animation frames. Each frame contains a single
pixels field — a flat, row-major array of ink indices of length width × height. See Sprite Pixel Encoding below.Server timestamp set when the sprite is first created.
Server timestamp refreshed on every auto-save (debounced 1.5 seconds after the last pixel mutation).
Tile Encoding
Map tiles are stored in Firestore as a flat integer array (mapTiles). In memory, the app works with a 2-D array of objects {col, row, idx} | null, but projectService.js encodes and decodes this representation on every save and load.
Encoding rules:
| Cell state | Stored value |
|---|---|
| Empty cell | -1 |
| Occupied cell | tileRow * 1000 + tileCol |
v:
2003.
Sprite Pixel Encoding
Each frame’spixels field is a flat, row-major array of ink indices of length width × height.
- Index
0— transparent (background shows through). The eraser tool and initial canvas state both write0. - Indices
1–N— correspond to ink slots 1 through N, where N is the number of inks for the sprite’svideoMode(16 for Mode 0, 4 for Mode 1, 2 for Mode 2).
(x, y) coordinate to an array offset:
generateExport in SpriteEditor.jsx), ink indices are mapped through the palette array to obtain CPC hardware color values, then packed into bytes according to the video mode’s bit-plane layout.
Old-Schema Migration
Early versions of Webtile stored map configuration fields (
tileW, tileH, mapW, mapH, mapTiles, etc.) directly on the project document and kept the tileset at projects/{pid}/assets/tileset rather than under a maps subcollection.When loadProject detects the old schema (presence of tileW on the project document) it automatically calls migrateOldProject() in projectService.js. This function:- Checks whether the
mapssubcollection already has documents (to avoid double-migration). - Creates a new map document under
users/{uid}/projects/{pid}/maps/{mid}with the inline map data. - Copies the old tileset document from
projects/{pid}/assets/tilesetto the new pathmaps/{mid}/assets/tileset.