# Header MFE (`@nuskin/nextgen-header`)

This repository produces **two** deployables:

1. **Module Federation app** — Webpack builds `remoteEntry` and static assets for CDN/S3 (via GitLab `static-client-app` pipeline). Host apps load the remote as `header_mfe` / `./App`.
2. **npm package** — `yarn build:package` emits `package-dist/` for **`@nuskin/nextgen-header`** on npmjs (via GitLab `npm-module-ci` release / pre-release jobs).

The UI is intentionally minimal (`HeaderPlaceholder`). Replace it when navigation, Contentstack types, and analytics are defined.

## Domain language (header UI)

Shared vocabulary for Nu Skin header work—use these names in code, docs, and Contentstack discussions so everyone means the same region of the UI.

![Domain language diagram for the Nu Skin header](docs/header-domain-language.png)

| Term | Description |
|------|-------------|
| **Logo** | Brand mark (e.g. NU SKIN), top-left. |
| **Utility bar** | Top-right strip: currency / language, Nu Skin Rewards, account (Sign Up / Sign In), cart with badge. |
| **Search bar** | Product search field (e.g. “Product Search”). Kept **separate from the utility bar** so future features can be added between or around them without coupling. |
| **Top navigation** | Primary horizontal category row under the logo (e.g. Devices, Beauty & Skincare, Health & Wellness). |
| **Jump to** | Left column in the expanded mega-menu: quick links (e.g. Most Popular, Science, Kits & Bundles). |
| **Categories** | Horizontal row inside the mega-menu that expresses the active hierarchy (e.g. Skincare → Concerns → Key ingredients). |
| **Sub categories** | Vertical link lists under each **Categories** heading (e.g. Anti-Aging, Lines & Wrinkles, Dry Skin under Concerns). |

## Prerequisites

- **Node.js 24+** (see `engines` in `package.json` and `.nvmrc` for `nvm` / `fnm`)
- Yarn
- Contentstack stack credentials (for real API calls)

## Install (monorepo / local development)

```bash
yarn install
```

## NPM library (`@nuskin/nextgen-header`)

Install in a host application that already provides the peer dependencies (React 18, Emotion, Contentstack SDKs):

```bash
yarn add @nuskin/nextgen-header
```

**Public export** (see [`src/library/index.js`](src/library/index.js)):

| Export | Description |
|--------|-------------|
| **`Header`** | **`AppContainer`** styling plus **market/language** resolution (browser URL or explicit props; SSR via **`requestUrl`** in **`renderAndExtractContext`**). Renders the header placeholder inside. |

**Example**

```jsx
import { Header } from "@nuskin/nextgen-header";
import "@nuskin/nextgen-header/index.css";

// CSR: optional market/language; SSR: pass props or wire `requestUrl` in `renderAndExtractContext`.
<Header />
<Header market="US" language="en" />
```

- **Exports** are defined in [`src/library/index.js`](src/library/index.js) (barrel for the published API).
- **Types** ship as [`src/library/index.d.ts`](src/library/index.d.ts) (copied to `package-dist/index.d.ts` on build).
- **Styles**: the library build emits Emotion-related CSS under `package-dist/index.css`; import `@nuskin/nextgen-header/index.css` (see `package.json` `exports["./index.css"]`).

**Build the tarball locally**

```bash
yarn build:package
```

**Publish** (GitLab **release** / **pre-release** jobs run `yarn build:package` in `before_script` before publish; align with your org’s versioning and `yarn npm publish` / tags. For a local publish, run `yarn build:package` first.)

### Peer dependencies

Declared in `package.json` under `peerDependencies`: `react`, `react-dom`, `prop-types`, `@emotion/react`, `@emotion/styled`, Contentstack packages, and `contentstack`. Your app must install compatible versions.

## Environment variables

For the **webpack / MFE** build, dotenv files are loaded per build via `CMS_ENV` (see `package.json` scripts): `.env.local`, `.env.dev`, `.env.test`, `.env.prod`. The **npm library** does not expose these values on its public API; consumers still configure the usual `CONTENTSTACK_*` variables in their own environment so internal Contentstack helpers can run.

### MFE / webpack (`CMS_ENV`)

| Variable | Purpose |
|----------|---------|
| `CONTENTSTACK_API_KEY` | Stack API key |
| `CONTENTSTACK_DELIVERY_TOKEN` | Delivery token |
| `CONTENTSTACK_ENVIRONMENT` | Environment name |
| `CONTENTSTACK_PREVIEW_TOKEN` | Preview token (Visual Builder / live preview) |
| `REACT_APP_GTM_KEY` | Optional; used by `src/utils/datalayer.js` if present |

`REACT_APP_BASENAME` is injected at build time from the client webpack config (static asset path segment).

## Scripts

