diff --git a/app/ai/page.tsx b/app/ai/page.tsx deleted file mode 100644 index 2b16838..0000000 --- a/app/ai/page.tsx +++ /dev/null @@ -1,58 +0,0 @@ -// ai/page.tsx - -'use client'; - -import { useState } from 'react'; - -export default function Page() { - const [prompt, setPrompt] = useState('A cute cartoon fox with a top-hat'); - const [imageUrl, setImageUrl] = useState(null); - - const generateImage = async (e: React.FormEvent) => { - e.preventDefault(); - - // Making a POST request to Modal's instant Stable Diffusion endpoint - try { - const response = await fetch('/api', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - prompt, - }), - }); - - if (response.status === 200) { - const imageBuffer = await response.arrayBuffer(); - const blob = new Blob([imageBuffer], { type: 'image/png' }); - const imageUrl = URL.createObjectURL(blob); - setImageUrl(imageUrl); - } else { - const message = await response.text(); - setImageUrl(null); - console.error(`Error: ${message}`); - } - } catch (error) { - console.error('Failed to fetch image:', error); - } - }; - - return ( -
-
- setPrompt(e.target.value)} - className='input w-full' - /> - -
- {imageUrl && Generated} -
- ); -} diff --git a/app/blog/[slug]/page.tsx b/app/blog/[slug]/page.tsx index ec182d2..cac21f9 100644 --- a/app/blog/[slug]/page.tsx +++ b/app/blog/[slug]/page.tsx @@ -28,14 +28,12 @@ export async function generateMetadata({ params }: { params: any }): Promise -

{blog.metadata.title}

+

{blog.metadata.title}

{blog.metadata.summary}

