Getting started with Weavy using React

This is a comprehensive guide on how to get started with Weavy when using a React framework. It guides you on all the basic steps you need to get it up and running and how to apply best practice when configuring Weavy in React.

It's a great idea to start with getting familiar with important Weavy concepts, if you're not familiar with Weavy yet.

1. Check requirements

React requirements

Weavy has a special UI kit for React named @weavy/uikit-react. It is using the Weavy web components under the hood, but available as React components. It also has some hooks and helpers to make the Weavy configuration even simpler. Since it's based on the web components, it always has all the features available in the web components.

You will need React v16 or later for the Weavy UI Kit React to work. We recommend using React v19 or later, which has great support for Web components as well.

The UI kit for React is compatible with React Server Components for SSR frameworks. This means the different parts in the UI kit for React knows if it should render on the sever side or the client side. It's not required to use React Server Components, but if you intend to use it you should use React v19 or later together with Next.js v14 or later using the App router.

App requirements

Your app needs to meet some criteria for Weavy to work. In short, Weavy only works on top of an app or website with properly authenticated users, which usually requires a backend.

Your app must be able to:

  • Fetch a Web API using a server function or server endpoint leveraging Bearer tokens for authentication.
  • Store and provide an API key securely on the server, for instance using environment variables.
  • Pass fetched data from the server side to client side.
  • Have access to the currently signed in user on the server side.
  • Import a javascript library client side.
  • Render Custom Elements aka Web Components client side.

2. Create Weavy account

If you haven’t already, go to https://www.weavy.com and sign up for a free account. The Weavy account is where you handle your Weavy environment and set up AI Agents.

3. Create Weavy environment

Now go to your account dashboard and create your first Weavy environment. The Weavy environment is your own Weavy server and handles all communication, databases, the Web API and serving files. There are both trial and free options, making it easy to get started. Make a note of the environment url as you’ll need it later. We'll reference this as {WEAVY_URL}.

It's also important to know which version you are using. This reflects, not only matching client and server versions, but also what API and syntax to use in your code. This guide is based on the latest version of Weavy, which can be found in the current changelog.

4. Create API key

On the environment management page, scroll down and create an API key. The API key is used for making requests in the Web API server-to-server. Take note of the created key as you’ll need it the next step. We will reference the API key as {WEAVY_API_KEY}.

The API key must always be kept secure! It should always be stored and used server side, and never on the client side. It must never be available publicly. Store it, preferably encrypted, with limited access.

5. Set up environment variables

To configure our environment settings in the app we're adding Weavy to, we'll add the Weavy environment configuration to our environment variables. We need to create two environment variables, one for the Weavy environment URL and one for the Weavy API key for the server to use.

A great way is to store the environment variables as strings in an .env file in the root of the project. You can then exclude this file in .gitignore to make sure the credentials are not saved in your repository code. Use any built-in support for environment variables in your build system, otherwise you may read the variables from the .env file using the built-in .env file support in NodeJS 20 for example.

Note: Your build system may require variables to be prefixed to be available on client side. For instance, Vite uses the VITE_ prefix to expose environmental variables that can be used on the client side, exposed in code using the special import.meta.env object. NextJS prefixes public variables using NEXT_PUBLIC_. Always check in client side code that the environment variable is actually available and has a value.

  • Create an environment variable called WEAVY_URL and let the value be the URL of your Weavy environment as a string, previously mentioned as {WEAVY_URL}. This variable is usually needed both server-side and client-side and can safely be available both to the client and the server. Use NEXT_PUBLIC_WEAVY_URL for name when using NextJS or VITE_WEAVY_URL when using Vite, to make it available both server side and client side.
  • Create an environment variable called WEAVY_API_KEY and let the value be the API key to the Weavy environment as a string, previously mentioned as {WEAVY_API_KEY}. This variable must be kept secure and only be available on the server side, never on the client side.

6. Provide user data

