1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2026-06-05 19:15:30 -04:00
Files
jarv.is/next.config.ts
T
jake e59aee63c5 fix: load OG image fonts from @fontsource/inter instead of Google Fonts
Vercel's build infra was intermittently hitting ETIMEDOUT against
fonts.googleapis.com, causing OG image generation errors during
prerender. Ship the Inter .woff files with the function via
outputFileTracingIncludes so the build is network-free. Also add
turbopackIgnore hints on process.cwd() calls to silence an NFT warning
that was over-tracing next.config.ts into the route bundle.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 15:44:40 -04:00

160 lines
4.7 KiB
TypeScript

import type { NextConfig } from "next";
const nextConfig = {
cacheComponents: true,
reactCompiler: true,
pageExtensions: ["js", "jsx", "ts", "tsx", "md", "mdx"],
images: {
qualities: [50, 75, 100],
remotePatterns: [
{
protocol: "https",
hostname: "ijyxfbpcm3itvdly.public.blob.vercel-storage.com",
},
{
protocol: "https",
hostname: "avatars.githubusercontent.com",
},
],
},
outputFileTracingIncludes: {
"/notes/[slug]/opengraph-image": [
"./notes/**/*",
"./app/opengraph-image.jpg",
"./node_modules/**/@fontsource/inter/files/inter-latin-400-normal.woff",
"./node_modules/**/@fontsource/inter/files/inter-latin-600-normal.woff",
],
},
productionBrowserSourceMaps: true,
experimental: {
viewTransition: true,
serverActions: {
// fix CSRF errors from tor reverse proxy
allowedOrigins: [
"jarv.is",
...(process.env.NEXT_PUBLIC_ONION_DOMAIN ? [process.env.NEXT_PUBLIC_ONION_DOMAIN] : []),
],
},
staleTimes: {
dynamic: 0, // disable client-side router cache for dynamic pages
},
},
headers: async () => [
// https://community.torproject.org/onion-services/advanced/onion-location/
// oxlint-disable-next-line unicorn/no-useless-spread
...(process.env.NEXT_PUBLIC_ONION_DOMAIN
? [
{
// only needed on actual pages, not static assets, so make a best effort by matching any path **without** a file
// extension (aka a period) and/or an underscore (e.g. /_next/image).
source: "/:path([^._]*)",
headers: [
{
key: "onion-location",
value: `http://${process.env.NEXT_PUBLIC_ONION_DOMAIN}/:path`,
},
],
},
]
: []),
],
rewrites: async () => [
{
// https://github.com/jakejarvis/tweets
source: "/tweets/:path*",
destination: "https://tweets-khaki.vercel.app/:path*",
},
{
source: "/y2k/:path*",
destination: "https://y2k.pages.dev/:path*",
},
],
redirects: async () => [
{
source: "/pubkey.asc",
destination:
"https://keys.openpgp.org/pks/lookup?op=get&options=mr&search=0x3bc6e5776bf379d36f6714802b0c9cf251e69a39",
permanent: false,
},
// NOTE: don't remove this, it ensures de-AMPing the site hasn't offended our google overlords too badly!
// https://developers.google.com/search/docs/advanced/experience/remove-amp#remove-only-amp
{
source: "/notes/:slug/amp.html",
destination: "/notes/:slug",
permanent: true,
},
// mastodon via subdomain:
// https://docs.joinmastodon.org/admin/config/#web_domain
{
source: "/.well-known/:path(host-meta|webfinger|nodeinfo)",
destination: "https://fediverse.jarv.is/.well-known/:path",
permanent: true,
},
{
source: "/@jake:path(/?|/.*)",
destination: "https://fediverse.jarv.is/@jake:path",
permanent: true,
},
// remnants of previous sites/CMSes:
{ source: "/index.xml", destination: "/feed.xml", permanent: true },
{ source: "/feed", destination: "/feed.xml", permanent: true },
{ source: "/rss", destination: "/feed.xml", permanent: true },
{ source: "/blog/(.*)", destination: "/notes", permanent: true },
{ source: "/archives/(.*)", destination: "/notes", permanent: true },
// WordPress permalinks:
{
source: "/2016/02/28/millenial-with-hillary-clinton",
destination: "/notes/millenial-with-hillary-clinton",
permanent: true,
},
{
source: "/2018/12/04/how-to-shrink-linux-virtual-disk-vmware",
destination: "/notes/how-to-shrink-linux-virtual-disk-vmware",
permanent: true,
},
{
source: "/2018/12/10/cool-bash-tricks-for-your-terminal-dotfiles",
destination: "/notes/cool-bash-tricks-for-your-terminal-dotfiles",
permanent: true,
},
],
} satisfies NextConfig;
// my own macgyvered version of next-compose-plugins (RIP)
const nextPlugins: Array<
(config: NextConfig) => NextConfig | [(config: NextConfig) => NextConfig, any]
> = [
require("@next/mdx")({
options: {
remarkPlugins: [
"remark-frontmatter",
"remark-mdx-frontmatter",
"remark-gfm",
"remark-smartypants",
],
rehypePlugins: [
"rehype-unwrap-images",
"rehype-slug",
[
"rehype-wrapper",
{
className: "markdown",
},
],
"rehype-mdx-code-props",
"rehype-mdx-import-media",
],
},
}),
];
export default (): NextConfig =>
nextPlugins.reduce(
(acc, plugin) => (Array.isArray(plugin) ? plugin[0](acc, plugin[1]) : plugin(acc)),
nextConfig,
);