+
+ {isWeb && (
+ <>
+
+
+ >
+ )}
+
+
+
+ {isWeb && (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+ {darkModeAvailable && (
+
+ Dark mode is a work-in-progress.
+
+ You can{' '}
+
+ opt out anytime
+ {' '}
+ if anything is unreadable or odd.
+
+ )}
+ >
+ )}
+ {/* layout */}
+ {isWeb && (
+
+ {renderAds && (
+
+
+
+ )}
+
+
+
+ )}
+ {isWeb && renderAds && config.hasSurveyAd && (
+
+ )}
+
+ Hello DCAR Sites shell!
+
+ {isWeb && (
+ <>
+ {props.nav.subNavSections && (
+
+ )}
+
+
+
+
+
+
+
+ >
+ )}
+ {isApps && (
+ <>
+ Coming soon. Thanks for dropping by.
+ >
+ )}
+
+ );
+};
diff --git a/dotcom-rendering/src/frontend/feShell.ts b/dotcom-rendering/src/frontend/feShell.ts
new file mode 100644
index 00000000000..25c82ea363b
--- /dev/null
+++ b/dotcom-rendering/src/frontend/feShell.ts
@@ -0,0 +1,16 @@
+import type { EditionId } from '../lib/edition';
+import type { ConfigType } from '../types/config';
+import type { FooterType } from '../types/footer';
+import type { FENavType } from '../types/frontend';
+
+export type FEShell = {
+ canonicalUrl: string;
+ config: ConfigType;
+ contributionsServiceUrl: string;
+ editionId: EditionId;
+ guardianBaseURL: string;
+ isAdFreeUser: boolean;
+ nav: FENavType;
+ pageFooter: FooterType;
+ pageId: string;
+};
diff --git a/dotcom-rendering/src/frontend/schemas/feShell.json b/dotcom-rendering/src/frontend/schemas/feShell.json
new file mode 100644
index 00000000000..fb1955ed46d
--- /dev/null
+++ b/dotcom-rendering/src/frontend/schemas/feShell.json
@@ -0,0 +1,858 @@
+{
+ "type": "object",
+ "properties": {
+ "canonicalUrl": {
+ "type": "string"
+ },
+ "config": {
+ "$ref": "#/definitions/ConfigType"
+ },
+ "contributionsServiceUrl": {
+ "type": "string"
+ },
+ "editionId": {
+ "$ref": "#/definitions/EditionId"
+ },
+ "guardianBaseURL": {
+ "type": "string"
+ },
+ "isAdFreeUser": {
+ "type": "boolean"
+ },
+ "nav": {
+ "$ref": "#/definitions/FENavType"
+ },
+ "pageFooter": {
+ "$ref": "#/definitions/FooterType"
+ },
+ "pageId": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "canonicalUrl",
+ "config",
+ "contributionsServiceUrl",
+ "editionId",
+ "guardianBaseURL",
+ "isAdFreeUser",
+ "nav",
+ "pageFooter",
+ "pageId"
+ ],
+ "definitions": {
+ "ConfigType": {
+ "description": "the config model will contain useful app/site\nlevel data. Although currently derived from the config model\nconstructed in frontend and passed to dotcom-rendering\nthis data could eventually be defined in dotcom-rendering",
+ "type": "object",
+ "properties": {
+ "abTests": {
+ "description": "Narrowest representation of the server-side tests\nobject shape, which is [defined in `frontend`](https://github.com/guardian/frontend/blob/23743723030a041e4f4f59fa265ee2be0bb51825/common/app/experiments/ExperimentsDefinition.scala#L24-L26).\n\n**Note:** This type is not support by JSON-schema, it evaluates as `object`",
+ "type": "object"
+ },
+ "adUnit": {
+ "type": "string"
+ },
+ "ajaxUrl": {
+ "type": "string"
+ },
+ "brazeApiKey": {
+ "type": "string"
+ },
+ "commercialBundleUrl": {
+ "type": "string"
+ },
+ "dcrCouldRender": {
+ "type": "boolean"
+ },
+ "dcrSentryDsn": {
+ "type": "string"
+ },
+ "dfpAccountId": {
+ "type": "string"
+ },
+ "discussionApiClientHeader": {
+ "type": "string"
+ },
+ "discussionApiUrl": {
+ "type": "string"
+ },
+ "discussionD2Uid": {
+ "type": "string"
+ },
+ "edition": {
+ "$ref": "#/definitions/EditionId"
+ },
+ "frontendAssetsFullURL": {
+ "type": "string"
+ },
+ "googleRecaptchaSiteKey": {
+ "type": "string"
+ },
+ "googleRecaptchaSiteKeyVisible": {
+ "type": "string"
+ },
+ "googletagUrl": {
+ "type": "string"
+ },
+ "hasPageSkin": {
+ "type": "boolean"
+ },
+ "host": {
+ "type": "string"
+ },
+ "idApiUrl": {
+ "type": "string"
+ },
+ "idUrl": {
+ "type": "string"
+ },
+ "ipsosTag": {
+ "type": "string"
+ },
+ "isDev": {
+ "type": "boolean"
+ },
+ "isLive": {
+ "type": "boolean"
+ },
+ "isLiveBlog": {
+ "type": "boolean"
+ },
+ "isPaidContent": {
+ "type": "boolean"
+ },
+ "isPhotoEssay": {
+ "type": "boolean"
+ },
+ "isPreview": {
+ "type": "boolean"
+ },
+ "isSensitive": {
+ "type": "boolean"
+ },
+ "keywordIds": {
+ "type": "string"
+ },
+ "mmaUrl": {
+ "type": "string"
+ },
+ "references": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ }
+ }
+ },
+ "revisionNumber": {
+ "type": "string"
+ },
+ "section": {
+ "type": "string"
+ },
+ "sentryHost": {
+ "type": "string"
+ },
+ "sentryPublicApiKey": {
+ "type": "string"
+ },
+ "serverSideABTests": {
+ "$ref": "#/definitions/Record