All Weavy components rely on actions based on users. The Weavy has a user system that needs data from your user system to make the components well integrated into your app. Providing user data is done server-to-server through the Weavy Web API using the Weavy API key. Weavy users are later authenticated using access tokens provided via your server.

Ensure the Weavy API key is only used server-side when using the Weavy Web API, while the client only receives data from your server.

Here are some points for setting the strategy on providing user data.

  • Make sure the user data is provided and available to Weavy at latest when an access token for the user is needed.
  • For one user to be able to interact with other users, those users needs to be provided to Weavy on beforehand.
  • Do not overload the Weavy environment with too many user data updates at the time. Avoid providing or updating all users at once, divide them into batches with 20-50 users at the time instead. Overloading the Weavy environment with user updates will slow down performance of using the components.

With that said, here are two recommended practical ways to do it:

  • It's best to update all the users when the server starts if the users are known and there are less than 20 users.
  • In other cases you can update the user the same time as you are fetching a user token.

When using React Server Components (in Next.js for example), this can be done using a Server Function to ensure that it's done on the server.

"use server";

/**
 * User
 *
 * @typedef {object} User
 * @property {string} username - Username
 * @property {string} name - Full name of the user
 * @property {string} email - Email of the user
 * @property {string} picture - Optional avatar URL for the user
 */

/**
 * Dummy user for this example.
 * Replace the reference to this dummy user with an actual user from your system.
 * @type {User}
 */
const dummyUser = {
  name: "Daffy Duck",
  username: "daffy",
  email: "daffy@acme.corp",
  picture: "https://i.pravatar.cc/150?u=daffy",
};

/**
 * Creates or updates the user server-to-server.
 *
 * - Using `WEAVY_URL` environment variable for the base URL to the Weavy environment. Use `NEXT_PUBLIC_WEAVY_URL` when using NextJS.
 * - Using `WEAVY_API_KEY` environment variable for server authentication on the Weavy environment.
 *
 * @param {string} uid - The user identifier to insert/update.
 * @param {User} userData - The data for the user. User properties should match the properties for users in the Weavy Web API. It should not contain a `uid` property.
 * @see https://www.weavy.com/docs/reference/api/users#upsert-user
 */
export async function upsertUser(uid, userData) {
  console.log("Upserting Weavy user", uid);

  // Ensure the WEAVY_URL environment variable is set and available. Use `NEXT_PUBLIC_WEAVY_URL` when using NextJS.
  if (!process.env.WEAVY_URL) {
    throw new Error("No WEAVY_URL defined in ENV.");
  }

  // Ensure the WEAVY_API_KEY environment variable is set and available.
  if (!process.env.WEAVY_API_KEY) {
    throw new Error("No WEAVY_API_KEY defined in ENV.");
  }

  const response = await fetch(
    new URL(`/api/users/${uid}`, process.env.WEAVY_URL),
    {
      method: "PUT",
      headers: {
        "content-type": "application/json",
        Authorization: `Bearer ${process.env.WEAVY_API_KEY}`,
      },
      body: JSON.stringify(userData),
    }
  );

  if (!response.ok) {
    throw new Error("Could not update user");
  }
}

7. Create a user token endpoint

For a Weavy to be able to fetch and render data you need to supply it with an access_token for your logged in user. Issuing an access tokens should always be done server side with a server-to-server call from your backend to the Weavy environment using the Weavy Web API together with the API key we previously created. This way we can keep the Weavy API key safe on the server.

On the client side, Weavy will later be set up to call the endpoint whenever a token is needed. In cases where the token is expired or invalid, Weavy will call the endpoint with a refresh=true parameter to explicitly request a fresh new token.

When using React Server Components, you can instead provide a tokenFactory Server Action, which can be called from client side, but executes server side. This will eliminate the need for a token endpoint.

Ensure the Weavy API key is only used server-side for working with the Weavy Web API, while the client only receives the access tokens.

Learn more about authentication.

Creating a user access token endpoint

