Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dependencies Upgrades, SEO, DX, Performance Improvements #69

Open
wants to merge 87 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
3c238a0
.npmrc added with support for legacy peer dependencies
nirnejak Jan 7, 2025
2ae82d0
Dependencies Updated
nirnejak Jan 8, 2025
b50fc49
Hero: sponsors added, style and responsiveness fixes
nirnejak Jan 10, 2025
86bc852
Hero: coderabbit and stream logo added
nirnejak Jan 12, 2025
2931e6e
Hero: link to sponsors added
nirnejak Jan 12, 2025
a24e896
Merge branch 'main' into next-15-react-19
nirnejak Jan 12, 2025
8857078
package-lock updated
nirnejak Jan 12, 2025
548ac07
Merge branch 'hero-sponsors' into next-15-react-19
nirnejak Jan 12, 2025
026cc41
Imports fixed for Next 15
nirnejak Jan 12, 2025
5ea9085
Next config: invalid config removed
nirnejak Jan 12, 2025
56afd20
next config: optimizeFonts removed since not required
nirnejak Jan 12, 2025
e610cc7
Blogs: layout changed
nirnejak Jan 12, 2025
3bd452d
Dynamic import fixes
nirnejak Jan 12, 2025
9534dc1
Unused MDX component removed
nirnejak Jan 12, 2025
1ac374e
Blog related components moved to a directory
nirnejak Jan 12, 2025
5f0956f
Unused metadata component removed
nirnejak Jan 12, 2025
30cdd30
Blog: imports updated
nirnejak Jan 12, 2025
c9c90f8
Blog: params type and usage fixed
nirnejak Jan 12, 2025
5c8b3da
Blogs: key prop issue fixed
nirnejak Jan 12, 2025
69191c6
View Counter implementation fixes
nirnejak Jan 12, 2025
f033497
Tools: params type and usage fixed
nirnejak Jan 12, 2025
7f6077b
Blog: import updated
nirnejak Jan 12, 2025
ab58080
CopyCode component moved to blogs folder
nirnejak Jan 12, 2025
b5aeb5d
Dependencies Updated
nirnejak Jan 14, 2025
0da387f
Not Found Page added
nirnejak Jan 14, 2025
fbbc7ae
MDX Renderer setup
nirnejak Jan 14, 2025
a93bfbd
Blogs: get blogs from the list instead of filesystem
nirnejak Jan 14, 2025
d1f466a
Blog: implementation changed
nirnejak Jan 14, 2025
7a71a5e
tailwind config: updated to use mdx-components.tsx
nirnejak Jan 14, 2025
f39bf18
next config simplified
nirnejak Jan 14, 2025
c58f32e
Unused dependencies removed
nirnejak Jan 14, 2025
94b8058
View Counter: hardcoded values removed
nirnejak Jan 14, 2025
0e5b140
View Counter: related elements added to the components
nirnejak Jan 14, 2025
01d2cb3
Blog Header: initial views as props
nirnejak Jan 14, 2025
3be18a2
Breadcrumbs style updated
nirnejak Jan 14, 2025
321a479
tsconfig updated
nirnejak Jan 14, 2025
b863617
unused dependency removed
nirnejak Jan 14, 2025
d50623c
Blogs: key prop issue fixed
nirnejak Jan 14, 2025
5b8ad48
Blog: h1 fixes
nirnejak Jan 14, 2025
390b17a
View Counter: headers, content type json
nirnejak Jan 14, 2025
4430ef5
MDX Components: blog wrapper non async
nirnejak Jan 14, 2025
0c124c9
MDX Components: custom components, name corrected
nirnejak Jan 14, 2025
0af9a1b
MDX: missing next/image imports
nirnejak Jan 14, 2025
287a7cf
next-view-transitions integration
nirnejak Jan 14, 2025
fd765be
Dependencies Updated
nirnejak Jan 15, 2025
b510512
app config file added
nirnejak Jan 15, 2025
4b4e731
config file removed
nirnejak Jan 15, 2025
05e4d2c
metadata util added
nirnejak Jan 15, 2025
c56ce30
metadata base added
nirnejak Jan 15, 2025
7350ff5
Old metadata config removed
nirnejak Jan 15, 2025
8355c2d
Next 15 Metadata setup
nirnejak Jan 15, 2025
6ea4397
prettier-plugin-tailwindcss updated
nirnejak Jan 15, 2025
bf110c0
ClerkProvider moved to blog level
nirnejak Jan 16, 2025
bd6f316
Blog: comments section updated to get slug from hook
nirnejak Jan 16, 2025
54510cc
Blog Header: slug from hook
nirnejak Jan 16, 2025
300f675
Social Share: use current page url instead of getting a prop
nirnejak Jan 16, 2025
6343b15
Slug from window.location
nirnejak Jan 16, 2025
1b4017e
Sponsor page: page move to a client component
nirnejak Jan 16, 2025
1b401c5
Social Share: window bugfix
nirnejak Jan 16, 2025
422da11
Dependencies Updated
nirnejak Jan 16, 2025
aa44771
Sponsor page: page move to a client component
nirnejak Jan 16, 2025
8d53fdf
Blog: import updated
nirnejak Jan 16, 2025
5215fec
View Counter: fetch data from API
nirnejak Jan 16, 2025
7891a34
View Counter: bugfix
nirnejak Jan 16, 2025
e8bcd8e
Categories and Tools UI fixes
nirnejak Jan 16, 2025
ec125c0
@umami/api-client added
nirnejak Jan 16, 2025
764513b
View Counter: api call updated
nirnejak Jan 16, 2025
74a20c2
View API: umami API to get pageview
nirnejak Jan 16, 2025
0979eb0
View API: url type fixes, handling if url param isn't sent
nirnejak Jan 16, 2025
3c8e80c
View API: console.log removed
nirnejak Jan 16, 2025
f3a3984
Merge branch 'main' into next-15-react-19
nirnejak Jan 16, 2025
cdbeaa5
Dependencies Updated
nirnejak Jan 21, 2025
f590f23
Dependencies Updated
nirnejak Jan 23, 2025
6ab46e9
ClerkProvider moved to CommentSection
nirnejak Jan 23, 2025
41680d0
Serverless Diagram to typescript
nirnejak Jan 23, 2025
89ec62e
Serverless Diagram bugfixes
nirnejak Jan 23, 2025
28333d3
unused css removed
nirnejak Jan 23, 2025
d397552
remote patterns added for external images
nirnejak Jan 23, 2025
298a6cb
Tools page bugfix
nirnejak Jan 26, 2025
df54061
Layout: Font classes moved to html
nirnejak Jan 27, 2025
7654582
Footer: minor style updates
nirnejak Jan 27, 2025
f8a5fd4
Tools: layout fixes
nirnejak Jan 27, 2025
3408e56
Algolia Fixes
nirnejak Jan 27, 2025
628f7a3
Home: hydration issue fixed
nirnejak Jan 27, 2025
2d5f3a9
generateMetadata → getMetadata
nirnejak Jan 28, 2025
ffbb30b
framer-motion → motion
nirnejak Jan 28, 2025
83ae419
Dependencies Updated
nirnejak Jan 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
legacy-peer-deps=true
190 changes: 86 additions & 104 deletions src/app/blog/[slug]/page.tsx → mdx-components.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,58 @@
import * as React from "react"

import { Link } from "next-view-transitions"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Review link transformation implementation.

The link transformation logic adds tracking parameters but has potential issues:

  1. It might break URLs that already have complex query parameters
  2. The transformation applies to all external links without discrimination

Consider a more robust implementation:

 const transformUrl = (url: string): string => {
+  try {
+    const urlObj = new URL(url);
+    // Skip transformation for certain domains or paths if needed
+    if (urlObj.hostname === 'your-excluded-domain.com') return url;
     urlObj.searchParams.append('ref', 'devtoolsacademy.com');
+    return urlObj.toString();
+  } catch {
+    // Return original URL if parsing fails
+    return url;
+  }
-  const separator = url.includes("?") ? "&" : "?"
-  return `${url}${separator}ref=devtoolsacademy.com`
 }

Also applies to: 103-116

import Image from "next/image"
import Link from "next/link"
import { MDXRemote } from "next-mdx-remote/rsc"
import { MDXComponents } from "mdx/types"
import type { MDXComponents } from "mdx/types"
import { codeToHtml } from "shiki"
import { v4 as uuidv4 } from "uuid"
import { ClerkProvider } from "@clerk/nextjs"

import { getPostBySlug, getViewCount, getAllPosts } from "@/lib/posts"
import TableOfContents from "@/components/TableOfContents"
import Breadcrumb from "@/components/Breadcrumb"
import CommentSection from "@/components/CommentSection"
import BlogHeader from "@/components/BlogHeader"
import ServerlessDiagram from "@/components/ServerlessDiagram"
import CodeCopyButton from "@/components/CodeCopyButton"

import { Callout } from "@/components/Callout"
import { Alert, AlertDescription } from "@/components/Alert"
import BackToTop from "@/components/BackToTop"
import ScrollProgressBar from "@/components/ScrollProgressBar"
import { cn } from "@/lib/utils"
import { SocialMetadata } from "@/components/SocialMetadata"

import CommentSection from "@/components/blog/CommentSection"
import TableOfContents from "@/components/blog/TableOfContents"
import CodeCopyButton from "@/components/blog/CodeCopyButton"
import { Callout } from "@/components/blog/Callout"
import { Alert, AlertDescription } from "@/components/blog/Alert"
import BackToTop from "@/components/blog/BackToTop"
import ScrollProgressBar from "@/components/blog/ScrollProgressBar"

interface Props {
children: React.ReactNode
}

const BlogWrapper: React.FC<Props> = ({ children }) => {
return (
<main className="relative mx-auto max-w-5xl px-4 py-36">
<div className="flex flex-col lg:flex-row">
<div className="w-full lg:w-3/4">
<article
className={cn(
"prose prose-neutral prose-invert prose-lg",
"prose-ul:opacity-80 prose-ol:opacity-80",
"prose-pre:py-0 prose-pre:px-3 prose-code:text-sm prose-pre:bg-[#121212]",
"prose-headings:font-semibold prose-headings:tracking-tight prose-headings:opacity-85 prose-img:rounded-md",
"prose-h1:font-bold prose-h1:tracking-tighter"
)}
>
{children}
</article>
<ClerkProvider>
<CommentSection />
</ClerkProvider>
</div>
<aside className="hidden lg:block lg:w-1/4 lg:pl-8">
<div className="sticky top-24">
<TableOfContents />
</div>
</aside>
</div>

<BackToTop />
<ScrollProgressBar />
</main>
)
}

