- Do not force registration before a customer can express interest.
- Store product identity, not copied prices or availability.
- Refresh saved products in the customer’s current market.
- Synchronise browser tabs without pretending this is cross-device sync.
- Define a clear merge policy before adding account-based wishlists.
The client problem was not account synchronisation
The first requirement was deliberately narrow: let a guest remember products in the same browser and later move simple purchasable items into the cart. Medusa supplies products, variants and cart mutations, but it does not prescribe whether a project’s wishlist belongs in an account, another backend module or the browser.
We chose a local-first implementation that stores stable product identifiers, synchronises tabs in the same browser profile and reloads current commerce data when rendering the list. Bulk add skips products that need an explicit option choice. This solved the client’s first promise without pretending to provide cross-device persistence.
The customer need is smaller than the usual solution
A visitor sees a product they like but is not ready to buy. They want to remember it. Many shops answer by demanding an account, password and email permission before saving one item. That turns a low-commitment signal of interest into a registration barrier. For an anonymous visitor, the browser already provides enough local storage to remember a short list of product identifiers.
We started with that narrow promise: click the heart and the product remains saved on this device. No account is required, no customer profile is created and the action is immediate. This is called local-first because the browser can perform the first useful action itself. It does not mean the browser becomes the source of truth for product prices, stock or catalogue content.
Store the intention, not a frozen product card
The saved list contains stable product identifiers. It does not preserve the displayed price, stock message or translated title as permanent truth. Those values change by market and over time. When the customer opens the wishlist, the storefront requests current product information for the active country, language and sales region.
This separation prevents a common trust problem: a visitor saves an item in France, later opens the list in Belgium and sees an old French price presented as current. The identifier remembers what interested them; the commerce system decides what can be sold now. If the product is unpublished or unavailable in the new market, the page explains that state instead of rendering stale information.
Decide whether the heart saves a product or an exact option
A product-level wishlist means ‘I like this product’. The customer can choose size or colour later. It survives changes to individual variants but cannot safely add an option-bearing product directly to the cart. A variant-level wishlist means ‘I want this exact blue size 40’. It supports a more precise action but must handle that exact option becoming unavailable.
Our first version stored product identifiers. Its bulk add-to-cart action skipped products that still required an option choice rather than guessing. A richer model can later store both the product and an optional selected variant. The interface must make that level of intent clear, because the system cannot infer a choice the customer never made.
Keep several tabs consistent
A customer may browse in one tab and keep the wishlist open in another. Browser storage does not automatically make every React component update. We used the browser’s storage event to notify other tabs in the same browser profile. Adding or removing an item in one tab updates the count and list in the others without a reload.
This solves one device and one browser profile only. It is not real-time collaboration and does not synchronise a phone with a laptop. That boundary should be stated honestly. The event listener also needs lifecycle tests: it must be removed when no longer used, ignore malformed data and never run during server rendering where browser APIs do not exist.
What happens when local storage disappears
The customer can clear browser data, use private browsing or switch devices. A local wishlist can therefore disappear. For an anonymous convenience feature, that may be an acceptable trade-off if the interface does not promise permanent cloud storage. The data should be small, versioned and validated before use so corrupted storage cannot break the page.
When accounts are introduced, local data becomes an input to a merge, not something to overwrite blindly. The system must decide what happens when both the browser and account already contain items. A common policy is to keep the union, preserve explicit variant choices and deduplicate by stable identity. The merge must be safe to repeat after a failed login response.
Measure usefulness without turning the wishlist into tracking
A wishlist reveals consideration before purchase. Useful measures include save rate, return-to-wishlist rate, add-to-cart from wishlist and products frequently saved but unavailable. These can inform merchandising and stock decisions. Anonymous storage does not require sending every saved item to an analytics profile.
Be clear about consent and retention when wishlist activity becomes server-side customer data. A local feature can remain private to the device until the customer signs in or chooses to share it. The product decision should lead the architecture: convenience first, then durable cross-device value when the customer has a reason to create an account.
The wishlist checklist
Define whether saving refers to a product or variant. Persist only stable identifiers. Re-fetch current market data. Handle unavailable and removed items. Synchronise tabs in the same browser. Keep server rendering safe. Explain local-storage limits. Never add an option-bearing product to the cart by guessing.
Before account sync, document merge, deduplication, privacy and retry behaviour. Then test two tabs, corrupted storage, a removed product, a market change and login interrupted during merge. A wishlist is a small feature with a simple customer promise. Good architecture protects that simplicity rather than exposing the storage mechanics to the user.
Common questions
No. It works in the same browser profile. Cross-device persistence requires an account-backed wishlist and a defined merge policy.
No. Save stable product or variant identity and retrieve current price, stock and translation for the active market when rendering.
Only when the exact purchasable variant is known. If size or colour still needs a choice, send the customer to select it rather than guessing.