For this example we'll create an endpoint for serving the access token using Express.js in NodeJS. The user information in this example is provided in session data for the express server. You should provide the data from your currently authenticated user and map it to the user data needed by Weavy to match your user.

// Cache for token data
const _tokenData = new Map();

/**
 * User token response data
 *
 * @typedef {object} UserToken
 * @property {string} access_token - The issued access token
 * @property {number} expires_in - Time in seconds until the token is expired
 * @see https://www.weavy.com/docs/reference/api/users#issue-access-token
 */

/**
 * GET /api/token?refresh=true
 * @summary Weavy environment user token.
 * @description Gets an authentication token server-to-server for the currently authenticated user. Using token cache to avoid unnecessary token request to the Weavy environment.
 * @param {string} refresh.query - Request the token to be refreshed - true
 * @return {UserToken} 200 - success response - application/json
 * @example response - 200 - success response example
 * {
 *  "access_token": "wyu_qf2llm...",
 *  "expires_in": 3600
 * }
 */
app.get("/api/token", async (req, res) => {
  // Ensure the WEAVY_URL environment variable is set and available. Use `NEXT_PUBLIC_WEAVY_URL` when using NextJS.
  if (!process.env.WEAVY_URL) {
    throw new Error("No WEAVY_URL defined in ENV.");
  }

  // Ensure the WEAVY_API_KEY environment variable is set and available.
  if (!process.env.WEAVY_API_KEY) {
    throw new Error("No WEAVY_API_KEY defined in ENV.");
  }

  /**
   * The current user - Replace this with data for the currently logged in user from your user system, for example using `req.session.user`.
   * It's important that the user can only get an access token for their own user account and not for any other user account, as that would compromise security.
   * @type {User}
   **/
  const currentUser = dummyUser;

  // Desired uid for the user. The uid is used for referencing and mentions in Weavy.
  const uid = currentUser.username;

  // Check the query parameters to see if a refresh token is requested
  const refresh = req.query.refresh === "true";

  // Get token from cache or by a server-to-server fetch
  // Try using a cached token if refresh isn't requested
  if (!refresh) {
    const tokenData = _tokenData.get(currentUser.username);
    if (tokenData) {
      // Return cached token data
      res.json(tokenData);
      return;
    }
  }

  // Upsert the user, as we don't need the response; we can skip awaiting this to enhance performance.
  void upsertUser(uid, currentUser);

  try {
    // Fetch access_token from server
    // - Using `WEAVY_URL` environment variable for the base URL to the Weavy environment. Use `NEXT_PUBLIC_WEAVY_URL` when using NextJS.
    // - Using `WEAVY_API_KEY` environment variable for server authentication on the Weavy environment.
    const response = await fetch(
      new URL(`/api/users/${uid}/tokens`, process.env.WEAVY_URL),
      {
        method: "POST",
        headers: {
          "content-type": "application/json",
          Authorization: `Bearer ${process.env.WEAVY_API_KEY}`,
        },
        body: JSON.stringify({ expires_in: 3600 }),
      }
    );

    if (response.ok) {
      const tokenData = await response.json();

      // Cache the token
      _tokenData.set(uid, tokenData);

      // Return fetched token
      res.json(tokenData);
    } else {
      // Forward any response codes from the Weavy environment
      res.status(response.status).json({ access_token: "" });
    }
  } catch {
    // Return 400 error to let Weavy handle it properly.
    res.status(400).json({ access_token: "" });
  }
});

Creating a user access token Server Function

When using React Server Components (with NextJS v14 using App router for instance), it's recommended to use a Server Function instead of an endpoint. Do not forget to use the "use server" directive properly.

"use server";

// Cache for current tokens
const _tokens = new Map();

/**
 * Gets an authentication token server-to-server for the currently authenticated user.
 *
 * @param {boolean} [refresh=false] - Whether to request a fresh token or use an existing token
 * @returns {string} The current user token
 */
