Interactive atom search - #1979
Conversation
| RECIPE: 'recipe', | ||
| CHEF: 'chef', | ||
| FEAST_COLLECTION: 'feast-collection', | ||
| INTERACTIVE_ATOM: 'interactive-atom', |
There was a problem hiding this comment.
What do you think about making this just ATOM: 'atom' rather than also specifying that it is interactive?
There was a problem hiding this comment.
This enum value is only used client-side in the tool. The shape of interactive atoms differs from other atoms in CAPI, so I think we'd still need some way of handling them differently in the client.
It's a bit hard to say right now, but I'm inclined to be more specific here, and we can revisit this later when we introduce more atom types to the tool.
There was a problem hiding this comment.
Pull request overview
Adds support for discovering interactive atoms via CAPI search and dragging them into collections/clipboard, while still persisting them downstream as snap links (client-side only change).
Changes:
- Adds an “Include atoms” search option and extends the CAPI feed to fetch interactive atoms alongside articles.
- Introduces an interactive-atom drag/drop type and UI rendering for atom feed items and cards.
- Generalises async resource bundle ordering to support non-string order entries (used by the mixed article/atom feed).
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| fronts-client/src/util/snap.ts | Adds helper to create snap cards from interactive atom search results. |
| fronts-client/src/util/externalArticle.ts | Updates staleness selector to handle interactive atoms. |
| fronts-client/src/util/collectionUtils.ts | Adds INTERACTIVE_ATOM drop type mapping for drag-and-drop. |
| fronts-client/src/util/card.ts | Routes interactive-atom drops to snap creation. |
| fronts-client/src/types/Capi.ts | Introduces CapiInteractiveAtom + type guard. |
| fronts-client/src/services/capiQuery.ts | Adds /atoms query support for interactive atoms. |
| fronts-client/src/lib/createAsyncResourceBundle/index.ts | Generalises stored fetch order typing to non-string orders. |
| fronts-client/src/constants/cardTypes.ts | Adds INTERACTIVE_ATOM card type constant. |
| fronts-client/src/components/feed/SearchInput.tsx | Adds “Include atoms” checkbox to search filters. |
| fronts-client/src/components/feed/Feed.tsx | Renders a mixed feed (articles + atoms) based on typed order entries. |
| fronts-client/src/components/feed/CapiSearchContainer.tsx | Plumbs includeAtoms through to feed fetch params. |
| fronts-client/src/components/feed/AtomFeedItem.tsx | New feed item UI + drag payload for interactive atoms. |
| fronts-client/src/components/feed/ArticleFeedItem.tsx | Avoids rendering articles when the resource is actually an atom. |
| fronts-client/src/components/card/interactiveAtom/InteractiveAtomCard.tsx | New card UI for interactive atom snaps. |
| fronts-client/src/components/card/Card.tsx | Adds rendering branch for INTERACTIVE_ATOM cards and disables meta form. |
| fronts-client/src/bundles/capiFeedBundle.ts | Fetches atoms in parallel and builds a typed mixed feed order. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| atoms: async (params: { q?: string }): Promise<CAPIAtomsQueryResponse> => { | ||
| return fetchCAPIResponse<CAPIAtomsQueryResponse>( | ||
| `${baseURL}/atoms${qs({ | ||
| types: 'interactive', | ||
| searchFields: 'data.interactive.interactive_title', | ||
| ...params, | ||
| })}`, | ||
| ); | ||
| }, |
davidfurey
left a comment
There was a problem hiding this comment.
I've added some feedback but I don't think we should let that block us getting this feature out.
Before merging we should discuss a comms strategy with CP
| results: checkIsContent(response) ? [response.content] : response.results, | ||
| results: checkIsContent(response) | ||
| ? [response.content] | ||
| : [...response.results, ...atomResults], |
There was a problem hiding this comment.
Would it be difficult to sort the results here so that atoms and articles are in one list? It seems unintuitive for atoms to be at the bottom with no UX hint that this is the case
There was a problem hiding this comment.
Yes good point, perhaps the UX needs a rethink here. If the user is looking for an atom, do they even want to see articles and atoms mixed together?
| response.results.filter(isNonCommercialArticle, { | ||
| prefillActions.fetchSuccess(filteredResults, { | ||
| order: filteredResults.map((item) => item.id), | ||
| pagination: { |
There was a problem hiding this comment.
Presumably the pagination of atoms and articles is independent? So given that we publish many more articles than interactive atoms, page 5 will continue quite fresh articles but quite old atoms?
|
This PR is stale because it has been open 30 days with no activity. Unless a comment is added or the “stale” label removed, this will be closed in 3 days |
|
Just for info - I've picked on up on this branch and spiked an expansion to the functionality to include surfacing more atoms (those created in atom workshop), as part of discovery work for the event kit mission (and thanks a ton @tomrf1 - your work was really helpful) . We're planning to chat to CP about this relatively soon, so I'm happy to bring up the question of UX and release comms with them then. |
Interactive atoms can be added to a front collection as a snap link.

This is done by dragging a url into the clipboard on the left, and then dragging from there into a collection.
This mechanism is used for thrashers.
The card then flows through to Frontend/MAPI as a snap link.
This PR proposes an alternative way to achieve the same thing in the tool. There are two motivations behind this:
An "Include atoms" checkbox is added to the content search settings:

If ticked, the results will include interactive atoms from CAPI as well as content. They will appear at the bottom of the results list:

In the client, any interactive atoms retrieved this way are modelled as a

INTERACTIVE_ATOMrather than as aSNAP_LINK.When the user drags an interactive atom from the list into a collection it is still persisted as a snap. This means the only change here is to the client side of the tool.
Downstream systems (e.g. Frontend/MAPI) should be unaffected.