Compare commits

..

1 commit

Author SHA1 Message Date
Aaron Yarborough
2a2e9005fd feat: add isr to ...path 2025-05-08 13:49:44 +01:00
22 changed files with 177 additions and 413 deletions

View file

@ -23,7 +23,6 @@
"Sitecore", "Sitecore",
"sportank", "sportank",
"Umbraco", "Umbraco",
"Yarborough",
"Yarbz" "Yarbz"
], ],
"files.autoSave": "off", "files.autoSave": "off",

View file

@ -1,15 +1,13 @@
const fs = require("fs"); const fs = require("fs");
const fm = require("front-matter"); const fm = require("front-matter");
const siteUrl = process.env.SITE_URL || "https://www.aaronjy.me";
/** @type {import('next-sitemap').IConfig} */ /** @type {import('next-sitemap').IConfig} */
module.exports = { module.exports = {
siteUrl, siteUrl: process.env.SITE_URL || "https://www.aaronjy.me",
changefreq: "weekly", changefreq: "weekly",
generateRobotsTxt: true, generateRobotsTxt: true,
autoLastmod: false, autoLastmod: false,
generateIndexSitemap: false, generateIndexSitemap: false,
exclude: ["/server-sitemap-index.xml"], // <= exclude here
robotsTxtOptions: { robotsTxtOptions: {
policies: [ policies: [
{ {
@ -17,25 +15,30 @@ module.exports = {
allow: "/", allow: "/",
}, },
], ],
additionalSitemaps: [
`${siteUrl}/server-sitemap-index.xml`, // <==== Add here
],
}, },
transform: async (config, path) => { // transform: async (config, path) => {
const metadata = { // const metadata = {
loc: path, // loc: path
}; // }
if (isHomepage(path)) { // if (isHomepage(path)) {
metadata.priority = 1; // metadata.priority = 1
} else if (isBasePage(path)) { // } else if (isBasePage(path)) {
metadata.priority = 0.8; // metadata.priority = 0.8
} else if (isArticle(path)) { // } else {
metadata.priority = 0.6; // if (isArticle(path)) {
} // metadata.priority = 0.6
// const attributes = getArticleAttibutes(`content${path}.md`)
// if (!attributes) { return null }
return metadata; // metadata.lastmod = attributes.moddate ?? attributes.pubdate ?? null
},
// console.log('Calculated sitemap dates for article', path)
// }
// }
// return metadata
// }
}; };
function isHomepage(path) { function isHomepage(path) {
@ -47,5 +50,20 @@ function isBasePage(path) {
} }
function isArticle(path) { function isArticle(path) {
return path.startsWith("/writing/") || path.startsWith("/library/"); return path.startsWith("/writing/");
}
function getArticleAttibutes(path) {
const fileContents = fs.readFileSync(path, {
encoding: "utf-8",
});
// @ts-ignore
const { attributes } = fm(fileContents);
return {
...attributes,
pubdate: attributes.pubdate?.toUTCString() ?? null,
moddate: attributes.moddate?.toUTCString() ?? null,
};
} }

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "www-aaronjy-me", "name": "www-aaronjy-me",
"version": "2.1.1", "version": "2.1.2",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "www-aaronjy-me", "name": "www-aaronjy-me",
"version": "2.1.1", "version": "2.1.2",
"dependencies": { "dependencies": {
"@highlightjs/cdn-assets": "^11.11.1", "@highlightjs/cdn-assets": "^11.11.1",
"@mdx-js/mdx": "^3.1.0", "@mdx-js/mdx": "^3.1.0",

View file

@ -1,6 +1,6 @@
{ {
"name": "www-aaronjy-me", "name": "www-aaronjy-me",
"version": "2.4.1", "version": "2.1.2",
"private": true, "private": true,
"type": "module", "type": "module",
"lint-staged": { "lint-staged": {

View file

@ -7,4 +7,3 @@ Host: https://www.aaronjy.me
# Sitemaps # Sitemaps
Sitemap: https://www.aaronjy.me/sitemap.xml Sitemap: https://www.aaronjy.me/sitemap.xml
Sitemap: https://www.aaronjy.me/server-sitemap-index.xml

14
public/sitemap-0.xml Normal file
View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<url><loc>https://www.aaronjy.me/</loc><priority>1</priority></url>
<url><loc>https://www.aaronjy.me/about/</loc><priority>0.8</priority></url>
<url><loc>https://www.aaronjy.me/cv/</loc><priority>0.8</priority></url>
<url><loc>https://www.aaronjy.me/tags/</loc><priority>0.8</priority></url>
<url><loc>https://www.aaronjy.me/writing/</loc><priority>0.8</priority></url>
<url><loc>https://www.aaronjy.me/writing/attitudes-to-reading/</loc><priority>0.6</priority><pubdate>Tue, 18 Mar 2025 00:00:00 GMT</pubdate></url>
<url><loc>https://www.aaronjy.me/writing/moving-from-github-to-forgejo/</loc><priority>0.6</priority><pubdate>Sun, 16 Mar 2025 00:00:00 GMT</pubdate></url>
<url><loc>https://www.aaronjy.me/writing/performance-considerations-tcp-game-server/</loc><priority>0.6</priority><pubdate>Sun, 23 Feb 2025 21:12:37 GMT</pubdate></url>
<url><loc>https://www.aaronjy.me/writing/quick-reflection-katherine-may/</loc><priority>0.6</priority><pubdate>Sun, 09 Mar 2025 00:00:00 GMT</pubdate></url>
<url><loc>https://www.aaronjy.me/writing/static-site-on-google-cloud/</loc><priority>0.6</priority><pubdate>Wed, 01 May 2024 00:00:00 GMT</pubdate></url>
<url><loc>https://www.aaronjy.me/writing/support-content-filte-structure-changes-on-a-static-site/</loc><priority>0.6</priority><pubdate>Mon, 18 Mar 2024 16:47:32 GMT</pubdate></url>
</urlset>

View file

@ -1,44 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<url><loc>https://www.aaronjy.me/cv</loc><priority>0.8</priority></url> <url><loc>https://www.aaronjy.me/cv</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://www.aaronjy.me/library</loc><priority>0.8</priority></url> <url><loc>https://www.aaronjy.me/library</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://www.aaronjy.me/tags</loc><priority>0.8</priority></url> <url><loc>https://www.aaronjy.me/tags</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://www.aaronjy.me/writing</loc><priority>0.8</priority></url> <url><loc>https://www.aaronjy.me/writing</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://www.aaronjy.me/library/the-alchemist</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/the-invisible-man</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/wintering-the-power-of-rest-and-retreat-in-difficult-times</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/the-time-machine</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/when-the-moon-hits-your-eye</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/the-song-of-achilles</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/to-be-taught-if-fortunate</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/on-tyranny</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/the-dangers-of-smoking-in-bed</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/the-midnight-library</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/a-night-to-remember</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/sex-punishment</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/a-monster-calls</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/diary-of-an-oxygen-thief</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/1984</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/alices-adventures-in-wonderland</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/the-nature-of-alexander</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/eleven-kinds-of-loneliness</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/star-maker</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/stray-reflections</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/stasiland-stories-from-behind-the-berlin-wall</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/cities-that-shaped-the-ancient-world</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/animal-farm</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/a-wizard-of-earthsea</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/one-thousand-and-one-nights-a-retelling</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/the-tombs-of-atuan</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/childhoods-end</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/library/the-farthest-shore</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/about</loc><priority>0.8</priority></url>
<url><loc>https://www.aaronjy.me</loc><priority>1</priority></url>
<url><loc>https://www.aaronjy.me/writing/migrating-from-github-to-forgejo</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/writing/performance-considerations-when-writing-a-tcp-game-server-in-dotnet</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/writing/deploying-aaronjy-me-on-a-google-storage-bucket</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/writing/supporting-content-file-structure-changes-on-a-static-site</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/writing/attitudes-to-reading-and-how-mine-have-changed</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/writing/a-reflection-on-wintering-by-katherine-may</loc><priority>0.6</priority></url>
<url><loc>https://www.aaronjy.me/writing/how-my-adhd-makes-handling-relationships-difficult</loc><priority>0.6</priority></url>
</urlset> </urlset>

View file

@ -7,7 +7,7 @@ import pck from "../../../package.json";
function Footer() { function Footer() {
return ( return (
<footer className={`${style.footer} hide-print`} data-testid="footer"> <footer className={style.footer} data-testid="footer">
<hr /> <hr />
<nav> <nav>
<div> <div>

View file

@ -5,7 +5,7 @@ import styles from "./Header.module.css";
function Header() { function Header() {
return ( return (
<header className={`${styles.header} hide-print`} data-testid="header"> <header className={styles.header} data-testid="header">
<nav> <nav>
<Link href="/">Home</Link> <Link href="/">Home</Link>
{", "} {", "}

View file

@ -1,3 +0,0 @@
export default function Loading() {
return <p>Loading...</p>;
}

View file

@ -2,11 +2,8 @@ import React from "react";
import style from "./Resume.module.css"; import style from "./Resume.module.css";
import { markdownToHtml } from "@/services/content-service"; import { markdownToHtml } from "@/services/content-service";
import { MDXClient } from "next-mdx-remote-client/csr";
import Link from "next/link";
function Resume({ function Resume({
introMdxSource,
competencies, competencies,
education, education,
certifications, certifications,
@ -15,7 +12,7 @@ function Resume({
}) { }) {
return ( return (
<div className={style.cv}> <div className={style.cv}>
<ol className="hide-print"> <ol>
<li> <li>
<a href="#experience">Professional experience</a> <a href="#experience">Professional experience</a>
</li> </li>
@ -33,68 +30,57 @@ function Resume({
</li> </li>
</ol> </ol>
<div> <div>
<div className={style.about}> <h2 id="experience">Professional experience</h2>
<MDXClient {...introMdxSource} />
<span className="print-only"> {experience?.map((exp, i) => (
See more at <a href="https://aaronjy.me/cv">aaronjy.me/cv</a> <div key={i}>
</span> <WorkExperience
</div> employer={exp.employer}
position={exp.position}
start={exp.start}
end={exp.end}
>
{markdownToHtml(exp.description)}
</WorkExperience>
{!!exp.skills?.length && (
<details>
<summary>Competencies</summary>
<>{exp.skills.sort().join(", ")}</>
</details>
)}
</div>
))}
</div> </div>
<div className={style.cvContent}> <div className="sidebar">
<div className={style.experience}> <h2 id="competencies">Competencies</h2>
<h2 id="experience">Professional experience</h2> <ul>
{competencies
{experience?.map((exp, i) => ( ?.sort((a, b) => a.name > b.name)
<div key={i}> .map((c, i) => (
<WorkExperience <li key={i}>{c.name}</li>
employer={exp.employer}
position={exp.position}
start={exp.start}
end={exp.end}
skills={exp.skills}
>
{markdownToHtml(exp.description)}
</WorkExperience>
</div>
))}
</div>
<div className={style.sidebar}>
<h2 id="competencies">Competencies</h2>
<ul>
{competencies
?.sort((a, b) => a.name - b.name)
.map((c, i) => (
<li key={i}>{c.name}</li>
))}
</ul>
<h2 id="certifications">Certifications</h2>
<ul>
{certifications
?.sort((a, b) => a.name > b.name)
.map((c, i) => (
<li key={i}>{c.name}</li>
))}
</ul>
<h2 className="languages">Languages</h2>
<ul>
{languages?.sort().map((c, i) => (
<li key={i}>
<strong>{c.name}</strong> - {c.proficiency}
</li>
))} ))}
</ul> </ul>
<h2 className="education">Education</h2> <h2 id="certifications">Certifications</h2>
<ul> <ul>
{education {certifications
?.sort((a, b) => a.name - b.name) ?.sort((a, b) => a.name > b.name)
.map((c, i) => ( .map((c, i) => (
<li key={i}>{c.name}</li> <li key={i}>{c.name}</li>
))} ))}
</ul> </ul>
</div>
<h2 className="languages">Languages</h2>
<ul>
{languages?.sort().map((c, i) => (
<li key={i}>
{c.name} - {c.proficiency}
</li>
))}
</ul>
<h2 className="education">Education</h2>
<p>{education.name}</p>
</div> </div>
</div> </div>
); );
@ -102,43 +88,23 @@ function Resume({
export default Resume; export default Resume;
function WorkExperience({ position, employer, start, end, skills, children }) { function WorkExperience({ position, employer, start, end, children }) {
return ( return (
<> <div className={style["work-experience"]}>
<table className={style.experienceTable}> <div>
<tbody> <h3 id={position}>
<tr> {position}
<td> <br />
<span id={position} className={style.position}> <small>{employer}</small>
{position} </h3>
</span> <small>
<br /> <time>{start}</time> - <time>{end}</time>
<span className={style.employer}>{employer}</span> </small>
</td> </div>
<td className="text-right"> <div
<time>{start}</time> - <time>{end}</time> data-test="children"
</td> dangerouslySetInnerHTML={{ __html: children }}
</tr> />
<tr> </div>
<td colSpan={2}>
<div
data-test="children"
dangerouslySetInnerHTML={{ __html: children }}
className={style.experienceContent}
/>
{!!skills?.length && (
<div className={style.skillList}>
{skills.sort().map((skill) => (
<span key={skill}>{skill}</span>
))}
</div>
)}
</td>
</tr>
</tbody>
</table>
<hr />
</>
); );
} }

View file

@ -1,74 +0,0 @@
.experienceTable {
width: 100%;
}
.position {
font-weight: 700;
}
.cvContent {
display: flex;
flex-direction: row-reverse;
gap: 0.5em;
position: relative;
}
.cvContent .experience {
flex-basis: 66.66%;
}
.cvContent .sidebar {
flex-basis: 33.33%;
position: sticky;
top: 10px;
left: 0px;
height: 1px;
/* Needed to make sticky work */
}
.about {
margin-bottom: 0;
}
.cvContent ol,
.cvContent ul {
padding: 0 1rem;
}
.skillList {
font-size: 0.8em;
display: flex;
flex-wrap: wrap;
gap: 0.2em;
}
.skillList span {
background-color: var(--dark);
color: var(--light);
padding: 0 0.5em;
}
.experienceContent > p {
margin-bottom: 0;
}
@media screen and (max-width: 768px) {
.cvContent {
display: block;
}
.cvContent .sidebar {
height: auto;
position: relative;
}
}
@media print {
.cvContent .experience {
flex-basis: 80%;
}
.cvContent .sidebar {
flex-basis: 20%;
}
}

View file

@ -1,35 +1,34 @@
import Loading from "@/components/Loading/Loading"; import {
import { FailedFetchBasicPagesError } from "@/errors"; FailedFetchBasicPageError,
FailedFetchBasicPagesError,
} from "@/errors";
import DefaultLayout from "@/layouts/DefaultLayout/DefaultLayout"; import DefaultLayout from "@/layouts/DefaultLayout/DefaultLayout";
import { mdxComponents } from "@/lib/mdx-components"; import { mdxComponents } from "@/lib/mdx-components";
import { fetchBasicPages } from "@/services/content-service"; import { fetchBasicPages } from "@/services/content-service";
import { MDXClient } from "next-mdx-remote-client"; import { MDXClient } from "next-mdx-remote-client";
import { serialize } from "next-mdx-remote-client/serialize"; import { serialize } from "next-mdx-remote-client/serialize";
import { NextSeo } from "next-seo"; import { NextSeo } from "next-seo";
import { useRouter } from "next/router";
export async function getStaticPaths() { export async function getStaticPaths() {
const res = await fetchBasicPages(["path"]); const res = await fetchBasicPages();
if (!res.ok) { if (!res.ok) {
throw new FailedFetchBasicPagesError(await res.text()); throw new FailedFetchBasicPagesError();
} }
const pages = (await res.json()).data; const pages = (await res.json()).data;
const paths = pages.map((page) => {
return { return {
paths: pages.map((page) => ({
params: { params: {
path: [page.path ?? ""], path: page.path?.split("/") ?? [],
}, },
})), };
fallback: true, });
};
return { paths, fallback: false };
} }
export async function getStaticProps({ params }) { export async function getStaticProps({ params }) {
const { path } = params; const { path } = params;
const res = await fetchBasicPages([], { const res = await fetchBasicPages([], {
path: { path: {
_eq: path?.join("/") ?? null, _eq: path?.join("/") ?? null,
@ -45,7 +44,6 @@ export async function getStaticProps({ params }) {
if (!page) { if (!page) {
return { return {
notFound: true, notFound: true,
revalidate: 60,
}; };
} }
@ -62,16 +60,6 @@ export async function getStaticProps({ params }) {
} }
export default function BasicPage({ title, mdxSource }) { export default function BasicPage({ title, mdxSource }) {
const { isFallback } = useRouter();
if (isFallback) {
return (
<DefaultLayout>
<Loading />
</DefaultLayout>
);
}
if (!mdxSource || "error" in mdxSource) { if (!mdxSource || "error" in mdxSource) {
return <p>Something went wrong: {mdxSource?.error ?? "???"}</p>; return <p>Something went wrong: {mdxSource?.error ?? "???"}</p>;
} }

View file

@ -1,15 +1,13 @@
import Resume from "@/components/Resume/Resume";
import { FailedFetchCVError } from "@/errors";
import DefaultLayout from "@/layouts/DefaultLayout/DefaultLayout"; import DefaultLayout from "@/layouts/DefaultLayout/DefaultLayout";
import { fetchCV } from "@/services/content-service"; import React from "react";
import { NextSeo } from "next-seo"; import { NextSeo } from "next-seo";
import Resume from "@/components/Resume/Resume";
import style from "./cv.module.css"; import { fetchCV } from "@/services/content-service";
import { serialize } from "next-mdx-remote-client/serialize"; import { FailedFetchCVError } from "@/errors";
export const Title = "CV"; export const Title = "CV";
export async function getStaticProps() { export async function getServerSideProps() {
const res = await fetchCV([]); const res = await fetchCV([]);
if (!res.ok) { if (!res.ok) {
@ -20,36 +18,23 @@ export async function getStaticProps() {
if (!cv) { if (!cv) {
return { return {
notFound: true, notFound: true,
revalidate: 60,
}; };
} }
const { const { competencies, education, languages, certifications, experience } = cv;
intro,
competencies,
education,
languages,
certifications,
experience,
} = cv;
const introMdxSource = await serialize({ source: intro });
return { return {
props: { props: {
introMdxSource,
competencies, competencies,
education, education,
languages, languages,
certifications, certifications,
experience, experience,
}, },
revalidate: 60,
}; };
} }
export default function ResumePage({ export default function ResumePage({
introMdxSource,
competencies, competencies,
education, education,
certifications, certifications,
@ -64,11 +49,9 @@ export default function ResumePage({
title: Title, title: Title,
}} }}
/> />
<h1 className="hide-print">{Title}</h1> <h1>{Title}</h1>
<h1 className={`${style.printHeading} print-only`}>Aaron Yarborough</h1>
<section> <section>
<Resume <Resume
introMdxSource={introMdxSource}
competencies={competencies} competencies={competencies}
education={education} education={education}
certifications={certifications} certifications={certifications}

View file

@ -6,33 +6,37 @@ import {
FailedFetchBookReviewError, FailedFetchBookReviewError,
FailedFetchBookReviewsError, FailedFetchBookReviewsError,
} from "@/errors"; } from "@/errors";
import { useRouter } from "next/router";
import Loading from "@/components/Loading/Loading";
export async function getStaticPaths() { // export async function getStaticPaths () {
const res = await fetchBookReviews(["slug"], { // const res = await fetchBookReviews(['slug'], {
status: "published", // status: 'published'
}); // })
if (!res.ok) { // if (!res.ok) {
throw new FailedFetchBookReviewsError(await res.text()); // throw new FailedFetchBookReviewsError(await res.text())
} // }
const reviews = (await res.json()).data; // const reviews = (await res.json()).data
return { // return {
paths: reviews.map((post) => ({ // paths: reviews.map(post => ({
params: { // params: {
slug: post.slug, // slug: post.slug
}, // }
})), // })),
fallback: true, // fallback: false // false or "blocking"
}; // }
} // }
export const getStaticProps = async ({ params }) => { export const getServerSideProps = async ({ params }) => {
const { slug } = params; const { slug } = params;
if (!slug) {
return {
notFound: true,
};
}
const res = await fetchBookReviews([], { const res = await fetchBookReviews([], {
slug, slug,
status: "published", status: "published",
@ -46,7 +50,6 @@ export const getStaticProps = async ({ params }) => {
if (!review) { if (!review) {
return { return {
notFound: true, notFound: true,
revalidate: 60,
}; };
} }
@ -58,17 +61,13 @@ export const getStaticProps = async ({ params }) => {
review, review,
html, html,
}, },
revalidate: 60,
}; };
}; };
export default function LibrarySingle({ review, html }) { export default function LibrarySingle({ review, html }) {
const { isFallback } = useRouter();
return ( return (
<DefaultLayout> <DefaultLayout>
{!isFallback && <BookReview review={review} html={html} />} <BookReview review={review} html={html} />
{isFallback && <Loading />}
</DefaultLayout> </DefaultLayout>
); );
} }

View file

@ -8,7 +8,7 @@ import { NextSeo } from "next-seo";
export const Title = "Library"; export const Title = "Library";
export async function getStaticProps() { export async function getServerSideProps() {
const res = await fetchBookReviews(); const res = await fetchBookReviews();
if (!res.ok) { if (!res.ok) {
@ -23,7 +23,6 @@ export async function getStaticProps() {
props: { props: {
reviews: stringifyAndParse(reviews), reviews: stringifyAndParse(reviews),
}, },
revalidate: 60,
}; };
} }

View file

@ -1,29 +0,0 @@
import {
fetchBasicPages,
fetchBookReviews,
fetchPosts,
} from "@/services/content-service";
import { getServerSideSitemapIndexLegacy } from "next-sitemap";
const siteUrl = process.env.SITE_URL || "https://www.aaronjy.me";
export const getServerSideProps = async (ctx) => {
const [basicPagesResp, bookReviewsResp, postsResp] = await Promise.all([
fetchBasicPages().then((res) => res.json()),
fetchBookReviews().then((res) => res.json()),
fetchPosts().then((res) => res.json()),
]);
const urls = [
...basicPagesResp.data.map((entry) => `${siteUrl}/${entry.path ?? ""}`),
...bookReviewsResp.data.map(
(entry) => `${siteUrl}/library/${entry.slug ?? ""}`,
),
...postsResp.data.map((entry) => `${siteUrl}/writing/${entry.slug ?? ""}`),
];
return getServerSideSitemapIndexLegacy(ctx, [...urls]);
};
// Default export to prevent next.js errors
export default function SitemapIndex() {}

View file

@ -9,7 +9,7 @@ import { NextSeo } from "next-seo";
import Link from "next/link"; import Link from "next/link";
import React from "react"; import React from "react";
export async function getStaticProps() { export async function getServerSideProps() {
const res = await fetchPosts(["title", "date_published", "tags", "slug"], { const res = await fetchPosts(["title", "date_published", "tags", "slug"], {
status: "published", status: "published",
}); });
@ -26,7 +26,6 @@ export async function getStaticProps() {
tags, tags,
posts, posts,
}, },
revalidate: 60,
}; };
} }

View file

@ -3,31 +3,8 @@ import DefaultLayout from "@/layouts/DefaultLayout/DefaultLayout";
import Article from "@/components/Article/Article"; import Article from "@/components/Article/Article";
import { fetchPosts, markdownToHtml } from "@/services/content-service"; import { fetchPosts, markdownToHtml } from "@/services/content-service";
import { FailedFetchPostError, FailedFetchPostsError } from "@/errors"; import { FailedFetchPostError, FailedFetchPostsError } from "@/errors";
import { useRouter } from "next/router";
import Loading from "@/components/Loading/Loading";
export async function getStaticPaths() { export const getServerSideProps = async ({ params }) => {
const res = await fetchPosts(["slug"], {
status: "published",
});
if (!res.ok) {
throw new FailedFetchPostsError(await res.text());
}
const posts = (await res.json()).data;
return {
paths: posts.map((post) => ({
params: {
slug: post.slug,
},
})),
fallback: true,
};
}
export const getStaticProps = async ({ params }) => {
const { slug } = params; const { slug } = params;
const res = await fetchPosts([], { const res = await fetchPosts([], {
slug, slug,
@ -42,7 +19,6 @@ export const getStaticProps = async ({ params }) => {
if (!post) { if (!post) {
return { return {
notFound: true, notFound: true,
revalidate: 60,
}; };
} }
@ -54,17 +30,13 @@ export const getStaticProps = async ({ params }) => {
post, post,
html, html,
}, },
revalidate: 60,
}; };
}; };
export default function WritingSingle({ post, html }) { export default function WritingSingle({ post, html }) {
const { isFallback } = useRouter();
return ( return (
<DefaultLayout> <DefaultLayout>
{!isFallback && <Article {...post} html={html} />} <Article {...post} html={html} />
{isFallback && <Loading />}
</DefaultLayout> </DefaultLayout>
); );
} }

View file

@ -5,7 +5,7 @@ import StaticContentList from "@/components/StaticContentList/StaticContentList"
import { fetchPosts } from "@/services/content-service"; import { fetchPosts } from "@/services/content-service";
import { FailedFetchPostsError } from "@/errors"; import { FailedFetchPostsError } from "@/errors";
export const getStaticProps = async () => { export const getServerSideProps = async () => {
const res = await fetchPosts(["title", "date_published", "slug"], { const res = await fetchPosts(["title", "date_published", "slug"], {
status: "published", status: "published",
}); });
@ -25,7 +25,6 @@ export const getStaticProps = async () => {
props: { props: {
posts, posts,
}, },
revalidate: 60,
}; };
}; };

View file

@ -22,31 +22,3 @@ td:first-child {
.bold { .bold {
font-weight: 700; font-weight: 700;
} }
.text-right {
text-align: right;
}
.print-only {
display: none;
}
@media print {
html {
padding-top: 1rem;
}
body {
font-size: 11.5px;
line-height: 1.3;
padding: 0;
}
.hide-print {
display: none;
}
.print-only {
display: initial;
}
}