export async function tokenFactory(refresh = false) {
  /**
   * The current user - Replace this with data for the currently logged in user from your user system, for example using `req.session.user`.
   * It's important that the user only can get an access token for their own user account and not for any other user account, as that would compromise security.
   * @type {User}
   **/
  const currentUser = dummyUser;

  // Desired uid for the user. The uid is used for referencing and mentions in Weavy.
  const uid = currentUser.username;

  // Get token from cache or by a server-to-server fetch
  // Try using a cached token if refresh isn't requested
  if (!refresh) {
    const token = _tokens.get(currentUser.username);
    if (token) {
      // Return cached token
      return token;
    }
  }

  // Upsert the user, as we don't need the response, we can skip awaiting this to enhance performance.
  void upsertUser(uid, currentUser);

  try {
    // Fetch access_token from server
    // - Using `NEXT_PUBLIC_WEAVY_URL` environment variable for the base URL to the Weavy environment.
    // - Using `WEAVY_API_KEY` environment variable for server authentication on the Weavy environment.
    const response = await fetch(
      new URL(`/api/users/${uid}/tokens`, process.env.NEXT_PUBLIC_WEAVY_URL),
      {
        method: "POST",
        headers: {
          "content-type": "application/json",
          Authorization: `Bearer ${process.env.WEAVY_API_KEY}`,
        },
        body: JSON.stringify({ expires_in: 3600 }),
      }
    );

    if (response.ok) {
      const tokenData = await response.json();
      const token = data.access_token;

      // Cache the token
      _tokens.set(uid, token);

      // Return fetched token
      return token;
    } else {
      // Forward any response codes from the Weavy environment
      throw new Error("Could not fetch token: " + response.status);
    }
  } catch {
    return "";
  }
}

8. Importing the Weavy UI Kit React lib

To be able to configure Weavy on the client side and render all the Weavy web components, we make use of the Weavy UI kit lib. The lib contains all the Weavy web components and also a Weavy class for configuration. The Weavy class automatically provides a global context provider to all the Weavy web components, so that the configuration can be placed anywhere and only needs to be done one time for all web components together.

The UI Kit React lib has modules to fit many different build systems. It selects the correct module type for your framework automatically. When loaded, it registers all Weavy web components in the custom element registry so they are available in the DOM.

  • We need to import the UI kit lib in the client. This will give access to the Weavy class to make a configuration and provide authentication for the components.
  • The Weavy web components will be available after the script has loaded and they have been registered by the script. Load the lib as early as possible to provide optimal rendering performance for the Weavy web components.
  • The version of the UI Kit React lib must always match the version of the Weavy environment. When installing via npm and importing the @weavy/uikit-react make sure to match the package version with the Weavy environment version. When the Weavy environment version is unknown, always use the latest npm package version for the UI kit lib.

Installing the UI kit from npm

The Weavy React UI kit is available as @weavy/uikit-react for installation using npm. This is optimal if you have npm available and know the exact version of your Weavy environment. This may provide much smoother usage and the possibility for your build system to perform tree shaking and optimizations of the bundle.

When using typescript in your project, you should always use the @weavy/uikit-react npm package if possible, as it contains type definitions for the whole lib, which helps you improve your code and easier debugging. It also provides global type definitions for the web components, so they are recognized in TypeScript when using JSX.

Install the Weavy UI kit package

Make sure you have NodeJS and npm installed already.

npm install @weavy/uikit-react

Import the lib in your code

import { useWeavy } from "@weavy/uikit-react";

// Weavy configuration goes here...

Importing the UI kit from the Weavy environment

The lib is available for import directly from the Weavy environment. Loading directly from the Weavy environment is optimal when you want to make sure that the Weavy environment version match. This is recommended when npm is not available or if the exact Weavy environment version is unknown.

To be able to import the lib in the browser you can simply use the native dynamic imports to load the lib as a module. Dynamic imports can be used in any async function or in scripts that has type="module".

