Jewelry AI · Model catalogue
One answer prepares both the grid photo and the zoom
The server prepares every model in a listing before the phone draws anything: two image addresses per model, an original file used in place of a missing small one, and an empty address for a model whose image record cannot be resolved. None of that produces an error, which is why an unusual card is difficult to interpret from the screen alone.
What one listing request does
Everything below happens inside a single answer, before the phone has drawn a card.
The app asks for a list of models
Opening or narrowing the catalogue produces one request. The steps that follow are all part of preparing its answer.
Two addresses are prepared for every model in the answer
For each model the server prepares the small image used in the grid and the full image used for zooming, in the same batch (`const [thumbnailUrl, imageUrl] = await Promise.all([`, apps/api/src/models/models.service.ts).
A model without a small image is given its original file instead
The grid slot falls back to the original asset (`sign(m.thumbnailAssetId ?? m.assetId),`). Nothing fails and the model keeps its place in the list; the difference is that this card carries the larger file.
A model whose image record is not found keeps its place too
The address is returned empty rather than the model being removed (`if (!id) return null;`). How an empty address is rendered — as a gap, a placeholder or something else — is decided in the app and was not verified here.
Opening a model uses the address that already arrived
Because the full-size address was prepared in the same answer, the app does not have to ask the server again to find the larger image.
Why both sizes are prepared together
The batching is deliberate, and the reason for it is recorded in the code.
- The purpose is written as a comment beside the code that carries it out.
- The comment states that the grid image and the zoom image are prepared in one batch so the phone does not download a full-resolution file for every card it shows (apps/api/src/models/models.service.ts). A number appearing in that comment describes the situation when it was written; it is not a limit the code reads or applies.
- Both addresses are prepared whether or not you open the model.
- The pair is assembled for every model in the answer, so the preparation happens once for the listing rather than at the moment you open a card.
- The substitution is limited to the model it applies to.
- The original file is used for the grid only where a model has no small image of its own. Every other model in the same answer is given its small image for the grid and its original for zooming.
What comes back, and what you cannot keep
For each model in the answer you receive two things: an address for the image the grid draws, and an address for the image a full-size view opens. Both can point at the same underlying file when the model has no separate small image, and an address arrives empty when the image record behind it cannot be resolved. In neither case is the model itself withheld from the list.
Those addresses are generated for the listing request that asked for them, so a model image address is not something to store and reuse, and how long a prepared address stays usable was not verified for this page.
What none of this settles is what the app does with an empty address once it has one. The server returns the model with the address blank; the decision to draw a gap, a placeholder or anything else is made in the mobile client and is outside what was examined here.
What you see, and what the server did
Three appearances, and the server-side action behind each one.
| What appears in the grid | What the server did | What it does not establish |
|---|---|---|
| A card with no picture | Kept the model in the answer and returned its image address empty, because the image record could not be resolved | That the model was withdrawn from the catalogue, or that the download failed on the phone |
| A card noticeably heavier than its neighbours | Filled the grid slot with the model's original file, because that model has no separate small image | That the picture is damaged, or that the request failed in any way |
| A full-size view that opens without a wait | Prepared the full-size address in the same answer as the grid address | That the server answered a second request quickly, or that anything was verified about what the app stores |
What a blank or heavy card does not prove
These conclusions are reasonable from the screen alone and wrong against the code behind it.
Reading a blank card as a broken installation or a lost connection.
The empty address is produced on the server, before anything reaches the phone. Reinstalling or reconnecting acts on a layer that was not involved.
Concluding that the whole grid downloads full-resolution pictures.
Only a model without its own small image is served from the original file. Preparing both sizes in one batch exists to keep that from applying to every card.
Assuming a zoom sends a fresh request to the server every time.
The full-size address is already in the listing answer, so no further call is needed to locate the image. What the app transfers while drawing the larger image was not examined here.
Comparing two models by how quickly their cards appear and judging one picture inferior.
The difference follows from which file was prepared for the grid slot, not from the quality of the photograph behind it.
Before you report a missing model photo
Five observations that separate the cases this page covers from the ones it does not.
- Establish whether the card is present without a picture, or the model is absent from the grid; only the first is described here.
- Check whether other cards in the same grid show their pictures, since every model's addresses are prepared separately inside one answer.
- Note the model, not the picture: the empty address follows that model's image record and is produced before the answer leaves the server.
- Open the model once. If the full-size view appears without a wait, the address for it arrived with the grid rather than on demand.
- Note whether the picture is missing on the card, in the full-size view, or in both; the grid address and the full-size address are prepared from different fields on the record.
What this page does not cover
The code that was read covers the listing path only, and does not extend to the screen.
- How long a prepared address stays usable. What was verified is only that addresses are generated per listing request.
- How an empty address is rendered on the phone. That is decided in the mobile client and was not verified.
- How many models the catalogue holds. The figure near the batching code is a comment, not a value the code enforces or reads.
- Where model images are stored, or under what access policy they are served.
- How model records and their images are created, uploaded or edited. Only the read path was examined.
- How a model is used, validated or rejected once a generation runs. That logic sits elsewhere in the API.
Questions
Why does one model card show no picture?
The server could not resolve that model's image record, so it returned the model with an empty image address instead of removing it from the list (apps/api/src/models/models.service.ts). What the app draws in that space was not verified for this page.
Does zooming a model photo send another request to the server?
No further call is needed to locate the image. The full-size address is prepared in the same answer as the grid address, so the app already has it when you open the model.
Why is one card slower or heavier than the rest?
If a model has no separate small image, its grid slot is filled with the original file, so that card carries a full-resolution image where the others carry a small one. Nothing fails, and the model keeps its place in the list.
Does every catalogue model have a small image of its own?
Not necessarily, and the code accounts for that by using the original file for the grid when no small image exists. Which models are in that state is catalogue data and is not readable from the code behind this page.