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 5a1636baa3 refactor: migrate from Biome to oxlint/oxfmt, remove contact form
- Replace Biome with oxlint + oxfmt (OXC toolchain) for linting and formatting
- Add .oxlintrc.json and .oxfmtrc.json configuration files
- Update VS Code settings and devcontainer to use oxc-vscode extension
- Remove contact form, Resend email integration, and related server action/schema
- Remove unused UI components (accordion, alert, card, tabs, toggle, etc.)
2026-04-05 19:45:18 -04:00

149 lines
4.5 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"],
},
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-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,
);