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 14 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
2 changes: 0 additions & 2 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ const nextConfig = {
mdxRs: true,
},
reactStrictMode: true,
optimizeFonts: true,
swcMinify: true,
images: {
remotePatterns: [
{
Expand Down
3,205 changes: 1,474 additions & 1,731 deletions package-lock.json

Large diffs are not rendered by default.

42 changes: 21 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,57 +15,57 @@
"@clerk/nextjs": "^5.2.4",
"@mdx-js/loader": "^3.1.0",
"@mdx-js/react": "^3.1.0",
"@neondatabase/serverless": "^0.9.4",
"@next/mdx": "^14.2.22",
"@neondatabase/serverless": "^0.9.5",
"@next/mdx": "^15.1.4",
"@prisma/client": "^5.17.0",
"@radix-ui/react-dialog": "^1.1.4",
"@radix-ui/react-dropdown-menu": "^2.1.4",
"@radix-ui/react-popover": "^1.1.4",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-tabs": "^1.1.2",
"@types/mdx": "^2.0.13",
"@vercel/analytics": "^1.3.1",
"@vercel/speed-insights": "^1.0.12",
"@vercel/analytics": "^1.4.1",
"@vercel/speed-insights": "^1.1.0",
"algoliasearch": "^4.24.0",
"axios": "^1.7.4",
"class-variance-authority": "^0.7.0",
"axios": "^1.7.9",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"framer-motion": "^11.15.0",
"framer-motion": "^11.16.0",
"gray-matter": "^4.0.3",
"lucide-react": "^0.416.0",
"lucide-react": "^0.469.0",
"mermaid": "^11.0.2",
"next": "^14.2.13",
"next": "^15.1.4",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Revert React 19 and ensure Next.js 15 compatibility

The upgrade to React 19 is premature as it's still in alpha/experimental stage. Additionally, Next.js 15 officially supports React 18, not React 19.

Apply this diff to revert to stable versions:

-    "next": "^15.1.4",
+    "next": "15.1.4",
-    "react": "^19.0.0",
-    "react-dom": "^19.0.0",
+    "react": "^18.2.0",
+    "react-dom": "^18.2.0",

Also, remove the caret (^) from Next.js version to prevent automatic minor version updates that might introduce breaking changes during the v15 migration.

Also applies to: 39-40

"next-mdx-remote": "^5.0.0",
"next-themes": "^0.3.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"next-themes": "^0.4.4",
"react": "^19.0.0",
"react-dom": "^19.0.0",
Comment on lines +40 to +41
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Verify React 19 compatibility with your codebase.

The upgrade to React 19 is a major version change that may introduce breaking changes. This version is currently in alpha/experimental stage and not recommended for production use.

Consider downgrading to React 18:

-    "react": "^19.0.0",
-    "react-dom": "^19.0.0",
+    "react": "^18.2.0",
+    "react-dom": "^18.2.0",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",

"react-icons": "^5.4.0",
"react-instantsearch-dom": "^6.40.4",
"react-type-animation": "^3.2.0",
"tailwind-merge": "^2.6.0",
"tailwindcss-animate": "^1.0.7",
"uuid": "^11.0.3",
"uuid": "^11.0.4",
"vaul": "^0.9.1",
"zod": "^3.23.8"
"zod": "^3.24.1"
},
"devDependencies": {
"@next/bundle-analyzer": "^14.2.7",
"@tailwindcss/typography": "^0.5.15",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"@next/bundle-analyzer": "^15.1.4",
"@tailwindcss/typography": "^0.5.16",
"@types/node": "^22.10.5",
"@types/react": "^19.0.3",
"@types/react-dom": "^19.0.2",
nirnejak marked this conversation as resolved.
Show resolved Hide resolved
"@types/tailwindcss": "^3.1.0",
"autoprefixer": "^10.4.20",
"eslint": "^8.57.1",
"eslint-config-next": "14.2.5",
"eslint-config-next": "^15.1.4",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-tailwindcss": "^3.17.5",
"postcss": "^8",
"prettier": "^3.4.2",
"prettier-plugin-tailwindcss": "^0.6.9",
"shiki": "^1.24.4",
"shiki": "^1.26.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2"
}
Expand Down
31 changes: 19 additions & 12 deletions src/app/blog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,34 @@ export default async function BlogPage() {
const posts = await getAllPosts()

return (
<div className="mx-auto max-w-4xl px-4 py-36">
<div className="mx-auto max-w-5xl px-4 py-36">
<h1 className="mb-8 text-3xl font-bold tracking-tighter text-neutral-200 md:mb-20 md:text-5xl">
Blog Posts
</h1>
<div className="-mx-3 flex flex-col">
<div className="-mx-3 flex flex-col gap-3">
{posts.map((post) => (
<>
<Link
href={`/blog/${post.slug}`}
key={post.slug}
className="rounded-lg p-4 transition-colors hover:bg-neutral-900 focus:bg-neutral-900"
className="flex items-start gap-6 rounded-lg p-4 transition-colors hover:bg-neutral-900 focus:bg-neutral-900"
>
<p className="mb-1 text-xl font-semibold tracking-tight text-neutral-300 md:text-2xl">
{post.title}
</p>
<p className="mb-2.5 text-sm text-neutral-500 md:text-base">
{post.summary}
</p>
<p className="text-xs text-neutral-500 md:text-sm">
{formatDate(new Date(post.publishedAt))} • {post.views} views
</p>
<div className="w-3/12 flex-1">
<p className="mb-1 mt-1.5 text-xs text-neutral-500 md:text-sm">
{formatDate(new Date(post.publishedAt))}
</p>
<p className="text-xs text-neutral-500 md:text-sm">
{post.views} views
</p>
</div>
<div className="w-9/12">
<p className="mb-1 text-xl font-semibold tracking-tight text-neutral-300 md:text-2xl">
{post.title}
</p>
<p className="mb-2.5 text-sm text-neutral-500 md:text-base">
{post.summary}
</p>
</div>
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

Enhance accessibility of the new two-column layout

The new two-column layout improves visual organization but needs accessibility considerations:

  1. Empty fragment (<>) with Link as child creates unnecessary nesting
  2. Missing aria-label for the blog post list

Apply these changes:

-      <div className="-mx-3 flex flex-col gap-3">
+      <div className="-mx-3 flex flex-col gap-3" role="list" aria-label="Blog posts">
         {posts.map((post) => (
-          <>
             <Link
               href={`/blog/${post.slug}`}
               key={post.slug}
               className="flex items-start gap-6 rounded-lg p-4 transition-colors hover:bg-neutral-900 focus:bg-neutral-900"
+              role="listitem"
             >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div className="-mx-3 flex flex-col gap-3">
{posts.map((post) => (
<>
<Link
href={`/blog/${post.slug}`}
key={post.slug}
className="rounded-lg p-4 transition-colors hover:bg-neutral-900 focus:bg-neutral-900"
className="flex items-start gap-6 rounded-lg p-4 transition-colors hover:bg-neutral-900 focus:bg-neutral-900"
>
<p className="mb-1 text-xl font-semibold tracking-tight text-neutral-300 md:text-2xl">
{post.title}
</p>
<p className="mb-2.5 text-sm text-neutral-500 md:text-base">
{post.summary}
</p>
<p className="text-xs text-neutral-500 md:text-sm">
{formatDate(new Date(post.publishedAt))} {post.views} views
</p>
<div className="w-3/12 flex-1">
<p className="mb-1 mt-1.5 text-xs text-neutral-500 md:text-sm">
{formatDate(new Date(post.publishedAt))}
</p>
<p className="text-xs text-neutral-500 md:text-sm">
{post.views} views
</p>
</div>
<div className="w-9/12">
<p className="mb-1 text-xl font-semibold tracking-tight text-neutral-300 md:text-2xl">
{post.title}
</p>
<p className="mb-2.5 text-sm text-neutral-500 md:text-base">
{post.summary}
</p>
</div>
<div className="-mx-3 flex flex-col gap-3" role="list" aria-label="Blog posts">
{posts.map((post) => (
<Link
href={`/blog/${post.slug}`}
key={post.slug}
className="flex items-start gap-6 rounded-lg p-4 transition-colors hover:bg-neutral-900 focus:bg-neutral-900"
role="listitem"
>
<div className="w-3/12 flex-1">
<p className="mb-1 mt-1.5 text-xs text-neutral-500 md:text-sm">
{formatDate(new Date(post.publishedAt))}
</p>
<p className="text-xs text-neutral-500 md:text-sm">
{post.views} views
</p>
</div>
<div className="w-9/12">
<p className="mb-1 text-xl font-semibold tracking-tight text-neutral-300 md:text-2xl">
{post.title}
</p>
<p className="mb-2.5 text-sm text-neutral-500 md:text-base">
{post.summary}
</p>
</div>

</Link>
</>
))}
Expand Down
5 changes: 1 addition & 4 deletions src/app/contribute/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import React from "react"
import dynamic from "next/dynamic"
import { Metadata } from "next"

const ContributePage = dynamic(() => import("@/components/ContributePage"), {
ssr: false,
})
import ContributePage from "@/components/ContributePage"

export const metadata: Metadata = {
title: "Contribute to Dev Tools Academy",
Expand Down
12 changes: 4 additions & 8 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import React from "react"
import dynamic from "next/dynamic"
import FeaturedPosts from "@/components/FeaturedPosts"
import Hero from "@/components/Hero"

const Testimonial = dynamic(
() => import("@/components/Testimonial").then((mod) => mod.Testimonial),
{ ssr: false }
)
const Footer = dynamic(() => import("@/components/Footer"), { ssr: true })
import Hero from "@/components/Hero"
import FeaturedPosts from "@/components/FeaturedPosts"
import Testimonial from "@/components/Testimonial"
import Footer from "@/components/Footer"

const featuredPosts = [
{
Expand Down
26 changes: 26 additions & 0 deletions src/assets/coderabbit.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/stream.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 34 additions & 10 deletions src/components/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@

import React from "react"
import Link from "next/link"

import { Button } from "@/components/ui/button"

import StreamLogo from "@/assets/stream.png"
import CodeRabbitLogo from "@/assets/coderabbit.svg"
import Image from "next/image"

const productHuntBadgeHtml = `<a href="https://www.producthunt.com/posts/dev-tools-academy?embed=true&utm_source=badge-featured&utm_medium=badge&utm_souce=badge-dev&#0045;tools&#0045;academy" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=493913&theme=light" alt="Dev&#0032;Tools&#0032;Academy - A&#0032;special&#0032;blog&#0032;made&#0032;for&#0032;Developers&#0046; | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>`

const Hero: React.FC = () => {
Expand All @@ -25,12 +30,12 @@ const Hero: React.FC = () => {
))}
</div>
<div className="relative z-10 mx-auto flex max-w-5xl flex-col items-center justify-center px-4 text-center text-white">
<div className="mb-6 flex flex-col items-center justify-center gap-2 md:flex-row">
<div className="mb-5 flex items-center justify-center gap-2 md:gap-0">
<a
href="https://news.ycombinator.com/item?id=41223327#41246861"
target="_blank"
rel="noopener noreferrer"
className="flex h-[40px] items-center gap-1.5 rounded-lg bg-[#ff7600] px-3 text-sm font-bold text-white shadow-md transition-colors duration-300 hover:bg-[#ff9933] hover:shadow-lg md:h-12"
className="flex h-[40px] items-center gap-1.5 rounded-lg bg-[#ff7600] px-3 text-xs font-bold text-white transition-colors duration-300"
>
<svg
xmlns="http://www.w3.org/2000/svg"
Expand All @@ -43,26 +48,45 @@ const Hero: React.FC = () => {
<span>Featured on Hacker News</span>
</a>
<div
className="scale-75 md:scale-90"
className="sm:scale-75"
dangerouslySetInnerHTML={{ __html: productHuntBadgeHtml }}
/>
Comment on lines +51 to 53
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Security: Replace dangerouslySetInnerHTML with Next.js Image component.

Using dangerouslySetInnerHTML poses potential XSS risks, even with trusted content. Consider refactoring to use the Next.js Image component for better security and optimization.

Here's a safer implementation:

-<div
-  className="sm:scale-75"
-  dangerouslySetInnerHTML={{ __html: productHuntBadgeHtml }}
-/>
+<Link
+  href="https://www.producthunt.com/posts/dev-tools-academy"
+  target="_blank"
+  rel="noopener noreferrer"
+  className="sm:scale-75"
+>
+  <Image
+    src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=493913&theme=light"
+    alt="Dev Tools Academy - A special blog made for Developers | Product Hunt"
+    width={250}
+    height={54}
+    priority
+  />
+</Link>

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Biome (1.9.4)

[error] 52-52: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

</div>
<h1
className="mb-8 bg-gradient-to-r from-purple-400 to-pink-600 bg-clip-text text-5xl font-extrabold leading-tight text-transparent md:text-8xl"
style={{ textShadow: "0 0 20px rgba(168, 85, 247, 0.5)" }}
>
<h1 className="mb-3 bg-gradient-to-r from-purple-400 to-pink-600 bg-clip-text text-5xl font-extrabold tracking-tight text-transparent md:mb-8 md:text-8xl md:leading-[1.1]">
A special blog made for Developers.
</h1>
<p className="mb-12 max-w-3xl text-xl text-neutral-300 md:text-3xl">
Honest reviews to help you choose the right developer tool for your
<p className="mb-8 max-w-3xl text-base text-neutral-300 md:mb-12 md:text-xl">
Honest reviews to help you choose the right developer tools for your
SaaS.
</p>
<Link href="/blog" passHref>
<Button className="rounded-full bg-gradient-to-r from-purple-500 to-pink-500 px-10 py-6 text-xl font-bold text-white transition-all duration-300 hover:scale-105 hover:from-purple-600 hover:to-pink-600 hover:shadow-lg">
<Button className="rounded-full bg-gradient-to-r from-purple-500 to-pink-500 px-6 py-3 text-sm font-bold text-neutral-100 transition-all duration-300 hover:scale-105 hover:from-purple-600 hover:to-pink-600 hover:shadow-lg md:px-10 md:py-6 md:text-xl">
Start Reading
</Button>
</Link>
</div>

<div className="absolute bottom-8 left-1/2 -translate-x-1/2">
<p className="mb-4 text-center text-sm font-medium text-neutral-100 md:mb-6 md:text-base">
Current Sponsors:
</p>
<div className="flex items-center justify-center gap-4">
<a href={"https://www.coderabbit.ai?rel=devtoolsacademy.com"}>
<Image
src={CodeRabbitLogo}
alt="CodeRabbit"
className="h-5 md:h-7"
/>
</a>
<a href={"https://getstream.io?rel=devtoolsacademy.com"}>
<Image
src={StreamLogo}
alt="Stream"
className="h-6 w-auto md:h-8"
/>
</a>
Comment on lines +74 to +87
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

Add missing Image props and secure external links.

While the sponsors section is well-implemented, there are a few improvements needed:

  1. Add width prop to Image components for proper optimization
  2. Add security attributes to external links
-<a href={"https://www.coderabbit.ai?rel=devtoolsacademy.com"}>
+<a 
+  href="https://www.coderabbit.ai?rel=devtoolsacademy.com"
+  target="_blank"
+  rel="noopener noreferrer"
+>
   <Image
     src={CodeRabbitLogo}
     alt="CodeRabbit"
     className="h-5 md:h-7"
+    width={120}
+    height={20}
   />
 </a>
-<a href={"https://getstream.io?rel=devtoolsacademy.com"}>
+<a 
+  href="https://getstream.io?rel=devtoolsacademy.com"
+  target="_blank"
+  rel="noopener noreferrer"
+>
   <Image
     src={StreamLogo}
     alt="Stream"
     className="h-6 w-auto md:h-8"
+    width={140}
+    height={24}
   />
 </a>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<a href={"https://www.coderabbit.ai?rel=devtoolsacademy.com"}>
<Image
src={CodeRabbitLogo}
alt="CodeRabbit"
className="h-5 md:h-7"
/>
</a>
<a href={"https://getstream.io?rel=devtoolsacademy.com"}>
<Image
src={StreamLogo}
alt="Stream"
className="h-6 w-auto md:h-8"
/>
</a>
<a
href="https://www.coderabbit.ai?rel=devtoolsacademy.com"
target="_blank"
rel="noopener noreferrer"
>
<Image
src={CodeRabbitLogo}
alt="CodeRabbit"
className="h-5 md:h-7"
width={120}
height={20}
/>
</a>
<a
href="https://getstream.io?rel=devtoolsacademy.com"
target="_blank"
rel="noopener noreferrer"
>
<Image
src={StreamLogo}
alt="Stream"
className="h-6 w-auto md:h-8"
width={140}
height={24}
/>
</a>

</div>
</div>
</section>
)
}
Expand Down
Loading
Loading