Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/kitchen-sink-vite/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
public/
33 changes: 33 additions & 0 deletions examples/kitchen-sink-vite/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Kitchen Sink

This example demonstrates all the pieces of Page Kit working together. It is intended to be used as a testbed for the Page Kit team to find out how packages should be composed together and try out the interfaces between them.

### Running the app

First run build at the root of the app to pick up the changes and the compiling of shared packages

```bash
npm run build
```

To start the example app enter this directory:

```bash
cd examples/kitchen-sink
```

To build the example app:

```bash
npm run build
```

Then start the app by running:

```bash
npm start
#or
npm run dev
```

Finally open `http://localhost:3456/` in your browser.
32 changes: 32 additions & 0 deletions examples/kitchen-sink-vite/__test__/build.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const fs = require('fs')

describe('examples/kitchen-sink/build', () => {
it('creates the expected JS, CSS, and manifest files', () => {
const output = fs.readdirSync('./public')
expect(output).toMatchInlineSnapshot(`
[
"assets-manifest.json",
"async.css",
"financial-times-n-tracking.bundle.js",
"financial-times-o-footer.bundle.js",
"financial-times-o-grid.bundle.js",
"financial-times-o-header.bundle.js",
"financial-times-o-private-foundation.bundle.js",
"financial-times-o-toggle.bundle.js",
"financial-times-o-tracking.bundle.js",
"financial-times-o-utils.bundle.js",
"financial-times-o-viewport.bundle.js",
"page-kit-components.bundle.js",
"page-kit-layout-styles.css",
"preact.bundle.js",
"privacy-components.bundle.js",
"scripts.bundle.js",
"shared.stable.bundle.js",
"styles.css",
"vendors.bundle.js",
"vendors.css",
"webpack-runtime.bundle.js",
]
`)
})
})
62 changes: 62 additions & 0 deletions examples/kitchen-sink-vite/__test__/integration.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
const app = require('../server/app')
const request = require('supertest')

describe('examples/kitchen-sink/integration', () => {
let response

beforeEach(async () => {
response = await request(app)
.get('/')
// NOTE: FT.com apps expect many headers to be set by the CDN+preflight and/or the router.
.set({
'ft-edition': 'international'
})
})

it('returns an OK response', () => {
expect(response.statusCode).toBe(200)
})

it('renders the Financial Times Header Logo as a link', () => {
expect(response.text).toContain('data-trackable="logo" href="/"')
})

it('renders the header top components; search and menu', () => {
expect(response.text).toContain('data-trackable="search-toggle">')
expect(response.text).toContain('data-trackable="drawer-toggle"')
})

it('populates navigation elements with navigation data', () => {
expect(response.text).toContain('data-trackable="Home"')
expect(response.text).toContain('data-trackable="World"')
expect(response.text).toContain('data-trackable="Markets"')
})

it('populates drawer elements with navigation data', () => {
expect(response.text).toContain('o-header__drawer-menu--primary')
expect(response.text).toContain('o-header__drawer-menu--user')
})

it('populates meganav elements with navigation data', () => {
expect(response.text).toContain('data-trackable="meganav | World"')
expect(response.text).toContain('data-trackable="meganav | Markets"')
expect(response.text).toContain('data-trackable="meganav | Opinion"')
expect(response.text).toContain('o-header__mega-heading')
expect(response.text).toContain('o-header__mega-content')
expect(response.text).toContain('o-header__mega-item')
})

it('renders edition with current edition selected', () => {
expect(response.text).toContain(
'<span class="o-header__drawer-menu-item o-header__drawer-current-edition">International</span>'
)
})

it('renders app context data as embedded JSON', () => {
expect(response.text).toContain('<script type="application/json" id="page-kit-app-context">')
})

it('renders data embed data as embedded JSON', () => {
expect(response.text).toContain('<script type="application/json" id="data-embed">')
})
})
8 changes: 8 additions & 0 deletions examples/kitchen-sink-vite/client/async.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// This stylesheet is loaded asynchonously; that is, it doesn't block the browser from rendering while it loads.
// See: href="https://github.com/Financial-Times/dotcom-page-kit/blob/HEAD/packages/dotcom-ui-shell/README.md

.asynchronous-example {
font-size: medium;
border: 1px solid lightgrey;
margin: 20px;
}
80 changes: 80 additions & 0 deletions examples/kitchen-sink-vite/client/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import readyState from 'ready-state'
import * as flags from '@financial-times/dotcom-ui-flags/src/client'
import * as layout from '@financial-times/dotcom-ui-layout'
import { init as initAppContent } from '@financial-times/dotcom-ui-app-context/src/client/browser'
import { displayAds, getAdsData, adsUtils } from '@financial-times/ads-display'
import * as dataEmbed from '@financial-times/dotcom-ui-data-embed'
import * as tracking from '@financial-times/n-tracking'

import { DATA_EMBED_ID } from '../constants.js'

