<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-5HGSQD2L" height="0" width="0" style="display:none;visibility:hidden" title="GTM"></iframe>

React setup

Install SWAN

Configuring the .npmrc file for your project

SWAN is hosted in a private npm repository. To install the package, you need to ensure your project’s .npmrc file is correctly configured.

For detailed steps on configuring your npm client, see Install NPM Packages from Vistaprint Artifactory.

Install the latest version of SWAN

Peer Dependency

  • react:>=17 <20 (Preferred version ^19)
  • react-dom:>=17 <20 (Preferred version ^19)

For Library Owners

Add @vp/swan as a dev dependency to help with building, developing, and testing your library. And also declare it as a peer dependency in package.json. This means that any project using your library needs to have @vp/swan installed. Your library will automatically use the version of @vp/swan that the consuming project has, so everything works together smoothly.

This peer dependency range (>=3 <4) ensures your library will stay compatible with all Swan v3.x releases while avoiding breaking changes from v4

Project setup

Choose the setup tab that matches your React project.

Getting Started With SWAN in UBIK

Fortunately, UBIK handles a lot of the scaffolding for the SWAN setup. If you generate a new UBIK fragment using @vp/init you can see an example of a component with SWAN support built in. Please see these docs for more information on UBIK fragments.

Important notes:

  • You do not need SwanProvider or SwanHead when working with UBIK fragments as this is done for you.
  • Set required style keys by passing a list to the useSwanStyleKeys hook provided by @vp/ubik-context. An example of how to do this is included in the component generated by @vp/init (shown below), so you can use that as a reference.
    • You can add style keys at the component level (scattered throughout your fragment) or you can add all required across a fragment in a single place at the root.
    • Note that this only works server side so won't add styles in the browser and we recommend doing this server side where possible.
  • In a UBIK world, the HTML <body> element doesn’t get the root class name, the root element does. This means that portals that get rendered against <body> don’t receive the styling. When using a portal, the SWAN component should be wrapped in a <Box> applying getRootClassNames(). See the example below.

Getting Started With Vite

  • SwanConfiguration → Sets up locale, providers, global link config, and injects styles content.
  • main.tsx → Wrap the entire app inside SwanConfiguration, making sure every page and component has access to global styles and provider.
  • App.tsx → Defines the page layout using Page Wrappers. To set up a consistent page structure and accessibility patterns (e.g., skip links).

Getting Started With NextJS (with app router)


NextJS's App Router introduces a framework for building applications and relies on React features such as React Server Components (RSCs). The App Router Uses React canary releases built-in, which include all the stable React 19 changes, as well as newer features being validated in frameworks, prior to a new React release.

As of SWAN 3.0, all components are marked with 'use client' - meaning they will render on the server, but also hydrate on the client.

SWAN Utility Components and CSS Classes

Because SWAN components are treated as client components, they cannot be used inside of server components (except when passed through as children props).

Instead of rendering something like <P marginTop={3}>My Paragraph</P> the CSS utility classes can be used instead: <p className="swan-mt-3">My Paragraph</p>. This approach lacks type safety, so is best avoided, if possible

app/layout.tsx → This is the single place where you wire up SWAN in a Next.js app.

  • Wrap the application with SwanProvider to configure the locale, set up the global link component
  • Apply root-level class names.
  • Add SwanHead to handle style injection.
  • Use Page Wrappers to set up a consistent page structure and accessibility patterns.

Getting Started With NextJS (with page router)

  • pages/_app.tsx → Wrap your app with SwanProvider to set up the locale and global link config.
  • pages/_document.tsx → Lets you customize the <html> and <body> tags. This is where you typically inject SwanHead for stylesheet keys and set the root class names.
  • layout.tsx → Defines the page layout using Page Wrappers. To set up a consistent page structure and accessibility patterns (e.g., skip links).

Getting Started With Gatsby

The latest version of Gatsby comes with its own Head management toolkit.

In Summary, all the pages and templates should return a named component called Head which should modify everything in Head. This will receive the data and pageContext that the default component receives.

Additionally, to modify attributes on html or body tag, you need to use the appropriate methods inside onRenderBody (as shown below). Additionally, you could modify head within this as well which are common to all the pages.

Since this doesn't need helmet, you don't need to install helmet, or configure gatsby-config with react-helmet plugin.

Please refer to PageOrTemplate example on how to manage SEO

When using SSR or SSG with React 17, wrap your application in <SwanSSRProvider /> to avoid hydration issues. This step is not needed for React 18 and above.

SwanProvider

It's a component that acts as a configuration hub for the SWAN. It wraps your application and makes global settings, like asset paths and link components, available to all SWAN components via React's Context API.

It takes the following props:

pathType (optional)

Controls how asset files are referenced. It can take two possible values: hashed | versioned exported via an enum SwanPathTypeEnum. Each asset is stored at two paths: one using the content hash and one using the package version. It defaults to hashed, which is the recommended value. Not all asset files change between different versions of SWAN. Therefore, if they have the same content, they will also have the same hash across different versions of SWAN. By default, it uses hashed path.

swanTenant (optional)

Specifies which tenant (i.e., site) to load assets for.

  • In Swan, only vistaprint is currently supported.
  • Typically, only needed in production, so assets resolve correctly.

swanLocale (optional)

Specifies the locale, which determines the domain (TLD) from which assets are loaded.

  • Valid values include standard locale codes like: en-US, en-gb, fr-FR, de-de, etc.
  • Ensure assets are fetched from the correct localized endpoint in production builds. Each locale maps to a specific production domain, e.g.:

swanBaseUrl (optional)

