1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2025-04-26 09:05:22 -04:00

bump next to 13.5

This commit is contained in:
Jake Jarvis 2023-10-02 11:59:15 -04:00
parent 1d8c2eab99
commit 893db7e951
Signed by: jake
GPG Key ID: 2B0C9CF251E69A39
24 changed files with 707 additions and 2528 deletions

View File

@ -1 +1 @@
18.17.1 18.18.0

View File

@ -11,9 +11,9 @@ I keep an ongoing list of [post ideas](https://github.com/jakejarvis/jarv.is/iss
## 🕹️ Getting Started ## 🕹️ Getting Started
Run `pnpm install` to install the necessary dependencies and `pnpm run dev` to start the local server, and then open [http://localhost:3000/](http://localhost:3000/). Pages will live-refresh when source files are changed. ([pnpm is required!](https://pnpm.io/installation)) Run `pnpm install` to install the necessary dependencies and `pnpm dev` to start the local server, and then open [http://localhost:3000/](http://localhost:3000/). Pages will live-refresh when source files are changed.
Most production steps are handled [automatically by Vercel](https://vercel.com/docs/concepts/next.js/overview#supported-next.js-features), but running `pnpm build` locally will still generate an unoptimized, less-than-ideal static version. Most production steps are handled [automatically by Vercel](https://vercel.com/docs/frameworks/nextjs), but running `pnpm build` locally will still generate an unoptimized, less-than-ideal static version which can be served via `pnpm start`.
**⚡ Bonus tip:** [Volta](https://volta.sh/), a magical, blazing-fast alternative to [nvm](https://github.com/nvm-sh/nvm), is used to pin the exact Node.js version used for development. It's completely optional but I highly recommend it in general! **⚡ Bonus tip:** [Volta](https://volta.sh/), a magical, blazing-fast alternative to [nvm](https://github.com/nvm-sh/nvm), is used to pin the exact Node.js version used for development. It's completely optional but I highly recommend it in general!

View File

@ -3,7 +3,8 @@ import { Formik, Form, Field } from "formik";
import TextareaAutosize from "react-textarea-autosize"; import TextareaAutosize from "react-textarea-autosize";
import Link from "../Link"; import Link from "../Link";
import Captcha from "../Captcha"; import Captcha from "../Captcha";
import { CheckOcticon, XOcticon, MarkdownIcon } from "../Icons"; import { GoCheck, GoX } from "react-icons/go";
import { SiMarkdown } from "react-icons/si";
import { styled, theme, css } from "../../lib/styles/stitches.config"; import { styled, theme, css } from "../../lib/styles/stitches.config";
import type { FormikHelpers, FormikProps, FieldInputProps, FieldMetaProps } from "formik"; import type { FormikHelpers, FormikProps, FieldInputProps, FieldMetaProps } from "formik";
@ -47,8 +48,7 @@ const MarkdownTip = styled("div", {
lineHeight: 1.75, lineHeight: 1.75,
}); });
const MarkdownTipIcon = styled(MarkdownIcon, { const MarkdownTipIcon = styled(SiMarkdown, {
fill: "currentColor",
width: "1.25em", width: "1.25em",
height: "1.25em", height: "1.25em",
verticalAlign: "-0.25em", verticalAlign: "-0.25em",
@ -288,7 +288,7 @@ const ContactForm = ({ className }: ContactFormProps) => {
</SubmitButton> </SubmitButton>
<Result status={success ? "success" : "error"} hidden={!submitted || !feedback || isSubmitting}> <Result status={success ? "success" : "error"} hidden={!submitted || !feedback || isSubmitting}>
<ResultIcon as={success ? CheckOcticon : XOcticon} /> {feedback} <ResultIcon as={success ? GoCheck : GoX} /> {feedback}
</Result> </Result>
</ActionRow> </ActionRow>
</Form> </Form>

View File

@ -1,7 +1,7 @@
import { forwardRef, useState, useEffect } from "react"; import { forwardRef, useState, useEffect } from "react";
import innerText from "react-innertext"; import innerText from "react-innertext";
import copy from "copy-to-clipboard"; import copy from "copy-to-clipboard";
import { ClipboardOcticon, CheckOcticon } from "../Icons"; import { FiClipboard, FiCheck } from "react-icons/fi";
import { styled, theme } from "../../lib/styles/stitches.config"; import { styled, theme } from "../../lib/styles/stitches.config";
import type { ReactNode, Ref, ComponentPropsWithoutRef, ElementRef, MouseEventHandler } from "react"; import type { ReactNode, Ref, ComponentPropsWithoutRef, ElementRef, MouseEventHandler } from "react";
@ -29,7 +29,6 @@ const Icon = styled("svg", {
width: "1.25em", width: "1.25em",
height: "1.25em", height: "1.25em",
verticalAlign: "-0.3em", verticalAlign: "-0.3em",
fill: "currentColor",
}); });
export type CopyButtonProps = ComponentPropsWithoutRef<typeof Button> & { export type CopyButtonProps = ComponentPropsWithoutRef<typeof Button> & {
@ -77,7 +76,7 @@ const CopyButton = ({ source, timeout = 2000, ...rest }: CopyButtonProps, ref: R
copied={copied} copied={copied}
{...rest} {...rest}
> >
<Icon as={copied ? CheckOcticon : ClipboardOcticon} /> <Icon as={copied ? FiCheck : FiClipboard} />
</Button> </Button>
); );
}; };

View File

@ -1,7 +1,7 @@
import innerText from "react-innertext"; import innerText from "react-innertext";
import Image, { ImageProps } from "../Image"; import Image from "../Image";
import { styled, theme } from "../../lib/styles/stitches.config"; import { styled, theme } from "../../lib/styles/stitches.config";
import type { PropsWithChildren } from "react"; import type { PropsWithChildren, ComponentPropsWithoutRef } from "react";
const Wrapper = styled("figure", { const Wrapper = styled("figure", {
margin: "1em auto", margin: "1em auto",
@ -15,7 +15,7 @@ const Caption = styled("figcaption", {
marginTop: "-0.4em", marginTop: "-0.4em",
}); });
export type FigureProps = Omit<ImageProps, "alt"> & export type FigureProps = Omit<ComponentPropsWithoutRef<typeof Image>, "alt"> &
PropsWithChildren<{ PropsWithChildren<{
alt?: string; // becomes optional -- pulled from plaintext-ified caption if missing alt?: string; // becomes optional -- pulled from plaintext-ified caption if missing
}>; }>;

View File

@ -1,5 +1,6 @@
import Link from "../Link"; import Link from "../Link";
import { HeartIcon, NextjsLogo } from "../Icons"; import { GoHeartFill } from "react-icons/go";
import { SiNextdotjs } from "react-icons/si";
import { styled, theme, keyframes } from "../../lib/styles/stitches.config"; import { styled, theme, keyframes } from "../../lib/styles/stitches.config";
import * as config from "../../lib/config"; import * as config from "../../lib/config";
import type { ComponentPropsWithoutRef } from "react"; import type { ComponentPropsWithoutRef } from "react";
@ -37,27 +38,11 @@ const PlainLink = styled(Link, {
color: theme.colors.mediumDark, color: theme.colors.mediumDark,
}); });
const NextjsLink = styled(PlainLink, {
"&:hover, &:focus-visible": {
color: theme.colors.medium,
},
});
const ViewSourceLink = styled(PlainLink, {
paddingBottom: "2px",
borderBottom: `1px solid ${theme.colors.light}`,
"&:hover, &:focus-visible": {
borderColor: theme.colors.kindaLight,
},
});
const Icon = styled("svg", { const Icon = styled("svg", {
width: "1.25em", width: "1.25em",
height: "1.25em", height: "1.25em",
verticalAlign: "-0.25em", verticalAlign: "-0.25em",
margin: "0 0.075em", margin: "0 0.075em",
fill: "currentColor",
}); });
const Heart = styled("span", { const Heart = styled("span", {
@ -99,20 +84,38 @@ const Footer = ({ ...rest }: FooterProps) => {
<div> <div>
Made with{" "} Made with{" "}
<Heart title="Love"> <Heart title="Love">
<Icon as={HeartIcon} /> <Icon as={GoHeartFill} css={{ strokeWidth: 2 }} />
</Heart>{" "} </Heart>{" "}
and{" "} and{" "}
<NextjsLink href="https://nextjs.org/" title="Powered by Next.js" aria-label="Next.js" underline={false}> <PlainLink
<Icon as={NextjsLogo} /> href="https://nextjs.org/"
</NextjsLink> title="Powered by Next.js"
aria-label="Next.js"
underline={false}
css={{
"&:hover, &:focus-visible": {
color: theme.colors.medium,
},
}}
>
<Icon as={SiNextdotjs} />
</PlainLink>
.{" "} .{" "}
<ViewSourceLink <PlainLink
href={`https://github.com/${config.githubRepo}`} href={`https://github.com/${config.githubRepo}`}
title="View Source on GitHub" title="View Source on GitHub"
underline={false} underline={false}
css={{
paddingBottom: "2px",
borderBottom: `1px solid ${theme.colors.light}`,
"&:hover, &:focus-visible": {
borderColor: theme.colors.kindaLight,
},
}}
> >
View source. View source.
</ViewSourceLink> </PlainLink>
</div> </div>
</Row> </Row>
</Wrapper> </Wrapper>

View File

@ -1,27 +1,17 @@
import Link from "../Link"; import Link from "../Link";
import { LinkIcon } from "../Icons"; import { FiLink } from "react-icons/fi";
import { styled } from "../../lib/styles/stitches.config";
import type { ComponentPropsWithoutRef } from "react"; import type { ComponentPropsWithoutRef } from "react";
const AnchorLink = styled(Link, { export type HeadingAnchorProps = Omit<ComponentPropsWithoutRef<typeof Link>, "href"> & {
lineHeight: 1,
});
const Icon = styled(LinkIcon, {
width: "0.8em",
height: "0.8em",
});
export type HeadingAnchorProps = Omit<ComponentPropsWithoutRef<typeof AnchorLink>, "href"> & {
id: string; id: string;
title: string; title: string;
}; };
const HeadingAnchor = ({ id, title, ...rest }: HeadingAnchorProps) => { const HeadingAnchor = ({ id, title, ...rest }: HeadingAnchorProps) => {
return ( return (
<AnchorLink href={`#${id}`} title={`Jump to "${title}"`} aria-hidden underline={false} {...rest}> <Link href={`#${id}`} title={`Jump to "${title}"`} aria-hidden underline={false} css={{ lineHeight: 1 }} {...rest}>
<Icon /> <FiLink size="0.8em" />
</AnchorLink> </Link>
); );
}; };

View File

@ -1,28 +0,0 @@
// Icons from various packs, imported directly from the package's SVG files instead of their exports so they're all
// processed consistently via svgr/webpack into React components.
// NOTE: each package's path inside ./node_modules *must* be listed in svgr's webpack config in next.config.js.
// feather icons: https://feathericons.com/
export { default as ContactIcon } from "feather-icons/dist/icons/mail.svg";
export { default as DateIcon } from "feather-icons/dist/icons/calendar.svg";
export { default as EditIcon } from "feather-icons/dist/icons/edit.svg";
export { default as HomeIcon } from "feather-icons/dist/icons/home.svg";
export { default as LinkIcon } from "feather-icons/dist/icons/link.svg";
export { default as NotesIcon } from "feather-icons/dist/icons/edit-3.svg";
export { default as ProjectsIcon } from "feather-icons/dist/icons/code.svg";
export { default as TagIcon } from "feather-icons/dist/icons/tag.svg";
export { default as ViewsIcon } from "feather-icons/dist/icons/eye.svg";
// octicons: https://primer.style/octicons/
export { default as CheckOcticon } from "@primer/octicons/build/svg/check-16.svg";
export { default as ClipboardOcticon } from "@primer/octicons/build/svg/paste-16.svg";
export { default as ForkOcticon } from "@primer/octicons/build/svg/repo-forked-16.svg";
export { default as HeartIcon } from "@primer/octicons/build/svg/heart-fill-16.svg";
export { default as MarkdownIcon } from "@primer/octicons/build/svg/markdown-16.svg";
export { default as OctocatOcticon } from "@primer/octicons/build/svg/mark-github-16.svg";
export { default as StarOcticon } from "@primer/octicons/build/svg/star-16.svg";
export { default as XOcticon } from "@primer/octicons/build/svg/x-16.svg";
// simple icons: https://simpleicons.org/
export { default as NextjsLogo } from "simple-icons/icons/nextdotjs.svg";
export { default as Windows95Logo } from "simple-icons/icons/windows95.svg";

View File

@ -1,5 +1,6 @@
import Link from "../Link"; import Link from "../Link";
import { styled, theme } from "../../lib/styles/stitches.config"; import { styled, theme } from "../../lib/styles/stitches.config";
import type { IconType } from "react-icons";
const MenuLink = styled(Link, { const MenuLink = styled(Link, {
display: "inline-block", display: "inline-block",
@ -45,20 +46,17 @@ const Label = styled("span", {
}); });
export type MenuItemProps = { export type MenuItemProps = {
href?: string; icon?: IconType;
text?: string; text?: string;
href?: string;
current?: boolean; current?: boolean;
className?: string; className?: string;
// `any` avoids conflicts with @svgr/webpack, see: node_modules/next/image-types/global.d.ts
// eslint-disable-next-line @typescript-eslint/no-explicit-any
icon: any;
}; };
const MenuItem = ({ icon: ItemIcon, href, text, current, className }: MenuItemProps) => { const MenuItem = ({ icon, text, href, current, className }: MenuItemProps) => {
const linkContent = ( const item = (
<> <>
<Icon as={ItemIcon} /> {icon && <Icon as={icon} />}
{text && <Label>{text}</Label>} {text && <Label>{text}</Label>}
</> </>
); );
@ -67,12 +65,12 @@ const MenuItem = ({ icon: ItemIcon, href, text, current, className }: MenuItemPr
if (href) { if (href) {
return ( return (
<MenuLink href={href} className={className} current={current} title={text} underline={false} aria-label={text}> <MenuLink href={href} className={className} current={current} title={text} underline={false} aria-label={text}>
{linkContent} {item}
</MenuLink> </MenuLink>
); );
} }
return linkContent; return item;
}; };
export default MenuItem; export default MenuItem;

View File

@ -2,7 +2,7 @@ import Link from "../Link";
import Time from "../Time"; import Time from "../Time";
import HitCounter from "../HitCounter"; import HitCounter from "../HitCounter";
import NoteTitle from "../NoteTitle"; import NoteTitle from "../NoteTitle";
import { DateIcon, TagIcon, EditIcon, ViewsIcon } from "../Icons"; import { FiCalendar, FiTag, FiEdit, FiEye } from "react-icons/fi";
import { styled, theme } from "../../lib/styles/stitches.config"; import { styled, theme } from "../../lib/styles/stitches.config";
import * as config from "../../lib/config"; import * as config from "../../lib/config";
import type { NoteFrontMatter } from "../../types"; import type { NoteFrontMatter } from "../../types";
@ -68,14 +68,14 @@ const NoteMeta = ({ slug, date, title, htmlTitle, tags }: NoteMetaProps) => {
}} }}
underline={false} underline={false}
> >
<Icon as={DateIcon} /> <Icon as={FiCalendar} />
<Time date={date} format="MMMM D, YYYY" /> <Time date={date} format="MMMM D, YYYY" />
</MetaLink> </MetaLink>
</MetaItem> </MetaItem>
{tags && ( {tags && (
<MetaItem> <MetaItem>
<Icon as={TagIcon} /> <Icon as={FiTag} />
<TagsList> <TagsList>
{tags.map((tag) => ( {tags.map((tag) => (
<Tag key={tag} title={tag} aria-label={`Tagged with ${tag}`}> <Tag key={tag} title={tag} aria-label={`Tagged with ${tag}`}>
@ -92,7 +92,7 @@ const NoteMeta = ({ slug, date, title, htmlTitle, tags }: NoteMetaProps) => {
title={`Edit "${title}" on GitHub`} title={`Edit "${title}" on GitHub`}
underline={false} underline={false}
> >
<Icon as={EditIcon} /> <Icon as={FiEdit} />
<span>Improve This Post</span> <span>Improve This Post</span>
</MetaLink> </MetaLink>
</MetaItem> </MetaItem>
@ -106,7 +106,7 @@ const NoteMeta = ({ slug, date, title, htmlTitle, tags }: NoteMetaProps) => {
marginRight: 0, marginRight: 0,
}} }}
> >
<Icon as={ViewsIcon} /> <Icon as={FiEye} />
<HitCounter slug={`notes/${slug}`} /> <HitCounter slug={`notes/${slug}`} />
</MetaItem> </MetaItem>
)} )}

View File

@ -18,23 +18,20 @@ const Title = styled("h1", {
}, },
}); });
const TitleLink = styled(Link, {
color: theme.colors.text,
});
export type NoteTitleProps = Pick<NoteFrontMatter, "slug" | "title" | "htmlTitle"> & export type NoteTitleProps = Pick<NoteFrontMatter, "slug" | "title" | "htmlTitle"> &
ComponentPropsWithoutRef<typeof Title>; ComponentPropsWithoutRef<typeof Title>;
const NoteTitle = ({ slug, title, htmlTitle, ...rest }: NoteTitleProps) => { const NoteTitle = ({ slug, title, htmlTitle, ...rest }: NoteTitleProps) => {
return ( return (
<Title {...rest}> <Title {...rest}>
<TitleLink <Link
href={{ href={{
pathname: "/notes/[slug]/", pathname: "/notes/[slug]/",
query: { slug }, query: { slug },
}} }}
dangerouslySetInnerHTML={{ __html: htmlTitle || title }} dangerouslySetInnerHTML={{ __html: htmlTitle || title }}
underline={false} underline={false}
css={{ color: theme.colors.text }}
/> />
</Title> </Title>
); );

View File

@ -1,33 +1,35 @@
import Link from "../Link"; import Link from "../Link";
import { OctocatOcticon } from "../Icons"; import { SiGithub } from "react-icons/si";
import { styled, theme } from "../../lib/styles/stitches.config"; import { styled, theme } from "../../lib/styles/stitches.config";
import type { ComponentPropsWithoutRef } from "react"; import type { ComponentPropsWithoutRef } from "react";
const GitHubLink = styled(Link, { const Octocat = styled(SiGithub, {
margin: "0 0.4em",
color: theme.colors.text,
"&:hover, &:focus-visible": {
color: theme.colors.link,
},
});
const Octocat = styled(OctocatOcticon, {
width: "1.2em", width: "1.2em",
height: "1.2em", height: "1.2em",
verticalAlign: "-0.2em", verticalAlign: "-0.2em",
fill: "currentColor",
}); });
export type OctocatLinkProps = Omit<ComponentPropsWithoutRef<typeof GitHubLink>, "href"> & { export type OctocatLinkProps = Omit<ComponentPropsWithoutRef<typeof Link>, "href"> & {
repo: string; repo: string;
}; };
const OctocatLink = ({ repo, className, ...rest }: OctocatLinkProps) => { const OctocatLink = ({ repo, className, ...rest }: OctocatLinkProps) => {
return ( return (
<GitHubLink href={`https://github.com/${repo}`} underline={false} {...rest}> <Link
href={`https://github.com/${repo}`}
underline={false}
css={{
margin: "0 0.4em",
color: theme.colors.text,
"&:hover, &:focus-visible": {
color: theme.colors.link,
},
}}
{...rest}
>
<Octocat className={className} /> <Octocat className={className} />
</GitHubLink> </Link>
); );
}; };

View File

@ -15,10 +15,6 @@ const Title = styled("h1", {
}, },
}); });
const TitleLink = styled(Link, {
color: theme.colors.text,
});
export type PageTitleProps = ComponentPropsWithoutRef<typeof Title>; export type PageTitleProps = ComponentPropsWithoutRef<typeof Title>;
const PageTitle = ({ children, ...rest }: PageTitleProps) => { const PageTitle = ({ children, ...rest }: PageTitleProps) => {
@ -26,9 +22,9 @@ const PageTitle = ({ children, ...rest }: PageTitleProps) => {
return ( return (
<Title {...rest}> <Title {...rest}>
<TitleLink href={router.pathname} underline={false}> <Link href={router.pathname} underline={false} css={{ color: theme.colors.text }}>
{children} {children}
</TitleLink> </Link>
</Title> </Title>
); );
}; };

View File

@ -1,7 +1,7 @@
import commaNumber from "comma-number"; import commaNumber from "comma-number";
import Link from "../Link"; import Link from "../Link";
import RelativeTime from "../RelativeTime"; import RelativeTime from "../RelativeTime";
import { StarOcticon, ForkOcticon } from "../Icons"; import { GoStar, GoRepoForked } from "react-icons/go";
import { styled, theme } from "../../lib/styles/stitches.config"; import { styled, theme } from "../../lib/styles/stitches.config";
import type { Project } from "../../types"; import type { Project } from "../../types";
@ -50,9 +50,9 @@ const MetaLink = styled(Link, {
const MetaIcon = styled("svg", { const MetaIcon = styled("svg", {
width: "16px", width: "16px",
height: "16px", height: "16px",
verticalAlign: "text-bottom", verticalAlign: "-0.3em",
marginRight: "0.5em", marginRight: "0.5em",
fill: "currentColor", strokeWidth: 0.75,
}); });
const LanguageCircle = styled("span", { const LanguageCircle = styled("span", {
@ -100,7 +100,7 @@ const RepositoryCard = ({
title={`${commaNumber(stars)} ${stars === 1 ? "star" : "stars"}`} title={`${commaNumber(stars)} ${stars === 1 ? "star" : "stars"}`}
underline={false} underline={false}
> >
<MetaIcon as={StarOcticon} /> <MetaIcon as={GoStar} />
{commaNumber(stars)} {commaNumber(stars)}
</MetaLink> </MetaLink>
</MetaItem> </MetaItem>
@ -113,7 +113,7 @@ const RepositoryCard = ({
title={`${commaNumber(forks)} ${forks === 1 ? "fork" : "forks"}`} title={`${commaNumber(forks)} ${forks === 1 ? "fork" : "forks"}`}
underline={false} underline={false}
> >
<MetaIcon as={ForkOcticon} /> <MetaIcon as={GoRepoForked} />
{commaNumber(forks)} {commaNumber(forks)}
</MetaLink> </MetaLink>
</MetaItem> </MetaItem>

View File

@ -17,9 +17,9 @@ const ThemeScript = memo<ThemeScriptProps>(({ themeClassNames, themeStorageKey }
// since the client function will end up being injected as a static hard-coded string, we need to determine all of // since the client function will end up being injected as a static hard-coded string, we need to determine all of
// the dynamic values within it *before* generating the final script. // the dynamic values within it *before* generating the final script.
const source = String(clientScript) const source = String(clientScript)
.replace("__MEDIA_QUERY__", "(prefers-color-scheme: dark)") .replaceAll("__MEDIA_QUERY__", "(prefers-color-scheme: dark)")
.replace("__STORAGE_KEY__", themeStorageKey) .replaceAll("__STORAGE_KEY__", themeStorageKey)
.replace("__CLASS_NAMES__", Object.values(themeClassNames).join('","')); .replaceAll("__CLASS_NAMES__", Object.values(themeClassNames).join('","'));
// turn the raw function into an iife // turn the raw function into an iife
const unminified = `(${source})()`; const unminified = `(${source})()`;

View File

@ -17,7 +17,7 @@ export const clientScript = () => {
const newTheme = (pref && pref === "dark") ?? window.matchMedia("__MEDIA_QUERY__").matches ? 1 : 0; const newTheme = (pref && pref === "dark") ?? window.matchMedia("__MEDIA_QUERY__").matches ? 1 : 0;
// remove both `classNames` to start fresh... // remove both `classNames` to start fresh...
classList.remove(classNames[0], classNames[1]); classList.remove(...classNames);
// ...and then FINALLY set the root class // ...and then FINALLY set the root class
classList.add(classNames[newTheme]); classList.add(classNames[newTheme]);

View File

@ -1,24 +1,24 @@
import { HomeIcon, NotesIcon, ProjectsIcon, ContactIcon } from "../../components/Icons"; import { FiHome, FiEdit3, FiCode, FiMail } from "react-icons/fi";
import type { MenuItemProps } from "../../components/MenuItem"; import type { MenuItemProps } from "../../components/MenuItem";
export const menuItems: MenuItemProps[] = [ export const menuItems: MenuItemProps[] = [
{ {
icon: HomeIcon, icon: FiHome,
text: "Home", text: "Home",
href: "/", href: "/",
}, },
{ {
icon: NotesIcon, icon: FiEdit3,
text: "Notes", text: "Notes",
href: "/notes", href: "/notes",
}, },
{ {
icon: ProjectsIcon, icon: FiCode,
text: "Projects", text: "Projects",
href: "/projects", href: "/projects",
}, },
{ {
icon: ContactIcon, icon: FiMail,
text: "Contact", text: "Contact",
href: "/contact", href: "/contact",
}, },

View File

@ -1,6 +1,5 @@
// @ts-check // @ts-check
/* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable @typescript-eslint/no-var-requires */
const path = require("path");
const config = require("./lib/config"); const config = require("./lib/config");
/** /**
@ -36,37 +35,8 @@ const nextConfig = {
], ],
}, },
experimental: { experimental: {
legacyBrowsers: false, largePageDataBytes: 512 * 1000, // raise getStaticProps limit to 512 kB since compiled MDX will exceed the default.
newNextLinkBehavior: true, // https://github.com/vercel/next.js/pull/36436
optimisticClientCache: false, // https://github.com/vercel/next.js/discussions/40268#discussioncomment-3572642 optimisticClientCache: false, // https://github.com/vercel/next.js/discussions/40268#discussioncomment-3572642
largePageDataBytes: 128 * 1000, // raise getStaticProps limit to 512 kB since compiled MDX might exceed this.
},
webpack: (config) => {
// allow processing SVGs from the below packages directly instead of through their different exports, and leave
// other static imports of SVGs alone.
// see: ./components/Icons/index.ts
config.module.rules.push({
test: /\.svg$/i,
issuer: { and: [/\.(js|ts)x?$/] },
use: [
{
loader: "@svgr/webpack",
options: {
icon: true,
typescript: true,
svgProps: {
"aria-hidden": true,
},
},
},
],
include: ["@primer/octicons", "feather-icons", "simple-icons"].map(
// pnpm uses symlinks extensively, so path.resolve(__dirname, "node_modules/...") won't cut it here.
(pkg) => path.dirname(require.resolve(pkg)) // => node_modules/.pnpm/feather-icons@4.29.0/node_modules/feather-icons/dist
),
});
return config;
}, },
eslint: { eslint: {
// https://nextjs.org/docs/basic-features/eslint#linting-custom-directories-and-files // https://nextjs.org/docs/basic-features/eslint#linting-custom-directories-and-files

View File

@ -20,24 +20,22 @@
"dependencies": { "dependencies": {
"@giscus/react": "^2.3.0", "@giscus/react": "^2.3.0",
"@hcaptcha/react-hcaptcha": "^1.8.1", "@hcaptcha/react-hcaptcha": "^1.8.1",
"@novnc/novnc": "1.4.0-ge81602d", "@novnc/novnc": "1.4.0",
"@octokit/graphql": "^7.0.1", "@octokit/graphql": "^7.0.2",
"@octokit/graphql-schema": "^14.27.3", "@octokit/graphql-schema": "^14.33.0",
"@primer/octicons": "^19.7.0", "@prisma/client": "^5.3.1",
"@prisma/client": "^5.2.0",
"@react-spring/web": "^9.7.3", "@react-spring/web": "^9.7.3",
"@stitches/react": "1.3.1-1", "@stitches/react": "1.3.1-1",
"@vercel/postgres": "^0.4.1", "@vercel/postgres": "^0.5.0",
"comma-number": "^2.1.0", "comma-number": "^2.1.0",
"copy-to-clipboard": "^3.3.3", "copy-to-clipboard": "^3.3.3",
"dayjs": "^1.11.9", "dayjs": "^1.11.10",
"fast-glob": "^3.3.1", "fast-glob": "^3.3.1",
"fathom-client": "^3.5.0", "fathom-client": "^3.5.0",
"feather-icons": "^4.29.1",
"feed": "^4.2.2", "feed": "^4.2.2",
"formik": "^2.4.4", "formik": "^2.4.5",
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",
"next": "13.4.19", "next": "13.5.3",
"next-mdx-remote": "^4.4.1", "next-mdx-remote": "^4.4.1",
"next-seo": "^6.1.0", "next-seo": "^6.1.0",
"obj-str": "^1.1.0", "obj-str": "^1.1.0",
@ -50,6 +48,7 @@
"react-dom": "18.2.0", "react-dom": "18.2.0",
"react-error-boundary": "^4.0.11", "react-error-boundary": "^4.0.11",
"react-gist": "^1.2.4", "react-gist": "^1.2.4",
"react-icons": "^4.11.0",
"react-innertext": "^1.1.5", "react-innertext": "^1.1.5",
"react-intersection-observer": "^9.5.2", "react-intersection-observer": "^9.5.2",
"react-is": "18.2.0", "react-is": "18.2.0",
@ -66,41 +65,39 @@
"remark-smartypants": "^2.0.0", "remark-smartypants": "^2.0.0",
"remark-unwrap-images": "^3.0.1", "remark-unwrap-images": "^3.0.1",
"remove-markdown": "^0.5.0", "remove-markdown": "^0.5.0",
"simple-icons": "^9.13.0",
"sitemap": "^7.1.1", "sitemap": "^7.1.1",
"stitches-normalize": "^2.0.0", "stitches-normalize": "^2.0.0",
"swr": "^2.2.2", "swr": "^2.2.4",
"unified": "^10.1.2" "unified": "^10.1.2"
}, },
"devDependencies": { "devDependencies": {
"@jakejarvis/eslint-config": "^3.1.0", "@jakejarvis/eslint-config": "^3.1.0",
"@svgr/webpack": "^8.1.0",
"@types/comma-number": "^2.1.0", "@types/comma-number": "^2.1.0",
"@types/node": "^18.17.14", "@types/node": "^18.17.14",
"@types/novnc__novnc": "^1.3.0", "@types/novnc__novnc": "^1.3.2",
"@types/prop-types": "^15.7.5", "@types/prop-types": "^15.7.8",
"@types/react": "^18.2.21", "@types/react": "^18.2.24",
"@types/react-dom": "^18.2.7", "@types/react-dom": "^18.2.8",
"@types/react-is": "^18.2.1", "@types/react-is": "^18.2.2",
"@types/remove-markdown": "^0.3.1", "@types/remove-markdown": "^0.3.2",
"@types/uglify-js": "^3.17.2", "@types/uglify-js": "^3.17.2",
"@typescript-eslint/eslint-plugin": "^6.6.0", "@typescript-eslint/eslint-plugin": "^6.7.3",
"@typescript-eslint/parser": "^6.6.0", "@typescript-eslint/parser": "^6.7.3",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"eslint": "~8.48.0", "eslint": "~8.50.0",
"eslint-config-next": "13.4.19", "eslint-config-next": "13.5.3",
"eslint-config-prettier": "~8.8.0", "eslint-config-prettier": "~9.0.0",
"eslint-plugin-mdx": "~2.2.0", "eslint-plugin-mdx": "~2.2.0",
"eslint-plugin-prettier": "~4.2.1", "eslint-plugin-prettier": "~5.0.0",
"lint-staged": "^14.0.1", "lint-staged": "^14.0.1",
"prettier": "^2.8.8", "prettier": "^3.0.3",
"prisma": "^5.2.0", "prisma": "^5.3.1",
"simple-git-hooks": "^2.9.0", "simple-git-hooks": "^2.9.0",
"typescript": "^5.2.2", "typescript": "^5.2.2",
"uglify-js": "^3.17.4" "uglify-js": "^3.17.4"
}, },
"optionalDependencies": { "optionalDependencies": {
"sharp": "^0.32.5" "sharp": "^0.32.6"
}, },
"engines": { "engines": {
"node": ">=16.x" "node": ">=16.x"
@ -117,9 +114,9 @@
"eslint" "eslint"
] ]
}, },
"packageManager": "pnpm@8.7.4", "packageManager": "pnpm@8.8.0",
"volta": { "volta": {
"node": "18.17.1", "node": "18.18.0",
"pnpm": "8.7.4" "pnpm": "8.8.0"
} }
} }

View File

@ -5,11 +5,6 @@ import Link from "../components/Link";
import ContactForm from "../components/ContactForm"; import ContactForm from "../components/ContactForm";
import { styled } from "../lib/styles/stitches.config"; import { styled } from "../lib/styles/stitches.config";
const Wrapper = styled(Content, {
maxWidth: "600px",
margin: "0 auto",
});
const PGPKey = styled("code", { const PGPKey = styled("code", {
fontSize: "0.925em", fontSize: "0.925em",
wordSpacing: "-0.25em", wordSpacing: "-0.25em",
@ -27,7 +22,12 @@ const Contact = () => {
<PageTitle>📬 Contact Me</PageTitle> <PageTitle>📬 Contact Me</PageTitle>
<Wrapper> <Content
css={{
maxWidth: "600px",
margin: "0 auto",
}}
>
<p> <p>
Fill out this quick form and I'll get back to you as soon as I can! You can also{" "} Fill out this quick form and I'll get back to you as soon as I can! You can also{" "}
<Link href="mailto:jake@jarv.is">email me directly</Link>, send me a{" "} <Link href="mailto:jake@jarv.is">email me directly</Link>, send me a{" "}
@ -43,7 +43,7 @@ const Contact = () => {
</p> </p>
<ContactForm /> <ContactForm />
</Wrapper> </Content>
</> </>
); );
}; };

View File

@ -1,12 +1,14 @@
import Link, { LinkProps } from "../components/Link"; import Link from "../components/Link";
import { GoLock } from "react-icons/go";
import { styled, theme, darkTheme, keyframes, stitchesConfig } from "../lib/styles/stitches.config"; import { styled, theme, darkTheme, keyframes, stitchesConfig } from "../lib/styles/stitches.config";
import type { ComponentPropsWithoutRef } from "react";
const ColorfulLink = ({ const ColorfulLink = ({
lightColor, lightColor,
darkColor, darkColor,
css, css,
...rest ...rest
}: LinkProps & { }: ComponentPropsWithoutRef<typeof Link> & {
lightColor: string; lightColor: string;
darkColor: string; darkColor: string;
}) => { }) => {
@ -333,7 +335,8 @@ const Index = () => {
underline={false} underline={false}
openInNewTab openInNewTab
> >
🔐 <PGPKey>2B0C 9CF2 51E6 9A39</PGPKey> <GoLock size="1.25em" style={{ verticalAlign: "-0.25em", strokeWidth: 0.5 }} />{" "}
<PGPKey>2B0C 9CF2 51E6 9A39</PGPKey>
</ColorfulLink> </ColorfulLink>
</Sup> </Sup>
,{" "} ,{" "}

View File

@ -7,7 +7,7 @@ import Figure from "../components/Figure";
import IFrame from "../components/IFrame"; import IFrame from "../components/IFrame";
import CodeInline from "../components/CodeInline"; import CodeInline from "../components/CodeInline";
import HorizontalRule from "../components/HorizontalRule"; import HorizontalRule from "../components/HorizontalRule";
import { Windows95Logo } from "../components/Icons"; import { SiWindows95 } from "react-icons/si";
import { styled, theme } from "../lib/styles/stitches.config"; import { styled, theme } from "../lib/styles/stitches.config";
import { ComicNeue } from "../lib/styles/fonts"; import { ComicNeue } from "../lib/styles/fonts";
import type { ReactElement } from "react"; import type { ReactElement } from "react";
@ -41,11 +41,11 @@ const Divider = styled(HorizontalRule, {
margin: "1em auto", margin: "1em auto",
}); });
const Icon = styled("svg", { const WindowsLogo = styled(SiWindows95, {
width: "1.2em", width: "1.2em",
height: "1.2em", height: "1.2em",
verticalAlign: "-0.15em", verticalAlign: "-0.15em",
marginRight: "0.15em", marginRight: "0.1em",
fill: "currentColor", fill: "currentColor",
}); });
@ -95,7 +95,7 @@ const Previously = () => {
fontSize: "0.95em", fontSize: "0.95em",
}} }}
> >
<Icon as={Windows95Logo} /> Click here for the <em>full</em> experience anyway. <WindowsLogo /> Click here for the <em>full</em> experience anyway.
</Link> </Link>
<ScreenShot as="figure"> <ScreenShot as="figure">

View File

@ -4,7 +4,7 @@ import Content from "../components/Content";
import PageTitle from "../components/PageTitle"; import PageTitle from "../components/PageTitle";
import Link from "../components/Link"; import Link from "../components/Link";
import RepositoryCard from "../components/RepositoryCard"; import RepositoryCard from "../components/RepositoryCard";
import { OctocatOcticon } from "../components/Icons"; import { SiGithub } from "react-icons/si";
import { styled, theme } from "../lib/styles/stitches.config"; import { styled, theme } from "../lib/styles/stitches.config";
import { authorSocial } from "../lib/config"; import { authorSocial } from "../lib/config";
import type { GetStaticProps, InferGetStaticPropsType } from "next"; import type { GetStaticProps, InferGetStaticPropsType } from "next";
@ -34,7 +34,7 @@ const ViewMore = styled("p", {
fontWeight: 500, fontWeight: 500,
}); });
const GitHubLogo = styled(OctocatOcticon, { const GitHubLogo = styled(SiGithub, {
width: "1.2em", width: "1.2em",
height: "1.2em", height: "1.2em",
verticalAlign: "-0.2em", verticalAlign: "-0.2em",

2884
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff