Appearance
Threads flow
Threads is the app's community feed, and the fifth tab beside home, shop, scan and rewards. A brand posts a photo and a note; shoppers like it, comment on it, reply to each other, and can start a thread of their own.
It is the only screen in the app where a customer writes something other customers read, which is why the questions at the foot of this page are mostly not about field names.
Play the flow
Three paths: reading and replying, composing a thread, and the image sheet.
4:4713
Night Shift x First Pour
this run comes down at the end of the week. we need a name for the cross — drop yours below.
♡💬↗···
Strain of the year
homeshopscanrewardsthreads
Space plays and pauses, ← and → step. The screens are the shipped design. What sits behind them is the problem.
Read this before building against it
Every call this flow needs is a gap. No thread, post, comment, like or feed route exists in either backend — not in the customer backend's routes/v1 or routes/v2, and not in the admin backend. So this page cannot tell you field names, and it does not guess at them: a screen needing data is not evidence that an endpoint returns it.
What that means in practice is that Threads is served by a separate service, and the trace it leaves in the customer backend is the one endpoint below.
The one documented call: POST /api/v1/feed/users
Not a mobile endpoint. It is service-to-service, and it is the feed asking the customer backend to turn a list of user ids into people.
Auth: HTTP Basic — Authorization: Basic <base64 user:pass>, checked by isValidInternalReq against a single username and password pair from the environment. Not the brand x-auth-token, not a customer JWT. Handler: getCustomers (customer_controller.js) → _getCustomers.
| field | type | req | notes |
|---|---|---|---|
user_ids | array of number | ✅ | under payload, as usual. Every item required |
It answers { success: true, result: { customers: [...] } } with the full customer row minus password, otp, brandId and the timestamps.
Three things follow from reading it rather than its name:
- It is not scoped to a brand. The query filters on
userIdandisVerifiedonly, andbrandIdis stripped from what comes back — so ids from one brand's feed resolve against every brand's customers. - Unverified customers come back as nothing. A row that has not verified is filtered out rather than returned as a stub, so a feed holding a comment from one has no author to render and has to cope with the shortfall itself.
- The feed holds the ids. It sends them; it is not handed them. Whatever stores a post already knows which customer wrote it.
Stages
API calls by stage
Every row marked Gap is a call the screen makes and no page can document.
| Stage | Action | API call | Auth |
|---|---|---|---|
| 1 | The feed page: posts, authors, images, counts | Gap | — |
| 1 | Resolving author names for the page | POST /api/v1/feed/users — internal, and called by the feed service, not the app | Basic |
| 2 | Like, and unlike | Gap | — |
| 3 | Open the comments | No call — a client-side navigation | — |
| 3a | Comments, with one level of replies | Gap | — |
| 3b | Post a comment or a reply | Gap | — |
| 4 | Download the image | No call — the image is already fetched | — |
| 5a | Attach an image | Gap, but POST /api/v1/user/mobile/uploadImage is the platform's one image upload and answers with a Cloudinary url | Customer |
| 5b | Create the thread | Gap | — |
| — | Share a post | Gap — whether the share sheet needs a server-side link at all is undecided | — |
The tab bar itself is ordinary: the other four tabs are the flows already documented — shop, scan, rewards — and home is published content.
What the design settles, and what it doesn't
Read off the screens rather than off any schema, so treat all of it as the requirement a real contract has to meet, not as the contract:
| The screens show | So the data needs |
|---|---|
| Author avatar and display name on every post and comment | A customer reference per row, resolved through feed/users |
| A post has a title line and a body | Two text fields, not one — the title is set in bolder type |
| One image per post | A single url, not a gallery. Nothing in the design pages through images |
| Replies indent exactly one level | Threading is capped at depth one. A reply to a reply has nowhere to go |
A parent comment shows ♡ 5 and Reply 3 | Per-comment like and reply counts on the parent, not computed from a fetched child list |
Relative ages — 1y, 11mo | A timestamp per row; the app formats it |
| The overflow sheet has Download Image and Cancel | There is no report, block, mute, delete or edit anywhere in the shipped design |
That last row is the one to take seriously. A feed shipping without a report path is a product decision, not an oversight to route around in the client.
Open questions
- Who may post? The compose screen is reachable from the feed, but every post in the design is from brand staff. If a shopper can post, nothing in the design moderates it; if they cannot, the compose button needs a gate and there is no field to gate it on.
- Does anything moderate a comment? No approval state appears on any screen, and the sheet offers no way to report one. The screenshots this page was drawn from already show a bare link posted under an unidentified account, so the answer today is no.
- Is a like idempotent per customer? The design has a filled and an unfilled heart and no count beside it on the post, so the client cannot tell a second tap from a double submission without the server saying which it was.
- How does the feed paginate, and does a new post land at the top? Nothing in the design is a cursor, and after posting the app returns to the feed.
- Can a post be deleted or edited? Not from the sheet, not from anywhere else in the design — including by its author.
- Is the feed brand-scoped? The one endpoint underneath it is not, which makes this worth confirming rather than assuming.
- Does a guest see the feed? The tab is reachable signed out on every other tab's pattern, but writing needs a customer session.
- Does anything notify? A reply to your comment has no notification in the documented set, and no screen shows one.
Related pages
- App flows — the other ten
- Template pages — the rest of the tab bar
- Gift cards, notifications and uploads — the image upload
- Auth, account and addresses — the customer rows
feed/usersreturns - Mobile API overview
- Duplicates, aliases and quirks