1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2026-06-05 19:15:30 -04:00

Tailwind redesign (#2387)

This commit is contained in:
2025-05-02 22:04:26 -04:00
committed by GitHub
parent c4f67f170b
commit 5058382f71
162 changed files with 2739 additions and 3554 deletions
+16
View File
@@ -0,0 +1,16 @@
const authorConfig = {
name: "Jake Jarvis",
email: "jake@jarv.is",
social: {
github: "jakejarvis",
twitter: "jakejarvis",
facebook: "jakejarvis",
medium: "jakejarvis",
linkedin: "jakejarvis",
instagram: "jakejarvis",
mastodon: "fediverse.jarv.is/@jake",
bluesky: "jarv.is",
},
} as const;
export default authorConfig;
+2 -2
View File
@@ -1,5 +1,5 @@
/** Path to directory with .mdx files, relative to project root. */
export const POSTS_DIR = "notes";
export const POSTS_DIR = "notes" as const;
/** Maximum width of content wrapper (e.g. for images) in pixels. */
export const MAX_WIDTH = 865;
export const MAX_WIDTH = 896 as const;
-23
View File
@@ -1,23 +0,0 @@
// Site info
export const siteName = "Jake Jarvis";
export const tagline = "Frontend Web Developer in Boston, MA";
export const description =
"Hi there! I'm a frontend web developer based in Boston, Massachusetts specializing in TypeScript, React, Next.js, and other JavaScript frameworks.";
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;
// Me info
export const authorName = "Jake Jarvis";
export const authorEmail = "jake@jarv.is";
export const authorSocial = {
github: "jakejarvis",
twitter: "jakejarvis",
facebook: "jakejarvis",
medium: "jakejarvis",
linkedin: "jakejarvis",
instagram: "jakejarvis",
mastodon: "fediverse.jarv.is/@jake",
bluesky: "jarv.is",
};
+1 -1
View File
@@ -1,5 +1,5 @@
import { CodeIcon, HomeIcon, MailIcon, PencilLineIcon } from "lucide-react";
import type { MenuItemProps } from "../../components/MenuItem";
import type { MenuItemProps } from "@/components/ui/menu-item";
export const menuItems: MenuItemProps[] = [
{
+10
View File
@@ -0,0 +1,10 @@
const siteConfig = {
name: "Jake Jarvis",
tagline: "Frontend Web Developer in Boston, MA",
description:
"Hi there! I'm a frontend web developer based in Boston, Massachusetts specializing in TypeScript, React, Next.js, and other JavaScript frameworks.",
license: "CC-BY-4.0",
copyrightYearStart: 2001,
} as const;
export default siteConfig;
+11 -10
View File
@@ -1,10 +1,11 @@
import { env } from "../../lib/env";
import { env } from "@/lib/env";
import { Feed } from "feed";
import { getFrontMatter, getContent } from "./posts";
import * as config from "../config";
import { getFrontMatter, getContent } from "@/lib/helpers/posts";
import siteConfig from "@/lib/config/site";
import authorConfig from "@/lib/config/author";
import type { Item as FeedItem } from "feed";
import ogImage from "../../app/opengraph-image.jpg";
import ogImage from "@/app/opengraph-image.jpg";
/**
* Returns a `Feed` object, which can then be processed with `feed.rss2()`, `feed.atom1()`, or `feed.json1()`.
@@ -14,9 +15,9 @@ export const buildFeed = async (): Promise<Feed> => {
const feed = new Feed({
id: `${env.NEXT_PUBLIC_BASE_URL}`,
link: `${env.NEXT_PUBLIC_BASE_URL}`,
title: config.siteName,
description: config.description,
copyright: config.licenseUrl,
title: siteConfig.name,
description: siteConfig.description,
copyright: `https://spdx.org/licenses/${siteConfig.license}.html`,
updated: new Date(),
image: `${env.NEXT_PUBLIC_BASE_URL}${ogImage.src}`,
feedLinks: {
@@ -24,9 +25,9 @@ export const buildFeed = async (): Promise<Feed> => {
atom: `${env.NEXT_PUBLIC_BASE_URL}/feed.atom`,
},
author: {
name: config.authorName,
name: authorConfig.name,
link: env.NEXT_PUBLIC_BASE_URL,
email: config.authorEmail,
email: authorConfig.email,
},
});
@@ -40,7 +41,7 @@ export const buildFeed = async (): Promise<Feed> => {
description: post.description,
author: [
{
name: config.authorName,
name: authorConfig.name,
link: `${env.NEXT_PUBLIC_BASE_URL}`,
},
],
+29
View File
@@ -0,0 +1,29 @@
import { h } from "hastscript";
import { toString as nodeToString } from "hast-util-to-string";
import type { ElementContent } from "hast";
const anchor = (heading: ElementContent) => [
h(
"span.anchor-icon",
{
ariaHidden: "true",
},
h(
"svg",
{
width: 16,
height: 16,
viewBox: "0 0 16 16",
xlmns: "http://www.w3.org/2000/svg",
},
h("path", {
fillRule: "evenodd",
fill: "currentcolor",
d: "M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z",
})
)
),
h("span.sr-only", `Jump to "${nodeToString(heading)}"`),
];
export default anchor;
-1
View File
@@ -1 +0,0 @@
export { default as recmaMdxEscapeMissingComponents } from "recma-mdx-escape-missing-components";
+3 -1
View File
@@ -1,4 +1,6 @@
export { default as rehypeAutolinkHeadings } from "rehype-autolink-headings";
export { default as rehypeMdxCodeProps } from "rehype-mdx-code-props";
export { default as rehypeMdxImportMedia } from "rehype-mdx-import-media";
export { default as rehypePrettyCode } from "rehype-pretty-code";
export { default as rehypeSlug } from "rehype-slug";
export { default as rehypeUnwrapImages } from "rehype-unwrap-images";
export { default as rehypeWrapper } from "rehype-wrapper";
+12 -10
View File
@@ -1,39 +1,41 @@
import { env } from "../env";
import * as config from "../config";
import { env } from "@/lib/env";
import siteConfig from "@/lib/config/site";
import authorConfig from "@/lib/config/author";
import type { Metadata } from "next";
export const defaultMetadata: Metadata = {
metadataBase: new URL(env.NEXT_PUBLIC_BASE_URL),
title: {
template: `%s ${config.siteName}`,
default: `${config.siteName} ${config.tagline}`,
template: `%s ${siteConfig.name}`,
default: `${siteConfig.name} ${siteConfig.tagline}`,
},
description: config.description,
description: siteConfig.description,
openGraph: {
siteName: config.siteName,
siteName: siteConfig.name,
title: {
template: "%s",
default: `${config.siteName} ${config.tagline}`,
default: `${siteConfig.name} ${siteConfig.tagline}`,
},
url: "/",
locale: env.NEXT_PUBLIC_SITE_LOCALE.replace("-", "_"),
type: "website",
},
twitter: {
creator: `@${config.authorSocial?.twitter}`,
creator: `@${authorConfig.social?.twitter}`,
},
alternates: {
canonical: "/",
types: {
"application/rss+xml": [
{
title: `${config.siteName} (RSS)`,
title: `${siteConfig.name} (RSS)`,
url: "/feed.xml",
},
],
"application/atom+xml": [
{
title: `${config.siteName} (Atom)`,
title: `${siteConfig.name} (Atom)`,
url: "/feed.atom",
},
],
+3 -3
View File
@@ -1,12 +1,12 @@
import { env } from "../../lib/env";
import { env } from "@/lib/env";
import { cache } from "react";
import path from "path";
import fs from "fs/promises";
import glob from "fast-glob";
import { unified } from "unified";
import { remarkHtml, remarkParse, remarkSmartypants, remarkFrontmatter } from "./mdx/remark";
import { remarkHtml, remarkParse, remarkSmartypants, remarkFrontmatter } from "@/lib/helpers/mdx/remark";
import { decode } from "html-entities";
import { POSTS_DIR } from "../config/constants";
import { POSTS_DIR } from "@/lib/config/constants";
export type FrontMatter = {
slug: string;
-7
View File
@@ -1,7 +0,0 @@
import { Redis } from "@upstash/redis";
// pulls credentials (prefixed with 'KV_REST_API_') set automatically by Vercel marketplace integration:
// https://github.com/upstash/redis-js/blob/091e0a0949593d74b905f41f7cb409ada16f936f/platforms/nodejs.ts#L184
const redis = Redis.fromEnv();
export default redis;
+6
View File
@@ -0,0 +1,6 @@
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export const cn = (...inputs: ClassValue[]) => {
return twMerge(clsx(inputs));
};