diff --git a/compendium-frontend/src/App.tsx b/compendium-frontend/src/App.tsx
index 56e412d763f61ebf70b0ab8a08564d27b537c266..dc9c25adbec4fd4ba092152c3bb2599b2e70f49a 100644
--- a/compendium-frontend/src/App.tsx
+++ b/compendium-frontend/src/App.tsx
@@ -13,6 +13,7 @@ import ParentOrganisation from "./pages/ParentOrganisation";
 import ECProjects from "./pages/ECProjects";
 import Providers from "./Providers";
 import PolicyPage from "./pages/Policy";
+import TrafficVolumePage from "./pages/TrafficVolumePerNren";
 
 
 const router = createBrowserRouter([
@@ -25,6 +26,7 @@ const router = createBrowserRouter([
   { path: "/parentorganisation", element: <ParentOrganisation />},
   { path: "/ec-projects", element: <ECProjects />},
   { path: "/policy", element: <PolicyPage />},
+  { path: "/traffic-volume", element: <TrafficVolumePage />},
   { path: "/data", element: <CompendiumData />},
   { path: "*", element: <Landing />},
 ]);
diff --git a/compendium-frontend/src/Schema.tsx b/compendium-frontend/src/Schema.tsx
index 2ea12a60f494dbdfe65a764534c6e6ffc78ad6b2..b7e39efdc80884be722b123802bbdcc683b25107 100644
--- a/compendium-frontend/src/Schema.tsx
+++ b/compendium-frontend/src/Schema.tsx
@@ -18,6 +18,13 @@ export interface Budget extends NrenAndYearDatapoint {
     budget: string
 }
 
+export interface TrafficVolume extends NrenAndYearDatapoint {
+    from_customers: number,
+    to_customers: number,
+    from_external: number,
+    to_external: number
+}
+
 export interface FundingSource extends NrenAndYearDatapoint {
     client_institutions: number,
     commercial: number,
diff --git a/compendium-frontend/src/components/DataPage.tsx b/compendium-frontend/src/components/DataPage.tsx
index c3af795939265d30774e4d8ef1bf3f092ca16c90..4c6a812bb730c53fe0dccb39be630979c2f61a09 100644
--- a/compendium-frontend/src/components/DataPage.tsx
+++ b/compendium-frontend/src/components/DataPage.tsx
@@ -9,6 +9,7 @@ import PolicySidebar from "./PolicySidebar";
 
 import { Chart as ChartJS } from 'chart.js';
 import { usePreview } from "../helpers/usePreview";
+import NetworkSidebar from "./NetworkSidebar";
 
 ChartJS.defaults.font.size = 16;
 ChartJS.defaults.font.family = 'Open Sans';
@@ -30,6 +31,7 @@ function DataPage({ title, description, filter, children, category }: inputProps
         <>
             {category === Sections.Organisation && <OrganizationSidebar />}
             {category === Sections.Policy && <PolicySidebar />}
+            {category === Sections.Network && <NetworkSidebar />}
             <PageHeader type={'data'} />
             { preview && <Row className="preview-banner">
                 <span>You are viewing a preview of the website which includes pre-published survey data. <a href={locationWithoutPreview}>Click here</a> to deactivate preview mode.</span>
diff --git a/compendium-frontend/src/components/NetworkSidebar.tsx b/compendium-frontend/src/components/NetworkSidebar.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..1274242afcc736e29c95897df673f32ff8dee36d
--- /dev/null
+++ b/compendium-frontend/src/components/NetworkSidebar.tsx
@@ -0,0 +1,19 @@
+import React from 'react';
+import { Link } from 'react-router-dom';
+import { Row } from 'react-bootstrap';
+import Sidebar from './SideBar';
+
+const PolicySidebar = () => {
+    return (
+        <Sidebar>
+            <h5>Network</h5>
+            <Row>
+                <Link to="/traffic-volume" className="link-text-underline">
+                    <span>Traffic volume</span>
+                </Link>
+            </Row>
+        </Sidebar>
+    )
+}
+
+export default PolicySidebar
\ No newline at end of file
diff --git a/compendium-frontend/src/components/SectionNavigation.tsx b/compendium-frontend/src/components/SectionNavigation.tsx
index 01c2a950a3fdd9067276aac6f0893e8e81cbe4c1..1636ac7dc260813d5c55831d2afd6d328b8ed1c9 100644
--- a/compendium-frontend/src/components/SectionNavigation.tsx
+++ b/compendium-frontend/src/components/SectionNavigation.tsx
@@ -33,10 +33,9 @@ const SectionNavigation = ({ activeCategory }: inputProps) => {
                         <span>{Sections.ConnectedUsers}</span>
                     </Button>
                     <Button
-                        onClick={() => navigate(activeCategory === Sections.Network ? '.' : '.')}
+                        onClick={() => navigate(activeCategory === Sections.Network ? '.' : '/traffic-volume')}
                         variant={'nav-box'}
-                        active={activeCategory === Sections.Network}
-                        disabled={true}>
+                        active={activeCategory === Sections.Network}>
                         <span>{Sections.Network}</span>
                     </Button>
                     <Button
diff --git a/compendium-frontend/src/helpers/dataconversion.tsx b/compendium-frontend/src/helpers/dataconversion.tsx
index c5a53aa8f1e758b209c741b0109fd300c7a79a5a..a8611c879ee69f2956115970f112acfb9c751aad 100644
--- a/compendium-frontend/src/helpers/dataconversion.tsx
+++ b/compendium-frontend/src/helpers/dataconversion.tsx
@@ -1,7 +1,7 @@
 import { cartesianProduct } from 'cartesian-product-multiple-arrays';
 import {
     FundingSource, FundingSourceDataset, ChargingStructure,
-    Budget, BasicDataset, NrenStaff, NrenStaffDataset, Organisation, ECProject, Policy
+    Budget, BasicDataset, NrenStaff, NrenStaffDataset, Organisation, ECProject, Policy, TrafficVolume
 } from "../Schema";
 
 // create a color from a string, credits https://stackoverflow.com/a/16348977
@@ -54,6 +54,50 @@ function CreateDataLookup(data: FundingSource[]) {
     return dataLookup
 }
 
+export const createTrafficVolumeDataset = (fundingSourcesData: TrafficVolume[]) => {
+    const data = fundingSourcesData;
+    const dataLookup = new Map<string, number>();
+    data.forEach((item: TrafficVolume) => {
+        const lookupKey = `${item.nren}/${item.year}`;
+        console.log(lookupKey );
+        dataLookup.set(lookupKey, item.from_customers);  // we ignore the rest of the data for now..
+    })
+
+    const labelsYear = [...new Set(data.map((item: TrafficVolume) => item.year))];
+    const labelsNREN = [...new Set(data.map((item: TrafficVolume) => item.nren))];
+
+    const sets = labelsYear.map(year => {
+        return {
+            backgroundColor: 'rgba(40, 40, 250, 0.8)',
+            data: labelsNREN.map((nren) => dataLookup.get(`${nren}/${year}`) ?? null),
+            label: year.toString(),
+            borderSkipped: true,
+            barPercentage: 0.8,
+            borderWidth: 0.5,
+            categoryPercentage: 0.8,
+            hidden: false,
+            datalabels: {
+                display: true,
+                color: 'grey',
+                formatter: function(value, context) {
+                    return context.dataset.label;
+                },
+                anchor: 'start',
+                align: 'end',
+                offset: function(context) {
+                    return context.chart.chartArea.width;
+                }
+            }
+        }
+    });
+
+    const dataResponse: BasicDataset = {
+        datasets: sets,
+        labels: labelsNREN.map(l => l.toString())
+    }
+    return dataResponse;
+}
+
 export const createFundingSourceDataset = (fundingSourcesData: FundingSource[]) => {
     const data = fundingSourcesData;
     const dataLookup = CreateDataLookup(data)
diff --git a/compendium-frontend/src/pages/CompendiumData.tsx b/compendium-frontend/src/pages/CompendiumData.tsx
index 2b20e067713a9f3fd27a6505ad70595a3fc579d7..504ecd7c48fea1e09828a91e1f70f31b43777ed5 100644
--- a/compendium-frontend/src/pages/CompendiumData.tsx
+++ b/compendium-frontend/src/pages/CompendiumData.tsx
@@ -95,7 +95,11 @@ function CompendiumData(): ReactElement {
                         </CollapsibleBox>
                         <CollapsibleBox title={Sections.Network} startCollapsed>
                             <div className="collapsible-column">
-                                <h5>Coming Soon</h5>
+                                <Row>
+                                    <Link to="/traffic-volume" className="link-text-underline">
+                                        <span>Total yearly traffic volume per NREN</span>
+                                    </Link>
+                                </Row>
                             </div>
                         </CollapsibleBox>
                         <CollapsibleBox title={Sections.Services} startCollapsed>
diff --git a/compendium-frontend/src/pages/TrafficVolumePerNren.tsx b/compendium-frontend/src/pages/TrafficVolumePerNren.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..5cd86d80df332dfe0175c3160cf583ff43ef58a2
--- /dev/null
+++ b/compendium-frontend/src/pages/TrafficVolumePerNren.tsx
@@ -0,0 +1,127 @@
+import React, { useContext } from 'react';
+import { Bar } from 'react-chartjs-2';
+import { Col, Row } from "react-bootstrap";
+import { Chart as ChartJS } from 'chart.js';
+import ChartDataLabels from 'chartjs-plugin-datalabels';
+
+import { TrafficVolume } from "../Schema";
+import { createTrafficVolumeDataset } from "../helpers/dataconversion";
+import DataPage from '../components/DataPage';
+import Filter from "../components/graphing/Filter"
+import { ExportType, Sections } from '../helpers/constants';
+import DownloadDataButton from "../components/DownloadDataButton";
+import { FilterSelectionContext } from '../helpers/FilterSelectionProvider';
+import DownloadImageChartButton from "../components/DownloadImageChartButton";
+import ChartContainer from "../components/graphing/ChartContainer";
+import { useData } from '../helpers/useData';
+
+export const chartOptions = {
+  maintainAspectRatio: false,
+  layout: {
+    padding: {
+      right: 60
+    }
+  },
+  animation: {
+    duration: 0,
+  },
+  plugins: {
+    legend: {
+      display: false
+    }
+  },
+  scales: {
+    x: {
+      position: "top" as const
+    },
+    xBottom: {
+      grid: {
+        drawOnChartArea: false
+      },
+      afterDataLimits: function (axis) {
+        const indices = Object.keys(ChartJS.instances)
+
+        // initial values should be far outside possible range
+        let max = -99999999
+        let min = 99999999
+
+        for (const index of indices) {
+          if (ChartJS.instances[index] && axis.chart.scales.xBottom) {
+            min = Math.min(ChartJS.instances[index].scales.x.min, min);
+            max = Math.max(ChartJS.instances[index].scales.x.max, max);
+          }
+        }
+
+        axis.chart.scales.xBottom.options.min = min;
+        axis.chart.scales.xBottom.options.max = max;
+        axis.chart.scales.xBottom.min = min;
+        axis.chart.scales.xBottom.max = max;
+      },
+    },
+    y: {
+      ticks: {
+        autoSkip: false
+      },
+    }
+  },
+  indexAxis: "y" as const,
+};
+
+function TrafficVolumePage() {
+  const { filterSelection, setFilterSelection } = useContext(FilterSelectionContext);
+  const { data: trafficVolumeData, years, nrens } = useData<TrafficVolume>('/api/traffic/', setFilterSelection);
+
+  const trafficVolumeDataset = createTrafficVolumeDataset(trafficVolumeData);
+
+  trafficVolumeDataset.datasets.forEach(dataset => {
+    dataset.hidden = !filterSelection.selectedYears.includes(parseInt(dataset.label));
+  });
+
+  // remove the datapoints and labels for the nrens that aren't selected
+  // unfortunately we cannot just hide them because chart.js doesn't want
+  // to create a stack from a single dataset
+  trafficVolumeDataset.datasets.forEach(dataset => {
+    dataset.data = dataset.data.filter((e, i) => {
+      return filterSelection.selectedNrens.includes(trafficVolumeDataset.labels[i]);
+    });
+  });
+  trafficVolumeDataset.labels = trafficVolumeDataset.labels.filter((e) => filterSelection.selectedNrens.includes(e));
+
+  const filterNode = <Filter
+    filterOptions={{ availableYears: [...years], availableNrens: [...nrens.values()] }}
+    filterSelection={filterSelection}
+    setFilterSelection={setFilterSelection}
+  />
+
+  const numNrens = filterSelection.selectedNrens.length;
+  const numYears = filterSelection.selectedYears.length;
+  const heightPerBar = 2; // every added bar should give this much additional height
+
+  console.log(trafficVolumeDataset)
+
+  // set a minimum height of 20rem, additional years need some more space
+  const height = numNrens * numYears * heightPerBar + 5;
+  return (
+    <DataPage title="Traffic Volume Of NRENs per Year"
+      description='Total yearly traffic volume in terabyte per NREN'
+      category={Sections.Network} filter={filterNode}>
+      <>
+        <Row>
+          <DownloadDataButton data={trafficVolumeData} filename="traffic_volume_of_nren_per_year.csv" exportType={ExportType.CSV} />
+          <DownloadDataButton data={trafficVolumeData} filename="traffic_volume_of_nren_per_year.xlsx" exportType={ExportType.EXCEL} />
+        </Row>
+        <DownloadImageChartButton filename="traffic_volume_of_nren_per_year" />
+        <ChartContainer>
+          <div className="chart-container" style={{ 'height': `${height}rem` }}>
+            <Bar
+              plugins={[ChartDataLabels]}
+              data={trafficVolumeDataset}
+              options={chartOptions}
+            />
+          </div>
+        </ChartContainer>
+      </>
+    </DataPage>
+  );
+}
+export default TrafficVolumePage;