// Import the lib directly from the Weavy environment to make sure the lib version and the environment version always are matching.
// Note: The ESM script does not expose the Weavy class in the globalRoot or window object, so you should use it within this script.
// A dynamic import may be used in script with `type="module"` or in any async function.
const { Weavy } = await import("{WEAVY_URL}/uikit-react/weavy.mjs");

// Weavy configuration goes here...

If you want to ensure that the script cache is updated when Weavy is updated, we recommend using integrity metadata using an import map with subresource integrity.

9. Configure Weavy in your app

Now that the library is imported and we have access to all modules, we can configure Weavy. There are several ways to provide the configuration, but the configuration always has the same properties and it essentially always creates an instance from the Weavy class.

When created, the instance makes itself available to all Weavy components as a context provider globally on the documentElement (which essentially is the <html> node in the DOM). This means only one Weavy instance is needed, so make sure to avoid creating multiple instances, as this only will raise memory consumption.

The Weavy instance needs to be configured at least with a URL and authentication. The following properties are required to configure for the Weavy instance.

  • url - The required url to the Weavy environment.
  • tokenUrl or tokenFactory - The authentication can either be an url to an api endpoint or an async function returning a token. It's recommended to use the tokenUrl in most cases, when you have an endpoint returning the access token as JSON in the normal { "access_token": "wyu_*****"} format. When you want to customize how to retrieve or provide the access token, you may use the tokenFactory instead. The tokenUrl or tokenFactory will not be used until a valid url property also is set.
  • If you are using React Server Components it's recommended to use the tokenFactory property and link it directly to a server side tokenFactory Server Function. This will eliminate the need for a token endpoint and reduce complexity in your app.

There are two recommended ways to configure Weavy when using React, using a hook or using a context provider. The simplest and most common way to start is to use the hook for configuration.

Configuration using the useWeavy hook

The UI kit provides a hook to use for configuration called useWeavy(configuration, dependencies). The hook provides configuration to all Weavy components in the DOM. It can be used in one of your components or in multiple components, it still refers to the same Weavy instance, which always is returned by the hook. Make sure to pass all configuration properties in the configuration object parameter of the hook to make the usage optimal for React, instead of configuring the afterwards (which may lead to unexpected effects).

It ensures that only one Weavy instance is created, so you don't have to handle that. Make sure that you use the same values for properties in each place you use the hook, unless you intend to change them. You can additionally pass a dependency array that explicitly triggers updates to the configuration when the dependent values change. Note that hooks are only available client side when using React Server Components or SSR.

// Place the hook inside your component
// Returns the Weavy instance
const weavy = useWeavy(
  {
    // The URL to your Weavy environment. Use NEXT_PUBLIC_WEAVY_URL when using NextJS.
    url: new URL(process.env.WEAVY_URL),

    // Provide the URL to a user access token endpoint.
    // When using React Server Components, you should provide a `tokenFactory` linked directly to a server action instead.
    tokenUrl: "/api/token",

    // Provide any dependencies needed for updating the configuration
  },
  [...deps]
);

Configuration using the Weavy context provider

If you have a larger app or if you want to limit which components can use the Weavy configuration, you can use the Weavy context provider instead of a hook. The context provider is named <WyContext> and works as a standard React context provider, which you wrap around any nodes that you want to provide configuration for. Context providers are usually placed high up in the app component tree. This places the configuration in a single place with full control. Note that this configuration is only available to its children and is not available globally in the DOM. The configuration properties should be set as attributes on the component.

"use client";
import React from "react";
import { WyContext } from "@weavy/uikit-react";

export function MyWeavyContextProvider(props: React.PropsWithChildren) {
  return (
    <WyContext url={process.env.WEAVY_URL} tokenUrl={"/api/user/token"}>
      {props.children}
    </WyContext>
  );
}

10. Create a component

Now that weavy is configured you can start adding Weavy components. Here we use the <WyChat> component, but you may also use other components such as <WyComments>, <WyCopilot>, <WyFiles>, <WyMessenger> or <WyPosts>. The <WyChat> React component essentially renders a <wy-chat> web component in the DOM. See UI kit for all available components.

