diff --git a/pages/news/[year]/[term].module.css b/pages/news/[year]/[term].module.css
new file mode 100644
index 00000000..ba5488c7
--- /dev/null
+++ b/pages/news/[year]/[term].module.css
@@ -0,0 +1,7 @@
+.page {
+ padding-bottom: calc(30rem / 16);
+}
+
+.term {
+ color: var(--primary-accent);
+}
diff --git a/pages/news/[year]/[term].tsx b/pages/news/[year]/[term].tsx
new file mode 100644
index 00000000..f6e33f36
--- /dev/null
+++ b/pages/news/[year]/[term].tsx
@@ -0,0 +1,84 @@
+import { ParsedUrlQuery } from "querystring";
+
+import { GetStaticPaths, GetStaticProps } from "next";
+import { MDXRemote } from "next-mdx-remote";
+import React from "react";
+
+import { NewsCard } from "@/components/NewsCard";
+import {
+ getNewsBySlug,
+ getNewsByTerm,
+ getNewsTermsByYear,
+ getNewsYears,
+ News,
+} from "@/lib/news";
+
+import styles from "./[term].module.css";
+
+interface Props {
+ year: string;
+ term: string;
+ news: News[];
+}
+
+export default function TermNews({ year, term, news }: Props) {
+ return (
+
+
+ News Archive:{" "}
+
+ {capitalize(term)} {year}
+
+
+ {news.map(({ content, metadata }, idx) => (
+
+
+
+ ))}
+
+ );
+}
+
+export const getStaticProps: GetStaticProps = async (
+ context
+) => {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const { year, term } = context.params!;
+ const slugs = await getNewsByTerm(year, term);
+ const news = await Promise.all(
+ slugs.map((slug) => getNewsBySlug(year, term, slug))
+ );
+
+ // Reverse so that we are displaying the most recent news
+ // of term first
+ return { props: { year, term, news: news.reverse() } };
+};
+
+interface Params extends ParsedUrlQuery {
+ year: string;
+ term: string;
+}
+
+export const getStaticPaths: GetStaticPaths = async () => {
+ const years = await getNewsYears();
+ const terms = await Promise.all(
+ years.map(async (year) => {
+ const termsInYear = await getNewsTermsByYear(year);
+ return termsInYear.map((term) => ({ year, term }));
+ })
+ );
+
+ return {
+ paths: terms.flat().map((params) => ({ params })),
+ fallback: false,
+ };
+};
+
+function capitalize(str: string) {
+ return str.slice(0, 1).toUpperCase() + str.slice(1);
+}