const components: MDXComponents = {
h1: (props: any) => <h1 {...props}>{props.children}</h1>,
Expand All @@ -39,28 +72,6 @@ const components: MDXComponents = {
</h4>
),
p: (props: any) => <p className="my-2 opacity-80" {...props} />,
a: ({ href = "", ...props }: React.ComponentPropsWithoutRef<"a">) => {
const transformUrl = (url: string): string => {
const separator = url.includes("?") ? "&" : "?"
return `${url}${separator}ref=devtoolsacademy.com`
}

return (
<Link
className="text-blue-500 no-underline outline-none hover:underline focus:underline"
href={href.startsWith("http") ? transformUrl(href) : href}
{...props}
/>
)
},
Image: (props: any) => <Image className="my-4" alt={props.alt} {...props} />,
blockquote: (props: any) => (
<blockquote
className="border-l-4 border-neutral-500 pl-4 font-normal not-italic opacity-80"
{...props}
/>
),
ServerlessDiagram: ServerlessDiagram,
code: async ({
className,
children,
Expand Down Expand Up @@ -91,6 +102,35 @@ const components: MDXComponents = {
)
}
},
a: ({ href = "", ...props }: React.ComponentPropsWithoutRef<"a">) => {
const transformUrl = (url: string): string => {
const separator = url.includes("?") ? "&" : "?"
return `${url}${separator}ref=devtoolsacademy.com`
}

return (
<Link
className="text-blue-500 no-underline outline-none hover:underline focus:underline"
href={href.startsWith("http") ? transformUrl(href) : href}
{...props}
/>
)
},
img: (props: any) => (
<Image
className="my-4"
alt={props.alt}
width={1200}
height={600}
{...props}
/>
),
blockquote: (props: any) => (
<blockquote
className="border-l-4 border-neutral-500 pl-4 font-normal not-italic opacity-80"
{...props}
/>
),
Callout: Callout,
Alert: Alert,
AlertDescription: AlertDescription,
Expand All @@ -109,70 +149,12 @@ const components: MDXComponents = {
hr: (props: any) => <hr className="my-12 opacity-50" {...props} />,
}

const baseUrl = "https://devtoolsacademy.com"

export default async function BlogPost({
params,
}: {
params: { slug: string }
}) {
const post = await getPostBySlug(params.slug)
const initialViews = await getViewCount(params.slug)

const breadcrumbItems = [
{ label: "Home", href: "/" },
{ label: "Blog", href: "/blog" },
{ label: post.title, href: `#` },
]

const postUrl = `${baseUrl}/blog/${params.slug}`

return (
<div className="relative mx-auto max-w-5xl px-4 py-36">
<SocialMetadata
title={post.title}
description={post.description}
url={postUrl}
image={`${baseUrl}${post.featuredImage || "/T.png"}`}
type="article"
/>
<Breadcrumb items={breadcrumbItems} />
<BlogHeader
slug={params.slug}
title={post.title}
publishedAt={post.publishedAt}
initialViews={initialViews}
content={post.content}
/>
<div className="flex flex-col lg:flex-row">
<div className="w-full lg:w-3/4">
<article
className={cn(
"prose prose-neutral prose-invert prose-lg",
"prose-ul:opacity-80 prose-ol:opacity-80",
"prose-pre:py-0 prose-pre:px-3 prose-code:text-sm prose-pre:bg-[#121212]",
"prose-headings:font-semibold prose-headings:tracking-tight prose-headings:opacity-85 prose-img:rounded-md"
)}
>
<MDXRemote source={post.content} components={components} />
</article>
<CommentSection postSlug={params.slug} />
</div>
<aside className="hidden lg:block lg:w-1/4 lg:pl-8">
<div className="sticky top-24">
<TableOfContents />
</div>
</aside>
</div>
<BackToTop />
<ScrollProgressBar />
</div>
)
}

export async function generateStaticParams() {
const posts = await getAllPosts()
return posts.map((post) => ({
slug: post.slug,
}))
export function useMDXComponents(
otherComponents: MDXComponents
): MDXComponents {
return {
...otherComponents,
...components,
wrapper: BlogWrapper,
}
}
60 changes: 0 additions & 60 deletions next.config.js

This file was deleted.

29 changes: 29 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import createMDX from "@next/mdx"

/** @type {import('next').NextConfig} */
const nextConfig = {
trailingSlash: true,
reactStrictMode: true,
pageExtensions: ["js", "jsx", "md", "mdx", "ts", "tsx"],

images: {
remotePatterns: [
{
protocol: "https",
hostname: "lh7-rt.googleusercontent.com",
},
{
protocol: "https",
hostname: "tender-bugle-dd6.notion.site",
},
],
},

experimental: {
mdxRs: true,
},
}

const withMDX = createMDX({})

export default withMDX(nextConfig)
Loading
Loading