readyState.domready.then(async () => {
const flagsClient = flags.init()
const appContextClient = initAppContent()
const dataEmbedClient = dataEmbed.init({ id: DATA_EMBED_ID })

console.log('Shared data', dataEmbedClient.getAll()) // eslint-disable-line no-console

layout.init()

tracking.init({ appContext: appContextClient.getAll() })

if (flagsClient.get('ads')) {
/**
* Make context-specific adjustments here
* e.g. checking whether an article is being previewed:
* sandbox: /\/preview/.test(location.pathname);
*/
const rootId = adsUtils.getRootID()
const displayAdsOptions = {
sandbox: true, // in this demo context, always sandbox ads
appName: appContextClient.get('appName'),
abTestState: appContextClient.get('abTestState'),
rootId,
disableMonitoring: false,
lazyLoadMargins: {
760: '15%',
980: '5%'
}
}

// Fetch the ads data
try {
const adsData = await getAdsData({
user: true,
page: {
type: 'article',
id: appContextClient.get('contentId')
}
})
displayAds.init(
{
...displayAdsOptions,
targeting: adsData.metadata,
adUnit: adsData.adUnit
},
flagsClient
)

if (flagsClient.get('AdsPermutive')) {
adsUtils.enablePermutiveFtCom({
metadata: adsData.metadata,
type: appContextClient.get('appName'),
rootId
})
}
} catch (err) {
// eslint-disable-next-line no-console
console.warn(
'There was an error fetching the ads data. Loading basic permutive and ads without targeting or ad unit',
err
)

displayAds.init(displayAdsOptions, flagsClient)
adsUtils.enablePermutiveFtCom({
type: appContextClient.get('appName'),
rootId
})
}
}
})
17 changes: 17 additions & 0 deletions examples/kitchen-sink-vite/client/main.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@import '@financial-times/o3-foundation/css/core.css';

@media (min-width: 76.25em){
.content {

line-height: var(--o3-type-body-lg-line-height);
font-size: var(--o3-type-body-lg-font-size);
font-family: var(--o3-type-body-lg-font-family);
font-weight: var(--o3-type-body-lg-font-weight);
max-width: 1220px;
margin: auto;
h3, p {
padding-left: 20px;
padding-right: 20px;
}
}
}
1 change: 1 addition & 0 deletions examples/kitchen-sink-vite/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const DATA_EMBED_ID = 'data-embed'
47 changes: 47 additions & 0 deletions examples/kitchen-sink-vite/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "example-kitchen-sink-vite",
"private": true,
"version": "0.0.0",
"license": "MIT",
"scripts": {
"build": "vite build",
"dev": "nodemon start.js",
"start": "node start.js",
"pretest": "npm run build",
"test": "../../node_modules/.bin/jest",
"test:ci": "../../node_modules/.bin/jest --runInBand --forceExit"
},
"dependencies": {
"@financial-times/ads-display": "^6.5.0",
"@financial-times/dotcom-middleware-app-context": "file:../../packages/dotcom-middleware-app-context",
"@financial-times/dotcom-middleware-asset-loader": "file:../../packages/dotcom-middleware-asset-loader",
"@financial-times/dotcom-middleware-navigation": "file:../../packages/dotcom-middleware-navigation",
"@financial-times/dotcom-ui-app-context": "file:../../packages/dotcom-ui-app-context",
"@financial-times/dotcom-ui-data-embed": "file:../../packages/dotcom-ui-data-embed",
"@financial-times/dotcom-ui-flags": "file:../../packages/dotcom-ui-flags",
"@financial-times/dotcom-ui-layout": "file:../../packages/dotcom-ui-layout",
"@financial-times/dotcom-ui-shell": "file:../../packages/dotcom-ui-shell",
"@financial-times/n-tracking": "7.2.1",
"express": "^4.21.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"sucrase": "^3.35.0"
},
"devDependencies": {
"@financial-times/dotcom-build-base": "file:../../packages/dotcom-build-base",
"@financial-times/dotcom-build-code-splitting": "file:../../packages/dotcom-build-code-splitting",
"@financial-times/dotcom-build-js": "file:../../packages/dotcom-build-js",
"@financial-times/dotcom-build-sass": "file:../../packages/dotcom-build-sass",
"@sucrase/jest-plugin": "^2.0.0",
"nodemon": "^1.18.9",
"ready-state": "^2.0.5",
"vite": "^8.0.8",
"webpack": "^5.88.2",
"webpack-cli": "^5.1.4"
},
"jest": {
"transform": {
".(js|jsx)": "@sucrase/jest-plugin"
}
}
}
26 changes: 26 additions & 0 deletions examples/kitchen-sink-vite/server/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const express = require('express')
const navigation = require('@financial-times/dotcom-middleware-navigation')
const appContext = require('@financial-times/dotcom-middleware-app-context')
const assets = require('@financial-times/dotcom-middleware-asset-loader')

const app = express()

app.use(
navigation.init(),
assets.init({ hostStaticAssets: true }),
appContext.init({
appContext: {
appName: 'Kitchen Sink'
}
})
)

// Embed custom data into every view
app.use((request, response, next) => {
response.locals.embeddedData = { foo: true, bar: 'qux' }
next()
})

app.get('/', require('./controllers/home'))

module.exports = app
Loading
Loading