pre-render optimizations
@ -7,7 +7,8 @@ const Analytics = () => {
|
||||
|
||||
return (
|
||||
<Script
|
||||
src="/_stream/u/script.js" // see next.config.ts rewrite
|
||||
src="/_stream/u/script.js" // see middleware rewrite
|
||||
id="umami-js"
|
||||
strategy="afterInteractive"
|
||||
data-website-id={process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID}
|
||||
data-domains={process.env.NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL}
|
||||
|
BIN
app/birthday/opengraph-image.png
Normal file
After Width: | Height: | Size: 128 KiB |
@ -11,7 +11,6 @@ export const metadata: Metadata = {
|
||||
openGraph: {
|
||||
...defaultMetadata.openGraph,
|
||||
title: "🎉 Cranky Birthday Boy on VHS Tape 📼",
|
||||
images: [thumbnail.src],
|
||||
url: "/birthday",
|
||||
},
|
||||
alternates: {
|
||||
|
BIN
app/cli/opengraph-image.png
Normal file
After Width: | Height: | Size: 110 KiB |
@ -1,15 +1,12 @@
|
||||
import PageTitle from "../../components/PageTitle";
|
||||
import { metadata as defaultMetadata } from "../layout";
|
||||
|
||||
import featuredImage from "./screenshot.png";
|
||||
|
||||
export const metadata = {
|
||||
title: "CLI",
|
||||
description: "AKA, the most useless Node module ever published, in history, by anyone, ever.",
|
||||
openGraph: {
|
||||
...defaultMetadata.openGraph,
|
||||
title: "CLI",
|
||||
images: [featuredImage.src],
|
||||
url: "/cli",
|
||||
},
|
||||
alternates: {
|
||||
|
@ -3,7 +3,7 @@
|
||||
import { headers } from "next/headers";
|
||||
import { z } from "zod";
|
||||
import { Resend } from "resend";
|
||||
import config from "../../lib/config";
|
||||
import * as config from "../../lib/config";
|
||||
|
||||
const schema = z.object({
|
||||
name: z.string().min(1, { message: "Name is required" }),
|
||||
|
@ -3,7 +3,7 @@
|
||||
padding: 0.8em;
|
||||
margin: 0.6em 0;
|
||||
border: 2px solid var(--colors-light);
|
||||
border-radius: var(--radii-corner);
|
||||
border-radius: 0.6em;
|
||||
color: var(--colors-text);
|
||||
background-color: var(--colors-superDuperLight);
|
||||
}
|
||||
@ -36,7 +36,7 @@
|
||||
padding: 1em 1.25em;
|
||||
margin-right: 1.5em;
|
||||
border: 0;
|
||||
border-radius: var(--radii-corner);
|
||||
border-radius: 0.6em;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
font-weight: 500;
|
||||
|
BIN
app/hillary/opengraph-image.png
Normal file
After Width: | Height: | Size: 283 KiB |
@ -12,7 +12,6 @@ export const metadata: Metadata = {
|
||||
openGraph: {
|
||||
...defaultMetadata.openGraph,
|
||||
title: "My Brief Apperance in Hillary Clinton's DNC Video",
|
||||
images: [thumbnail.src],
|
||||
url: "/hillary",
|
||||
},
|
||||
alternates: {
|
||||
|
@ -13,7 +13,6 @@
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: var(--sizes-maxLayoutWidth);
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
|
@ -4,7 +4,8 @@ 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";
|
||||
import * as config from "../lib/config";
|
||||
import { BASE_URL, MAX_WIDTH } from "../lib/config/constants";
|
||||
import type { Metadata } from "next";
|
||||
import type { Person, WithContext } from "schema-dts";
|
||||
|
||||
@ -15,10 +16,10 @@ import "./global.css";
|
||||
|
||||
import styles from "./layout.module.css";
|
||||
|
||||
import meJpg from "../public/static/me.jpg";
|
||||
import ogImage from "./opengraph-image.jpg";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
metadataBase: new URL(config.baseUrl),
|
||||
metadataBase: new URL(BASE_URL),
|
||||
title: {
|
||||
template: `%s – ${config.siteName}`,
|
||||
default: `${config.siteName} – ${config.shortDescription}`,
|
||||
@ -64,10 +65,10 @@ const jsonLd: WithContext<Person> = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Person",
|
||||
name: config.authorName,
|
||||
url: config.baseUrl,
|
||||
image: `${config.baseUrl}${meJpg.src}`,
|
||||
url: BASE_URL,
|
||||
image: `${BASE_URL}${ogImage.src}`,
|
||||
sameAs: [
|
||||
config.baseUrl,
|
||||
BASE_URL,
|
||||
`https://github.com/${config.authorSocial?.github}`,
|
||||
`https://keybase.io/${config.authorSocial?.keybase}`,
|
||||
`https://twitter.com/${config.authorSocial?.twitter}`,
|
||||
@ -96,7 +97,9 @@ const RootLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
|
||||
<main className={styles.default}>
|
||||
<SkipToContentTarget />
|
||||
<div className={styles.container}>{children}</div>
|
||||
<div className={styles.container} style={{ maxWidth: MAX_WIDTH }}>
|
||||
{children}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
|
BIN
app/leo/opengraph-image.png
Normal file
After Width: | Height: | Size: 74 KiB |
@ -12,7 +12,6 @@ export const metadata: Metadata = {
|
||||
openGraph: {
|
||||
...defaultMetadata.openGraph,
|
||||
title: 'Facebook App on "The Lab with Leo Laporte"',
|
||||
images: [thumbnail.src],
|
||||
url: "/leo",
|
||||
},
|
||||
alternates: {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import config from "../lib/config";
|
||||
import * as config from "../lib/config";
|
||||
import type { MetadataRoute } from "next";
|
||||
|
||||
const manifest = (): MetadataRoute.Manifest => {
|
||||
|
@ -3,7 +3,7 @@ import Video from "../components/Video";
|
||||
import type { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "404 Not Found",
|
||||
title: "Page Not Found",
|
||||
description: null,
|
||||
openGraph: {},
|
||||
alternates: {
|
||||
@ -23,7 +23,7 @@ const Page = () => {
|
||||
}}
|
||||
/>
|
||||
|
||||
<h1>404: Page Not Found 😢</h1>
|
||||
<h1 style={{ margin: "0.2em auto" }}>Page Not Found 😢</h1>
|
||||
|
||||
<Link href="/">Go home?</Link>
|
||||
</div>
|
||||
|
@ -1,13 +1,11 @@
|
||||
/* eslint-disable jsx-a11y/alt-text */
|
||||
|
||||
import { ImageResponse } from "next/og";
|
||||
import { notFound } from "next/navigation";
|
||||
import path from "path";
|
||||
import fs from "fs/promises";
|
||||
import glob from "fast-glob";
|
||||
import { join } from "path";
|
||||
import { existsSync } from "fs";
|
||||
import { readFile } from "fs/promises";
|
||||
import { getPostSlugs, getFrontMatter } from "../../../lib/helpers/posts";
|
||||
import { POSTS_DIR, AVATAR_PATH } from "../../../lib/config/constants";
|
||||
|
||||
export const dynamicParams = false;
|
||||
export const contentType = "image/png";
|
||||
export const size = {
|
||||
// https://developers.facebook.com/docs/sharing/webmasters/images/
|
||||
@ -15,6 +13,10 @@ export const size = {
|
||||
height: 630,
|
||||
};
|
||||
|
||||
// generate and cache these images at build-time for each slug, since doing this on-demand is mega slow...
|
||||
export const dynamic = "force-static";
|
||||
export const dynamicParams = false;
|
||||
|
||||
export const generateStaticParams = async () => {
|
||||
const slugs = await getPostSlugs();
|
||||
|
||||
@ -24,29 +26,35 @@ export const generateStaticParams = async () => {
|
||||
}));
|
||||
};
|
||||
|
||||
const getLocalImage = async (src: string) => {
|
||||
const imagePath = await glob(src);
|
||||
if (imagePath.length > 0) {
|
||||
const imageData = await fs.readFile(path.join(process.cwd(), imagePath[0]));
|
||||
return Uint8Array.from(imageData).buffer;
|
||||
}
|
||||
const getLocalImage = async (src: string): Promise<ArrayBuffer | string> => {
|
||||
// https://stackoverflow.com/questions/5775469/whats-the-valid-way-to-include-an-image-with-no-src/14115340#14115340
|
||||
const NO_IMAGE = "data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=";
|
||||
|
||||
// image doesn't exist
|
||||
return null;
|
||||
const imagePath = join(process.cwd(), src);
|
||||
|
||||
try {
|
||||
if (!existsSync(imagePath)) {
|
||||
console.error(`[og-image] couldn't find an image file located at "${imagePath}"`);
|
||||
|
||||
// return a 1x1 transparent gif if the image doesn't exist instead of crashing
|
||||
return NO_IMAGE;
|
||||
}
|
||||
|
||||
// return the raw image data as a buffer
|
||||
return Uint8Array.from(await readFile(imagePath)).buffer;
|
||||
} catch (error) {
|
||||
// fail silently and return a 1x1 transparent gif instead of crashing
|
||||
console.error(`[og-image] found "${imagePath}" but couldn't read it:`, error);
|
||||
return NO_IMAGE;
|
||||
}
|
||||
};
|
||||
|
||||
const Image = async ({ params }: { params: Promise<{ slug: string }> }) => {
|
||||
try {
|
||||
const { slug } = await params;
|
||||
|
||||
// get the note's title and image filename from its frontmatter
|
||||
const { title, image } = await getFrontMatter(slug);
|
||||
|
||||
// load the image specified in the note's frontmatter from its directory
|
||||
const imageSrc = await getLocalImage(`notes/${slug}/${image}`);
|
||||
|
||||
// load the author avatar
|
||||
const avatarSrc = await getLocalImage("public/static/me.jpg");
|
||||
// get the post's title and image filename from its frontmatter
|
||||
const { title, image: imagePath } = await getFrontMatter(slug);
|
||||
|
||||
return new ImageResponse(
|
||||
(
|
||||
@ -59,7 +67,7 @@ const Image = async ({ params }: { params: Promise<{ slug: string }> }) => {
|
||||
background: "linear-gradient(0deg, hsla(197, 14%, 57%, 1) 0%, hsla(192, 17%, 94%, 1) 100%)",
|
||||
}}
|
||||
>
|
||||
{imageSrc && (
|
||||
{imagePath && (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
@ -67,14 +75,15 @@ const Image = async ({ params }: { params: Promise<{ slug: string }> }) => {
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
{/* eslint-disable-next-line jsx-a11y/alt-text */}
|
||||
<img
|
||||
// @ts-expect-error
|
||||
src={imageSrc}
|
||||
src={await getLocalImage(`${POSTS_DIR}/${slug}/${imagePath}`)}
|
||||
style={{ objectFit: "cover", height: "100%", width: "100%" }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{avatarSrc && (
|
||||
{AVATAR_PATH && (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
@ -83,9 +92,10 @@ const Image = async ({ params }: { params: Promise<{ slug: string }> }) => {
|
||||
top: 42,
|
||||
}}
|
||||
>
|
||||
{/* eslint-disable-next-line jsx-a11y/alt-text */}
|
||||
<img
|
||||
// @ts-expect-error
|
||||
src={avatarSrc}
|
||||
src={await getLocalImage(AVATAR_PATH)}
|
||||
style={{ height: 96, width: 96, borderRadius: "100%" }}
|
||||
/>
|
||||
</div>
|
||||
@ -117,9 +127,8 @@ const Image = async ({ params }: { params: Promise<{ slug: string }> }) => {
|
||||
{
|
||||
name: "Geist",
|
||||
// load the Geist font directly from its npm package
|
||||
data: await fs.readFile(
|
||||
path.join(process.cwd(), "node_modules/geist/dist/fonts/geist-sans/Geist-SemiBold.ttf")
|
||||
),
|
||||
// IMPORTANT: include this exact path in next.config.ts under "outputFileTracingIncludes"
|
||||
data: await readFile(join(process.cwd(), "node_modules/geist/dist/fonts/geist-sans/Geist-SemiBold.ttf")),
|
||||
style: "normal",
|
||||
weight: 600,
|
||||
},
|
||||
@ -127,7 +136,7 @@ const Image = async ({ params }: { params: Promise<{ slug: string }> }) => {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("[og-image] Error generating image:", error);
|
||||
console.error("[og-image] error generating image:", error);
|
||||
notFound();
|
||||
}
|
||||
};
|
||||
|
@ -8,7 +8,8 @@ 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";
|
||||
import * as config from "../../../lib/config";
|
||||
import { BASE_URL } from "../../../lib/config/constants";
|
||||
import type { Metadata, Route } from "next";
|
||||
import type { Article, WithContext } from "schema-dts";
|
||||
|
||||
@ -72,7 +73,7 @@ const Page = async ({ params }: { params: Promise<{ slug: string }> }) => {
|
||||
author: {
|
||||
"@type": "Person",
|
||||
name: config.authorName,
|
||||
url: config.baseUrl,
|
||||
url: BASE_URL,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -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";
|
||||
import * as config from "../../lib/config";
|
||||
import { metadata as defaultMetadata } from "../layout";
|
||||
import type { ReactElement } from "react";
|
||||
import type { Metadata, Route } from "next";
|
||||
|
BIN
app/opengraph-image.jpg
Normal file
After Width: | Height: | Size: 71 KiB |
18
app/page.tsx
@ -2,27 +2,11 @@ import hash from "@emotion/hash";
|
||||
import { rgba } from "polished";
|
||||
import { LockIcon } from "lucide-react";
|
||||
import UnstyledLink from "../components/Link";
|
||||
import { metadata as defaultMetadata } from "./layout";
|
||||
import type { ComponentPropsWithoutRef } from "react";
|
||||
import type { Metadata, Route } from "next";
|
||||
import type { Route } from "next";
|
||||
|
||||
import styles from "./page.module.css";
|
||||
|
||||
import meJpg from "../public/static/me.jpg";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
openGraph: {
|
||||
...defaultMetadata.openGraph,
|
||||
images: [
|
||||
{
|
||||
url: meJpg.src,
|
||||
width: meJpg.width,
|
||||
height: meJpg.height,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const Link = ({
|
||||
lightColor,
|
||||
darkColor,
|
||||
|
BIN
app/previously/opengraph-image.png
Normal file
After Width: | Height: | Size: 86 KiB |
@ -24,7 +24,6 @@ body:has(.wackyWrapper) a {
|
||||
display: block;
|
||||
margin: 0.6em 0;
|
||||
border: 2px solid var(--colors-kindaLight);
|
||||
border-radius: var(--radii-corner);
|
||||
}
|
||||
|
||||
.screenshot,
|
||||
|
@ -13,7 +13,7 @@
|
||||
width: 370px;
|
||||
padding: 1.2em 1.2em 0.8em;
|
||||
border: 1px solid var(--colors-kindaLight);
|
||||
border-radius: var(--radii-corner);
|
||||
border-radius: 1em;
|
||||
font-size: 0.9em;
|
||||
color: var(--colors-mediumDark);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import PageTitle from "../../components/PageTitle";
|
||||
import Link from "../../components/Link";
|
||||
import RelativeTime from "../../components/RelativeTime";
|
||||
import { metadata as defaultMetadata } from "../layout";
|
||||
import config from "../../lib/config";
|
||||
import * as config from "../../lib/config";
|
||||
import type { Metadata } from "next";
|
||||
import type { User, Repository } from "@octokit/graphql-schema";
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import config from "../lib/config";
|
||||
import { BASE_URL } from "../lib/config/constants";
|
||||
import type { MetadataRoute } from "next";
|
||||
|
||||
export const dynamic = "force-static";
|
||||
@ -74,7 +74,7 @@ const robots = (): MetadataRoute.Robots => {
|
||||
disallow: "/",
|
||||
},
|
||||
],
|
||||
sitemap: `${config.baseUrl}/sitemap.xml`,
|
||||
sitemap: `${BASE_URL}/sitemap.xml`,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import path from "path";
|
||||
import glob from "fast-glob";
|
||||
import { getAllPosts } from "../lib/helpers/posts";
|
||||
import config from "../lib/config";
|
||||
import { BASE_URL } from "../lib/config/constants";
|
||||
import type { MetadataRoute } from "next";
|
||||
|
||||
export const dynamic = "force-static";
|
||||
@ -11,13 +11,13 @@ const sitemap = async (): Promise<MetadataRoute.Sitemap> => {
|
||||
const routes: MetadataRoute.Sitemap = [
|
||||
{
|
||||
// homepage
|
||||
url: config.baseUrl,
|
||||
url: BASE_URL,
|
||||
priority: 1.0,
|
||||
lastModified: new Date(process.env.RELEASE_DATE || Date.now()), // timestamp frozen when a new build is deployed
|
||||
},
|
||||
{ url: `${config.baseUrl}/stats` },
|
||||
{ url: `${config.baseUrl}/tweets` },
|
||||
{ url: `${config.baseUrl}/y2k` },
|
||||
{ url: `${BASE_URL}/stats` },
|
||||
{ url: `${BASE_URL}/tweets` },
|
||||
{ url: `${BASE_URL}/y2k` },
|
||||
];
|
||||
|
||||
// add each directory in the app folder as a route (excluding special routes)
|
||||
@ -35,7 +35,7 @@ const sitemap = async (): Promise<MetadataRoute.Sitemap> => {
|
||||
).forEach((route) => {
|
||||
routes.push({
|
||||
// remove matching page.(tsx|mdx) file and make all URLs absolute
|
||||
url: `${config.baseUrl}/${route.replace(/\/page\.(tsx|mdx)$/, "")}`,
|
||||
url: `${BASE_URL}/${route.replace(/\/page\.(tsx|mdx)$/, "")}`,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -26,8 +26,6 @@
|
||||
--colors-codeVariable: #d88200;
|
||||
--colors-codeAddition: #44a248;
|
||||
--colors-codeDeletion: #ff1b1b;
|
||||
--sizes-maxLayoutWidth: 865px;
|
||||
--radii-corner: 0.6rem;
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
|
BIN
app/uses/opengraph-image.png
Normal file
After Width: | Height: | Size: 810 KiB |
@ -1,15 +1,12 @@
|
||||
import PageTitle from "../../components/PageTitle";
|
||||
import { metadata as defaultMetadata } from "../layout";
|
||||
|
||||
import featuredImage from "./desktop.png";
|
||||
|
||||
export const metadata = {
|
||||
title: "/uses",
|
||||
description: "Things I use daily.",
|
||||
openGraph: {
|
||||
...defaultMetadata.openGraph,
|
||||
title: "/uses",
|
||||
images: [featuredImage.src],
|
||||
url: "/uses",
|
||||
},
|
||||
alternates: {
|
||||
|
BIN
app/zip/opengraph-image.jpg
Normal file
After Width: | Height: | Size: 477 KiB |
@ -26,7 +26,7 @@ const Page = () => {
|
||||
backgroundImage: `url(${backgroundImg.src})`,
|
||||
backgroundRepeat: "repeat",
|
||||
backgroundPosition: "center",
|
||||
borderRadius: "var(--radii-corner)",
|
||||
borderRadius: "0.6em",
|
||||
}}
|
||||
>
|
||||
<CodeBlock
|
||||
|
@ -13,7 +13,7 @@
|
||||
tab-size: 2px;
|
||||
background-color: var(--colors-codeBackground);
|
||||
border: 1px solid var(--colors-kindaLight);
|
||||
border-radius: var(--radii-corner);
|
||||
border-radius: 0.6em;
|
||||
}
|
||||
|
||||
.codeBlock :global(.line-number)::before {
|
||||
@ -106,8 +106,8 @@
|
||||
width: 3em;
|
||||
color: var(--colors-mediumDark);
|
||||
border: 1px solid var(--colors-kindaLight);
|
||||
border-top-right-radius: var(--radii-corner);
|
||||
border-bottom-left-radius: var(--radii-corner);
|
||||
border-top-right-radius: 0.6em;
|
||||
border-bottom-left-radius: 0.6em;
|
||||
background-color: var(--colors-backgroundHeader);
|
||||
backdrop-filter: saturate(180%) blur(5px);
|
||||
}
|
||||
|
@ -4,5 +4,5 @@
|
||||
page-break-inside: avoid;
|
||||
background-color: var(--colors-codeBackground);
|
||||
border: 1px solid var(--colors-kindaLight);
|
||||
border-radius: var(--radii-corner);
|
||||
border-radius: 0.6em;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import Giscus from "@giscus/react";
|
||||
import config from "../../lib/config";
|
||||
import * as config from "../../lib/config";
|
||||
import type { GiscusProps } from "@giscus/react";
|
||||
|
||||
export type CommentsProps = {
|
||||
|
@ -10,7 +10,6 @@
|
||||
.row {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
max-width: var(--sizes-maxLayoutWidth);
|
||||
margin: 0 auto;
|
||||
justify-content: space-between;
|
||||
font-size: 0.8em;
|
||||
|
@ -1,7 +1,8 @@
|
||||
import clsx from "clsx";
|
||||
import { HeartIcon } from "lucide-react";
|
||||
import Link from "../Link";
|
||||
import config from "../../lib/config";
|
||||
import * as config from "../../lib/config";
|
||||
import { MAX_WIDTH } from "../../lib/config/constants";
|
||||
import type { ComponentPropsWithoutRef } from "react";
|
||||
|
||||
import styles from "./Footer.module.css";
|
||||
@ -11,7 +12,7 @@ export type FooterProps = ComponentPropsWithoutRef<"footer">;
|
||||
const Footer = ({ className, ...rest }: FooterProps) => {
|
||||
return (
|
||||
<footer className={clsx(styles.footer, className)} {...rest}>
|
||||
<div className={styles.row}>
|
||||
<div className={styles.row} style={{ maxWidth: MAX_WIDTH }}>
|
||||
<div>
|
||||
Content{" "}
|
||||
<Link href="/license" title={config.license} plain className={styles.link}>
|
||||
|
@ -14,22 +14,22 @@
|
||||
backdrop-filter: saturate(180%) blur(5px);
|
||||
}
|
||||
|
||||
.selfieImage {
|
||||
.homeImage {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border: 1px solid var(--colors-light);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.selfieLink {
|
||||
.homeLink {
|
||||
display: inline-flex;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
color: var(--colors-mediumDark) !important;
|
||||
}
|
||||
|
||||
.selfieLink:hover,
|
||||
.selfieLink:focus-visible {
|
||||
.homeLink:hover,
|
||||
.homeLink:focus-visible {
|
||||
color: var(--colors-link) !important;
|
||||
}
|
||||
|
||||
@ -46,7 +46,6 @@
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
max-width: var(--sizes-maxLayoutWidth);
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@ -56,14 +55,14 @@
|
||||
height: 5.9em;
|
||||
}
|
||||
|
||||
.selfieImage {
|
||||
.homeImage {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
border-width: 2px;
|
||||
}
|
||||
|
||||
.selfieLink:hover .selfieImage,
|
||||
.selfieLink:focus-visible .selfieImage {
|
||||
.homeLink:hover .homeImage,
|
||||
.homeLink:focus-visible .homeImage {
|
||||
border-color: var(--colors-linkUnderline);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,8 @@ import clsx from "clsx";
|
||||
import Link from "../Link";
|
||||
import Image from "../Image";
|
||||
import Menu from "../Menu";
|
||||
import config from "../../lib/config";
|
||||
import * as config from "../../lib/config";
|
||||
import { MAX_WIDTH } from "../../lib/config/constants";
|
||||
import type { ComponentPropsWithoutRef } from "react";
|
||||
|
||||
import styles from "./Header.module.css";
|
||||
@ -14,12 +15,12 @@ export type HeaderProps = ComponentPropsWithoutRef<"header">;
|
||||
const Header = ({ className, ...rest }: HeaderProps) => {
|
||||
return (
|
||||
<header className={clsx(styles.header, className)} {...rest}>
|
||||
<nav className={styles.nav}>
|
||||
<Link href="/" rel="author" title={config.authorName} plain className={styles.selfieLink}>
|
||||
<nav className={styles.nav} style={{ maxWidth: MAX_WIDTH }}>
|
||||
<Link href="/" rel="author" title={config.authorName} plain className={styles.homeLink}>
|
||||
<Image
|
||||
src={selfieJpg}
|
||||
alt={`Photo of ${config.authorName}`}
|
||||
className={styles.selfieImage}
|
||||
className={styles.homeImage}
|
||||
width={70}
|
||||
height={70}
|
||||
quality={60}
|
||||
|
@ -9,7 +9,7 @@ export type HeadingAnchorProps = Omit<ComponentPropsWithoutRef<typeof Link>, "hr
|
||||
|
||||
const HeadingAnchor = ({ id, title, ...rest }: HeadingAnchorProps) => {
|
||||
return (
|
||||
<Link href={`#${id}`} title={`Jump to "${title}"`} aria-hidden plain {...rest}>
|
||||
<Link href={`#${id}`} title={`Jump to "${title}"`} plain {...rest}>
|
||||
<LinkIcon size="0.8em" />
|
||||
</Link>
|
||||
);
|
||||
|
@ -1,5 +0,0 @@
|
||||
.image {
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
border-radius: var(--radii-corner);
|
||||
}
|
@ -1,15 +1,11 @@
|
||||
import NextImage from "next/image";
|
||||
import clsx from "clsx";
|
||||
import { MAX_WIDTH } from "../../lib/config/constants";
|
||||
import type { ComponentPropsWithoutRef } from "react";
|
||||
import type { StaticImageData } from "next/image";
|
||||
|
||||
import styles from "./Image.module.css";
|
||||
|
||||
const MAX_WIDTH = 865;
|
||||
|
||||
export type ImageProps = ComponentPropsWithoutRef<typeof NextImage>;
|
||||
|
||||
const Image = ({ src, height, width, quality, placeholder, className, ...rest }: ImageProps) => {
|
||||
const Image = ({ src, height, width, quality, placeholder, style, ...rest }: ImageProps) => {
|
||||
const constrainWidth = (width?: number | `${number}`) => {
|
||||
if (!width) return MAX_WIDTH;
|
||||
|
||||
@ -22,10 +18,14 @@ const Image = ({ src, height, width, quality, placeholder, className, ...rest }:
|
||||
width: constrainWidth(width || (src as StaticImageData).width),
|
||||
quality: quality || 75,
|
||||
placeholder: placeholder || (typeof src === "string" ? "empty" : "blur"),
|
||||
style: {
|
||||
height: "auto",
|
||||
...style,
|
||||
},
|
||||
...rest,
|
||||
};
|
||||
|
||||
return <NextImage className={clsx(styles.image, className)} {...imageProps} />;
|
||||
return <NextImage {...imageProps} />;
|
||||
};
|
||||
|
||||
export default Image;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import NextLink from "next/link";
|
||||
import clsx from "clsx";
|
||||
import objStr from "obj-str";
|
||||
import config from "../../lib/config";
|
||||
import { BASE_URL } from "../../lib/config/constants";
|
||||
import type { ComponentPropsWithoutRef } from "react";
|
||||
|
||||
import styles from "./Link.module.css";
|
||||
@ -14,7 +14,7 @@ export type LinkProps = ComponentPropsWithoutRef<typeof NextLink> & {
|
||||
const Link = ({ href, rel, target, prefetch = false, plain, openInNewTab, className, ...rest }: LinkProps) => {
|
||||
// This component auto-detects whether or not this link should open in the same window (the default for internal
|
||||
// links) or a new tab (the default for external links). Defaults can be overridden with `openInNewTab={true}`.
|
||||
const isExternal = typeof href === "string" && !(["/", "#"].includes(href[0]) || href.startsWith(config.baseUrl));
|
||||
const isExternal = typeof href === "string" && !(["/", "#"].includes(href[0]) || href.startsWith(BASE_URL));
|
||||
|
||||
if (openInNewTab || isExternal) {
|
||||
return (
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* accessible invisibility stuff pulled from @reach/skip-nav:
|
||||
https://github.com/reach/reach-ui/blob/main/packages/skip-nav/styles.css */
|
||||
|
||||
.hiddenLink {
|
||||
.skipNav {
|
||||
border: 0;
|
||||
clip: rect(0 0 0 0);
|
||||
height: 1px;
|
||||
@ -12,7 +12,7 @@ https://github.com/reach/reach-ui/blob/main/packages/skip-nav/styles.css */
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.hiddenLink:focus {
|
||||
.skipNav:focus {
|
||||
padding: 1rem;
|
||||
position: fixed;
|
||||
top: 10px;
|
||||
@ -24,6 +24,5 @@ https://github.com/reach/reach-ui/blob/main/packages/skip-nav/styles.css */
|
||||
background: var(--colors-superDuperLight);
|
||||
color: var(--colors-link);
|
||||
border: 2px solid var(--colors-kindaLight);
|
||||
border-radius: var(--radii-corner);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ const skipNavId = "skip-nav";
|
||||
|
||||
export const SkipToContentLink = () => {
|
||||
return (
|
||||
<a href={`#${skipNavId}`} tabIndex={0} className={styles.hiddenLink}>
|
||||
<a href={`#${skipNavId}`} tabIndex={0} className={styles.skipNav}>
|
||||
Skip to content
|
||||
</a>
|
||||
);
|
||||
|
@ -11,3 +11,15 @@
|
||||
.toggle:focus-visible {
|
||||
color: var(--colors-warning);
|
||||
}
|
||||
|
||||
/* hacky way to avoid flashing icon for a few milliseconds on initial render */
|
||||
.toggle > .sun,
|
||||
[data-theme="dark"] .toggle > .moon {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line no-descending-specificity */
|
||||
.toggle > .moon,
|
||||
[data-theme="dark"] .toggle > .sun {
|
||||
display: none;
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { useHasMounted, useTheme } from "../../hooks";
|
||||
import { EllipsisIcon, MoonIcon, SunIcon } from "lucide-react";
|
||||
import clsx from "clsx";
|
||||
import { MoonIcon, SunIcon } from "lucide-react";
|
||||
import { useTheme } from "../../hooks";
|
||||
import type { ComponentPropsWithoutRef } from "react";
|
||||
import type { LucideIcon } from "lucide-react";
|
||||
|
||||
@ -9,27 +10,17 @@ import styles from "./ThemeToggle.module.css";
|
||||
|
||||
export type ThemeToggleProps = ComponentPropsWithoutRef<LucideIcon>;
|
||||
|
||||
const ThemeToggle = ({ ...rest }: ThemeToggleProps) => {
|
||||
const hasMounted = useHasMounted();
|
||||
const ThemeToggle = ({ className, ...rest }: ThemeToggleProps) => {
|
||||
const { theme, setTheme } = useTheme();
|
||||
|
||||
// render a placeholder icon to avoid layout shifting until we're fully mounted and self-aware
|
||||
if (!hasMounted) {
|
||||
return (
|
||||
<div className={styles.toggle}>
|
||||
<EllipsisIcon style={{ stroke: "var(--colors-mediumLight)" }} {...rest} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={() => setTheme(theme === "light" ? "dark" : "light")}
|
||||
aria-label="Toggle Theme"
|
||||
className={styles.toggle}
|
||||
title={theme === "light" ? "Toggle Dark Mode" : "Toggle Light Mode"}
|
||||
aria-label={theme === "light" ? "Toggle Dark Mode" : "Toggle Light Mode"}
|
||||
>
|
||||
{theme === "light" ? <SunIcon {...rest} /> : <MoonIcon {...rest} />}
|
||||
<SunIcon className={clsx(styles.sun, className)} {...rest} />
|
||||
<MoonIcon className={clsx(styles.moon, className)} {...rest} />
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
@ -2,10 +2,6 @@
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.player video {
|
||||
border-radius: var(--radii-corner);
|
||||
}
|
||||
|
||||
.wrapper.responsive {
|
||||
position: relative;
|
||||
padding-top: 56.25%; /* ratio of 1280x720 */
|
||||
|
17
lib/config/constants.ts
Normal file
@ -0,0 +1,17 @@
|
||||
// path to directory with .mdx files, relative to project root
|
||||
export const POSTS_DIR = "notes";
|
||||
|
||||
// path to an image used in various places to represent the site, relative to project root
|
||||
// IMPORTANT: must be included in next.config.ts under "outputFileTracingIncludes"
|
||||
export const AVATAR_PATH = "app/opengraph-image.jpg";
|
||||
|
||||
// maximum width of content wrapper (e.g. for images) in pixels
|
||||
export const MAX_WIDTH = 865;
|
||||
|
||||
// same logic as metadataBase: https://nextjs.org/docs/app/api-reference/functions/generate-metadata#default-value
|
||||
export const BASE_URL =
|
||||
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
|
||||
? `https://${process.env.NEXT_PUBLIC_VERCEL_URL}`
|
||||
: `http://localhost:${process.env.PORT || 3000}`;
|
@ -1,39 +1,28 @@
|
||||
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
|
||||
? `https://${process.env.NEXT_PUBLIC_VERCEL_URL}`
|
||||
: `http://localhost:${process.env.PORT || 3000}`,
|
||||
timeZone: "America/New_York", // https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
|
||||
onionDomain: "http://jarvis2i2vp4j4tbxjogsnqdemnte5xhzyi7hziiyzxwge3hzmh57zad.onion",
|
||||
shortDescription: "Front-End Web Developer in Boston, MA",
|
||||
longDescription:
|
||||
"Hi there! I'm a frontend web developer based in Boston, Massachusetts specializing in the JAMstack, modern JavaScript frameworks, and progressive web apps.",
|
||||
license: "Creative Commons Attribution 4.0 International",
|
||||
licenseAbbr: "CC-BY-4.0",
|
||||
licenseUrl: "https://creativecommons.org/licenses/by/4.0/",
|
||||
copyrightYearStart: 2001,
|
||||
githubRepo: "jakejarvis/jarv.is",
|
||||
// Site info
|
||||
export const siteName = "Jake Jarvis";
|
||||
export const siteLocale = "en-US";
|
||||
export const timeZone = "America/New_York"; // https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
|
||||
export const onionDomain = "jarvis2i2vp4j4tbxjogsnqdemnte5xhzyi7hziiyzxwge3hzmh57zad.onion";
|
||||
export const shortDescription = "Front-End Web Developer in Boston; MA";
|
||||
export const longDescription =
|
||||
"Hi there! I'm a frontend web developer based in Boston, Massachusetts specializing in the JAMstack, modern JavaScript frameworks, and progressive web apps.";
|
||||
export const license = "Creative Commons Attribution 4.0 International";
|
||||
export const licenseAbbr = "CC-BY-4.0";
|
||||
export const licenseUrl = "https://creativecommons.org/licenses/by/4.0/";
|
||||
export const copyrightYearStart = 2001;
|
||||
export const githubRepo = "jakejarvis/jarv.is";
|
||||
|
||||
// Me info
|
||||
authorName: "Jake Jarvis",
|
||||
authorEmail: "jake@jarv.is",
|
||||
authorSocial: {
|
||||
github: "jakejarvis",
|
||||
twitter: "jakejarvis",
|
||||
facebook: "jakejarvis",
|
||||
keybase: "jakejarvis",
|
||||
medium: "jakejarvis",
|
||||
linkedin: "jakejarvis",
|
||||
instagram: "jakejarvis",
|
||||
mastodon: "fediverse.jarv.is/@jake",
|
||||
bluesky: "jarv.is",
|
||||
},
|
||||
// Me info
|
||||
export const authorName = "Jake Jarvis";
|
||||
export const authorEmail = "jake@jarv.is";
|
||||
export const authorSocial = {
|
||||
github: "jakejarvis",
|
||||
twitter: "jakejarvis",
|
||||
facebook: "jakejarvis",
|
||||
keybase: "jakejarvis",
|
||||
medium: "jakejarvis",
|
||||
linkedin: "jakejarvis",
|
||||
instagram: "jakejarvis",
|
||||
mastodon: "fediverse.jarv.is/@jake",
|
||||
bluesky: "jarv.is",
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
@ -1,26 +1,27 @@
|
||||
import { Feed } from "feed";
|
||||
import { getAllPosts } from "./posts";
|
||||
import config from "../config";
|
||||
import * as config from "../config";
|
||||
import { BASE_URL } from "../config/constants";
|
||||
|
||||
import meJpg from "../../public/static/me.jpg";
|
||||
import ogImage from "../../app/opengraph-image.jpg";
|
||||
|
||||
export const buildFeed = async (): Promise<Feed> => {
|
||||
// https://github.com/jpmonette/feed#example
|
||||
const feed = new Feed({
|
||||
id: config.baseUrl,
|
||||
link: config.baseUrl,
|
||||
id: BASE_URL,
|
||||
link: BASE_URL,
|
||||
title: config.siteName,
|
||||
description: config.longDescription,
|
||||
copyright: config.licenseUrl,
|
||||
updated: new Date(process.env.RELEASE_DATE || Date.now()),
|
||||
image: `${config.baseUrl}${meJpg.src}`,
|
||||
image: `${BASE_URL}${ogImage.src}`,
|
||||
feedLinks: {
|
||||
rss: `${config.baseUrl}/feed.xml`,
|
||||
atom: `${config.baseUrl}/feed.atom`,
|
||||
rss: `${BASE_URL}/feed.xml`,
|
||||
atom: `${BASE_URL}/feed.atom`,
|
||||
},
|
||||
author: {
|
||||
name: config.authorName,
|
||||
link: config.baseUrl,
|
||||
link: BASE_URL,
|
||||
email: config.authorEmail,
|
||||
},
|
||||
});
|
||||
@ -35,7 +36,7 @@ export const buildFeed = async (): Promise<Feed> => {
|
||||
author: [
|
||||
{
|
||||
name: config.authorName,
|
||||
link: config.baseUrl,
|
||||
link: BASE_URL,
|
||||
},
|
||||
],
|
||||
date: new Date(post.date),
|
||||
|
@ -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";
|
||||
import * as config from "../config";
|
||||
|
||||
const IsomorphicDayJs = (date?: dayjs.ConfigType): dayjs.Dayjs => {
|
||||
// plugins
|
||||
|
@ -3,10 +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";
|
||||
|
||||
// path to directory with .mdx files, relative to project root
|
||||
const POSTS_DIR = "notes";
|
||||
import { BASE_URL, POSTS_DIR } from "../config/constants";
|
||||
|
||||
export type FrontMatter = {
|
||||
slug: string;
|
||||
@ -65,7 +62,7 @@ export const getFrontMatter = async (slug: string): Promise<FrontMatter> => {
|
||||
htmlTitle,
|
||||
slug,
|
||||
date: formatDate(frontmatter.date), // validate/normalize the date string provided from front matter
|
||||
permalink: `${config.baseUrl}/${POSTS_DIR}/${slug}`,
|
||||
permalink: `${BASE_URL}/${POSTS_DIR}/${slug}`,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import type { NextRequest } from "next/server";
|
||||
|
||||
import siteConfig from "./lib/config";
|
||||
import * as siteConfig from "./lib/config";
|
||||
|
||||
// assign "short codes" to approved reverse proxy destinations. for example:
|
||||
// ["abc", "https://jakejarvis.github.io"] => /_stream/abc/123.html -> https://jakejarvis.github.io/123.html
|
||||
@ -16,7 +16,12 @@ export const middleware = (request: NextRequest) => {
|
||||
|
||||
// https://gitweb.torproject.org/tor-browser-spec.git/tree/proposals/100-onion-location-header.txt
|
||||
if (siteConfig.onionDomain) {
|
||||
headers.set("Onion-Location", `${siteConfig.onionDomain}${request.nextUrl.pathname}${request.nextUrl.search}`);
|
||||
const onionUrl = request.nextUrl.clone();
|
||||
onionUrl.hostname = siteConfig.onionDomain;
|
||||
onionUrl.protocol = "http";
|
||||
onionUrl.port = "";
|
||||
|
||||
headers.set("onion-location", onionUrl.toString());
|
||||
}
|
||||
|
||||
// debugging 🥛
|
||||
|
@ -22,7 +22,7 @@ const nextConfig: NextConfig = {
|
||||
outputFileTracingIncludes: {
|
||||
"/notes/[slug]/opengraph-image": [
|
||||
"./notes/**/*",
|
||||
"./public/static/me.jpg",
|
||||
"./app/opengraph-image.jpg",
|
||||
"./node_modules/geist/dist/fonts/geist-sans/Geist-SemiBold.ttf",
|
||||
],
|
||||
},
|
||||
|
16
package.json
@ -22,9 +22,9 @@
|
||||
"@giscus/react": "^3.1.0",
|
||||
"@mdx-js/loader": "^3.1.0",
|
||||
"@mdx-js/react": "^3.1.0",
|
||||
"@next/bundle-analyzer": "15.3.0-canary.6",
|
||||
"@next/mdx": "15.3.0-canary.6",
|
||||
"@next/third-parties": "15.3.0-canary.6",
|
||||
"@next/bundle-analyzer": "15.3.0-canary.8",
|
||||
"@next/mdx": "15.3.0-canary.8",
|
||||
"@next/third-parties": "15.3.0-canary.8",
|
||||
"@octokit/graphql": "^8.2.1",
|
||||
"@octokit/graphql-schema": "^15.26.0",
|
||||
"@prisma/client": "^6.5.0",
|
||||
@ -35,9 +35,9 @@
|
||||
"fast-glob": "^3.3.3",
|
||||
"feed": "^4.2.2",
|
||||
"geist": "^1.3.1",
|
||||
"lucide-react": "0.479.0",
|
||||
"lucide-react": "0.481.0",
|
||||
"modern-normalize": "^3.0.1",
|
||||
"next": "15.3.0-canary.6",
|
||||
"next": "15.3.0-canary.8",
|
||||
"obj-str": "^1.1.0",
|
||||
"p-map": "^7.0.3",
|
||||
"p-memoize": "^7.1.1",
|
||||
@ -78,7 +78,7 @@
|
||||
"@types/react-is": "^19.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^9.22.0",
|
||||
"eslint-config-next": "15.3.0-canary.6",
|
||||
"eslint-config-next": "15.3.0-canary.8",
|
||||
"eslint-config-prettier": "^10.1.1",
|
||||
"eslint-plugin-css-modules": "^2.12.0",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
@ -92,7 +92,7 @@
|
||||
"prisma": "^6.5.0",
|
||||
"schema-dts": "^1.1.5",
|
||||
"simple-git-hooks": "^2.11.1",
|
||||
"stylelint": "^16.15.0",
|
||||
"stylelint": "^16.16.0",
|
||||
"stylelint-config-css-modules": "^4.4.0",
|
||||
"stylelint-config-recommended": "^15.0.0",
|
||||
"stylelint-config-standard": "^37.0.0",
|
||||
@ -104,7 +104,7 @@
|
||||
"engines": {
|
||||
"node": ">=20.x"
|
||||
},
|
||||
"packageManager": "pnpm@10.6.2+sha512.47870716bea1572b53df34ad8647b42962bc790ce2bf4562ba0f643237d7302a3d6a8ecef9e4bdfc01d23af1969aa90485d4cebb0b9638fa5ef1daef656f6c1b",
|
||||
"packageManager": "pnpm@10.6.3+sha512.bb45e34d50a9a76e858a95837301bfb6bd6d35aea2c5d52094fa497a467c43f5c440103ce2511e9e0a2f89c3d6071baac3358fc68ac6fb75e2ceb3d2736065e6",
|
||||
"cacheDirectories": [
|
||||
"node_modules",
|
||||
".next/cache"
|
||||
|
216
pnpm-lock.yaml
generated
@ -21,14 +21,14 @@ importers:
|
||||
specifier: ^3.1.0
|
||||
version: 3.1.0(@types/react@19.0.10)(react@19.0.0)
|
||||
'@next/bundle-analyzer':
|
||||
specifier: 15.3.0-canary.6
|
||||
version: 15.3.0-canary.6
|
||||
specifier: 15.3.0-canary.8
|
||||
version: 15.3.0-canary.8
|
||||
'@next/mdx':
|
||||
specifier: 15.3.0-canary.6
|
||||
version: 15.3.0-canary.6(@mdx-js/loader@3.1.0(acorn@8.14.1))(@mdx-js/react@3.1.0(@types/react@19.0.10)(react@19.0.0))
|
||||
specifier: 15.3.0-canary.8
|
||||
version: 15.3.0-canary.8(@mdx-js/loader@3.1.0(acorn@8.14.1))(@mdx-js/react@3.1.0(@types/react@19.0.10)(react@19.0.0))
|
||||
'@next/third-parties':
|
||||
specifier: 15.3.0-canary.6
|
||||
version: 15.3.0-canary.6(next@15.3.0-canary.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)
|
||||
specifier: 15.3.0-canary.8
|
||||
version: 15.3.0-canary.8(next@15.3.0-canary.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)
|
||||
'@octokit/graphql':
|
||||
specifier: ^8.2.1
|
||||
version: 8.2.1
|
||||
@ -58,16 +58,16 @@ importers:
|
||||
version: 4.2.2
|
||||
geist:
|
||||
specifier: ^1.3.1
|
||||
version: 1.3.1(next@15.3.0-canary.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
|
||||
version: 1.3.1(next@15.3.0-canary.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
|
||||
lucide-react:
|
||||
specifier: 0.479.0
|
||||
version: 0.479.0(react@19.0.0)
|
||||
specifier: 0.481.0
|
||||
version: 0.481.0(react@19.0.0)
|
||||
modern-normalize:
|
||||
specifier: ^3.0.1
|
||||
version: 3.0.1
|
||||
next:
|
||||
specifier: 15.3.0-canary.6
|
||||
version: 15.3.0-canary.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
specifier: 15.3.0-canary.8
|
||||
version: 15.3.0-canary.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
obj-str:
|
||||
specifier: ^1.1.0
|
||||
version: 1.1.0
|
||||
@ -184,8 +184,8 @@ importers:
|
||||
specifier: ^9.22.0
|
||||
version: 9.22.0
|
||||
eslint-config-next:
|
||||
specifier: 15.3.0-canary.6
|
||||
version: 15.3.0-canary.6(eslint@9.22.0)(typescript@5.8.2)
|
||||
specifier: 15.3.0-canary.8
|
||||
version: 15.3.0-canary.8(eslint@9.22.0)(typescript@5.8.2)
|
||||
eslint-config-prettier:
|
||||
specifier: ^10.1.1
|
||||
version: 10.1.1(eslint@9.22.0)
|
||||
@ -194,7 +194,7 @@ importers:
|
||||
version: 2.12.0(eslint@9.22.0)
|
||||
eslint-plugin-import:
|
||||
specifier: ^2.31.0
|
||||
version: 2.31.0(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.8.2))(eslint-import-resolver-typescript@3.8.6)(eslint@9.22.0)
|
||||
version: 2.31.0(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.8.2))(eslint-import-resolver-typescript@3.8.7)(eslint@9.22.0)
|
||||
eslint-plugin-jsx-a11y:
|
||||
specifier: ^6.10.2
|
||||
version: 6.10.2(eslint@9.22.0)
|
||||
@ -226,17 +226,17 @@ importers:
|
||||
specifier: ^2.11.1
|
||||
version: 2.11.1
|
||||
stylelint:
|
||||
specifier: ^16.15.0
|
||||
version: 16.15.0(typescript@5.8.2)
|
||||
specifier: ^16.16.0
|
||||
version: 16.16.0(typescript@5.8.2)
|
||||
stylelint-config-css-modules:
|
||||
specifier: ^4.4.0
|
||||
version: 4.4.0(stylelint@16.15.0(typescript@5.8.2))
|
||||
version: 4.4.0(stylelint@16.16.0(typescript@5.8.2))
|
||||
stylelint-config-recommended:
|
||||
specifier: ^15.0.0
|
||||
version: 15.0.0(stylelint@16.15.0(typescript@5.8.2))
|
||||
version: 15.0.0(stylelint@16.16.0(typescript@5.8.2))
|
||||
stylelint-config-standard:
|
||||
specifier: ^37.0.0
|
||||
version: 37.0.0(stylelint@16.15.0(typescript@5.8.2))
|
||||
version: 37.0.0(stylelint@16.16.0(typescript@5.8.2))
|
||||
typescript:
|
||||
specifier: 5.8.2
|
||||
version: 5.8.2
|
||||
@ -649,17 +649,17 @@ packages:
|
||||
'@types/react': '>=16'
|
||||
react: '>=16'
|
||||
|
||||
'@next/bundle-analyzer@15.3.0-canary.6':
|
||||
resolution: {integrity: sha512-M6eaBkxo60WbGYv5pY5/FcpfMT8I9R7qepcoEpIxP0N7cMuo2IURXMhdt2rgmrZmBs+8xsqCotVRDt2rO4tA0w==}
|
||||
'@next/bundle-analyzer@15.3.0-canary.8':
|
||||
resolution: {integrity: sha512-K3PLM+bxciuah4Q/coJQvxEVWhkptKAWous0fjjbajSgNY8h+DqK77ZZZc00u+0EOiLYsTUntoXb8VDNGyChNw==}
|
||||
|
||||
'@next/env@15.3.0-canary.6':
|
||||
resolution: {integrity: sha512-ZaiOaNef86GzehX2W7ZbKf3F9XXwrzcKQBnVvmKjHokumQkixoRb4cmSpro5wuEZ761nu15Z5cQeIudvEad4QA==}
|
||||
'@next/env@15.3.0-canary.8':
|
||||
resolution: {integrity: sha512-/cGLuOWycBJnskYxETUtVH8XdwfYNiWJ7Db17qnZd76nLDLfulnIKSZ4QiHTm3cm5uWj9HhkXhm1Pkbj2LObuA==}
|
||||
|
||||
'@next/eslint-plugin-next@15.3.0-canary.6':
|
||||
resolution: {integrity: sha512-s2M/oWJR5dDP3nzzdHpsC83YZgz/QF0Wlt7Kus0dxSTgur8WpyO59QvNFqeYWxHwcrk1tM6XHkaGGBBdodYX7g==}
|
||||
'@next/eslint-plugin-next@15.3.0-canary.8':
|
||||
resolution: {integrity: sha512-WIa24zXGlI/8xpAOvWrdiHA9ypj8eTh2KHowNMHoU2u4GC9igV+GOOjghhBx/PhAkYyiXpG2iJ3EFnvf7sBMQA==}
|
||||
|
||||
'@next/mdx@15.3.0-canary.6':
|
||||
resolution: {integrity: sha512-opVhy5uHLs6nuSxSxeScKLrHzNMzM6Vy3EGet7vvm6pV1o5oFWjDTpd8QcBcUovbPRZst2UQJ4R39SCj4wsSww==}
|
||||
'@next/mdx@15.3.0-canary.8':
|
||||
resolution: {integrity: sha512-VaKbWHy32z72JyCNT5kqDALy253aPlJsavNvRC+Wm8d3diXUdOc+ztou4KGy0iRC8+o6flE9sncy/6bzzBV0VA==}
|
||||
peerDependencies:
|
||||
'@mdx-js/loader': '>=0.15.0'
|
||||
'@mdx-js/react': '>=0.15.0'
|
||||
@ -669,56 +669,56 @@ packages:
|
||||
'@mdx-js/react':
|
||||
optional: true
|
||||
|
||||
'@next/swc-darwin-arm64@15.3.0-canary.6':
|
||||
resolution: {integrity: sha512-Ha7GrbUmF5sdMYGHwcTP1+eFtsl/1Bobxc2yEzBONF4ZGsDwTJtJ0mg6/duyDBH6vB4Qi5mvO9ohe8AKcubFwA==}
|
||||
'@next/swc-darwin-arm64@15.3.0-canary.8':
|
||||
resolution: {integrity: sha512-ItDJSApzYkYLKxjXvI2WRYeb8FkCww6/Wou0Tsdunixh5XeUp/UE7cNP88YGgmp3bI3FgDpVYnP+rUsPToJBUg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@next/swc-darwin-x64@15.3.0-canary.6':
|
||||
resolution: {integrity: sha512-SwEH5UZ1D7BhUThx5qu0ONhSXYaIAziC3o021lfWMzPtsZlylxP6W5CLRnyf16geTNEsn9/PcipaI9pRvmVaEQ==}
|
||||
'@next/swc-darwin-x64@15.3.0-canary.8':
|
||||
resolution: {integrity: sha512-kh55C9939RM0unsZ7700LlHeqUNwnv2Vmd8iz40HQ+G8aaS/Dkd5M7kdzMXkGcY3D79TFL1dxGSL6s1te5R4dg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@next/swc-linux-arm64-gnu@15.3.0-canary.6':
|
||||
resolution: {integrity: sha512-IqRHfFOaICHC8Pfb/8NFGn1jzSb3pbR9IE6ea/DjQp4dv5NguMQ3iPB3SEMEojh9mvpUhmXT7FoSF9xZO24E5w==}
|
||||
'@next/swc-linux-arm64-gnu@15.3.0-canary.8':
|
||||
resolution: {integrity: sha512-YVyuFoF0GAssBsCTnv1w4rJCxPApVe3UQyNRBjrTL/szRm5kZc6lPz+bBTc/QfgsOZz7iGV/6z4CuR8L+NSm0w==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@next/swc-linux-arm64-musl@15.3.0-canary.6':
|
||||
resolution: {integrity: sha512-jyplseHznib0tfe/fx5l2lV4f/ZpDHSJBnq8d5dOQZwa9kqGD/plcfqOqdwR7XmwYrDoXXyDiWArk6F1XCMWDQ==}
|
||||
'@next/swc-linux-arm64-musl@15.3.0-canary.8':
|
||||
resolution: {integrity: sha512-YMZxUsvNz7LtVd8q9pXlp+AJoN73lvycUMLB+Or2Zc207KvnPxIspkmeOj4AiiNC6q5AIxc0W3YxWH7NmFvJJg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@next/swc-linux-x64-gnu@15.3.0-canary.6':
|
||||
resolution: {integrity: sha512-vMPd9dTR1eRYFGYGb2J/5WYuBYiUXy/hNFhnXbBq5hVf2kZ8wlJblJuNC/yyXr9lvSf4jsXDuWeXNYPaRl85hA==}
|
||||
'@next/swc-linux-x64-gnu@15.3.0-canary.8':
|
||||
resolution: {integrity: sha512-Cbij+lmUlqj0FSv64jAU5j8iTAGSb2BAfXpE0Crz8pymddlny1h+mYJtiYo3fOACQPqQnExBXyzXRY5RveiH7Q==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@next/swc-linux-x64-musl@15.3.0-canary.6':
|
||||
resolution: {integrity: sha512-va7/O3oqgWUMIzNLAuQXbKFw6DqTS6S45FneyGWGorDlttq1K11cBYKOQhz3If7Lw/ftrLLOLPdlYZGcciCdeg==}
|
||||
'@next/swc-linux-x64-musl@15.3.0-canary.8':
|
||||
resolution: {integrity: sha512-zJyaG6tiYFHhLsge8MULXwOhaWqAj2OLWSL7yjWGLMSm+c5n06S4tfppQiY4E/4fJiqtpo7Ty9s7AjG3TbTWSw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@next/swc-win32-arm64-msvc@15.3.0-canary.6':
|
||||
resolution: {integrity: sha512-SeUU5mQSIZXGwMxl5Bn94CdWF0R3YIWCxWq9Lpo1KW2B2S6F61WCmjeZnZZ9TOGMi4D7BAP96ptMCNiNOZUi0Q==}
|
||||
'@next/swc-win32-arm64-msvc@15.3.0-canary.8':
|
||||
resolution: {integrity: sha512-qhV+9EkjyRlxvS54aC1e+wDqe2JgP2vXCo00VkyVPJqiVXIvpSIR/7DXg7bDuSvxr7t1sufm7P7v4jhUWTmg1w==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@next/swc-win32-x64-msvc@15.3.0-canary.6':
|
||||
resolution: {integrity: sha512-P+O19Iet4806xsdVFwbVfzxeTRb50xImjK5NT9Ge5gXCSuBw+DdRdJhENijRYa9lS/RnQVrXfII5gLdLy4X3sQ==}
|
||||
'@next/swc-win32-x64-msvc@15.3.0-canary.8':
|
||||
resolution: {integrity: sha512-3lE7Qz7XmAswjJ+WczXsiLjdQ9TpXNX9yJ33cEAsaCBP6+5dsmYeyviguvKDza1VbmQXlxRHqSeZvMFr9jXrBQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@next/third-parties@15.3.0-canary.6':
|
||||
resolution: {integrity: sha512-6M5iSbY21atKOYfw4Kx4xWgPv0aoYKrNrz/3PIgcDROnkgT05LkIJMQecZ06+2r+ff93NuKYqtEz+NvZMHPcXQ==}
|
||||
'@next/third-parties@15.3.0-canary.8':
|
||||
resolution: {integrity: sha512-ELJ6bR4AFgsDboH0pC856jauB16U+574uGM6r2JsQz2IM/iI+d3TJvUa6C942sbGNsbnPd4eo5ycORZZV0PS7Q==}
|
||||
peerDependencies:
|
||||
next: ^13.0.0 || ^14.0.0 || ^15.0.0
|
||||
react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
|
||||
@ -1476,8 +1476,8 @@ packages:
|
||||
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
eslint-config-next@15.3.0-canary.6:
|
||||
resolution: {integrity: sha512-NEefwyiCUtXGkpJN5CwCJSYra2+8+YyMYo6TtG59b+jsrZxa9r12emTWYJcWMzNgxDZvRM4xYO6pyXs1ie2FyA==}
|
||||
eslint-config-next@15.3.0-canary.8:
|
||||
resolution: {integrity: sha512-3kcG6U4jii1+Vur5XQbUUYZrDHa4pvHa0Me2GdWAa2JhevJuNOzIVmWLHrKlPtULBbVmxWjX09wUesQIkoYb4Q==}
|
||||
peerDependencies:
|
||||
eslint: ^7.23.0 || ^8.0.0 || ^9.0.0
|
||||
typescript: '>=3.3.1'
|
||||
@ -1494,8 +1494,8 @@ packages:
|
||||
eslint-import-resolver-node@0.3.9:
|
||||
resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
|
||||
|
||||
eslint-import-resolver-typescript@3.8.6:
|
||||
resolution: {integrity: sha512-d9UjvYpj/REmUoZvOtDEmayPlwyP4zOwwMBgtC6RtrpZta8u1AIVmxgZBYJIcCKKXwAcLs+DX2yn2LeMaTqKcQ==}
|
||||
eslint-import-resolver-typescript@3.8.7:
|
||||
resolution: {integrity: sha512-U7k84gOzrfl09c33qrIbD3TkWTWu3nt3dK5sDajHSekfoLlYGusIwSdPlPzVeA6TFpi0Wpj+ZdBD8hX4hxPoww==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
@ -1937,8 +1937,8 @@ packages:
|
||||
hastscript@9.0.1:
|
||||
resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==}
|
||||
|
||||
hookified@1.7.1:
|
||||
resolution: {integrity: sha512-OXcdHsXeOiD7OJ5zvWj8Oy/6RCdLwntAX+wUrfemNcMGn6sux4xbEHi2QXwqePYhjQ/yvxxq2MvCRirdlHscBw==}
|
||||
hookified@1.8.1:
|
||||
resolution: {integrity: sha512-GrO2l93P8xCWBSTBX9l2BxI78VU/MAAYag+pG8curS3aBGy0++ZlxrQ7PdUOUVMbn5BwkGb6+eRrnf43ipnFEA==}
|
||||
|
||||
hosted-git-info@7.0.2:
|
||||
resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==}
|
||||
@ -2302,8 +2302,8 @@ packages:
|
||||
lru-cache@10.4.3:
|
||||
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
|
||||
|
||||
lucide-react@0.479.0:
|
||||
resolution: {integrity: sha512-aBhNnveRhorBOK7uA4gDjgaf+YlHMdMhQ/3cupk6exM10hWlEU+2QtWYOfhXhjAsmdb6LeKR+NZnow4UxRRiTQ==}
|
||||
lucide-react@0.481.0:
|
||||
resolution: {integrity: sha512-NrvUDNFwgLIvHiwTEq9boa5Kiz1KdUT8RJ+wmNijwxdn9U737Fw42c43sRxJTMqhL+ySHpGRVCWpwiF+abrEjw==}
|
||||
peerDependencies:
|
||||
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
|
||||
@ -2544,8 +2544,8 @@ packages:
|
||||
natural-compare@1.4.0:
|
||||
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
||||
|
||||
next@15.3.0-canary.6:
|
||||
resolution: {integrity: sha512-2ud5m+f6q4iCwRGJSCODhJHTlSXi1ueY4tMx38EYp8obLCT1VBpCqLm70ppu0RYU+D79Vkqgf1VaQ+tu3i0nuw==}
|
||||
next@15.3.0-canary.8:
|
||||
resolution: {integrity: sha512-RuXoaWX13+VhfK0lD/r8XqcyZFpyER4/KaomW/wZYaEyoiHVEFH6ndpD6m4b9+a60w1bua3CoRn2Ih1419FZ8Q==}
|
||||
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@ -3275,8 +3275,8 @@ packages:
|
||||
peerDependencies:
|
||||
stylelint: ^16.0.2
|
||||
|
||||
stylelint@16.15.0:
|
||||
resolution: {integrity: sha512-OK6Rs7EPdcdmjqiDycadZY4fw3f5/TC1X6/tGjnF3OosbwCeNs7nG+79MCAtjEg7ckwqTJTsku08e0Rmaz5nUw==}
|
||||
stylelint@16.16.0:
|
||||
resolution: {integrity: sha512-40X5UOb/0CEFnZVEHyN260HlSSUxPES+arrUphOumGWgXERHfwCD0kNBVILgQSij8iliYVwlc0V7M5bcLP9vPg==}
|
||||
engines: {node: '>=18.12.0'}
|
||||
hasBin: true
|
||||
|
||||
@ -3910,53 +3910,53 @@ snapshots:
|
||||
'@types/react': 19.0.10
|
||||
react: 19.0.0
|
||||
|
||||
'@next/bundle-analyzer@15.3.0-canary.6':
|
||||
'@next/bundle-analyzer@15.3.0-canary.8':
|
||||
dependencies:
|
||||
webpack-bundle-analyzer: 4.10.1
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
|
||||
'@next/env@15.3.0-canary.6': {}
|
||||
'@next/env@15.3.0-canary.8': {}
|
||||
|
||||
'@next/eslint-plugin-next@15.3.0-canary.6':
|
||||
'@next/eslint-plugin-next@15.3.0-canary.8':
|
||||
dependencies:
|
||||
fast-glob: 3.3.1
|
||||
|
||||
'@next/mdx@15.3.0-canary.6(@mdx-js/loader@3.1.0(acorn@8.14.1))(@mdx-js/react@3.1.0(@types/react@19.0.10)(react@19.0.0))':
|
||||
'@next/mdx@15.3.0-canary.8(@mdx-js/loader@3.1.0(acorn@8.14.1))(@mdx-js/react@3.1.0(@types/react@19.0.10)(react@19.0.0))':
|
||||
dependencies:
|
||||
source-map: 0.7.4
|
||||
optionalDependencies:
|
||||
'@mdx-js/loader': 3.1.0(acorn@8.14.1)
|
||||
'@mdx-js/react': 3.1.0(@types/react@19.0.10)(react@19.0.0)
|
||||
|
||||
'@next/swc-darwin-arm64@15.3.0-canary.6':
|
||||
'@next/swc-darwin-arm64@15.3.0-canary.8':
|
||||
optional: true
|
||||
|
||||
'@next/swc-darwin-x64@15.3.0-canary.6':
|
||||
'@next/swc-darwin-x64@15.3.0-canary.8':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-arm64-gnu@15.3.0-canary.6':
|
||||
'@next/swc-linux-arm64-gnu@15.3.0-canary.8':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-arm64-musl@15.3.0-canary.6':
|
||||
'@next/swc-linux-arm64-musl@15.3.0-canary.8':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-gnu@15.3.0-canary.6':
|
||||
'@next/swc-linux-x64-gnu@15.3.0-canary.8':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-musl@15.3.0-canary.6':
|
||||
'@next/swc-linux-x64-musl@15.3.0-canary.8':
|
||||
optional: true
|
||||
|
||||
'@next/swc-win32-arm64-msvc@15.3.0-canary.6':
|
||||
'@next/swc-win32-arm64-msvc@15.3.0-canary.8':
|
||||
optional: true
|
||||
|
||||
'@next/swc-win32-x64-msvc@15.3.0-canary.6':
|
||||
'@next/swc-win32-x64-msvc@15.3.0-canary.8':
|
||||
optional: true
|
||||
|
||||
'@next/third-parties@15.3.0-canary.6(next@15.3.0-canary.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)':
|
||||
'@next/third-parties@15.3.0-canary.8(next@15.3.0-canary.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)':
|
||||
dependencies:
|
||||
next: 15.3.0-canary.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
next: 15.3.0-canary.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
react: 19.0.0
|
||||
third-party-capital: 1.0.20
|
||||
|
||||
@ -4440,7 +4440,7 @@ snapshots:
|
||||
|
||||
cacheable@1.8.9:
|
||||
dependencies:
|
||||
hookified: 1.7.1
|
||||
hookified: 1.8.1
|
||||
keyv: 5.3.1
|
||||
|
||||
call-bind-apply-helpers@1.0.2:
|
||||
@ -4858,16 +4858,16 @@ snapshots:
|
||||
|
||||
escape-string-regexp@5.0.0: {}
|
||||
|
||||
eslint-config-next@15.3.0-canary.6(eslint@9.22.0)(typescript@5.8.2):
|
||||
eslint-config-next@15.3.0-canary.8(eslint@9.22.0)(typescript@5.8.2):
|
||||
dependencies:
|
||||
'@next/eslint-plugin-next': 15.3.0-canary.6
|
||||
'@next/eslint-plugin-next': 15.3.0-canary.8
|
||||
'@rushstack/eslint-patch': 1.11.0
|
||||
'@typescript-eslint/eslint-plugin': 8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.8.2))(eslint@9.22.0)(typescript@5.8.2)
|
||||
'@typescript-eslint/parser': 8.26.1(eslint@9.22.0)(typescript@5.8.2)
|
||||
eslint: 9.22.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-import-resolver-typescript: 3.8.6(eslint-plugin-import@2.31.0)(eslint@9.22.0)
|
||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.8.2))(eslint-import-resolver-typescript@3.8.6)(eslint@9.22.0)
|
||||
eslint-import-resolver-typescript: 3.8.7(eslint-plugin-import@2.31.0)(eslint@9.22.0)
|
||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.8.2))(eslint-import-resolver-typescript@3.8.7)(eslint@9.22.0)
|
||||
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.22.0)
|
||||
eslint-plugin-react: 7.37.4(eslint@9.22.0)
|
||||
eslint-plugin-react-hooks: 5.2.0(eslint@9.22.0)
|
||||
@ -4890,7 +4890,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-import-resolver-typescript@3.8.6(eslint-plugin-import@2.31.0)(eslint@9.22.0):
|
||||
eslint-import-resolver-typescript@3.8.7(eslint-plugin-import@2.31.0)(eslint@9.22.0):
|
||||
dependencies:
|
||||
'@nolyfill/is-core-module': 1.0.39
|
||||
debug: 4.4.0
|
||||
@ -4901,7 +4901,7 @@ snapshots:
|
||||
stable-hash: 0.0.4
|
||||
tinyglobby: 0.2.12
|
||||
optionalDependencies:
|
||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.8.2))(eslint-import-resolver-typescript@3.8.6)(eslint@9.22.0)
|
||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.8.2))(eslint-import-resolver-typescript@3.8.7)(eslint@9.22.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@ -4926,14 +4926,14 @@ snapshots:
|
||||
- bluebird
|
||||
- supports-color
|
||||
|
||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.6)(eslint@9.22.0):
|
||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.7)(eslint@9.22.0):
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 8.26.1(eslint@9.22.0)(typescript@5.8.2)
|
||||
eslint: 9.22.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-import-resolver-typescript: 3.8.6(eslint-plugin-import@2.31.0)(eslint@9.22.0)
|
||||
eslint-import-resolver-typescript: 3.8.7(eslint-plugin-import@2.31.0)(eslint@9.22.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@ -4943,7 +4943,7 @@ snapshots:
|
||||
gonzales-pe: 4.3.0
|
||||
lodash: 4.17.21
|
||||
|
||||
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.8.2))(eslint-import-resolver-typescript@3.8.6)(eslint@9.22.0):
|
||||
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.8.2))(eslint-import-resolver-typescript@3.8.7)(eslint@9.22.0):
|
||||
dependencies:
|
||||
'@rtsao/scc': 1.1.0
|
||||
array-includes: 3.1.8
|
||||
@ -4954,7 +4954,7 @@ snapshots:
|
||||
doctrine: 2.1.0
|
||||
eslint: 9.22.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.6)(eslint@9.22.0)
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.7)(eslint@9.22.0)
|
||||
hasown: 2.0.2
|
||||
is-core-module: 2.16.1
|
||||
is-glob: 4.0.3
|
||||
@ -5238,7 +5238,7 @@ snapshots:
|
||||
dependencies:
|
||||
cacheable: 1.8.9
|
||||
flatted: 3.3.3
|
||||
hookified: 1.7.1
|
||||
hookified: 1.8.1
|
||||
|
||||
flatted@3.3.3: {}
|
||||
|
||||
@ -5267,9 +5267,9 @@ snapshots:
|
||||
|
||||
functions-have-names@1.2.3: {}
|
||||
|
||||
geist@1.3.1(next@15.3.0-canary.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)):
|
||||
geist@1.3.1(next@15.3.0-canary.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)):
|
||||
dependencies:
|
||||
next: 15.3.0-canary.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
next: 15.3.0-canary.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
|
||||
get-east-asian-width@1.3.0: {}
|
||||
|
||||
@ -5536,7 +5536,7 @@ snapshots:
|
||||
property-information: 7.0.0
|
||||
space-separated-tokens: 2.0.2
|
||||
|
||||
hookified@1.7.1: {}
|
||||
hookified@1.8.1: {}
|
||||
|
||||
hosted-git-info@7.0.2:
|
||||
dependencies:
|
||||
@ -5903,7 +5903,7 @@ snapshots:
|
||||
|
||||
lru-cache@10.4.3: {}
|
||||
|
||||
lucide-react@0.479.0(react@19.0.0):
|
||||
lucide-react@0.481.0(react@19.0.0):
|
||||
dependencies:
|
||||
react: 19.0.0
|
||||
|
||||
@ -6392,9 +6392,9 @@ snapshots:
|
||||
|
||||
natural-compare@1.4.0: {}
|
||||
|
||||
next@15.3.0-canary.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
||||
next@15.3.0-canary.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
||||
dependencies:
|
||||
'@next/env': 15.3.0-canary.6
|
||||
'@next/env': 15.3.0-canary.8
|
||||
'@swc/counter': 0.1.3
|
||||
'@swc/helpers': 0.5.15
|
||||
busboy: 1.6.0
|
||||
@ -6404,14 +6404,14 @@ snapshots:
|
||||
react-dom: 19.0.0(react@19.0.0)
|
||||
styled-jsx: 5.1.6(react@19.0.0)
|
||||
optionalDependencies:
|
||||
'@next/swc-darwin-arm64': 15.3.0-canary.6
|
||||
'@next/swc-darwin-x64': 15.3.0-canary.6
|
||||
'@next/swc-linux-arm64-gnu': 15.3.0-canary.6
|
||||
'@next/swc-linux-arm64-musl': 15.3.0-canary.6
|
||||
'@next/swc-linux-x64-gnu': 15.3.0-canary.6
|
||||
'@next/swc-linux-x64-musl': 15.3.0-canary.6
|
||||
'@next/swc-win32-arm64-msvc': 15.3.0-canary.6
|
||||
'@next/swc-win32-x64-msvc': 15.3.0-canary.6
|
||||
'@next/swc-darwin-arm64': 15.3.0-canary.8
|
||||
'@next/swc-darwin-x64': 15.3.0-canary.8
|
||||
'@next/swc-linux-arm64-gnu': 15.3.0-canary.8
|
||||
'@next/swc-linux-arm64-musl': 15.3.0-canary.8
|
||||
'@next/swc-linux-x64-gnu': 15.3.0-canary.8
|
||||
'@next/swc-linux-x64-musl': 15.3.0-canary.8
|
||||
'@next/swc-win32-arm64-msvc': 15.3.0-canary.8
|
||||
'@next/swc-win32-x64-msvc': 15.3.0-canary.8
|
||||
sharp: 0.33.5
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
@ -7277,22 +7277,22 @@ snapshots:
|
||||
client-only: 0.0.1
|
||||
react: 19.0.0
|
||||
|
||||
stylelint-config-css-modules@4.4.0(stylelint@16.15.0(typescript@5.8.2)):
|
||||
stylelint-config-css-modules@4.4.0(stylelint@16.16.0(typescript@5.8.2)):
|
||||
dependencies:
|
||||
stylelint: 16.15.0(typescript@5.8.2)
|
||||
stylelint: 16.16.0(typescript@5.8.2)
|
||||
optionalDependencies:
|
||||
stylelint-scss: 6.11.1(stylelint@16.15.0(typescript@5.8.2))
|
||||
stylelint-scss: 6.11.1(stylelint@16.16.0(typescript@5.8.2))
|
||||
|
||||
stylelint-config-recommended@15.0.0(stylelint@16.15.0(typescript@5.8.2)):
|
||||
stylelint-config-recommended@15.0.0(stylelint@16.16.0(typescript@5.8.2)):
|
||||
dependencies:
|
||||
stylelint: 16.15.0(typescript@5.8.2)
|
||||
stylelint: 16.16.0(typescript@5.8.2)
|
||||
|
||||
stylelint-config-standard@37.0.0(stylelint@16.15.0(typescript@5.8.2)):
|
||||
stylelint-config-standard@37.0.0(stylelint@16.16.0(typescript@5.8.2)):
|
||||
dependencies:
|
||||
stylelint: 16.15.0(typescript@5.8.2)
|
||||
stylelint-config-recommended: 15.0.0(stylelint@16.15.0(typescript@5.8.2))
|
||||
stylelint: 16.16.0(typescript@5.8.2)
|
||||
stylelint-config-recommended: 15.0.0(stylelint@16.16.0(typescript@5.8.2))
|
||||
|
||||
stylelint-scss@6.11.1(stylelint@16.15.0(typescript@5.8.2)):
|
||||
stylelint-scss@6.11.1(stylelint@16.16.0(typescript@5.8.2)):
|
||||
dependencies:
|
||||
css-tree: 3.1.0
|
||||
is-plain-object: 5.0.0
|
||||
@ -7302,10 +7302,10 @@ snapshots:
|
||||
postcss-resolve-nested-selector: 0.1.6
|
||||
postcss-selector-parser: 7.1.0
|
||||
postcss-value-parser: 4.2.0
|
||||
stylelint: 16.15.0(typescript@5.8.2)
|
||||
stylelint: 16.16.0(typescript@5.8.2)
|
||||
optional: true
|
||||
|
||||
stylelint@16.15.0(typescript@5.8.2):
|
||||
stylelint@16.16.0(typescript@5.8.2):
|
||||
dependencies:
|
||||
'@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3)
|
||||
'@csstools/css-tokenizer': 3.0.3
|
||||
|
Before Width: | Height: | Size: 128 KiB |