@fluid-app/sites is the browser SDK of a member site. It speaks only to your site’s own host, which brokers each call to Fluid. Your code never holds a Fluid token or a database credential.
Import it once
Add the package and import it at the top of your app, before anything renders:src/main.tsx
fluid where you need it. The SDK also puts the same object on window.fluid.
Read who is here
fluid.auth.me() returns the visitor and the site:
me() throws a FluidRequestError when the site’s host answers with an error. The fields in viewer.fields come from the member fields the site declares in config/access.json. See Fluid data the site uses.
Sign in and sign out
fluid.auth.signIn({ returnTo })asks the storefront to send the visitor to its sign-in, then back toreturnTo, a path of your site. With noreturnTo, the visitor comes back to the page they’re on.fluid.auth.signOut()opens the storefront’s account menu, where the visitor signs out and confirms it.
Call the Fluid API
fluid.api calls the Fluid Member API as the visitor. Pass a Member API path without its version prefix: "/search" calls /api/member/v2026-10/search.
fluid.api.get(path, query)sends aGETand returns the parsed JSON. It throws aFluidRequestErrorfor any status that isn’t 2xx.fluid.api.fetch(path, init)takesfetch’s options and returns the response, whatever its status.- Both throw a
TypeErrorfor a path that isn’t a Member API path, such as a full URL.
403 with scope_not_granted and the scope it needed. Fluid data the site uses says how a site gets a scope.
For each operation, see the generated Member API reference.
Handle errors
FluidRequestError carries the answer:
Use the site’s database
fluid.db reads and writes your site’s own tables, declared in db/schema.json. It follows Supabase’s query builder, and every call resolves { data, error }:
Use the storefront’s cart
The storefront’s cart runs in the storefront, not in your frame, so member pricing and the visit’s credit stay the storefront’s.fluid.cart passes each call to it, with the FairShare cart’s own arguments.
add, update, remove and get return a promise of what the cart answered. Each rejects with an Error when the storefront reports a failure, when the site isn’t in a storefront, or when no answer comes within 30 seconds. open, close and checkout log a failure and never throw.
The cart API describes FairShare’s arguments.
The cart’s HTML controls work in your site too. A click on an element with data-fluid-add-to-cart adds its variants, and data-fluid-cart="open" or "close" opens or closes the drawer:
data-fluid-cart="toggle" do nothing in a member site. See Declarative HTML controls for the attributes.
Follow Back and Forward
The storefront keeps your site’s history: one entry per page. Your site’shistory.pushState calls and same-site link clicks still work, and the SDK reports each move to the storefront.
A single-page app’s router listens with fluid.history.onGo. On Back, Forward or a re-sync, the SDK calls your listener with the path and the fragment, instead of reloading the frame:
src/router.ts
path is your site’s own path and query, such as /events/42?tab=agenda, and hash is the fragment, such as #schedule, or null. Move your router there with pushState or replaceState. The SDK doesn’t report a move it started through onGo to the storefront, so Back and Forward never add an entry twice. The call returns a function that removes the listener. With no listener, the SDK moves the frame to the path itself.
A multi-page site needs no listener: plain links between its pages work.
Link to the storefront
The frame’s sandbox refuses top-level navigation, so a script can’t move the storefront’s window andtarget="_top" doesn’t work. Link to storefront pages with a plain <a href>. When the visitor clicks it, the SDK asks the storefront to open it in its own window.
fluid.storefront.url(path) returns a storefront address that carries the visit’s credit, so the person who shared the site gets credit for what the visitor buys:
fluid.storefront.url("/shop") returns an address such as https://yoli.com/janedoe/shop. With no credit, or the default home, the address has no credit prefix. It throws a TypeError for a path that leaves the storefront.
The SDK also adds the visit’s credit to the storefront links already on your page, and to new ones as the page changes, so a link opened in a new tab keeps it. To keep a link as you wrote it, add data-fluid-credit="off":