From 07eaff88f92445270fc1ace5215760a7207d5092 Mon Sep 17 00:00:00 2001 From: David Levai Date: Sun, 23 Jul 2023 23:05:34 +0200 Subject: [PATCH 01/17] feat: SEO updates, author, mdx math, type fixes --- CHANGELOG.md | 7 ++ README.md | 11 ++- app/(site)/page.tsx | 2 - app/(site)/posts/[slug]/page.tsx | 4 +- app/layout.tsx | 15 ++- app/robots.ts | 1 + app/sitemap.ts | 2 +- components/post-preview.tsx | 2 +- content/posts/choosing-providers.mdx | 7 ++ contentlayer.config.ts | 9 +- lib/content-definitions/author.ts | 9 ++ lib/content-definitions/post.ts | 5 + lib/metadata.ts | 1 + package.json | 2 + pnpm-lock.yaml | 134 +++++++++++++++++++++++++++ types/index.tsx | 7 +- 16 files changed, 204 insertions(+), 14 deletions(-) create mode 100644 lib/content-definitions/author.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 76c01b4..65bef03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Convertkit newsletter provider - Plausible analytics provider +- Math and Katex support +- Author content definition + +### Changed + +- Small SEO updates +- Codebase and type fixes ## [0.6.0] - 2023-07-16 diff --git a/README.md b/README.md index 8f51d5c..f4ff5ac 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ![Image2](/screenshots/garden2.png) [More screenshots here](/screenshots/) -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/thedevdavid/digital-garden) +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fthedevdavid%2Fdigital-garden%2F) An open source blogging (digital gardening) template for developers using [Next.js](https://nextjs.org/) app router, MDX, [Contentlayer](https://contentlayer.dev/), [Tailwind CSS](https://tailwindcss.com/), [@shadcn/ui](https://ui.shadcn.com/) , [Lucide Icons](https://lucide.dev/icons), and more. @@ -190,18 +190,24 @@ Note: DO NOT overdo it. You can easily make images look bad with lossy compressi - [x] Social sharing buttons - [x] Tags - [x] newsletter integration (form, api route, keys, thank you/welcome page, MailerLite provider) +- [x] more MDX components (katex, math) +- [x] author content definition - [ ] Other newsletter providers (Convertkit, Substack, Buttondown, Mailchimp, etc) - [ ] Other analytics providers (fathom, simplelytics, plausible, etc) - [ ] CLI and/or recipes - [ ] Post series page - [ ] prev/next post links -- [ ] related posts +- [ ] related/similar posts +- [ ] Donate component & page +- [ ] RTL Support - [ ] Newsletter previous issues page - [ ] Layouts/templates system - [ ] Notion data source - [ ] Sanity data source +- [ ] custom admin CMS(?) - [ ] hero title and subtitle text HTML support(?) - [ ] Design improvements (whitespace, layout, etc.) +- [ ] more MDX components (embed) - [ ] error, and loading pages - [ ] Code preview component - [ ] Code highlight improvements (copy code, theme) @@ -221,6 +227,7 @@ Note: DO NOT overdo it. You can easily make images look bad with lossy compressi - [ ] general cleanup - [ ] implement content security policies - [ ] implement a videoask-like solution for the hero section +- [ ] lightbox for images - [ ] RSS feed improvements (image, description, etc.) - [ ] multi-author support (?) - [ ] Post like counter (?) diff --git a/app/(site)/page.tsx b/app/(site)/page.tsx index dc0a7f1..32e6b7c 100644 --- a/app/(site)/page.tsx +++ b/app/(site)/page.tsx @@ -1,12 +1,10 @@ import Image from "next/image"; import Link from "next/link"; -import { notFound } from "next/navigation"; import { allPages, allPosts } from "@/.contentlayer/generated"; import { compareDesc } from "date-fns"; import { ArrowRight } from "lucide-react"; import { defaultAuthor } from "@/lib/metadata"; -import { cn } from "@/lib/utils"; import { HeroImage } from "@/components/hero-image"; import { HeroMinimal } from "@/components/hero-minimal"; import { HeroSimple } from "@/components/hero-simple"; diff --git a/app/(site)/posts/[slug]/page.tsx b/app/(site)/posts/[slug]/page.tsx index a90f2a1..d931fd5 100644 --- a/app/(site)/posts/[slug]/page.tsx +++ b/app/(site)/posts/[slug]/page.tsx @@ -1,8 +1,8 @@ import { Metadata } from "next"; import Link from "next/link"; import { notFound } from "next/navigation"; +import { allPosts } from "@/.contentlayer/generated"; import { PostSeries, SeriesItem } from "@/types"; -import { allPosts } from "contentlayer/generated"; import { format, parseISO } from "date-fns"; import { Home } from "lucide-react"; @@ -59,6 +59,8 @@ export async function generateMetadata({ params }: PostProps): Promise return { title: post.title, description: post.description, + authors: [{ name: post?.author?.name || defaultAuthor.name, url: defaultAuthor.website }], + keywords: post.tags, }; } diff --git a/app/layout.tsx b/app/layout.tsx index 662b322..4c86efd 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,8 +1,9 @@ import "./globals.css"; +import { Metadata } from "next"; import { Inter, Space_Grotesk } from "next/font/google"; -import siteMetadata from "@/lib/metadata"; +import siteMetadata, { BASE_URL, defaultAuthor } from "@/lib/metadata"; import { Toaster } from "@/components/ui/toaster"; import { Analytics } from "@/components/analytics"; import { BackTopButton } from "@/components/back-to-top"; @@ -16,9 +17,17 @@ const spaceGrotesk = Space_Grotesk({ }); const inter = Inter({ subsets: ["latin"], display: "swap", variable: "--font-inter" }); -export const metadata = { +export const metadata: Metadata = { + metadataBase: new URL(BASE_URL), title: siteMetadata.title, description: siteMetadata.description, + authors: [{ name: defaultAuthor.name, url: defaultAuthor.website }], + alternates: { + canonical: "./", + types: { + "application/rss+xml": `${BASE_URL}/feed.xml`, + }, + }, }; interface RootLayoutProps { @@ -29,7 +38,7 @@ export default function RootLayout({ children }: RootLayoutProps) { return ( - + {children} diff --git a/app/robots.ts b/app/robots.ts index ed15aef..63d9ee2 100644 --- a/app/robots.ts +++ b/app/robots.ts @@ -10,5 +10,6 @@ export default function robots(): MetadataRoute.Robots { disallow: "/private/", }, sitemap: `${BASE_URL}/sitemap.xml`, + host: BASE_URL, }; } diff --git a/app/sitemap.ts b/app/sitemap.ts index 47f6f94..bf6e1e1 100644 --- a/app/sitemap.ts +++ b/app/sitemap.ts @@ -13,7 +13,7 @@ export default function sitemap(): MetadataRoute.Sitemap { })); const posts = loadedPosts.map((post) => ({ url: `${BASE_URL}/posts/${post.slug}`, - lastModified: post.lastUpdatedDate, + lastModified: post.lastUpdatedDate || post.publishedDate, })); const pages = allPages .filter((page) => page.status === "published") diff --git a/components/post-preview.tsx b/components/post-preview.tsx index e97782d..78ed006 100644 --- a/components/post-preview.tsx +++ b/components/post-preview.tsx @@ -32,7 +32,7 @@ const PostPreview = ({ post }: PostPreviewProps) => { {post?.tags && ( -