npm package: @psu-flex/core-ui-federated-wc
Description: This package provides a collection of web components and utility functions to integrate federated brand footers, navigation links, and other content into your web applications.
Latest version: 1.3.12

# Federated Web Component Package

This package provides a collection of web components and utility functions to integrate federated brand footers, navigation links, and other content into your web applications.

Example projects can be seen below for a more in depth look:

- [React/Next.js](https://github.com/Penn-State-Web-and-Digital/psf-wc-react)
- more to come

## Features

- Federated Web Components: Reusable components built with React and exported as web components for seamless integration in various frontend projects.
- On brand themed components.
- Optional automatic data hydration

### Installation

To install the package, use the following yarn command:

```bash
yarn add @psu-flex/core-ui-federated-wc @psu-flex/wp-wc-resolver @psu-flex/wc-styles
```

## Usage

Mount the web components in a client

```jsx
'use client';
import '@psu-flex/core-ui-federated-wc';

const FederatedClient = () => {
  return null;
};

export default FederatedClient;
```

### Add resolver

Since the federated components are part of a mono repo, when importing these components as an external package, the child nested component import paths need to be resolved in projects outside the mono repo since the paths differ during the bundle phase compared to what they are in the mono repo. This can be automatically done by using the @psu-flex/wp-wc-resolver.

_The components will throw a run time error if this resolver is not included in your webpack config because the nested component paths won't be found_

#### Example in next.js

```jsx
// next.config.mjs
import CustomResolverPlugin from '@psu-flex/wp-wc-resolver';

/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack: (config) => {
    // Add the custom resolver plugin
    config.resolve.plugins = [...(config.resolve.plugins || []), new CustomResolverPlugin()];

    return config;
  },
};

export default nextConfig;
```

### Fetching Data

To fetch the federated data, the recommended approach is to cache the data on the server and pass it to the component. This takes load off PSU's vercel usage and increases your page speed.

### Available API's

- [Brand footer api](https://psu-flex-endpoints.vercel.app/api/fetchBrandFooter)
- [Brand bar api](https://psu-flex-endpoints.vercel.app/api/fetchBrandBar)
- [Header api](https://psu-flex-endpoints.vercel.app/api/fetchHeader)
- [Footer api](https://psu-flex-endpoints.vercel.app/api/fetchFooter)
- [All navigation elements api](https://psu-flex-endpoints.vercel.app/api/fetchAllFederatedData) (recommended)

#### Example of fetching data in next.js

```jsx

// fetchFederatedData.ts
export async function fetchAllFederatedData() {
  try {
    const response = await fetch(
      'https://psu-flex-endpoints.vercel.app/api/fetchAllFederatedData'
    );
    if (!response.ok) {
      throw new Error('Failed to fetch federated data');
    }
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Error fetching federated data:', error);
    return null;
  }
}

export function serializeObjects(...objects: any[]): string[] {
  return objects.map((obj) => JSON.stringify(obj));
}

...

// layout.tsx

import dynamic from 'next/dynamic';
import React from 'react';
import '../../node_modules/@psu-flex/wc-styles/dist/psf-styles.css';
import { fetchAllFederatedData, serializeObjects } from '../components/utility';
// Dynamically import the Client component, preventing it from being server-side rendered
const FederatedClient = dynamic(() => import('../components/FederatedClient'), {
  ssr: false,
});

export default async function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  const federatedData = await fetchAllFederatedData();
  const { brandFooter, brandBar, header, footer } = federatedData;
  // Example usage
  const [
    serializedBrandFooter,
    serializedBrandBar,
    serializedHeader,
    serializedFooter,
  ] = serializeObjects(
    brandFooter.linkContentCollection.items,
    brandBar,
    header,
    footer
  );

  return (
    <html lang="en">
      <body>
        <FederatedClient />
        <psf-brand-bar data={serializedBrandBar} />
        <psf-header data={serializedHeader} />
        {children}
        <psf-footer data={serializedFooter} />
        <psf-brand-footer data={serializedBrandFooter} />
      </body>
    </html>
  );
}


```