11 — Assets
What it is: Centralized image (and eventually video/PDF) storage. Assets are uploaded to S3/CloudFront by the admin project; this backend just stores the URL and maps it to entities.
Tables
tbl_assets
One row per uploaded file.
| Field | Notes |
|---|---|
assetId | PK — a text column holding a UUID-formatted string generated by the admin project on upload (not a Postgres uuid type; cast/compare as text) |
url | CloudFront URL |
aspectRatio | e.g. "16:9", "1:1" — for responsive layouts |
width / height | pixels, optional |
name / description | admin UI labels |
tbl_asset_entity_mapping
Links an asset to an entity. One asset can map to many entities; one entity can have many assets.
| Field | Notes |
|---|---|
assetId | FK to tbl_assets |
entityCode | entity type — stored lowercase: event, suite, suite_type, map, program, addon, notification |
entityId | the entity's identifier (string IDs used directly; integer IDs cast to VARCHAR) |
entitySubcode | asset purpose within that entity (see below) |
deviceType | DESKTOP, MOBILE, TABLET |
displayOrder | sort order for carousels (lower = first) |
backgroundColor | hex, optional — for text overlay readability |
Entity code + subcode combinations
All values below are the actual stored strings (lowercase).
| entityCode | subcodes | Used for |
|---|---|---|
event | logo, background, carousel | opponent logo, event background, image carousel |
suite / suite_type | hero, gallery, menu | suite hero image, photo gallery, food/drink menu |
map | static | static venue map image (iomedia or static source only — 3DDV doesn't use assets) |
program | banner | program banner (sign-up / home page) |
addon | addon_logo, addon_image | add-on logo and image |
notification | buyer_email_banner | banner in the buyer confirmation email |
Entity ID format
- String-based IDs (e.g.
eventCode): used directly - Integer IDs (e.g.
suiteId,mapId,programId): cast to VARCHAR —CAST(id AS VARCHAR)
Key rules
- All assets are public CloudFront URLs — no auth required to access them
- Admin project handles upload to S3 and UUID generation; this backend only stores the result
- Named "asset" not "image" so it can grow to video/PDF in future (not supported yet)
- ON DELETE RESTRICT on the FK — can't hard-delete an asset while active mappings exist; use soft delete
- Device type is always required on mappings; frontend picks the right one for the client