diff --git a/ab-testing/config/abTests.ts b/ab-testing/config/abTests.ts
index d795763977a..fd162b1f6ab 100644
--- a/ab-testing/config/abTests.ts
+++ b/ab-testing/config/abTests.ts
@@ -107,6 +107,19 @@ const ABTests: ABTest[] = [
groups: ["control"],
shouldForceMetricsCollection: false,
},
+ {
+ name: "fronts-and-curation-slim-homepage",
+ description:
+ "Test placing the Most Viewed and Deeply Read components in the right-hand column on the homepage.",
+ owners: ["fronts.and.curation@guardian.co.uk"],
+ status: "OFF",
+ expirationDate: `2026-04-28`,
+ type: "server",
+ audienceSize: 0 / 100,
+ audienceSpace: "A",
+ groups: ["control", "variant"],
+ shouldForceMetricsCollection: false,
+ },
{
name: "growth-holdback-group",
description:
diff --git a/dotcom-rendering/src/components/LinkHeadline.tsx b/dotcom-rendering/src/components/LinkHeadline.tsx
index 8bcb4089cbd..8feaac3c670 100644
--- a/dotcom-rendering/src/components/LinkHeadline.tsx
+++ b/dotcom-rendering/src/components/LinkHeadline.tsx
@@ -5,6 +5,7 @@ import {
headlineMedium20,
headlineMedium24,
headlineMedium28,
+ textSans15,
textSans17,
textSans20,
textSans24,
@@ -33,9 +34,23 @@ type Props = {
size?: SmallHeadlineSize;
link?: HeadlineLink; // An optional link object configures if/how the component renders an anchor tag
byline?: string;
+ /**
+ * This headline is being used on the right-hand side of a front in a most popular container,
+ * either Most Viewed or Deeply Read, as part of the Slim Homepage AB test.
+ */
+ isInSlimHomepageAbTest?: boolean;
};
-const fontStyles = (size: SmallHeadlineSize) => {
+const fontStyles = (
+ size: SmallHeadlineSize,
+ isInSlimHomepageAbTest: boolean,
+) => {
+ if (isInSlimHomepageAbTest) {
+ return css`
+ ${textSans15};
+ `;
+ }
+
switch (size) {
case 'ginormous':
case 'huge':
@@ -124,9 +139,10 @@ export const LinkHeadline = ({
size = 'medium',
link,
byline,
+ isInSlimHomepageAbTest = false,
}: Props) => {
return (
-
+
{!!kickerText && (
@@ -175,7 +191,7 @@ export const LinkHeadline = ({
fontStyles={
isLabs
? bylineLabsStyles(size)
- : fontStyles(size)
+ : fontStyles(size, isInSlimHomepageAbTest)
}
text={byline}
/>
diff --git a/dotcom-rendering/src/components/MostPopularFrontRight.stories.tsx b/dotcom-rendering/src/components/MostPopularFrontRight.stories.tsx
new file mode 100644
index 00000000000..5beec8cf891
--- /dev/null
+++ b/dotcom-rendering/src/components/MostPopularFrontRight.stories.tsx
@@ -0,0 +1,29 @@
+import type { Meta, StoryObj } from '@storybook/react-webpack5';
+import { rightColumnDecorator } from '../../.storybook/decorators/gridDecorators';
+import { trails } from '../../fixtures/manual/trails';
+import { MostPopularFrontRight } from './MostPopularFrontRight';
+
+const meta = {
+ component: MostPopularFrontRight,
+ title: 'Components/MostPopularFrontRight',
+ decorators: [rightColumnDecorator],
+ render: (args) => ,
+} satisfies Meta;
+
+export default meta;
+
+type Story = StoryObj;
+
+export const MostViewed = {
+ args: {
+ heading: 'Most viewed',
+ trails: trails.slice(0, 10),
+ },
+} satisfies Story;
+
+export const DeeplyRead = {
+ args: {
+ heading: 'Deeply read',
+ trails: trails.slice(10, 20),
+ },
+} satisfies Story;
diff --git a/dotcom-rendering/src/components/MostPopularFrontRight.tsx b/dotcom-rendering/src/components/MostPopularFrontRight.tsx
new file mode 100644
index 00000000000..a05da13bac3
--- /dev/null
+++ b/dotcom-rendering/src/components/MostPopularFrontRight.tsx
@@ -0,0 +1,153 @@
+import { css } from '@emotion/react';
+import {
+ headlineBold24,
+ space,
+ textSans15,
+} from '@guardian/source/foundations';
+import { ArticleDesign, ArticleSpecial } from '../lib/articleFormat';
+import { palette as schemePalette } from '../palette';
+import type { TrailType } from '../types/trails';
+import { AgeWarning } from './AgeWarning';
+import { BigNumber } from './BigNumber';
+import { FormatBoundary } from './FormatBoundary';
+import { LinkHeadline } from './LinkHeadline';
+
+const containerStyles = css`
+ padding-top: ${space[2]}px;
+ display: flex;
+ flex-direction: column;
+ gap: ${space[8]}px;
+`;
+
+const headingStyles = css`
+ padding-left: 80px;
+ ${headlineBold24};
+ color: ${schemePalette('--slim-homepage-most-viewed-header')};
+ overflow-wrap: break-word;
+`;
+
+const gridItem = css`
+ position: relative;
+ border-top: 1px solid ${schemePalette('--article-section-border')};
+ min-height: 52px;
+
+ &:hover {
+ cursor: pointer;
+ }
+
+ &:hover,
+ :focus {
+ background: ${schemePalette('--most-viewed-footer-hover')};
+ }
+`;
+
+const bigNumber = css`
+ position: absolute;
+ top: 6px;
+ left: 10px;
+ fill: ${schemePalette('--slim-homepage-most-viewed-big-number')};
+ svg {
+ height: 40px;
+ }
+`;
+
+const headlineLink = css`
+ display: block; /* To ensure focus outline works okay */
+ padding: 3px 10px 18px 80px;
+ ${textSans15};
+ text-decoration: none;
+ color: ${schemePalette('--slim-homepage-most-viewed-headline')};
+ font-weight: 500;
+ word-wrap: break-word;
+ overflow: hidden;
+`;
+
+const ageWarningStyles = css`
+ padding-left: 75px;
+ margin-top: -16px;
+ margin-bottom: 16px;
+`;
+
+type Props = {
+ heading: 'Most viewed' | 'Deeply read';
+ trails: TrailType[];
+};
+
+/**
+ * Renders the Most Viewed or Deeply Read component, often seen at the bottom of the page on
+ * network front, into a newly created right column high up on a front page. This component is
+ * only used as a part of an ongoing AB test and should not be used outside of this AB test.
+ */
+export const MostPopularFrontRight = ({ heading, trails }: Props) => {
+ if (trails.length === 0) return null;
+
+ return (
+
+ );
+};
diff --git a/dotcom-rendering/src/paletteDeclarations.ts b/dotcom-rendering/src/paletteDeclarations.ts
index 42c5f2f68f9..c3191163df0 100644
--- a/dotcom-rendering/src/paletteDeclarations.ts
+++ b/dotcom-rendering/src/paletteDeclarations.ts
@@ -7995,6 +7995,18 @@ const paletteColours = {
light: slideshowPaginationDotActiveLight,
dark: slideshowPaginationDotActiveDark,
},
+ '--slim-homepage-most-viewed-big-number': {
+ light: () => sourcePalette.neutral[60],
+ dark: () => sourcePalette.neutral[60],
+ },
+ '--slim-homepage-most-viewed-header': {
+ light: () => sourcePalette.neutral[46],
+ dark: () => sourcePalette.neutral[46],
+ },
+ '--slim-homepage-most-viewed-headline': {
+ light: () => sourcePalette.neutral[0],
+ dark: () => sourcePalette.neutral[0],
+ },
'--speech-bubble-background': {
light: speechBubbleBackgroundLight,
dark: speechBubbleBackgroundLight,