All Weavy components have predefined styles for optimal rendering in flex and grid layouts with predefined adaptable height and width with built-in scrolling when needed. Always try to use flexbox or grid CSS layout for the parent container where the Weavy component is placed, otherwise, you may have to specify the height of the Weavy component instead (which is not optimal). For components that feature reverse scrolling, such as <WyChat>, <WyCopilot> and <WyMessenger> it's recommended to also have a predefined height on the container and not let it grow with the content. This will enable proper reverse infinite scrolling; otherwise, all messages may load at once when the component first renders. The "use client" directive is usually required when using hooks in React Server Components.

"use client";
import React from "react";
import { useWeavy, WyChat } from "@weavy/uikit-react";

// Create a chat component with Weavy configuration.
export default function MyChat() {
  // The useWeavy hook ensures that the same Weavy instance always is used.
  // The configured Weavy instance is available to all other Weavy components as well without further configuration.
  useWeavy({
    // The URL to the Weavy environment.
    url: process.env.WEAVY_URL,

    // The URL to the user access token endpoint. This replaces the need for a full `tokenFactory` function and automatically handles communication with the user access token endpoint.
    tokenUrl: "/api/token",
  });

  // The WyChat needs a `uid` with a name that is related to where it's placed in the app.
  return <WyChat uid={"test-chat"} />;
}

Place the component anywhere in your app. You should now have a fully functional chat – send your first message and start chatting away.

11. Basic styling

To match the visual style of the Weavy components to your app, you can provide some basic styling that makes the component match your theme better.

CSS variables

You only need a few CSS variables (aka CSS custom properties) to set the overall appearance of the Weavy components to match your own theming. The CSS variables can be set on any parent node of the Weavy components. You can have globally applied CSS variables in :root or applied per-component.

To apply CSS variables as styles on React components when using TypeScript, you may need to extend the style type.

const styles: React.CSSProperties & {
  [key: `--${string}`]: string | number | undefined;
};

All CSS variables are optional. Set the ones you need to match your theme. There is no need to provide a CSS variable for the font, as the style is inherited from parent nodes.

/**
 * Component wrapper for providing theme styling to multiple components
 */
export function WeavyThemeProvider(props: React.PropsWithChildren) {
  const darkMode = true;

  // Follow the dark theme

  let className = darkMode ? "wy-dark" : "";

  // Link your theme to Weavy CSS variables

  const styles = {
    // Make the div not take up layout space in the DOM.
    display: "contents",

    /** Sets the accent color, which generates a full theme palette based on this color. Any valid CSS color. */
    "--wy-theme-color": "#00ffcc",

    /** Sets the base roundness. Any valid CSS measurement unit. */
    "--wy-border-radius": "4px",

    /** Sets the base padding. Any valid CSS measurement unit. */
    "--wy-padding": "1rem",
  };

  return (
    <div className={className} style={styles}>
      {props.children}
    </div>
  );
}

Dark mode theme

Dark mode theming of Weavy components is achieved by setting the wy-dark class on the component or any parent node in the DOM. Removing the class will revert the theme to light mode. Setting the class name on the <html> element will apply it to all Weavy components on the page. Weavy will automatically adapt the color palette, so you don't need to change the colors for dark mode unless your theme color is very different.

Additional styling

Read more about how to customize the style and appearance.

12. Troubleshooting

If things are not working as expected, check the output in the browser console. You can also ask for help in the support chat.

Next steps

This guide covered the basics to get you started.

As a next step, we suggest reading more about the UI kit components you can use.

Dive into customizing the styling of Weavy to better fit your UI.

You might also want to learn more about the Web API and how to use webhooks.

If your app is built using a specific framework or platform and you are curious about how to integrate Weavy, check out our webpage for demos and in-depth tutorials.

Support
Book a demo

To access live chat with our developer success team you need a Weavy account.

Sign in or create a Weavy account