@@ -129,6 +127,18 @@ export default function Blog({ params }: { params: any }) {

+
+ {blog.metadata.tags?.map((tag) => ( + + + + ))} +
{ publishedAt='Dec 4, 2020' views={2506} readingTime={'📖 8 min read'} - tags='machine learning, deep learning' + tags={['machine learning', 'deep learning']} external /> { publishedAt='Oct 24, 2020' views={3453} readingTime={'📖 3 min read'} - tags='github, github action, jupyter notebook' + tags={['github', 'github action', 'jupyter notebook']} external /> {/* -

Oh no! This page does not exist.

+
+

Oh no! This page does not exist.

The page you are looking for might have been removed, had its name changed, or is temporarily unavailable.

Please check the URL and try again.

- If you think this is an error, please contact me at + If you think this is an error, please contact me at{' '} - {' '} me@patelvivek.dev + {' '} + Or open issues at{' '} + + Github

diff --git a/app/og/route.tsx b/app/og/route.tsx index 02d3f5d..b0f3bc2 100644 --- a/app/og/route.tsx +++ b/app/og/route.tsx @@ -1,7 +1,7 @@ import { ImageResponse } from 'next/og'; import { NextRequest } from 'next/server'; -export const runtime = 'edge'; +// export const runtime = 'edge'; export async function GET(req: NextRequest) { const { searchParams } = req.nextUrl; diff --git a/app/page.tsx b/app/page.tsx index 53f5d05..9d33cd1 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -5,8 +5,10 @@ import { Button } from '@/components/ui/button'; import Image from 'next/image'; import RecentBlogs from '@/components/RecentBlogs'; +import { getLatestProjects } from '@/lib/get-projects'; export default function Home() { + const projects = getLatestProjects(); return (

About

@@ -23,34 +25,15 @@ export default function Home() {
*/}

Latest Project

- - - + {projects.map((project) => ( + + ))}
+ + ))} +
{ - const projects = [ - { - slug: 'market-hub', - title: 'Market Hub: A multi-vendor marketplace', - description: - "Market-hub is a MERN-powered platform for buying and selling computer items. Vendors can easily manage their products, while users enjoy a smooth shopping experience. It's a user-friendly solution for tech enthusiasts and sellers alike.", - link: 'projects/market-hub', - tags: ['MERN', 'React', 'Nodejs', 'Express', 'MongoDB', 'FullStack'], - }, - { - slug: 'acme-auth', - title: 'Acme Auth: A Next.js Based Authentication', - description: - 'Acme Auth is a learning project focused on integrating third-party authentication APIs. It covers registration, login, logout, password recovery, and email verification. With a responsive design and efficient routing, it showcases modern web development practices using Next.js server actions and Tailwind CSS.', - link: 'projects/acme-auth', - tags: [ - 'Nextjs', - 'React', - 'AppRouter', - 'ShadcnUI', - 'TailwindCSS', - 'Authentication', - 'FreeAPI', - 'RESTAPI', - 'ServerActions', - 'TypeScript', - ], - }, - { - slug: 'true-feedback', - title: 'True Feedback: Where your identity remains a secret', - description: 'Explore a Next.js 14 project that dive into the World of Anonymous Feedback.', - link: 'projects/true-feedback', - tags: ['NextJs', 'Server Actions', 'Supabase', 'Next-Auth'], - }, - { - slug: 'nextjs-blog', - title: 'Next.js 14 Blog with App Router and MDX', - description: - 'Explore a Next.js 14 project demonstrating the new App Router, server actions, and MDX integration for streamlined blog creation.', - image: { - src: 'https://firebasestorage.googleapis.com/v0/b/patelvivekdev.appspot.com/o/images%2Fdefault.png?alt=media&token=d917a346-35fd-4e33-ac34-3c725b6f2769', - alt: 'Next.js 14 Blog logo', - }, - link: 'projects/nextjs-blog', - tags: ['NextJs', 'React', 'MDX', 'App Router', 'Server Components', 'Server Actions', 'Blog'], - }, - ]; + const projects = getProjects(); return (
@@ -79,10 +33,10 @@ const ProjectPage = () => { {projects.map((project) => ( ))}
diff --git a/app/snippet/[slug]/page.tsx b/app/snippet/[slug]/page.tsx index d174d48..35b43f9 100644 --- a/app/snippet/[slug]/page.tsx +++ b/app/snippet/[slug]/page.tsx @@ -23,14 +23,12 @@ export async function generateMetadata({ params }: { params: any }): Promise -
+
+ + ))} +
{ return ( @@ -65,13 +65,11 @@ async function InternalBlogPost({ summary: string; slug: string; readingTime: string; - publishedAt?: string; - tags?: string; + publishedAt: string; + tags: string[]; views?: number | boolean; }) { - // here tags is string, so we need to convert it to array - let newTags = tags?.split(','); - + tags.sort(); return (
@@ -105,7 +103,7 @@ async function InternalBlogPost({

{summary}

- {newTags?.map((tag) => ( + {tags?.map((tag) => (
@@ -174,11 +173,12 @@ function ExternalBlogPost({ )}
+ m

{summary}

- {tags?.split(',').map((tag) => ( + {tags?.map((tag) => (

- + {title}

diff --git a/components/SnippetCard.tsx b/components/SnippetCard.tsx index cfef7df..59c6a56 100644 --- a/components/SnippetCard.tsx +++ b/components/SnippetCard.tsx @@ -17,12 +17,9 @@ const SnippetCard = ({ slug: string; readingTime: string; publishedAt?: string; - tags?: string; + tags: string[]; views?: number | boolean; }) => { - // here tags is string, so we need to convert it to array - let newTags = tags?.split(','); - return (
@@ -54,7 +51,7 @@ const SnippetCard = ({

{description}

- {newTags?.map((tag) => ( + {tags?.map((tag) => ( {pathname === navItem.link && ( - + {navItem.name} )} diff --git a/components/MobileNav.tsx b/components/navbar/MobileNav.tsx similarity index 100% rename from components/MobileNav.tsx rename to components/navbar/MobileNav.tsx diff --git a/components/Navbar.tsx b/components/navbar/Navbar.tsx similarity index 76% rename from components/Navbar.tsx rename to components/navbar/Navbar.tsx index ed3e25e..6bd5213 100644 --- a/components/Navbar.tsx +++ b/components/navbar/Navbar.tsx @@ -1,5 +1,5 @@ -import { FloatingNav } from '@/components/ui/FloatingNav'; -import MobileNav from './MobileNav'; +import { FloatingNav } from '@/components/navbar/FloatingNav'; +import MobileNav from '@/components/navbar/MobileNav'; const links = [ { link: '/', name: 'Home' }, diff --git a/components/pre.tsx b/components/pre.tsx deleted file mode 100644 index d03c95f..0000000 --- a/components/pre.tsx +++ /dev/null @@ -1,35 +0,0 @@ -'use client'; -import { useState, useRef } from 'react'; -import { Clipboard } from 'lucide-react'; -import { toast } from 'react-hot-toast'; - -const Pre = (props: any) => { - const textInput = useRef(null); - const [copied, setCopied] = useState(false); - - const onExit = () => { - setCopied(false); - }; - const onCopy = () => { - setCopied(true); - navigator.clipboard.writeText(textInput?.current?.textContent); - toast.success('Copied to clipboard!', { - position: 'bottom-center', - duration: 2500, - }); - setTimeout(() => { - setCopied(false); - }, 2500); - }; - - return ( -
-      {props.children}
-      
-    
- ); -}; - -export default Pre; diff --git a/content/blogs/MDX-and-Next.js.mdx b/content/blogs/MDX-and-Next.js.mdx index 308e2ef..527fc54 100644 --- a/content/blogs/MDX-and-Next.js.mdx +++ b/content/blogs/MDX-and-Next.js.mdx @@ -3,7 +3,7 @@ title: 'MDX and Next.js: A Powerful Combination' summary: 'Unleash the power of MDX and Next.js to create interactive web content. This article explores their basics and how they work together.' slug: 'MDX-and-Next.js' publishedAt: 'April 5, 2024' -tags: 'MDX, Next, React, JSX, Markdown, Blog' +tags: [MDX, NextJs, React, JSX, Markdown, Blog] published: true --- diff --git a/content/blogs/hello-world.mdx b/content/blogs/hello-world.mdx index 13f915f..44e1ad5 100644 --- a/content/blogs/hello-world.mdx +++ b/content/blogs/hello-world.mdx @@ -2,7 +2,7 @@ title: 'Hello, World!' publishedAt: 'April 1, 2024' summary: 'My first blog post on my new blog!' -tags: 'hello, world, first, blog' +tags: [hello, world, first, blog] published: true --- diff --git a/content/blogs/learn-github-markdown.mdx b/content/blogs/learn-github-markdown.mdx index 062ec78..3dc085b 100644 --- a/content/blogs/learn-github-markdown.mdx +++ b/content/blogs/learn-github-markdown.mdx @@ -1,7 +1,7 @@ --- title: Custom Component In MDX and Nextjs summary: A guide to create reusable components -tags: 'markdown, github, MDX, Nextjs' +tags: [markdown, github, MDX, NextJs] publishedAt: April 6, 2024 published: true --- diff --git a/content/blogs/server-actions.mdx b/content/blogs/server-actions.mdx index 4c8e5b9..9f757fe 100644 --- a/content/blogs/server-actions.mdx +++ b/content/blogs/server-actions.mdx @@ -3,7 +3,7 @@ title: 'A Deep Dive To Next.js 14 Server Actions' summary: 'Harness the power of Next.js 14 Server Actions for streamlined data fetching and mutations in your Nextjs applications.' slug: 'server-actions' publishedAt: 'April 13, 2024' -tags: 'NextJs, React, Server Actions, Data Fetching, Mutations, Server Components, JavaScript, TypeScript' +tags: [NextJs, React, Server Actions, Data Fetching, Mutations, Server Components, JavaScript, TypeScript] published: true --- diff --git a/content/projects/acme-auth.mdx b/content/projects/acme-auth.mdx index f1b5793..28a2517 100644 --- a/content/projects/acme-auth.mdx +++ b/content/projects/acme-auth.mdx @@ -3,7 +3,7 @@ title: 'Acme Auth: A Next.js Based Authentication' description: 'Discover how Acme Auth, a robust full-stack authentication system crafted with React, Next.js, Express, and MongoDB, empowers seamless user authentication, signup, login, logout, and password reset functionalities.' slug: 'acme-auth' publishedAt: 'April 03, 2024' -tags: 'NextJs, React, Express, MongoDB, JWT, TypeScript, Zod, ShadcnUI, AcertinityUI' +tags: [NextJs, React, Express, MongoDB, JWT, TypeScript, Zod, ShadcnUI, AcertinityUI] --- ## Acme Auth diff --git a/content/projects/market-hub.mdx b/content/projects/market-hub.mdx index 433d8d6..a6beffc 100644 --- a/content/projects/market-hub.mdx +++ b/content/projects/market-hub.mdx @@ -1,8 +1,9 @@ --- title: 'Market Hub: A multi-vendor marketplace' description: 'Market-hub is a MERN-powered platform for buying and selling computer items. It is a user-friendly solution for tech enthusiasts and sellers alike.' -sulg: 'market-hub' publishedAt: 'April 01, 2024' +slug: 'market-hub' +tags: [MERN, React, Redux, Nodejs, Express, MongoDB, FullStack] --- ## Market hub diff --git a/content/projects/nextjs-blog.mdx b/content/projects/nextjs-blog.mdx index fb3566e..d0f137c 100644 --- a/content/projects/nextjs-blog.mdx +++ b/content/projects/nextjs-blog.mdx @@ -3,7 +3,7 @@ title: 'Next.js 14 Blog with App Router and MDX' description: 'Explore a Next.js 14 project demonstrating the new App Router, server actions, and MDX integration for streamlined blog creation.' slug: 'nextjs-blog' publishedAt: 'April 12, 2024' -tags: 'NextJs, React, MDX, App Router, Server Components, Server Actions, Blog' +tags: [NextJs, React, MDX, App Router, Server Components, Server Actions, Blog] published: true --- diff --git a/content/projects/true-feedback.mdx b/content/projects/true-feedback.mdx index 21a521e..06c8d9a 100644 --- a/content/projects/true-feedback.mdx +++ b/content/projects/true-feedback.mdx @@ -3,10 +3,14 @@ title: 'True Feedback - Where your identity remains a secret' description: 'Explore a Next.js 14 project that dive into the World of Anonymous Feedback.' slug: 'true-feedback' publishedAt: 'May 04, 2024' -tags: 'NextJs, Server Actions, Supabase, Next-Auth' +tags: [NextJs, Server Actions, Supabase, Next-Auth] published: true --- +## True Feedback + + + ## Overview True Feedback is a Next.js 14 project that delves into the realm of anonymous feedback. It provides a platform where users can express their thoughts and opinions without revealing their identity. This project showcases the capabilities of Next.js 14, including server actions, Supabase integration, and Next-Auth for user authentication. diff --git a/content/snippets/copy-to-clipboard.mdx b/content/snippets/copy-to-clipboard.mdx index ce5827f..95d21f6 100644 --- a/content/snippets/copy-to-clipboard.mdx +++ b/content/snippets/copy-to-clipboard.mdx @@ -2,8 +2,8 @@ title: 'How to add copy to clipboard button.' publishedAt: 'April 25, 2024' slug: 'copy-to-clipboard' -summary: 'Adding copy button in mdx in next js app router' -tags: mdx, copy, react +description: 'Adding copy button in mdx in next js app router' +tags: [mdx, copy, react] published: false --- diff --git a/content/snippets/dark-mode.mdx b/content/snippets/dark-mode.mdx new file mode 100644 index 0000000..9eefb9b --- /dev/null +++ b/content/snippets/dark-mode.mdx @@ -0,0 +1,145 @@ +--- +title: Adding Dark Mode to a Next.js App with TailwindCSS +description: Discover how to effortlessly implement a dark mode feature in your Next.js application using TailwindCSS. +slug: 'dark-mode' +publishedAt: May 05, 2024 +tags: [dark, next-themes, Nextjs, Tailwindcss] +published: true +--- + +## Dark Mode - Introduction + +In today's digital world, users often spend extended hours interacting with screens. Dark mode has emerged as a popular solution, offering a more comfortable viewing experience in low-light environments. Beyond user comfort, dark mode has demonstrably positive impacts on battery life and can even contribute to better sleep patterns. This blog will guide you through implementing a user-friendly dark mode feature within your Next.js web application, equipping you with the tools to enhance user experience and cater to modern preferences. + +## Why It Matters + +- **Reduced Eye Strain:** Dark mode minimizes bright light emission, alleviating eye fatigue, headaches, and dry eyes. +- **Improved Accessibility:** Dark mode enhances readability and contrast for users with visual impairments or light sensitivity. +- **Energy Efficiency:** Dark mode extends battery life and reduces energy consumption, especially on devices with OLED displays. +- **Enhanced Visual Appeal:** Dark mode offers a sleek and immersive aesthetic, making applications more visually appealing. +- **Reduced Screen Glare:** Dark mode minimizes screen glare in brightly lit environments, improving usability and reducing distractions. + +## Installation + +### Install the next-themes package: + +```bash +npm install next-themes +``` + +## Setup and Usage + +### 2. Wrap layout.tsx with ThemeProvider component + +```tsx +// layout.tsx +import { ThemeProvider } from 'next-themes'; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + +
{children}
+
+ + + ); +} +``` + +### 3. Add darkMode to tailwind.config.js + +```tsx +// tailwind.config.js +import type { Config } from 'tailwindcss'; + +const config: Config = { + darkMode: 'class', +}; +export default config; +``` + +### 4. Create a switch to toggle themes + +```tsx +// ThemeToggle.tsx + +'use client'; +import React, { useEffect, useState } from 'react'; +import { useTheme } from 'next-themes'; +// import svg icons + +export function ThemeToggle() { + const { resolvedTheme, setTheme } = useTheme(); + const [loaded, setLoaded] = useState(false); + useEffect(() => { + setLoaded(true); + }, [setLoaded]); + + return ( + + ); +} +``` + +### 5. Add ThemeToggle component to layout.tsx + +```tsx +// layout.tsx + + +``` + +## Explanation + +[next-themes](https://github.com/pacocoursey/next-themes) package provides a simple API for managing dark mode in Next.js applications. + +Option for ThemeProvider: + +- defaultTheme = 'system' (based on prefers-color-scheme) +- attribute = 'class' (This will add the dark mode class to the html element) +- enableSystem = true (Whether to switch between dark and light based on prefers-color-scheme) + +Read more on all the available options of [themeprovider](https://github.com/pacocoursey/next-themes?tab=readme-ov-file#themeprovider) + + + You can add More than light and dark mode. Read more about it on + [Gihub](https://github.com/pacocoursey/next-themes?tab=readme-ov-file#more-than-light-and-dark-mode) + + +## Conclusion + +In this blog post, we have explored the implementation of a user-friendly dark mode feature in a Next.js application using TailwindCSS, leveraging the capabilities of the next-themes package. By following the provided code snippets and explanations, you can seamlessly toggle between light and dark themes, enhancing user experience and catering to modern preferences. Experiment with dark mode and explore its potential benefits for your users. + +💕 Happy reading! + +## Links + +- [Live link](https://next-ppr-dark-mode.vercel.app/) +- [Next-Themes](https://github.com/pacocoursey/next-themes) +- [TailwindCSS](https://tailwindcss.com/docs/dark-mode) +- [My Github Repo](https://github.com/patelvivekdev/next-ppr-dark-mode) +- [Examples](https://github.com/pacocoursey/next-themes/tree/main/examples) diff --git a/content/snippets/toast.mdx b/content/snippets/toast.mdx index 2a6ed43..474082f 100644 --- a/content/snippets/toast.mdx +++ b/content/snippets/toast.mdx @@ -4,7 +4,7 @@ description: How to add toast in React/Next JS slug: toast published: true publishedAt: April 29, 2024 -tags: 'Next, React, JSX, Markdown, Blog, Toast, React-Hot-Toast' +tags: [Next, React, JSX, Markdown, Blog, Toast, React-Hot-Toast] --- ## Install diff --git a/lib/get-blogs.ts b/lib/get-blogs.ts index 22d8afd..f79990e 100644 --- a/lib/get-blogs.ts +++ b/lib/get-blogs.ts @@ -12,9 +12,9 @@ type Metadata = { title: string; publishedAt: string; summary: string; - image?: string; - tags: string; + tags: string[]; published: boolean; + image?: string; }; function getBlogFiles(dir: string) { diff --git a/lib/get-projects.ts b/lib/get-projects.ts index f549f72..99c978a 100644 --- a/lib/get-projects.ts +++ b/lib/get-projects.ts @@ -10,8 +10,9 @@ type Metadata = { title: string; publishedAt: string; description: string; + tags: string[]; + published: boolean; image?: string; - tags: string; }; function getProjectFiles(dir: string) { @@ -44,3 +45,14 @@ export function getProject(slug: string) { const project = projects.find((post) => post.slug === slug); return project; } + +export function getLatestProjects() { + const projects = getProjects(); + // Sort projects by publishedAt in descending order + const sortedProjects = projects.sort((a, b) => { + const dateA = new Date(a.metadata.publishedAt!); + const dateB = new Date(b.metadata.publishedAt!); + return dateB.getTime() - dateA.getTime(); + }); + return sortedProjects.slice(0, 4); +} diff --git a/lib/get-snippets.ts b/lib/get-snippets.ts index a286f3b..8a0167c 100644 --- a/lib/get-snippets.ts +++ b/lib/get-snippets.ts @@ -10,9 +10,9 @@ type Metadata = { title: string; publishedAt: string; description: string; - image?: string; - tags: string; + tags: string[]; published: boolean; + image?: string; }; function getMdxFiles(dir: string) { diff --git a/public/projects/true-feedback.png b/public/projects/true-feedback.png new file mode 100644 index 0000000..d434d98 Binary files /dev/null and b/public/projects/true-feedback.png differ