| Command | Description |
|---------|-------------|
| `yarn start` | On each `src/` change: runs **`yarn build:local`** (MFE client + server webpack + **Storybook** static → `dist/storybook/`), then starts the Express server (`server-launcher.js`) |
| `yarn build` | Same as **`yarn build:local`** |
| `yarn build:local` | Client + server **webpack** in **development** mode with `CMS_ENV=local`, then **Storybook** static output to `dist/storybook/` (alongside MF assets under `dist/`). **`yarn start`** runs this on each rebuild. Use **`yarn build-prod`** for production mode + minification (**Storybook is not** included on `build-prod`). |
| `yarn build:package` | **Library** build to `package-dist/` via [`config/webpack.library.js`](config/webpack.library.js) (dual CJS/ESM + extracted CSS + copied `index.d.ts`); required before `npm publish` |
| `yarn build-storybook` | Storybook static build → **`dist/storybook/`** (included in **`yarn build:local`** / **`yarn start`**; use `CI=true` in automation to avoid interactive prompts) |
| `yarn test` | Jest + coverage |
| `yarn lint` | ESLint on `src/` |

## Storybook

Storybook in this repo is used to develop and review isolated UI components for both the shared component library and header/top-navigation work.

### What is covered

- **Header view and regions** stories under `src/header/components/`
- **Shared UI components** stories under `src/components/` (for example tabs, top-navigation, jump-to, sub-category, and label-icon)
- **Component states and variants** for visual QA and interaction checks without running the full MFE shell

### How to run and build

- **Dev flow:** run `yarn start`, then open `http://localhost:3000/storybook/`
- **preproduction environments:** open https://dev.nuskin.com/static/header-mfe/storybook/ or https://test.nuskin.com/static/header-mfe/storybook/
- **production environments:** STORYBOOK IS NOT INCLUDED IN PRODUCTION BUILDS

### Notes for CI and deploys

- Storybook is intended for local/non-prod review workflows.
- `build-prod` does not include Storybook output.
- Keep `dist/storybook/` out of production CDN/static deploy targets

## Host integration (Module Federation)

| Item | Value |
|------|--------|
| Remote / global name | `header_mfe` (`globalThis['header_mfe']` on the server remote) |
| Static public path | `/static/header-mfe/` |
| Exposed module | `./App` only |

The host must load `remoteEntry.js` and consume the `./App` expose.

**Locale:** The npm **`Header`** export accepts **`market`** / **`language`** (see [`src/utils/locale.js`](src/utils/locale.js) `resolveHeaderLocale`). On **SSR**, pass them explicitly or rely on Express passing **`requestUrl`** into **`renderAndExtractContext`**. On **CSR**, they are optional; URL parsing **throws** if `window` is missing or the path is invalid. The header does not ship React Router; the host owns routing.

## Contentstack

- `src/utils/contentstack.js` — stack proxy, `getContent`, `initLivePreview`, `onEntryChange`, `isEditingMode`
- `src/utils/config.js` — `getStackConfig()` returns a fixed header content type (internal to that module) and locale from the URL
- `src/constants.js` — Contentstack credentials from env (used by the webpack/MFE build and internally by `contentstack.js`; not exported from the npm package)

The **npm library** currently exports only **`Header`** (the `Main` shell under that name); Contentstack helpers are not part of the published API yet. Header UI data is loaded from mock **`Header*Service`** modules until real `getContent` wiring; replace **`HEADER_CONTENT_ENTRY_UID`** in [`src/header/constants.js`](src/header/constants.js) when the slug/UID strategy is decided.

## Header scaffold (`src/header/`)

- **`HeaderView`** — header regions; receives each **`header*Service`** as its own prop. Each region calls async **`get*`** methods on its service (for example **`getLogoCopy`**, **`getNavigationTree`**) in **`useEffect`**, then renders; placeholders show until copy resolves. Click/search handlers still call the same service methods.
- **`HeaderContainer`** — resolves locale, builds default **`services`** (or uses injected **`services`**) with **`createHeader*Service`**, and passes each service into **`HeaderView`** as explicit props. Server **`renderAndExtractContext`** does not preload header data yet; SSR markup includes the header shell with per-region loading placeholders until real SSR hydration or client fetch completes.
- **`src/header/constants.js`** — `HEADER_CONTENT_ENTRY_UID` placeholder with **TODO** until the real Contentstack entry UID exists.
- **Storybook** — [`src/header/components/HeaderView.stories.jsx`](src/header/components/HeaderView.stories.jsx); config under [`.storybook/`](.storybook/). After **`yarn start`** or **`yarn build:local`**, open **`dist/storybook/index.html`** (or serve **`dist/storybook/`**). For a live dev server with HMR on port 6006: `cross-env SB_DISABLE_TELEMETRY=1 npx storybook dev -p 6006`.

**TODO:** Exclude **`dist/storybook/`** from production CDN / static deploy when tightening the pipeline (Storybook is for local dev and non-prod review).

## GitLab CI

- **`npm-module-ci.yml`** — release / pre-release publish to npmjs (`PRIVATE_NPM: "false"`); runs `yarn build:package` before publish.
- **`static-client-app.yml`** — static MFE deploy; `APP_NAME` / `CONTENT_TYPE_UID` are set for that pipeline.

## Local HTTPS / Storefront

If your team still integrates with Storefront UI over HTTPS and a hosts file entry (e.g. `local.nuskin.com`), align URLs and micro-frontend resolution with that app’s documentation. This repo does not ship Storefront config.

## License

ISC
