Jewelry AI - library and collections
Your library looks empty: what that screen can and cannot tell you
Some of the app's failure paths do not produce a sentence. A Collections tab reporting nothing yet, a grid that stops growing while you scroll, and a card showing the photo you uploaded are screens you have to read rather than errors you are shown. This page separates the surfaces that report a failure from the ones that stay quiet.
Three failures that arrive as silence
Not every failure in this app produces a sentence. In three places the client draws a screen that looks like an answer rather than a fault: twice because a failed request is not reported, and once because a status is drawn as a picture you recognise.
The first is the Collections tab. If the collections list cannot be fetched, the failure is passed over silently in apps/jewelry-mobile/src/features/generation/store.tsx and the tab renders the 'no collections yet' empty state - the same screen an account with no collections would get. The collection detail screen behaves differently with the same failure: it shows the error and a Retry action. Those two behaviours are not versions of each other and should not be read as one.
The second is the library feed. A first page that fails clears the items being held and shows an error state with Retry; a page that fails while you scroll changes nothing on screen. The reasoning is written into the code next to the branch (apps/jewelry-mobile/src/features/generation/use-generation-feed.ts:79): on a later-page error the existing list is kept. What reaches you is a list that is short without saying that it is short.
The third is the thumbnail. A completed job shows the generated image; a processing or failed job shows the photograph you uploaded. That is a status being drawn - not a partial result, and not a preview of anything.
What the library hands back to you, then, is one image per job chosen by status and, when it has nothing to draw, one of three empty states. None of that describes what is stored. The evidence behind this page covers what the app displays; a failed fetch and an empty account produce the same screen precisely because the screen is not reporting the difference.
What each screen is actually doing
File and line references below are to the jewelry-mobile client as read on 2026-08-18.
- The collections error is swallowed in one place and reported in another.
- apps/jewelry-mobile/src/features/generation/store.tsx passes a failed collections fetch over silently, and the Collections tab falls back to its 'no collections yet' empty state. The collection detail screen shows an explicit error with Retry for the same failure. If collections had already loaded earlier in the session, the list held in memory stays, which is why the misleading empty tab belongs especially to a first load that failed.
- The feed clears itself on a first-page error and stays put on a later one.
- apps/jewelry-mobile/src/features/generation/use-generation-feed.ts empties the items (setItems([])) and raises an error state with Retry when the first page fails. For a page requested further down, the comment at line 79 records the opposite decision: the existing list is preserved and nothing is shown. A connection that drops during scrolling therefore leaves an incomplete list with no error on it.
- The missing action button distinguishes a filtered view from an empty account.
- In apps/jewelry-mobile/src/app/(tabs)/library.tsx the empty state is one of three - deleted, filtered to nothing, or no generations at all - and the button that starts a new visual is rendered only for the last: actionLabel={!isDeleted && !filtered ? t('home.newVisual') : undefined}. The filtered test is broad (library.tsx:499) and the Favorites tab satisfies it, so a seller with no favorites is told that nothing matches the filters.
- Three different job outcomes draw the same picture.
- const thumb = job.status === 'completed' ? (job.outputUri ?? job.imageUri) : job.imageUri; means processing and failed jobs show your source photo, and a record marked completed with an empty output URL falls back to it as well. The enlarged preview uses the same rule (library.tsx:701), so opening the card bigger adds no information about the outcome.
Which surface reports a failure, and which one stays quiet
One class of problem - a request that did not come back - reported differently depending on where you are standing when it happens.
| Surface | What failed | What you see |
|---|---|---|
| Collections tab | The collections list could not be fetched | The 'no collections yet' empty state; the failure is passed over silently in the generation store |
| Collection detail screen | The same failed fetch | An explicit error, with a Retry action |
| Library grid, first load | The first page of the feed | The items being held are cleared and an error state with Retry appears |
| Library grid, while scrolling | A later page of the feed | Nothing. The list stays as it is and no warning is shown |
| A card inside the grid | A job that is processing, failed, or completed with an empty output URL | The photo you uploaded, in place of a generated image |
Reading your own screen
Each row is a screen you can actually be looking at, the move that follows from it, and the behaviour that makes that move the right one.
| Situation | Choose | Why |
|---|---|---|
| The Collections tab is empty on the first screen you opened after launching the app. | Open a collection you know you created before concluding anything. | The tab folds a failed fetch into the empty state, while the detail screen reports that failure and offers Retry. |
| Collections were listed earlier in this session, and the tab is empty now. | Treat the empty tab as a weaker signal of a failed load. | Once collections have loaded, the app keeps the list it holds; the misleading empty state is tied to the session's first load failing. |
| The grid stopped adding rows while you were scrolling. | Do not read the visible list as the whole history. | A later-page failure is silent by design and leaves the existing list untouched. |
| The empty state offers no button for starting a new visual. | Look for something filtering the view rather than for missing work. | That action is rendered only when there are genuinely no generations; a filtered view, the Favorites tab included, renders no action at all. |
| A card shows the photograph you uploaded. | Read the status badge, and do not infer failure from the image. | Processing, failed, and completed-with-an-empty-output-URL all fall back to the input photo. |
Before you conclude that work is missing
Checks in the order that costs the least.
- Note which surface is empty: the Collections tab, a collection's detail screen, or the library grid.
- Ask whether this is the first load since the app was opened, or whether the list had already appeared once in this session.
- Open a collection detail screen and see whether an error with a Retry action comes up there.
- Look for the action button in the empty state; without one, the app is treating the view as filtered.
- Treat a grid that stopped growing while scrolling as incomplete rather than as finished.
- Match each card to its status badge before deciding that a run failed.
What this page does not settle
What follows was read from the client's own behaviour. Everything below sits outside that boundary.
- Whether your work is stored or gone. The evidence covers what the app displays, not what is held on the server, so this page will not tell you that your data is safe and will not tell you that it is lost.
- Why a particular run failed. The sentence shown for a failed generation is chosen elsewhere and is covered on its own page; nothing here re-derives it.
- How filters and the quick tabs behave - which dimension a tab resets, what a badge counts. That mechanism is documented separately; this page goes only as far as the finding that something may be hiding rows.
- How much the feed loads in one page, and under what conditions paging is held back. The only statement made here is that loading can stop quietly.
- How often any of this happens. Nothing on this page is a frequency, scale, or performance claim - that has not been measured.
- What a web or admin surface would show. The behaviour described was read from the API and the jewelry-mobile client only.
- Whether anything that depends on environment configuration is switched on in production. That cannot be established from the code.
Questions
My Collections tab says I have no collections yet. Did I lose them?
That screen cannot answer the question. When the collections list fails to load, the failure is passed over silently in apps/jewelry-mobile/src/features/generation/store.tsx and the tab falls back to the 'no collections yet' state - the same screen an account with no collections sees. Open a collection's detail screen instead: it reports the failure and offers Retry. The misleading empty tab belongs especially to a first load of the session that failed, because a list that has already loaded is kept. What is stored on the server is outside what this page can tell you.
The grid stopped loading new rows while I scrolled. Is that everything I have?
Not necessarily. A first-page failure clears the list and raises an error with Retry, but a page that fails while you scroll is silent by design: the list stays as it is and no message appears. The decision is recorded in the code at apps/jewelry-mobile/src/features/generation/use-generation-feed.ts:79. A short list is not evidence of a short history.
A card shows the photo I uploaded, not a generated image. Did that run fail?
It may have, but the image does not prove it. Processing and failed jobs both display the source photo, and a record marked completed whose output URL arrives empty falls back to the same image, badge included. Read the status on the card rather than the picture - and note that the enlarged preview uses the same rule (apps/jewelry-mobile/src/app/(tabs)/library.tsx:701). Why a run failed is answered by the failure message itself, which has its own page.
The library says nothing matches my filters, but I know I have generations. Why?
The test for a filtered view is broad and the Favorites tab satisfies it (apps/jewelry-mobile/src/app/(tabs)/library.tsx:499), so a seller who has never marked a favorite is shown the filtered message rather than the empty-account one. The tell is the missing action button: the app offers to start a new visual only when there are genuinely no generations. The behaviour of the filters and the tabs themselves is documented on its own page.