mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2025-04-26 06:45:23 -04:00
consistent arrow functions
This commit is contained in:
parent
6a57fde2f1
commit
e61ca889a7
@ -15,7 +15,7 @@ NEXT_PUBLIC_UMAMI_WEBSITE_ID=
|
||||
# optional. the base URL of a self-hosted Umami instance (including https://) to proxy requests to. if the website ID is
|
||||
# set but this isn't, the managed Umami Cloud endpoint is used.
|
||||
# https://umami.is/docs/bypass-ad-blockers
|
||||
NEXT_PUBLIC_UMAMI_HOST=
|
||||
NEXT_PUBLIC_UMAMI_URL=
|
||||
|
||||
# optional. enables comments on blog posts via GitHub discussions.
|
||||
# https://giscus.app/
|
||||
|
@ -4,12 +4,12 @@ import type { hits as Hits } from "@prisma/client";
|
||||
|
||||
export const revalidate = 900; // 15 mins
|
||||
|
||||
export async function GET(): Promise<
|
||||
export const GET = async (): Promise<
|
||||
NextResponse<{
|
||||
total: Pick<Hits, "hits">;
|
||||
pages: Hits[];
|
||||
}>
|
||||
> {
|
||||
> => {
|
||||
// fetch all rows from db sorted by most hits
|
||||
const pages = await prisma.hits.findMany({
|
||||
orderBy: [
|
||||
@ -28,4 +28,4 @@ export async function GET(): Promise<
|
||||
});
|
||||
|
||||
return NextResponse.json({ total, pages });
|
||||
}
|
||||
};
|
||||
|
@ -20,7 +20,7 @@ export const metadata: Metadata = {
|
||||
},
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
const Page = () => {
|
||||
return (
|
||||
<>
|
||||
<PageTitle canonical="/birthday">1996.mov</PageTitle>
|
||||
@ -28,4 +28,6 @@ export default function Page() {
|
||||
<Video src={["/static/birthday/birthday.webm", "/static/birthday/birthday.mp4"]} poster={thumbnail.src} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Page;
|
||||
|
@ -3,7 +3,7 @@
|
||||
import { headers } from "next/headers";
|
||||
import { z } from "zod";
|
||||
import { Resend } from "resend";
|
||||
import config from "../../lib/config/constants";
|
||||
import config from "../../lib/config";
|
||||
|
||||
const schema = z.object({
|
||||
name: z.string().min(1, { message: "Name is required" }),
|
||||
@ -12,7 +12,7 @@ const schema = z.object({
|
||||
["cf-turnstile-response"]: z.string().min(1, { message: "CAPTCHA not completed" }),
|
||||
});
|
||||
|
||||
export async function sendMessage(
|
||||
export const sendMessage = async (
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
prevState: any,
|
||||
formData: FormData
|
||||
@ -21,7 +21,7 @@ export async function sendMessage(
|
||||
message: string;
|
||||
errors?: z.inferFormattedError<typeof schema>;
|
||||
payload?: FormData;
|
||||
}> {
|
||||
}> => {
|
||||
try {
|
||||
const validatedFields = schema.safeParse(Object.fromEntries(formData));
|
||||
|
||||
@ -85,4 +85,4 @@ export async function sendMessage(
|
||||
payload: formData,
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -71,7 +71,7 @@ const ContactForm = () => {
|
||||
}}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M22.27 19.385H1.73A1.73 1.73 0 010 17.655V6.345a1.73 1.73 0 011.73-1.73h20.54A1.73 1.73 0 0124 6.345v11.308a1.73 1.73 0 01-1.73 1.731zM5.769 15.923v-4.5l2.308 2.885 2.307-2.885v4.5h2.308V8.078h-2.308l-2.307 2.885-2.308-2.885H3.46v7.847zM21.232 12h-2.309V8.077h-2.307V12h-2.308l3.461 4.039z"></path>
|
||||
<path d="M22.27 19.385H1.73A1.73 1.73 0 010 17.655V6.345a1.73 1.73 0 011.73-1.73h20.54A1.73 1.73 0 0124 6.345v11.308a1.73 1.73 0 01-1.73 1.731zM5.769 15.923v-4.5l2.308 2.885 2.307-2.885v4.5h2.308V8.078h-2.308l-2.307 2.885-2.308-2.885H3.46v7.847zM21.232 12h-2.309V8.077h-2.307V12h-2.308l3.461 4.039z" />
|
||||
</svg>{" "}
|
||||
Basic{" "}
|
||||
<Link href="https://commonmark.org/help/" title="Markdown reference sheet" style={{ fontWeight: 600 }}>
|
||||
|
@ -18,7 +18,7 @@ export const metadata: Metadata = {
|
||||
},
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
const Page = () => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@ -46,4 +46,6 @@ export default function Page() {
|
||||
<ContactForm />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Page;
|
||||
|
@ -21,7 +21,7 @@ export const metadata: Metadata = {
|
||||
},
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
const Page = () => {
|
||||
return (
|
||||
<>
|
||||
<PageTitle canonical="/hillary">HRC.mov</PageTitle>
|
||||
@ -60,4 +60,6 @@ export default function Page() {
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Page;
|
||||
|
@ -4,7 +4,7 @@ import { ThemeProvider } from "../contexts/ThemeContext";
|
||||
import Header from "../components/Header";
|
||||
import Footer from "../components/Footer";
|
||||
import { SkipToContentLink, SkipToContentTarget } from "../components/SkipToContent";
|
||||
import config from "../lib/config/constants";
|
||||
import config from "../lib/config";
|
||||
import type { Metadata } from "next";
|
||||
import type { Person, WithContext } from "schema-dts";
|
||||
|
||||
@ -37,9 +37,14 @@ export const metadata: Metadata = {
|
||||
{
|
||||
url: meJpg.src,
|
||||
alt: `${config.siteName} – ${config.shortDescription}`,
|
||||
width: meJpg.width,
|
||||
height: meJpg.height,
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
creator: `@${config.authorSocial?.twitter}`,
|
||||
},
|
||||
alternates: {
|
||||
canonical: "/",
|
||||
types: {
|
||||
@ -83,7 +88,7 @@ const jsonLd: WithContext<Person> = {
|
||||
],
|
||||
};
|
||||
|
||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||
const RootLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
return (
|
||||
<html lang={config.siteLocale} suppressHydrationWarning>
|
||||
<head>
|
||||
@ -110,4 +115,6 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default RootLayout;
|
||||
|
@ -21,7 +21,7 @@ export const metadata: Metadata = {
|
||||
},
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
const Page = () => {
|
||||
return (
|
||||
<>
|
||||
<PageTitle canonical="/leo">TheLab.mov</PageTitle>
|
||||
@ -49,4 +49,6 @@ export default function Page() {
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Page;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import config from "../lib/config/constants";
|
||||
import config from "../lib/config";
|
||||
import type { MetadataRoute } from "next";
|
||||
|
||||
const manifest = (): MetadataRoute.Manifest => {
|
||||
|
@ -11,7 +11,7 @@ export const metadata: Metadata = {
|
||||
},
|
||||
};
|
||||
|
||||
export default async function Page() {
|
||||
const Page = () => {
|
||||
return (
|
||||
<div style={{ textAlign: "center" }}>
|
||||
<Video
|
||||
@ -28,4 +28,6 @@ export default async function Page() {
|
||||
<Link href="/">Go home?</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Page;
|
||||
|
@ -8,7 +8,7 @@ import Loading from "../../../components/Loading";
|
||||
import HitCounter from "./counter";
|
||||
import { getPostSlugs, getFrontMatter } from "../../../lib/helpers/posts";
|
||||
import { metadata as defaultMetadata } from "../../layout";
|
||||
import config from "../../../lib/config/constants";
|
||||
import config from "../../../lib/config";
|
||||
import type { Metadata, Route } from "next";
|
||||
import type { Article, WithContext } from "schema-dts";
|
||||
|
||||
@ -20,16 +20,16 @@ export const dynamicParams = false;
|
||||
// https://nextjs.org/docs/app/building-your-application/rendering/partial-prerendering#using-partial-prerendering
|
||||
export const experimental_ppr = true;
|
||||
|
||||
export async function generateStaticParams() {
|
||||
export const generateStaticParams = async () => {
|
||||
const slugs = await getPostSlugs();
|
||||
|
||||
// map slugs into a static paths object required by next.js
|
||||
return slugs.map((slug) => ({
|
||||
slug,
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> {
|
||||
export const generateMetadata = async ({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> => {
|
||||
const { slug } = await params;
|
||||
const frontmatter = await getFrontMatter(slug);
|
||||
|
||||
@ -54,9 +54,9 @@ export async function generateMetadata({ params }: { params: Promise<{ slug: str
|
||||
canonical: `/notes/${slug}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export default async function Page({ params }: { params: Promise<{ slug: string }> }) {
|
||||
const Page = async ({ params }: { params: Promise<{ slug: string }> }) => {
|
||||
const { slug } = await params;
|
||||
const frontmatter = await getFrontMatter(slug);
|
||||
|
||||
@ -153,4 +153,6 @@ export default async function Page({ params }: { params: Promise<{ slug: string
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Page;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import Link from "../../components/Link";
|
||||
import Time from "../../components/Time";
|
||||
import { getAllPosts } from "../../lib/helpers/posts";
|
||||
import config from "../../lib/config/constants";
|
||||
import config from "../../lib/config";
|
||||
import { metadata as defaultMetadata } from "../layout";
|
||||
import type { ReactElement } from "react";
|
||||
import type { Metadata, Route } from "next";
|
||||
@ -23,7 +23,7 @@ export const metadata: Metadata = {
|
||||
},
|
||||
};
|
||||
|
||||
export default async function Page() {
|
||||
const Page = async () => {
|
||||
// parse the year of each note and group them together
|
||||
const notes = await getAllPosts();
|
||||
const notesByYear: {
|
||||
@ -58,5 +58,7 @@ export default async function Page() {
|
||||
// grouped posts enter this component ordered chronologically -- we want reverse chronological
|
||||
const reversed = sections.reverse();
|
||||
|
||||
return <>{reversed}</>;
|
||||
}
|
||||
return reversed;
|
||||
};
|
||||
|
||||
export default Page;
|
||||
|
@ -34,7 +34,7 @@ const Link = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
const Page = () => {
|
||||
return (
|
||||
<div className={styles.page}>
|
||||
<h1>
|
||||
@ -286,4 +286,6 @@ export default function Page() {
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Page;
|
||||
|
@ -38,7 +38,7 @@ export const metadata: Metadata = {
|
||||
},
|
||||
};
|
||||
|
||||
export default async function Page() {
|
||||
const Page = () => {
|
||||
return (
|
||||
<div
|
||||
className={styles.wackyWrapper}
|
||||
@ -86,7 +86,7 @@ export default async function Page() {
|
||||
marginRight: "0.1em",
|
||||
}}
|
||||
>
|
||||
<path d="M5.712 1.596l-.756.068-.238.55.734-.017zm1.39.927l-.978.137-.326.807.96-.12.345-.824zM4.89 3.535l-.72.05-.24.567.721-.017zm3.724.309l-1.287.068-.394.96 1.27-.052zm1.87.566l-1.579.069-.566 1.357 1.596-.088.548-1.338zm-4.188.037l-.977.153-.343.806.976-.12zm6.144.668l-1.87.135-.637 1.527 1.87-.154zm2.925.219c-.11 0-.222 0-.334.002l-.767 1.85c1.394-.03 2.52.089 3.373.38l-1.748 4.201c-.955-.304-2.082-.444-3.36-.394l-.54 1.305a8.762 8.762 0 0 1 3.365.396l-1.663 4.014c-1.257-.27-2.382-.395-3.387-.344l-.782 1.887c3.363-.446 6.348.822 9.009 3.773L24 9.23c-2.325-2.575-5.2-3.88-8.637-3.896zm-.644.002l-2.024.12-.687 1.68 2.025-.19zm-10.603.05l-.719.036-.224.566h.703l.24-.601zm3.69.397l-1.287.069-.395.959 1.27-.05zM5.54 6.3l-.994.154-.344.807.98-.121zm4.137.066l-1.58.069L7.53 7.77l1.596-.085.55-1.32zm1.955.688l-1.87.135-.636 1.527 1.887-.154zm2.282.19l-2.01.136-.7 1.682 2.04-.19.67-1.63zm-10.57.066l-.739.035-.238.564h.72l.257-.6zm3.705.293l-1.303.085-.394.96 1.287-.034zm11.839.255a6.718 6.718 0 0 1 2.777 1.717l-1.75 4.237c-.617-.584-1.15-.961-1.611-1.149l-1.201-.498zM4.733 8.22l-.976.154-.344.807.961-.12.36-.841zm4.186 0l-1.594.052-.549 1.354L8.37 9.54zm1.957.668L8.99 9.04l-.619 1.508 1.87-.135.636-1.527zm2.247.275l-2.007.12-.703 1.665 2.042-.156zM2.52 9.267l-.718.033-.24.549.718-.016zm3.725.273l-1.289.07-.41.96 1.287-.03.412-1zm1.87.6l-1.596.05-.55 1.356 1.598-.084.547-1.322zm-4.186.037l-.979.136-.324.805.96-.119zm6.14.633l-1.87.154-.653 1.527 1.906-.154zm2.267.275l-2.026.12-.686 1.663 2.025-.172zm-10.569.031l-.739.037-.238.565.72-.016zm3.673.362l-1.289.068-.41.978 1.305-.05zm-2.285.533l-.976.154-.326.805.96-.12.342-.84zm4.153.07l-1.596.066-.565 1.356 1.612-.084zm1.957.666l-1.889.154-.617 1.526 1.886-.15zm2.28.223l-2.025.12-.685 1.665 2.041-.172.67-1.613zm-10.584.05l-.738.053L0 13.64l.72-.02.24-.6zm3.705.31l-1.285.07-.395.976 1.287-.05.393-.997zm11.923.07c1.08.29 2.024.821 2.814 1.613l-1.715 4.183c-.892-.754-1.82-1.32-2.814-1.664l1.715-4.133zm-10.036.515L4.956 14l-.549 1.32 1.578-.066.567-1.338zm-4.184.014l-.996.156-.309.79.961-.106zm6.14.67l-1.904.154-.617 1.527 1.89-.154.632-1.527zm2.231.324l-2.025.123-.686 1.682 2.026-.174zm-6.863.328l-1.3.068-.397.98 1.285-.054zm1.871.584l-1.578.068-.566 1.334 1.595-.064zm1.953.701l-1.867.137-.635 1.51 1.87-.137zm2.23.31l-2.005.122-.703 1.68 2.04-.19.67-1.61z"></path>
|
||||
<path d="M5.712 1.596l-.756.068-.238.55.734-.017zm1.39.927l-.978.137-.326.807.96-.12.345-.824zM4.89 3.535l-.72.05-.24.567.721-.017zm3.724.309l-1.287.068-.394.96 1.27-.052zm1.87.566l-1.579.069-.566 1.357 1.596-.088.548-1.338zm-4.188.037l-.977.153-.343.806.976-.12zm6.144.668l-1.87.135-.637 1.527 1.87-.154zm2.925.219c-.11 0-.222 0-.334.002l-.767 1.85c1.394-.03 2.52.089 3.373.38l-1.748 4.201c-.955-.304-2.082-.444-3.36-.394l-.54 1.305a8.762 8.762 0 0 1 3.365.396l-1.663 4.014c-1.257-.27-2.382-.395-3.387-.344l-.782 1.887c3.363-.446 6.348.822 9.009 3.773L24 9.23c-2.325-2.575-5.2-3.88-8.637-3.896zm-.644.002l-2.024.12-.687 1.68 2.025-.19zm-10.603.05l-.719.036-.224.566h.703l.24-.601zm3.69.397l-1.287.069-.395.959 1.27-.05zM5.54 6.3l-.994.154-.344.807.98-.121zm4.137.066l-1.58.069L7.53 7.77l1.596-.085.55-1.32zm1.955.688l-1.87.135-.636 1.527 1.887-.154zm2.282.19l-2.01.136-.7 1.682 2.04-.19.67-1.63zm-10.57.066l-.739.035-.238.564h.72l.257-.6zm3.705.293l-1.303.085-.394.96 1.287-.034zm11.839.255a6.718 6.718 0 0 1 2.777 1.717l-1.75 4.237c-.617-.584-1.15-.961-1.611-1.149l-1.201-.498zM4.733 8.22l-.976.154-.344.807.961-.12.36-.841zm4.186 0l-1.594.052-.549 1.354L8.37 9.54zm1.957.668L8.99 9.04l-.619 1.508 1.87-.135.636-1.527zm2.247.275l-2.007.12-.703 1.665 2.042-.156zM2.52 9.267l-.718.033-.24.549.718-.016zm3.725.273l-1.289.07-.41.96 1.287-.03.412-1zm1.87.6l-1.596.05-.55 1.356 1.598-.084.547-1.322zm-4.186.037l-.979.136-.324.805.96-.119zm6.14.633l-1.87.154-.653 1.527 1.906-.154zm2.267.275l-2.026.12-.686 1.663 2.025-.172zm-10.569.031l-.739.037-.238.565.72-.016zm3.673.362l-1.289.068-.41.978 1.305-.05zm-2.285.533l-.976.154-.326.805.96-.12.342-.84zm4.153.07l-1.596.066-.565 1.356 1.612-.084zm1.957.666l-1.889.154-.617 1.526 1.886-.15zm2.28.223l-2.025.12-.685 1.665 2.041-.172.67-1.613zm-10.584.05l-.738.053L0 13.64l.72-.02.24-.6zm3.705.31l-1.285.07-.395.976 1.287-.05.393-.997zm11.923.07c1.08.29 2.024.821 2.814 1.613l-1.715 4.183c-.892-.754-1.82-1.32-2.814-1.664l1.715-4.133zm-10.036.515L4.956 14l-.549 1.32 1.578-.066.567-1.338zm-4.184.014l-.996.156-.309.79.961-.106zm6.14.67l-1.904.154-.617 1.527 1.89-.154.632-1.527zm2.231.324l-2.025.123-.686 1.682 2.026-.174zm-6.863.328l-1.3.068-.397.98 1.285-.054zm1.871.584l-1.578.068-.566 1.334 1.595-.064zm1.953.701l-1.867.137-.635 1.51 1.87-.137zm2.23.31l-2.005.122-.703 1.68 2.04-.19.67-1.61z" />
|
||||
</svg>{" "}
|
||||
Click here for the <em>full</em> experience anyway.
|
||||
</Link>
|
||||
@ -96,7 +96,6 @@ export default async function Page() {
|
||||
<iframe
|
||||
src="https://jakejarvis.github.io/my-first-website/"
|
||||
title="My Terrible, Horrible, No Good, Very Bad First Website"
|
||||
sandbox="allow-same-origin allow-scripts allow-popups"
|
||||
className={styles.iframe}
|
||||
style={{ height: "500px" }}
|
||||
/>
|
||||
@ -188,4 +187,6 @@ export default async function Page() {
|
||||
</Figure>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Page;
|
||||
|
@ -4,7 +4,7 @@ import PageTitle from "../../components/PageTitle";
|
||||
import Link from "../../components/Link";
|
||||
import RelativeTime from "../../components/RelativeTime";
|
||||
import commaNumber from "comma-number";
|
||||
import config from "../../lib/config/constants";
|
||||
import config from "../../lib/config";
|
||||
import { metadata as defaultMetadata } from "../layout";
|
||||
import type { Metadata } from "next";
|
||||
import type { User, Repository } from "@octokit/graphql-schema";
|
||||
@ -39,7 +39,7 @@ type Project = {
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
async function getRepos(): Promise<Project[] | null> {
|
||||
const getRepos = async (): Promise<Project[] | null> => {
|
||||
// don't fail the entire site build if the required API key for this page is missing
|
||||
if (!process.env.GITHUB_TOKEN) {
|
||||
console.warn(`ERROR: I can't fetch any GitHub projects without "GITHUB_TOKEN" set! Skipping for now...`);
|
||||
@ -102,9 +102,9 @@ async function getRepos(): Promise<Project[] | null> {
|
||||
}));
|
||||
|
||||
return repos;
|
||||
}
|
||||
};
|
||||
|
||||
export default async function Page() {
|
||||
const Page = async () => {
|
||||
const repos = await getRepos();
|
||||
|
||||
return (
|
||||
@ -190,11 +190,13 @@ export default async function Page() {
|
||||
fill: "var(--colors-text)",
|
||||
}}
|
||||
>
|
||||
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"></path>
|
||||
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
|
||||
</svg>{" "}
|
||||
GitHub...
|
||||
</Link>
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Page;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import config from "../lib/config/constants";
|
||||
import config from "../lib/config";
|
||||
import type { MetadataRoute } from "next";
|
||||
|
||||
export const dynamic = "force-static";
|
||||
|
@ -1,7 +1,7 @@
|
||||
import path from "path";
|
||||
import glob from "fast-glob";
|
||||
import { getAllPosts } from "../lib/helpers/posts";
|
||||
import config from "../lib/config/constants";
|
||||
import config from "../lib/config";
|
||||
import type { MetadataRoute } from "next";
|
||||
|
||||
export const dynamic = "force-static";
|
||||
|
@ -19,7 +19,7 @@ export const metadata: Metadata = {
|
||||
},
|
||||
};
|
||||
|
||||
export default async function Page() {
|
||||
const Page = () => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@ -73,4 +73,6 @@ export default async function Page() {
|
||||
</CodeBlock>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Page;
|
||||
|
@ -3,7 +3,9 @@ import type { ComponentPropsWithoutRef } from "react";
|
||||
|
||||
import styles from "./Blockquote.module.css";
|
||||
|
||||
const Blockquote = ({ className, ...rest }: ComponentPropsWithoutRef<"blockquote">) => (
|
||||
export type BlockquoteProps = ComponentPropsWithoutRef<"blockquote">;
|
||||
|
||||
const Blockquote = ({ className, ...rest }: BlockquoteProps) => (
|
||||
<blockquote className={clsx(styles.blockquote, className)} {...rest} />
|
||||
);
|
||||
|
||||
|
@ -3,7 +3,9 @@ import type { ComponentPropsWithoutRef } from "react";
|
||||
|
||||
import styles from "./CodeInline.module.css";
|
||||
|
||||
const CodeInline = ({ className, ...rest }: ComponentPropsWithoutRef<"code">) => (
|
||||
export type CodeInlineProps = ComponentPropsWithoutRef<"code">;
|
||||
|
||||
const CodeInline = ({ className, ...rest }: CodeInlineProps) => (
|
||||
<code className={clsx(styles.codeInline, className)} {...rest} />
|
||||
);
|
||||
|
||||
|
@ -22,9 +22,7 @@ const CodePen = ({
|
||||
preview: `${!!preview}`,
|
||||
editable: `${!!editable}`,
|
||||
})}`}
|
||||
scrolling="no"
|
||||
sandbox="allow-same-origin allow-scripts allow-popups allow-top-navigation-by-user-activation"
|
||||
style={{ height: `${height}px`, width: "100%", border: "0" }}
|
||||
style={{ height: `${height}px`, width: "100%", border: "0", overflow: "hidden" }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import Giscus from "@giscus/react";
|
||||
import config from "../../lib/config/constants";
|
||||
import config from "../../lib/config";
|
||||
import type { GiscusProps } from "@giscus/react";
|
||||
|
||||
export type CommentsProps = {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import clsx from "clsx";
|
||||
import { HeartIcon } from "lucide-react";
|
||||
import Link from "../Link";
|
||||
import config from "../../lib/config/constants";
|
||||
import config from "../../lib/config";
|
||||
import type { ComponentPropsWithoutRef } from "react";
|
||||
|
||||
import styles from "./Footer.module.css";
|
||||
@ -47,7 +47,7 @@ const Footer = ({ className, ...rest }: FooterProps) => {
|
||||
width="1.25em"
|
||||
className={styles.icon}
|
||||
>
|
||||
<path d="M18.665 21.978C16.758 23.255 14.465 24 12 24 5.377 24 0 18.623 0 12S5.377 0 12 0s12 5.377 12 12c0 3.583-1.574 6.801-4.067 9.001L9.219 7.2H7.2v9.596h1.615V9.251l9.85 12.727Zm-3.332-8.533 1.6 2.061V7.2h-1.6v6.245Z"></path>
|
||||
<path d="M18.665 21.978C16.758 23.255 14.465 24 12 24 5.377 24 0 18.623 0 12S5.377 0 12 0s12 5.377 12 12c0 3.583-1.574 6.801-4.067 9.001L9.219 7.2H7.2v9.596h1.615V9.251l9.85 12.727Zm-3.332-8.533 1.6 2.061V7.2h-1.6v6.245Z" />
|
||||
</svg>
|
||||
</Link>
|
||||
.{" "}
|
||||
|
@ -12,7 +12,7 @@ const Gist = async ({ id, file }: GistProps) => {
|
||||
const scriptResponse = await fetch(scriptUrl);
|
||||
|
||||
if (!scriptResponse.ok) {
|
||||
console.warn(`[gist] fetching js for https://gist.github.com/${id} failed:`, scriptResponse.statusText);
|
||||
console.warn(`[gist] failed to fetch js:`, scriptResponse.statusText);
|
||||
|
||||
return (
|
||||
<p style={{ textAlign: "center" }}>
|
||||
@ -33,10 +33,9 @@ const Gist = async ({ id, file }: GistProps) => {
|
||||
scrolling="no"
|
||||
id={iframeId}
|
||||
srcDoc={iframeHtml}
|
||||
sandbox="allow-same-origin allow-scripts allow-popups allow-top-navigation-by-user-activation"
|
||||
style={{ border: "0", overflow: "hidden" }}
|
||||
suppressHydrationWarning
|
||||
></iframe>
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -2,7 +2,7 @@ import clsx from "clsx";
|
||||
import Link from "../Link";
|
||||
import Image from "../Image";
|
||||
import Menu from "../Menu";
|
||||
import config from "../../lib/config/constants";
|
||||
import config from "../../lib/config";
|
||||
import type { ComponentPropsWithoutRef } from "react";
|
||||
|
||||
import styles from "./Header.module.css";
|
||||
|
@ -3,7 +3,9 @@ import type { ComponentPropsWithoutRef } from "react";
|
||||
|
||||
import styles from "./HorizontalRule.module.css";
|
||||
|
||||
const HorizontalRule = ({ className, ...rest }: ComponentPropsWithoutRef<"hr">) => (
|
||||
export type HorizontalRuleProps = ComponentPropsWithoutRef<"hr">;
|
||||
|
||||
const HorizontalRule = ({ className, ...rest }: HorizontalRuleProps) => (
|
||||
<hr className={clsx(styles.hr, className)} {...rest} />
|
||||
);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import NextLink from "next/link";
|
||||
import clsx from "clsx";
|
||||
import objStr from "obj-str";
|
||||
import config from "../../lib/config/constants";
|
||||
import config from "../../lib/config";
|
||||
import type { ComponentPropsWithoutRef } from "react";
|
||||
|
||||
import styles from "./Link.module.css";
|
||||
|
@ -79,7 +79,8 @@ export const ThemeProvider = ({ children }: PropsWithChildren) => {
|
||||
id="restore-theme"
|
||||
// unminified: https://gist.github.com/jakejarvis/79b0ec8506bc843023546d0d29861bf0
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `(()=>{try{const e=document.documentElement,t="undefined"!=typeof Storage?window.localStorage.getItem("theme"):null,a=(t&&"dark"===t)??window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light";e.dataset.theme=a,e.style.colorScheme=a}catch(e){}})()`,
|
||||
__html:
|
||||
"(()=>{try{const e=document.documentElement,t='undefined'!=typeof Storage?window.localStorage.getItem('theme'):null,a=(t&&'dark'===t)??window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light';e.dataset.theme=a,e.style.colorScheme=a}catch(e){}})()",
|
||||
}}
|
||||
/>
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
const constants = {
|
||||
const config = {
|
||||
// Site info
|
||||
siteName: "Jake Jarvis",
|
||||
siteLocale: "en-US",
|
||||
baseUrl:
|
||||
// same logic as metadataBase: https://nextjs.org/docs/app/api-reference/functions/generate-metadata#default-value
|
||||
process.env.NEXT_PUBLIC_VERCEL_ENV === "production" && process.env.NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL
|
||||
? `https://${process.env.NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL}`
|
||||
: process.env.NEXT_PUBLIC_VERCEL_ENV === "preview" && process.env.NEXT_PUBLIC_VERCEL_URL
|
||||
@ -35,4 +36,4 @@ const constants = {
|
||||
},
|
||||
};
|
||||
|
||||
export default constants;
|
||||
export default config;
|
@ -1,6 +1,6 @@
|
||||
import { Feed } from "feed";
|
||||
import { getAllPosts } from "./posts";
|
||||
import config from "../config/constants";
|
||||
import config from "../config";
|
||||
|
||||
import meJpg from "../../app/me.jpg";
|
||||
|
||||
|
@ -5,7 +5,7 @@ import dayjsRelativeTime from "dayjs/plugin/relativeTime";
|
||||
import dayjsLocalizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import dayjsAdvancedFormat from "dayjs/plugin/advancedFormat";
|
||||
import "dayjs/locale/en";
|
||||
import config from "../config/constants";
|
||||
import config from "../config";
|
||||
|
||||
const IsomorphicDayJs = (date?: dayjs.ConfigType): dayjs.Dayjs => {
|
||||
// plugins
|
||||
|
@ -3,7 +3,7 @@ import glob from "fast-glob";
|
||||
import pMap from "p-map";
|
||||
import pMemoize from "p-memoize";
|
||||
import { formatDate } from "./format-date";
|
||||
import config from "../config/constants";
|
||||
import config from "../config";
|
||||
|
||||
// path to directory with .mdx files, relative to project root
|
||||
const POSTS_DIR = "notes";
|
||||
|
@ -14,7 +14,7 @@ import YouTube from "./components/YouTube";
|
||||
import Gist from "./components/Gist";
|
||||
import CodePen from "./components/CodePen";
|
||||
|
||||
export function useMDXComponents(components: MDXComponents): MDXComponents {
|
||||
export const useMDXComponents = (components: MDXComponents): MDXComponents => {
|
||||
return {
|
||||
...components,
|
||||
|
||||
@ -44,4 +44,4 @@ export function useMDXComponents(components: MDXComponents): MDXComponents {
|
||||
Gist,
|
||||
CodePen,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -1,17 +1,17 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import type { NextRequest } from "next/server";
|
||||
|
||||
import siteConfig from "./lib/config/constants";
|
||||
import siteConfig from "./lib/config";
|
||||
|
||||
// assign "short codes" to approved reverse proxy destinations. for example:
|
||||
// ["abc", "https://jakejarvis.github.io/blah"] => /_stream/abc/123.html -> https://jakejarvis.github.io/blah/123.html
|
||||
// ["abc", "https://jakejarvis.github.io"] => /_stream/abc/123.html -> https://jakejarvis.github.io/123.html
|
||||
const rewritePrefix = "/_stream/";
|
||||
const rewrites = new Map([
|
||||
// umami backend, see https://umami.is/docs/guides/running-on-vercel#proxy-umami-analytics-via-vercel
|
||||
["u", process.env.NEXT_PUBLIC_UMAMI_HOST || "https://cloud.umami.is"],
|
||||
["u", process.env.NEXT_PUBLIC_UMAMI_URL || "https://cloud.umami.is"],
|
||||
]);
|
||||
|
||||
export function middleware(request: NextRequest) {
|
||||
export const middleware = (request: NextRequest) => {
|
||||
const headers = new Headers();
|
||||
|
||||
// https://gitweb.torproject.org/tor-browser-spec.git/tree/proposals/100-onion-location-header.txt
|
||||
@ -31,9 +31,6 @@ export function middleware(request: NextRequest) {
|
||||
// search the rewrite map for the short code
|
||||
const proxiedOrigin = rewrites.get(key);
|
||||
|
||||
// TODO: remove debugging headers
|
||||
headers.set("x-middleware-proxy-key", key);
|
||||
|
||||
// return a 400 error if a rewrite was requested but the short code isn't found
|
||||
if (!proxiedOrigin) {
|
||||
return NextResponse.json(
|
||||
@ -50,7 +47,7 @@ export function middleware(request: NextRequest) {
|
||||
const proxiedUrl = new URL(`${proxiedPath}${request.nextUrl.search}`, proxiedOrigin);
|
||||
|
||||
// TODO: remove debugging headers
|
||||
headers.set("x-middleware-proxy-to", proxiedUrl.toString());
|
||||
headers.set("x-middleware-rewrite", proxiedUrl.toString());
|
||||
|
||||
// finally do the rewriting
|
||||
return NextResponse.rewrite(proxiedUrl, {
|
||||
@ -64,7 +61,7 @@ export function middleware(request: NextRequest) {
|
||||
request,
|
||||
headers,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const config = {
|
||||
// save compute time by skipping middleware for static and metadata files
|
||||
|
@ -40,23 +40,13 @@ const nextConfig: NextConfig = {
|
||||
],
|
||||
},
|
||||
],
|
||||
rewrites: async () => ({
|
||||
beforeFiles: [
|
||||
rewrites: async () => [
|
||||
{
|
||||
// https://github.com/jakejarvis/tweets
|
||||
source: "/tweets/:path*",
|
||||
destination: "https://tweets-khaki.vercel.app/:path*",
|
||||
},
|
||||
],
|
||||
afterFiles: [
|
||||
{
|
||||
// access security.txt, etc at both /security.txt and /.well-known/security.txt
|
||||
source: "/.well-known/:slug.txt",
|
||||
destination: "/:slug.txt",
|
||||
},
|
||||
],
|
||||
fallback: [],
|
||||
}),
|
||||
redirects: async () => [
|
||||
{ source: "/y2k", destination: "https://y2k.pages.dev", permanent: false },
|
||||
{
|
||||
|
@ -28,7 +28,6 @@ I've written a simple implementation below, which...
|
||||
title="Dark Mode Example"
|
||||
loading="lazy"
|
||||
style={{ height: "190px", width: "100%" }}
|
||||
sandbox="allow-same-origin allow-scripts allow-popups allow-top-navigation-by-user-activation"
|
||||
></iframe>
|
||||
|
||||
A _very_ barebones example is embedded above ([view the source here](https://github.com/jakejarvis/dark-mode-example), or [open in a new window](https://jakejarvis.github.io/dark-mode-example/) if your browser is blocking the frame) and you can try it out on this site by clicking the 💡 lightbulb in the upper right corner of this page. You'll notice that the dark theme sticks when refreshing this page, navigating between other pages, or if you were to return to this example weeks from now.
|
||||
|
@ -35,7 +35,7 @@
|
||||
- Umami
|
||||
- Giscus
|
||||
- Resend
|
||||
- ...and more: https://jarv.is/uses/
|
||||
- ...and more: https://jarv.is/uses
|
||||
|
||||
# VIEW SOURCE
|
||||
|
||||
@ -43,7 +43,7 @@
|
||||
|
||||
# PRIVACY POLICY
|
||||
|
||||
https://jarv.is/privacy/
|
||||
https://jarv.is/privacy
|
||||
|
||||
# TOR MIRROR
|
||||
|
||||
@ -54,4 +54,4 @@
|
||||
All content is licensed under CC-BY-4.0, an
|
||||
open & permissive Creative Commons license:
|
||||
|
||||
https://jarv.is/license/
|
||||
https://jarv.is/license
|
||||
|
@ -1,24 +0,0 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA256
|
||||
|
||||
Contact: https://jarv.is/contact/
|
||||
Encryption: https://jarv.is/pubkey.asc
|
||||
Encryption: openpgp4fpr:3bc6e5776bf379d36f6714802b0c9cf251e69a39
|
||||
Preferred-Languages: en
|
||||
Expires: 2025-01-01T06:00:00.000Z
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIzBAEBCAAdFiEEO8bld2vzedNvZxSAKwyc8lHmmjkFAmXTsxwACgkQKwyc8lHm
|
||||
mjlwqA//ZyIYleG3sh5OeVpHS0mI4Tr5crR6SG08A5DEwe8ysbQqDhPx0LxodRMd
|
||||
XulfZ+TIDM3TXmw7LffeiKpRRFm0ecQtQT3hKorQgzHtUuKoPdr6gPC7Lrs9H7fE
|
||||
4QlAa/WM4M/yYJfW9HZnh1/2Lh5LulQ4dkGAhb5cBvSCAWYF3W0eLjUXI6xBWyzx
|
||||
FEnfTxsFCBd2h1g+S/Sc99mOvwHkcMOZflsiWCvXJb8ELwcusAK4SWYUM/bTJMil
|
||||
a3BzvYinjyGEGqX2u+SNp+6ZxFYpDUCq8Vl+LPUFvlYpfjqVjiK9knZBHo2YADH0
|
||||
6HPP+FdMUnZTd3gGwLsUS4NOcXWqqRivL9bWOVgklsoawjOeQtelgrGXrzhtIaYo
|
||||
bbUko3kpYBy9EkGKtefQ4BYAy3CTjFjfkeadm5EOXPFdEEPjQRqdfJdniHCYG+27
|
||||
xmriwobd2Ht+e3f0oOOf7Ae/ZD9MvaAA5Qn5uIbebVQaOxjetKbKGwDiPSLRJ5On
|
||||
zfOsJn2qY1NVjWG6IlqNHpI1vjzmNOsFFlknELg5NOFstpXvLYGX1TkqBnI2g3f4
|
||||
KuGXx4gOoq2oyoZuCi2bGO0Yn6lZ1UlEnfAO2ixW2FAPe8gqzxCeyxHzgvb4vNbr
|
||||
VpmZuRxsOcdCgvItZkYCaS164GYvRTPWCtC1Q3lzAZViCOgMUmk=
|
||||
=XWDQ
|
||||
-----END PGP SIGNATURE-----
|
Loading…
x
Reference in New Issue
Block a user