Client-Side and Server-Side Workflow

Plan: Composable Developer

Lesson 4 of 27 · 30 min

A major point of distinction in the architecture of any web application front-end is whether its interaction with a given service, the BigCommerce GraphQL Storefront API in our context, occurs in a client or server context. Client-side requests are performed directly in a user’s browser, while server-side requests involve a server layer that retrieves data from the API before page content is ever served to the client.

The choice of data fetching strategy is often intrinsically connected to rendering strategy. In web applications with a heavily client-side approach, data fetched within the browser is then used to hydrate page content using JavaScript-based techniques. With a server-side strategy, the API-fetched data is directly incorporated into the rendered page content initially sent to the user’s web browser.

Client-Side Rendering

Client-side rendering is often beneficial for highly dynamic and interactive user interfaces. A web application that exclusively fetches and renders content in the browser can often be deployed as static content on a CDN, without the need for traditional server resources like databases, cache storage, or script runtimes. Since purely client-rendered applications do not have to make repeated round trips to the web server for re-rendering as content on the page changes, they can potentially present an experience that feels quicker and more responsive. Progressive Web Applications are web-based apps that look and feel like native apps, can be installed on a user’s device, and often have limited offline capability. These apps usually benefit from client-side data fetching and rendering.

For traditional websites, there are a number of hurdles that client-side fetching and rendering strategy must overcome. JavaScript-based applications must implement solutions for URL-based routing and intuitive integration between page content and browser history. Search engine optimization is more challenging since content is not present in the initial HTML sent in the page response (although search engine support for JavaScript-generated content continues to become more reliable). Most importantly, client-side data fetching means that API endpoints and authentication credentials — a GraphQL token in our case — are publicly exposed. As a result, such tokens should be short-lived and regenerated frequently.

Server-Side Rendering

Server-side rendering is the way content has been delivered since dynamic websites first emerged. Pre-rendered pages are compatible with standard web navigation flow without any extra effort, and they lend themselves to more reliable search engine optimization. Server rendering allows data fetching to be done on the server as well, which means that API endpoints and auth tokens remain private. Applications benefit from a server-side strategy when they present and navigate like traditional websites or when it’s necessary to fetch data in a private context. Modern frameworks like Next.js and Nuxt incorporate the benefits of front-end toolsets (React and Vue) while adding support for server-side rendering, combining secure data fetching and fully rendered page responses with client-side routing and dynamic interaction. This means that modern web applications can often embrace server-side data fetching without sacrificing responsive user interfaces.

Most ecommerce storefronts navigate like traditional websites, require reliable search engine optimization, and benefit from the simplicity of private data fetching. As such, a server-side strategy for data fetching and rendering is an increasingly common choice. Which strategy works best for you will ultimately depend on the unique goals and requirements of your own application. Hybrid approaches are perfectly valid as well. For example, critical content like the main product details on a product page might be rendered on the server, while the product’s reviews are less essential and can be loaded with a client-side fetch (using a different GraphQL token) after the initial page is rendered.

Whatever strategy you choose, note that the distinction between client-side and server-side data fetching has no bearing on whether a front-end is compatible with composable architecture. A headless storefront is defined by its decoupled relationship with the services it consumes, not by whether the interactions with those services occur in a browser or in a server layer.

The Normal Storefront GraphQL Token

A normal Storefront API token — generated with the /v3/storefront/api-token REST endpoint — is the standard authentication method whether for server-side or client-side context. In a client-side context, it supports a couple of different strategies that facilitate secure access and user context.

  • Allowed CORS Origins - The allowed_cors_origins parameter of the Create Token request allows you to specify the domains that CORS (cross-origin resource sharing) rules will allow for requests using the resulting token. For example, let’s say a token is created with an allowed origin of petespastries.com. When a page served from that domain executes a JavaScript-initiated request to store-{hash}.mybigcommerce.com with that token, BigCommerce will recognize the referring domain and return data. If a malicious actor obtains this token and entices users to execute a similar request from a page on pastryfraud.com, the request will be rejected.
  • Session cookies - When a normal token is used, the HTTP response includes Set-Cookie headers, most notably for the SHOP_SESSION_TOKEN cookie. This cookie, as it does in a typical Stencil storefront, tracks the user’s session context. When the session cookie is sent along with future requests, this automatically provides the right customer context. For example, if a Customer Login mutation is performed from a user’s browser, any future requests from that user for catalog data will receive accurate customer pricing thanks to the customer context provided by the session cookie.

About Session Cookies

A number of challenges make relying on the SHOP_SESSION_TOKEN cookie a less than ideal solution for tracking state across requests.