Controls where SWAN assets are loaded from.

  • If you provide swanTenant + swanLocale, swanBaseUrl is generated automatically using them.
  • You can use this prop to explicitly set a base URL if needed.
  • If both swanTenant + swanLocale and swanBaseUrl are provided, the preference is given to the swanBaseUrl.
  • By default, SWAN uses the https://swan.prod.merch.vpsvc.com domain as the swanBaseUrl. But we've also made sure that our assets are available via each of our production domains (e.g. vistaprint.ie) on a proxy path /swan/. So, when building for production, we recommend that you specify the appropriate domain via the domain option in SwanProvider’s swanBaseUrl prop.

Why this matters:
When assets are served from the same domain as your app, the browser can reuse its existing connection instead of opening a new one for a different domain. This reduces connection overhead, speeds up asset loading, and improves overall performance.

For best results, configure your app and swanBaseUrl to use the same domain.

globalLinkComponent (optional)

Defines the default component used by the Swan Link component.

In single-page applications, it’s common to rely on a routing library (like React Router, Next.js, or Gatsby) for client-side navigation. These libraries ship their own Link components, which must be used instead of plain <a> tags. Why? Because they handle navigation internally (and sometimes prefetching), bypassing the browser’s default anchor behavior for better performance and user experience.

By default, Swan Link renders a regular <a>. But since SWAN components are configurable, you can replace that with your framework’s routing component.

You can tell a Swan Link component to render a NextJsLink rather than an <a> like this:

If you want all Swan Link components to use NextJsLink (or any other routing component) automatically, set it once via the globalLinkComponent prop on SwanProvider:

Now, every Swan Link inside <SwanProvider> will use NextJsLink by default, no need to pass the component via as prop each time.


SwanHead

Handles stylesheet loading and font setup. It takes the following props:

swanBaseUrl (Optional)

Tries to read from SwanProvider when used as a child. For cases where SwanHead is used outside the SwanProvider like (NextJs) _document.js or gatsby-ssr pass the appropriate value. By default, it uses the https://swan.prod.merch.vpsvc.com domain as the swanBaseUrl.

swanPathType (Optional)

Defaults to SwanProvider's value if inside the SwanProvider else, it defaults to hashed.

styleSheetKeys (Required)

List of all the stylesheets that it needs to load. Swan doesn't support auto-loading of styles. So pass all the values. It defaults to loading all the CSS.

fontNames (Optional)

You can control which fonts Swan loads by explicitly listing them.

  • Default behavior: If you don’t configure anything, Swan will load all available fonts.
  • Custom behavior: If you provide a fontNames list, Swan will load only the fonts you specify.
    • This means you must include all fonts you need, not just the ones you want to add.

For example, if your application uses both Graphik and Tiempos, configure it like this:

renderWith (optional)

You can control which custom head management component should be used. In React 19 or above, if not provided, Swan defaults to React’s native head management API. And below React 19, it defaults to React.Fragment. When using a framework like NextJs, we can use its Head component. In non-framework projects, you can use the default or Helmet from react-helmet-async

Let you choose a custom component for managing the <head> of a document. If you don't specify one, Swan uses React's native head management API in React 19 and later. For older React versions, it defaults to a React.Fragment. When you're using a framework like NextJs, you should use its built-in <Head> component. For projects without a framework, you can use the default setting or a library like react-helmet-async.

renderStyleContentAsChildren (optional)

You can control how <style> tag content is rendered. Instead of using dangerouslySetInnerHTML, it renders the content as a child. This is useful when you are working with libraries like react-helmet that expect the style content to be a child of the <style> tag.

Managing <head> in React projects

If your project is built with a modern framework, like Next.js, or other, you should always use the framework's built-in solution for managing the <head>. These tools are designed to work seamlessly with the framework's server-side rendering (SSR) and routing, providing the best performance and a unified DX.
If you’re not using a framework, then you can prefer React19's new built-in head management APIs (like meta, link, or title).

If you are working on a project with a version of React older than 19, you will need to use a library to manage your document's head. The recommended choice is react-helmet-async. It is a modern, actively maintained successor to the deprecated react-helmet and is fully compatible with older React versions.

Page Meta Tag

The SWAN library simplifies the management of essential page meta tags as part of the SwanHead component, ensuring optimal performance and functionality for your web application.

With SWAN, you no longer need to manually include and configure these meta tags individually. The library takes care of the following meta tags for you within the SwanHead component:

By leveraging the SWAN library's meta tag management capabilities, you can focus on developing your application without worrying about the intricate details of meta tag setup.


getRootClassNames

Swan is designed to be interoperable with other design systems, enabling incremental adoption. To support this, all Swan-related styles are scoped under a root swan class.

  • Full-page usage → Apply the generated class names to the <body> tag if you want Swan styles applied globally.
  • Incremental adoption → Apply the class names only to the container element where Swan components are rendered, so other parts of your app remain unaffected.

This function accepts a configuration object with the following options:

  • standardMode?: boolean – Enables Swan’s standard theme mode (default: false).
  • darkMode?: boolean – Enables Swan’s dark theme mode (default: false).

The preview has been updated.


useBrowserClasses

This accepts an optional boolean parameter that will add the browser's name as a class name on the <head> tag. For instance, if you are using Firefox, you should see the class swan-firefox on the <head> tag.

We account for the following browsers by analyzing the navigator.userAgent:

  • Safari
  • Firefox
  • IE
  • Edge (pre-Chromium, and Chromium-based)

The preview has been updated.


Testing

waitForStyles


When testing SWAN components, especially in a browser-based testing solution like Playwright or Cypress, you may need to wait for SWAN styles to be loaded before running your test assertions. We provide a testing utility called waitForStyles that does exactly what it's called - it returns a promise that resolves when the SWAN-style keys are loaded. To use, put await waitForStyles() in your test.