# @newskit-render/core

А template website built using the React framework Next.js.

This package is used by [@newskit-render/create-render-app](https://www.npmjs.com/package/@newskit-render/create-render-app) as a template structure to scaffold the newly created project which the users of @newskit-render/create-render-app can use and modify for their purposes.

## Running

To get the data used by the website, you will first need to add a `.env.local` file with the following keys:

```sh
NEWSKIT_API_ENV_URL=""
NEWSKIT_API_X_API_KEY=""
```

```
yarn start
```

or with npm

```
npm start
```

## Rquired Environment Variables

In order to run the application, we need the following required environment variables.

```
NEWSKIT_API_ENV_URL=""
NEWSKIT_API_X_API_KEY=""
OKTA_CLIENT_ID=""
OKTA_CLIENT_SECRET=""
OKTA_DOMAIN=""
PUBLISHER=""
```

## Endpoints

GET /api/recommendations - Returns a list on recommendations articles based on the recommendations slug.The recommendations slug is provided be the query param `articleId`.Also accepts a `userId` which allows us to fetch personalised recommendations.

## Ads Library

Reach out to the Commercial team to discuss the ad slots names and to get a custom `ads.min.js` file which should be placed in the public directory / or the url to file on their CDN.

More information on the names of the slots can be found here: `https://nidigitalsolutions.jira.com/wiki/spaces/COMM/pages/2370339149/Naming+convention+for+Ad+slots`

The ad slots should be placed as an id propery of the component.

In order to test ads locally you should enable SourcePoint integration and add a new entry on your host file,
e.g. 127.0.0.1 newskit.render.

```
sudo nano /etc/hosts
```

After that you will be able to see them on your custom site domain (for example `newskit.render:3000`) instead of `localhost:3000`.

## 3rd Party Integrations supported

If you have enabled integrations during the generation process, make sure to add the following keys in your `.env.local` file.

### SourcePoint

```sh
SOURCEPOINT_ACCOUNT_ID=""
SOURCEPOINT_PROPERTY_HREF=""
```

### OptimizelyWeb

```sh
EXPERIMENTATION_WEB=""
```

### Tealium

```sh
TEALIUM_ACCOUNT_ID=""
TEALIUM_PROFILE_ID=""
TEALIUM_ENV=""
```

## Contract testing

We use [Pact](https://docs.pact.io/) to run consumer and provider contract tests.

Contract tests are run against a mocked service. The service address is configurable and runs by default on localhost:4343. If you want to change it just update NEWSKIT_API_ENV_URL in the pact:test script. Keep in mind that if you change the port, you will also need to update jest.config.pact.js with the same port.

You can run the contract tests by executing:

```sh
npm run pact:test
```

In order to publish the contracts from your local machine to the Pact Broker you need to add to the following keys to `.env.local`

```sh
PACT_BROKER_URL=""
PACT_BROKER_TOKEN=""
```

In order to publish the contracts you need to execute:

```sh
npm run pact:publish
```

## Multi-tenant application

A multi-tenant application allows you to run an application from various (sub-)domains and show different content depending on the domain that is used.

This means that the titles would be able to load different brands' content and themes, while running the same application. The codebase will be the same across all brands.

### Getting started

How to configure your application for multitenancy

1. If you want to build a project from scratch, that will have everything from newskit-render, you need to run `create-render-app` (See [Newskit-Render Getting started](https://github.com/newscorp-ghfb/ncu-newskit-render#getting-started)).

When creating a new project a question whether you'd like your application to be multi tenant will prompt in the terminal.

2. If you already have a Next application and you want to make it multi-tenant you need to add the following files:

In config folder: `config/multiTenancy.ts`:

```
import { sharedTheme, timesTheme } from '@newskit-render/shared-components'
import { Publisher } from '@newskit-render/api'
import { demoStrings, timesStrings } from '../theme/strings'

export const translationsMap = {
  [Publisher.DEMO]: demoStrings,
  [Publisher.TIMES]: timesStrings,
}

export const themesMap = {
  [Publisher.DEMO]: sharedTheme,
  [Publisher.TIMES]: timesTheme,
}
```

- `translationsMap` is used for re-mapping variables like site title, or any other string for each brand. Example:

```
export const demoStrings = {
    title: 'Demo Site'
}

export const timesStrings = {
    title: 'Times Site'
}
```

- `themesMap` is used for mapping the theme for each brand.
  Brand names live in the `PUBLISHER` object

In context folder `context/multi-tenancy`
Add a multi-tenancy context that will keep the current tenant:

```
import React, { createContext, useContext } from 'react'
import get from 'lodash.get'
import { Publisher } from '@newskit-render/api'
import { translationsMap } from '../../config'

export interface MultiTenancyContextProps {
  tenant?: Publisher
  getTenantString?: (key: string, defaultValue?: string) => string
}

const MultiTenancyContext = createContext<MultiTenancyContextProps>({})

const MultiTenancyProvider: React.FC<MultiTenancyContextProps> = ({
  tenant,
  children,
}) => (
  <MultiTenancyContext.Provider
    value={{
      tenant,
      getTenantString: (key: string, defaultValue: string = ''): string => {
        const data = translationsMap[tenant]
        return get(data, key, defaultValue)
      },
    }}
  >
    {children}
  </MultiTenancyContext.Provider>
)

export const useMultiTenancy = () => useContext(MultiTenancyContext)
export default MultiTenancyProvider
```

Now you need to update `_app.js`. To pass the tenant to the app, you need to wrap it in `MultitenancyProvide`:

```
interface MyAppProps extends AppProps {
  tenant: Publisher
}

function MyApp({ Component, pageProps, tenant }: MyAppProps) {
  return (
    <MultiTenancyProvider tenant={tenant}>
      <AppContextProvider>
	    ………
      </AppContextProvider>
    </MultiTenancyProvider>
  )
}

export default MyApp
```

Then call the `getTenant()` helper function in `getInitialProps()`. This function extracts the brands' hostname ( domain name ) from the request headers and then we save the tenant in the context provider:

```
MyApp.getInitialProps = async ({ Component, ctx }: AppContextType) => {
  let pageProps = {}
  const tenant = getTenant(ctx.req?.headers?.host as string)

  if (Component.getInitialProps) {
    pageProps = await Component.getInitialProps(ctx)
  }
  return { pageProps, tenant }
}
```

### How to set the theme for each tenant

You can use the `useMultiTenancy` hook anywhere in the code to get the current tenant

In `context/app-context.js`:

```
const AppContext = React.createContext({
  theme: sharedTheme,
} as AppContextType)

const AppContextProvider = ({ children }: { children: JSX.Element }) => {
  const { tenant } = useMultiTenancy()
  const tenantTheme = themesMap[tenant]
  const [theme, setTheme] = useState(tenantTheme)

  return (
    <AppContext.Provider value={{ theme, setTheme }}>
      {children}
    </AppContext.Provider>
  )
}

export { AppContextProvider, AppContext }
```

### cra-effected comments

You may see some lines of code that have comments next to them:

```
code here. /* cra-effected */
```

Or around them:

```
/* start cra-effected */
code here.
/* end cra-effected */
```

This comment denotes that the line or lines in between are effected by the running of the [@newskit-render/create-render-app package](https://github.com/newscorp-ghfb/ncu-newskit-render/tree/master/packages/create-render-app).

If you are touching / modifiying code with these comments you need to be aware that you may affect the successful running of the [@newskit-render/create-render-app package](https://github.com/newscorp-ghfb/ncu-newskit-render/tree/master/packages/create-render-app)