Prevalent privacy concerns with data sharing on the web have led to more restrictions on cross-domain cookies by browser vendors. This has implications for the session cookie if your storefront domain is not the same as your BigCommerce GraphQL domain.

Let’s say that petespastries.com is a headless storefront making client-side GraphQL requests to a BigCommerce endpoint on a different domain. (Perhaps Pete’s BigCommerce store has the domain pete-bc.com, or perhaps the storefront is simply sending requests to store-{hash}.mybigcommerce.com.) This constitutes a cross-domain cookie scenario.

With the right configuration for your client-side requests, cross-domain cookies can still be sent and can provide the right context for your queries. However, cross-domain cookie rules continue to change, and several browser vendors have signaled clear plans to restrict them further in the future.

Even if you can adopt a DNS strategy that puts the storefront on the same domain as the BigCommerce endpoint (say, in the above example, a domain like api.petespastries.com), it is still inadvisable to rely on a cookie created and controlled by the BigCommerce web service for session state important to your own front-end application.

It is recommended practice to disregard the SHOP_SESSION_TOKEN cookie and avoid relying on it for customer context in a headless storefront.

In cases where you are using a client-side fetching strategy and must maintain customer or cart context on such requests, we recommend proxying your requests via a server layer that can use a customer access token. We will discuss strategies for tracking the customer context when we dive into the topic of customer authentication.

Server-Side Context

Deprecation Notice for normal/storefront tokens: Normal/storefront tokens are being deprecated for server-to-server use. For headless storefronts and other server-to-server integrations, use Private Tokens.

  • Normal/storefront tokens created after June 30, 2026 will no longer support server-to-server (S2S) requests
  • Normal/storefront tokens created on or before June 30, 2026 will be able to make S2S calls until March 31, 2027
  • If you’re planning server-to-server usage, you should already choose Private Tokens

In a server-side context, a Private Token is used in conjunction with a Customer Access Token — generated with the login mutation or the loginWithCustomerLoginJwt mutation — to facilitate data fetching with customer context.

  • Customer context - The Customer Access Token is unique to an individual user’s account because it represents an authenticated storefront session for GraphQL requests.
  • Server-side use only - Customer Access Tokens cannot be obtained or used in a client-side context.

The Private Token

A Private Token — generated with the /v3/storefront/api-token-private REST endpoint — is designed for headless server-to-server integrations. It is the recommended token type for headless storefronts and other server-to-server applications.

  • No session/cookie required - Private tokens do not use sessions or cookies
  • Server-to-server only - Private tokens cannot be used from browsers; browser requests will be rejected
  • Modern integration - Preferred over normal tokens for new headless server-to-server integrations

For more details on creating and using Private Tokens, see Creating a Private Token.

The Customer Impersonation Token

A customer impersonation token (CIT) — generated with the /v3/storefront/api-token-customer-impersonation REST endpoint — is an alternative method for providing customer context and is necessarily relegated to server-side data fetching.

  • Customer impersonation- A customer impersonation token can provide the context of any customer by passing the X-Bc-Customer-Id header.
  • Private use- Because of the ability to impose customer context, a customer impersonation token must not be publicly exposed! Such a token could be used by any party to impersonate the context of any customer. Customer impersonation tokens are therefore a sensitive credential and appropriately only for server-side context.

Using a customer impersonation token in combination with a customer ID is an alternative way of providing customer context, in contrast with using a standard token with a customer access token. This is a legacy approach, and because of the elevated privileges of a CIT, the customer access token approach is the preferred method.

Using GraphQL Tokens the Right Way

Client-Side Data Fetching

  • Normal tokens are always used in client-side contexts.
  • Customer impersonation tokens (CIT) should never be used in a client-side context. CITs have the elevated permission of accessing data for any customer’s context, and such tokens should not be exposed publicly. Any request using a CIT that includes Cookie headers will be rejected.
  • If client-side requests must maintain a customer or cart context, the front-end should be on the same domain as the BigCommerce GraphQL endpoint.
  • Publicly exposed tokens should be short-lived, and therefore your application should include logic for generating and refreshing them.
  • Your front-end application’s domain must be included as an allowed CORS origin when you generate a normal token.

Server-Side Data Fetching

  • Private Tokens should be used in a server-side context for requests that don’t need customer or cart context. Sending or consuming cookies shouldn’t be attempted in a server-side context.
  • In addition to the Private Token, a Customer Access Token can be provided in a header for requests that need customer or cart context.
  • Customer Access tokens will expire when the user logs out of a single device, or after 1 week. Users will need to provide credentials again after the token expires.

Resources