├── .env.example ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .vscode ├── extensions.json └── settings.json ├── README.md ├── components.json ├── gatsby-browser.js ├── gatsby-config.ts ├── gatsby-node.ts ├── graphql.config.js ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── src ├── assets │ └── icons │ │ ├── action.tsx │ │ ├── general.tsx │ │ ├── index.ts │ │ ├── nav.tsx │ │ └── social.tsx ├── components │ ├── common │ │ ├── body.tsx │ │ ├── comment-box.tsx │ │ ├── cta.tsx │ │ ├── dev-tools │ │ │ └── breakpoint-viewer.tsx │ │ ├── donation-box.tsx │ │ ├── footer.tsx │ │ ├── layout.tsx │ │ ├── nav.tsx │ │ ├── seo.tsx │ │ ├── social-items.tsx │ │ └── subscribe.tsx │ ├── modules │ │ ├── about │ │ │ ├── intro.tsx │ │ │ └── timeline.tsx │ │ ├── blog │ │ │ ├── post │ │ │ │ ├── footer.tsx │ │ │ │ ├── header.tsx │ │ │ │ ├── post-item.tsx │ │ │ │ └── sidebar.tsx │ │ │ ├── posts-list.tsx │ │ │ ├── series-list.tsx │ │ │ └── series │ │ │ │ ├── body.tsx │ │ │ │ ├── header.tsx │ │ │ │ └── index.tsx │ │ ├── contact │ │ │ └── index.tsx │ │ ├── home │ │ │ ├── hero.tsx │ │ │ ├── latest-blog-posts.tsx │ │ │ ├── latest-snippets.tsx │ │ │ ├── past-clients.tsx │ │ │ ├── recent-projects.tsx │ │ │ └── why-hire-me.tsx │ │ ├── projects │ │ │ ├── project │ │ │ │ ├── body.tsx │ │ │ │ ├── header.tsx │ │ │ │ └── project-item.tsx │ │ │ └── projects-list.tsx │ │ └── snippets │ │ │ ├── snippet-item.tsx │ │ │ └── snippets-list.tsx │ └── ui │ │ ├── center.tsx │ │ ├── col.tsx │ │ ├── heading.tsx │ │ ├── reusables │ │ ├── aspect-ratio.tsx │ │ ├── badge.tsx │ │ ├── button.tsx │ │ ├── carousel.tsx │ │ ├── dialog.tsx │ │ ├── dropdown-menu.tsx │ │ ├── form.tsx │ │ ├── input.tsx │ │ ├── label.tsx │ │ ├── sonner.tsx │ │ └── textarea.tsx │ │ ├── row.tsx │ │ └── scroll-to-top.tsx ├── config │ └── site.ts ├── hooks │ ├── use-copy-to-clipboard.tsx │ └── use-site-metadata.tsx ├── images │ ├── ad.png │ ├── avatar.png │ ├── collaborative.png │ ├── communicative.png │ ├── featured.jpeg │ ├── icon.png │ ├── self-motivation.png │ ├── upi-logo.svg │ ├── upi.png │ └── work-ethic.png ├── pages │ ├── 404.tsx │ ├── about.tsx │ ├── blog │ │ ├── index.tsx │ │ └── series.tsx │ ├── contact.tsx │ ├── index.tsx │ ├── projects.tsx │ └── snippets.tsx ├── styles │ └── global.css ├── templates │ ├── post.tsx │ ├── project.tsx │ ├── series.tsx │ └── snippet.tsx └── utils │ ├── cn.ts │ └── shorten-text.ts ├── static ├── og.png ├── resume.pdf └── robots.txt ├── tailwind.config.js └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | CONTENTFUL_SPACE_ID= 2 | CONTENTFUL_ACCESS_TOKEN= 3 | GATSBY_BACKEND_URL= 4 | GA_MEASUREMENT_ID= 5 | CLOUDINARY_CLOUD_NAME= -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Ignore built files 2 | public/ 3 | .cache/ 4 | 5 | # Ignore node_modules 6 | node_modules/ 7 | 8 | # Ignore environment variables 9 | .env 10 | .env.*.local 11 | 12 | # Ignore logs 13 | logs/ 14 | *.log 15 | 16 | # Ignore temporary files 17 | *.tmp 18 | *.swp -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | globals: { 3 | __PATH_PREFIX__: true, 4 | }, 5 | extends: `react-app`, 6 | plugins: ["simple-import-sort"], 7 | rules: { 8 | "simple-import-sort/imports": "warn", 9 | "simple-import-sort/exports": "warn", 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .cache/ 3 | public/ 4 | src/gatsby-types.d.ts 5 | .env.development 6 | .env.production 7 | .DS_Store -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "graphql.vscode-graphql", 4 | "esbenp.prettier-vscode", 5 | "bradlc.vscode-tailwindcss" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": ["CONTENTFUL", "INLINES", "reusables"] 3 | } 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Gatsby 4 | 5 |

6 |

7 | Gatsby Minimal TypeScript Starter 8 |

9 | 10 | ## 🚀 Quick start 11 | 12 | 1. **Create a Gatsby site.** 13 | 14 | Use the Gatsby CLI to create a new site, specifying the minimal TypeScript starter. 15 | 16 | ```shell 17 | # create a new Gatsby site using the minimal TypeScript starter 18 | npm init gatsby -- -ts 19 | ``` 20 | 21 | 2. **Start developing.** 22 | 23 | Navigate into your new site’s directory and start it up. 24 | 25 | ```shell 26 | cd my-gatsby-site/ 27 | npm run develop 28 | ``` 29 | 30 | 3. **Open the code and start customizing!** 31 | 32 | Your site is now running at http://localhost:8000! 33 | 34 | Edit `src/pages/index.tsx` to see your site update in real-time! 35 | 36 | 4. **Learn more** 37 | 38 | - [Documentation](https://www.gatsbyjs.com/docs/?utm_source=starter&utm_medium=readme&utm_campaign=minimal-starter-ts) 39 | - [Tutorials](https://www.gatsbyjs.com/docs/tutorial/?utm_source=starter&utm_medium=readme&utm_campaign=minimal-starter-ts) 40 | - [Guides](https://www.gatsbyjs.com/docs/how-to/?utm_source=starter&utm_medium=readme&utm_campaign=minimal-starter-ts) 41 | - [API Reference](https://www.gatsbyjs.com/docs/api-reference/?utm_source=starter&utm_medium=readme&utm_campaign=minimal-starter-ts) 42 | - [Plugin Library](https://www.gatsbyjs.com/plugins?utm_source=starter&utm_medium=readme&utm_campaign=minimal-starter-ts) 43 | - [Cheat Sheet](https://www.gatsbyjs.com/docs/cheat-sheet/?utm_source=starter&utm_medium=readme&utm_campaign=minimal-starter-ts) 44 | 45 | ## 🚀 Quick start (Netlify) 46 | 47 | Deploy this starter with one click on [Netlify](https://app.netlify.com/signup): 48 | 49 | [Deploy to Netlify](https://app.netlify.com/start/deploy?repository=https://github.com/gatsbyjs/gatsby-starter-minimal-ts) 50 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.js", 8 | "css": "src/styles/global.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/utils/cn", 16 | "ui": "@/components/ui/reusables", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } 22 | -------------------------------------------------------------------------------- /gatsby-browser.js: -------------------------------------------------------------------------------- 1 | import "./src/styles/global.css"; 2 | import "@fontsource/poppins"; 3 | import "@fontsource/poppins/500.css"; 4 | import "@fontsource/poppins/600.css"; 5 | import "@fontsource/poppins/700.css"; 6 | -------------------------------------------------------------------------------- /gatsby-config.ts: -------------------------------------------------------------------------------- 1 | import type { GatsbyConfig } from "gatsby"; 2 | 3 | require("dotenv").config({ 4 | path: `.env.${process.env.NODE_ENV}`, 5 | }); 6 | 7 | const config: GatsbyConfig = { 8 | siteMetadata: { 9 | title: "itsrakesh - Rakesh Potnuru", 10 | description: 11 | "I'm Rakesh - a software engineer, tech enthusiast and product creator with expertise in building innovative tools and products.", 12 | siteUrl: "https://itsrakesh.com", 13 | feedUrl: "https://itsrakesh.com/rss.xml", 14 | twitterUsername: "@rakesh_at_tweet", 15 | image: "/og.png", 16 | author: "Rakesh Potnuru", 17 | }, 18 | // More easily incorporate content into your pages through automatic TypeScript type generation and better GraphQL IntelliSense. 19 | // If you use VSCode you can also use the GraphQL plugin 20 | // Learn more at: https://gatsby.dev/graphql-typegen 21 | graphqlTypegen: true, 22 | plugins: [ 23 | { 24 | resolve: "gatsby-source-contentful", 25 | options: { 26 | spaceId: process.env.CONTENTFUL_SPACE_ID, 27 | accessToken: process.env.CONTENTFUL_ACCESS_TOKEN, 28 | }, 29 | }, 30 | "gatsby-plugin-image", 31 | "gatsby-plugin-sharp", 32 | "gatsby-transformer-sharp", 33 | "gatsby-plugin-postcss", 34 | "gatsby-plugin-sitemap", 35 | { 36 | resolve: "gatsby-plugin-manifest", 37 | options: { 38 | icon: "src/images/icon.png", 39 | }, 40 | }, 41 | { 42 | resolve: "gatsby-source-filesystem", 43 | options: { 44 | name: "images", 45 | path: "./src/images/", 46 | }, 47 | __key: "images", 48 | }, 49 | { 50 | resolve: `gatsby-plugin-google-gtag`, 51 | options: { 52 | trackingIds: [ 53 | process.env.GA_MEASUREMENT_ID, // Google Analytics / GA 54 | ], 55 | gtagConfig: { 56 | // optimize_id: "OPT_CONTAINER_ID", 57 | // anonymize_ip: true, 58 | cookie_expires: 0, 59 | }, 60 | // This object is used for configuration specific to this plugin 61 | pluginConfig: { 62 | // Puts tracking script in the head instead of the body 63 | head: true, 64 | respectDNT: true, 65 | // Avoids sending pageview hits from custom paths 66 | exclude: ["/preview/**", "/do-not-track/me/too/"], 67 | delayOnRouteUpdate: 0, 68 | }, 69 | }, 70 | }, 71 | { 72 | resolve: `gatsby-transformer-cloudinary`, 73 | options: { 74 | transformTypes: [ 75 | { 76 | type: "contentfulBlogPostCoverJsonNode", 77 | cloudName: process.env.CLOUDINARY_CLOUD_NAME, 78 | }, 79 | ], 80 | }, 81 | }, 82 | { 83 | resolve: `gatsby-plugin-feed`, 84 | options: { 85 | query: ` 86 | { 87 | site { 88 | siteMetadata { 89 | title 90 | description 91 | siteUrl 92 | site_url: siteUrl 93 | feed_url: feedUrl 94 | author 95 | } 96 | } 97 | } 98 | `, 99 | feeds: [ 100 | { 101 | serialize: ({ 102 | query: { site, allContentfulBlogPost }, 103 | }: { 104 | query: { 105 | site: { siteMetadata: { siteUrl: string } }; 106 | allContentfulBlogPost: { nodes: Queries.ContentfulBlogPost[] }; 107 | }; 108 | }) => { 109 | return allContentfulBlogPost.nodes.map((node) => { 110 | return { 111 | title: node.title, 112 | description: node.description, 113 | date: node.publishedAt, 114 | url: site.siteMetadata.siteUrl + `/${node.slug}`, 115 | guid: site.siteMetadata.siteUrl + `/${node.slug}`, 116 | categories: node.tags, 117 | }; 118 | }); 119 | }, 120 | query: ` 121 | { 122 | allContentfulBlogPost(sort: {publishedAt: DESC}) { 123 | nodes { 124 | title 125 | slug 126 | publishedAt 127 | description 128 | tags 129 | } 130 | } 131 | } 132 | `, 133 | output: "/rss.xml", 134 | title: "Rakesh's Blog", 135 | match: "^/blog/", 136 | }, 137 | ], 138 | }, 139 | }, 140 | ], 141 | trailingSlash: "never", 142 | }; 143 | 144 | export default config; 145 | -------------------------------------------------------------------------------- /gatsby-node.ts: -------------------------------------------------------------------------------- 1 | import { CreatePagesArgs, CreateWebpackConfigArgs } from "gatsby"; 2 | import * as path from "path"; 3 | 4 | export const onCreateWebpackConfig = ({ actions }: CreateWebpackConfigArgs) => { 5 | actions.setWebpackConfig({ 6 | resolve: { 7 | alias: { 8 | "@/components": path.resolve(__dirname, "src/components"), 9 | "@/common": path.resolve(__dirname, "src/common"), 10 | "@/utils": path.resolve(__dirname, "src/utils"), 11 | "@/config": path.resolve(__dirname, "src/config"), 12 | "@/assets": path.resolve(__dirname, "src/assets"), 13 | "@/hooks": path.resolve(__dirname, "src/hooks"), 14 | }, 15 | }, 16 | }); 17 | }; 18 | 19 | exports.createPages = async ({ 20 | graphql, 21 | actions, 22 | reporter, 23 | }: CreatePagesArgs) => { 24 | const { createPage } = actions; 25 | 26 | const projectResult = await graphql<{ 27 | allContentfulProject: { nodes: { slug: string }[] }; 28 | }>(` 29 | query Projects { 30 | allContentfulProject { 31 | nodes { 32 | slug 33 | } 34 | } 35 | } 36 | `); 37 | 38 | if (projectResult.errors) { 39 | reporter.panicOnBuild( 40 | `There was an error loading your Contentful projects`, 41 | projectResult.errors 42 | ); 43 | return; 44 | } 45 | 46 | const projects = projectResult.data?.allContentfulProject.nodes; 47 | 48 | if (projects?.length) { 49 | projects.forEach((project) => { 50 | createPage({ 51 | path: `/projects/${project.slug}`, 52 | component: path.resolve("./src/templates/project.tsx"), 53 | context: { 54 | slug: project.slug, 55 | }, 56 | }); 57 | }); 58 | } 59 | 60 | const blogResult = await graphql<{ 61 | allContentfulBlogPost: { nodes: { slug: string }[] }; 62 | }>(` 63 | query BlogPosts { 64 | allContentfulBlogPost { 65 | nodes { 66 | slug 67 | } 68 | } 69 | } 70 | `); 71 | 72 | if (blogResult.errors) { 73 | reporter.panicOnBuild( 74 | `There was an error loading your Contentful blog posts`, 75 | blogResult.errors 76 | ); 77 | return; 78 | } 79 | 80 | const blogPosts = blogResult.data?.allContentfulBlogPost.nodes; 81 | 82 | if (blogPosts?.length) { 83 | blogPosts.forEach((post) => { 84 | createPage({ 85 | path: `/blog/${post.slug}`, 86 | component: path.resolve("./src/templates/post.tsx"), 87 | context: { 88 | slug: post.slug, 89 | }, 90 | }); 91 | }); 92 | } 93 | 94 | const seriesResult = await graphql<{ 95 | allContentfulBlogSeries: { nodes: { slug: string }[] }; 96 | }>(` 97 | query BlogSeries { 98 | allContentfulBlogSeries { 99 | nodes { 100 | slug 101 | } 102 | } 103 | } 104 | `); 105 | 106 | if (seriesResult.errors) { 107 | reporter.panicOnBuild( 108 | `There was an error loading your Contentful blog series`, 109 | seriesResult.errors 110 | ); 111 | return; 112 | } 113 | 114 | const series = seriesResult.data?.allContentfulBlogSeries.nodes; 115 | 116 | if (series?.length) { 117 | series.forEach((series) => { 118 | createPage({ 119 | path: `/blog/series/${series.slug}`, 120 | component: path.resolve("./src/templates/series.tsx"), 121 | context: { 122 | slug: series.slug, 123 | }, 124 | }); 125 | }); 126 | } 127 | 128 | const snippetsResult = await graphql<{ 129 | allContentfulSnippet: { nodes: { slug: string }[] }; 130 | }>(` 131 | query Snippets { 132 | allContentfulSnippet { 133 | nodes { 134 | slug 135 | } 136 | } 137 | } 138 | `); 139 | 140 | if (snippetsResult.errors) { 141 | reporter.panicOnBuild( 142 | `There was an error loading your Contentful snippets`, 143 | snippetsResult.errors 144 | ); 145 | return; 146 | } 147 | 148 | const snippets = snippetsResult.data?.allContentfulSnippet.nodes; 149 | 150 | if (snippets?.length) { 151 | snippets.forEach((snippets) => { 152 | createPage({ 153 | path: `/snippets/${snippets.slug}`, 154 | component: path.resolve("./src/templates/snippet.tsx"), 155 | context: { 156 | slug: snippets.slug, 157 | }, 158 | }); 159 | }); 160 | } 161 | }; 162 | -------------------------------------------------------------------------------- /graphql.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require("./.cache/typegen/graphql.config.json"); 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "portfolio", 3 | "version": "2.0.0", 4 | "private": true, 5 | "description": "portfolio", 6 | "author": "Rakesh Potnuru", 7 | "keywords": [ 8 | "gatsby" 9 | ], 10 | "scripts": { 11 | "dev": "gatsby develop -p 3000", 12 | "start": "gatsby develop", 13 | "build": "gatsby build", 14 | "serve": "gatsby serve", 15 | "clean": "gatsby clean", 16 | "typecheck": "tsc --noEmit", 17 | "lint": "eslint . --ext .js,.jsx,.ts,.tsx", 18 | "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix" 19 | }, 20 | "dependencies": { 21 | "@contentful/rich-text-types": "^17.0.0", 22 | "@fontsource/poppins": "^5.1.1", 23 | "@giscus/react": "^3.1.0", 24 | "@hookform/resolvers": "^3.10.0", 25 | "@radix-ui/react-aspect-ratio": "^1.1.1", 26 | "@radix-ui/react-dialog": "^1.1.11", 27 | "@radix-ui/react-dropdown-menu": "^2.1.4", 28 | "@radix-ui/react-label": "^2.1.1", 29 | "@radix-ui/react-slot": "^1.1.1", 30 | "class-variance-authority": "^0.7.1", 31 | "clsx": "^2.1.1", 32 | "date-fns": "^4.1.0", 33 | "embla-carousel-autoplay": "^8.5.1", 34 | "embla-carousel-react": "^8.5.1", 35 | "gatsby": "^5.14.0", 36 | "gatsby-plugin-feed": "^5.14.0", 37 | "gatsby-plugin-google-gtag": "^5.14.0", 38 | "gatsby-plugin-image": "^3.14.0", 39 | "gatsby-plugin-manifest": "^5.14.0", 40 | "gatsby-plugin-sharp": "^5.14.0", 41 | "gatsby-plugin-sitemap": "^6.14.0", 42 | "gatsby-source-contentful": "^8.15.0", 43 | "gatsby-source-filesystem": "^5.14.0", 44 | "gatsby-transformer-cloudinary": "^4.7.0", 45 | "gatsby-transformer-sharp": "^5.14.0", 46 | "lucide-react": "^0.469.0", 47 | "next-themes": "^0.4.4", 48 | "react": "^18.2.0", 49 | "react-dom": "^18.2.0", 50 | "react-fast-marquee": "^1.6.5", 51 | "react-hook-form": "^7.54.2", 52 | "react-icons": "^5.4.0", 53 | "react-markdown": "^9.0.3", 54 | "react-player": "^2.16.0", 55 | "react-syntax-highlighter": "^15.6.1", 56 | "react-type-animation": "^3.2.0", 57 | "reading-time-estimator": "^1.11.0", 58 | "rehype-slug": "^6.0.0", 59 | "remark": "^15.0.1", 60 | "remark-html": "^16.0.1", 61 | "sonner": "^1.7.1", 62 | "tailwind-merge": "^2.6.0", 63 | "tailwindcss-animate": "^1.0.7", 64 | "zod": "^3.24.1" 65 | }, 66 | "devDependencies": { 67 | "@tailwindcss/typography": "^0.5.16", 68 | "@types/node": "^20.11.19", 69 | "@types/react": "^18.2.55", 70 | "@types/react-dom": "^18.2.19", 71 | "@types/react-syntax-highlighter": "^15.5.13", 72 | "autoprefixer": "^10.4.20", 73 | "eslint-config-react-app": "^7.0.1", 74 | "eslint-plugin-simple-import-sort": "^12.1.1", 75 | "gatsby-plugin-postcss": "^6.14.0", 76 | "postcss": "^8.4.49", 77 | "tailwindcss": "^3.4.17", 78 | "typescript": "^5.3.3" 79 | }, 80 | "packageManager": "pnpm@9.15.2" 81 | } 82 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /src/assets/icons/action.tsx: -------------------------------------------------------------------------------- 1 | import { FaDownload } from "react-icons/fa"; 2 | import { IoIosCopy } from "react-icons/io"; 3 | import { IoSearch } from "react-icons/io5"; 4 | import { LuFilter } from "react-icons/lu"; 5 | 6 | export const ActionIcons = { 7 | Download: FaDownload, 8 | Filter: LuFilter, 9 | Copy: IoIosCopy, 10 | Search: IoSearch, 11 | }; 12 | -------------------------------------------------------------------------------- /src/assets/icons/general.tsx: -------------------------------------------------------------------------------- 1 | import { SquareArrowOutUpRight } from "lucide-react"; 2 | import { AiOutlineLoading3Quarters } from "react-icons/ai"; 3 | import { BsBoxArrowInDownLeft } from "react-icons/bs"; 4 | import { FaDonate } from "react-icons/fa"; 5 | import { FaRss } from "react-icons/fa6"; 6 | import { IoReader } from "react-icons/io5"; 7 | import { MdEmail } from "react-icons/md"; 8 | 9 | export const GeneralIcons = { 10 | Email: MdEmail, 11 | ExternalLink: SquareArrowOutUpRight, 12 | InternalLink: BsBoxArrowInDownLeft, 13 | Read: IoReader, 14 | Loading: AiOutlineLoading3Quarters, 15 | Feed: FaRss, 16 | Donate: FaDonate, 17 | }; 18 | -------------------------------------------------------------------------------- /src/assets/icons/index.ts: -------------------------------------------------------------------------------- 1 | import { ActionIcons } from "./action"; 2 | import { GeneralIcons } from "./general"; 3 | import { NavIcons } from "./nav"; 4 | import { SocialIcons } from "./social"; 5 | 6 | export const Icons = { 7 | ...NavIcons, 8 | ...SocialIcons, 9 | ...GeneralIcons, 10 | ...ActionIcons, 11 | }; 12 | -------------------------------------------------------------------------------- /src/assets/icons/nav.tsx: -------------------------------------------------------------------------------- 1 | import { ArrowUp } from "lucide-react"; 2 | 3 | export const NavIcons = { 4 | Up: ArrowUp, 5 | }; 6 | -------------------------------------------------------------------------------- /src/assets/icons/social.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | FaGithub, 3 | FaInstagram, 4 | FaLinkedin, 5 | FaMedium, 6 | FaPlaystation, 7 | FaProductHunt, 8 | } from "react-icons/fa"; 9 | import { FaSquareXTwitter } from "react-icons/fa6"; 10 | 11 | export const SocialIcons = { 12 | GitHub: FaGithub, 13 | LinkedIn: FaLinkedin, 14 | Medium: FaMedium, 15 | Instagram: FaInstagram, 16 | Playstation: FaPlaystation, 17 | ProductHunt: FaProductHunt, 18 | Twitter: FaSquareXTwitter, 19 | }; 20 | -------------------------------------------------------------------------------- /src/components/common/body.tsx: -------------------------------------------------------------------------------- 1 | import { CheckIcon, CopyIcon } from "lucide-react"; 2 | import React from "react"; 3 | import Markdown, { ExtraProps } from "react-markdown"; 4 | import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; 5 | import { darcula as theme } from "react-syntax-highlighter/dist/cjs/styles/prism"; 6 | import rehypeSlug from "rehype-slug"; 7 | 8 | import { Button } from "@/components/ui/reusables/button"; 9 | import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard"; 10 | import { cn } from "@/utils/cn"; 11 | 12 | export default function Body({ content }: { content: string }) { 13 | return ( 14 | , 17 | }} 18 | rehypePlugins={[rehypeSlug]} 19 | > 20 | {content} 21 | 22 | ); 23 | } 24 | 25 | function Codeblock( 26 | props: React.ClassAttributes & 27 | React.HTMLAttributes & 28 | ExtraProps 29 | ) { 30 | const { isCopied, copyToClipboard } = useCopyToClipboard({ 31 | timeout: 2000, 32 | }); 33 | 34 | const { children, className, node, ...rest } = props; 35 | const match = /language-(\w+)/.exec(className || ""); 36 | 37 | const language = match?.[1]; 38 | const value = String(children).replace(/\n$/, ""); 39 | 40 | const onCopy = () => { 41 | if (isCopied) return; 42 | copyToClipboard(value); 43 | }; 44 | 45 | return match ? ( 46 |
47 |
48 | {language} 49 | 62 |
63 | {/* @ts-ignore */} 64 | 79 |
80 | ) : ( 81 | 88 | {children} 89 | 90 | ); 91 | } 92 | -------------------------------------------------------------------------------- /src/components/common/comment-box.tsx: -------------------------------------------------------------------------------- 1 | import Giscus from "@giscus/react"; 2 | import React from "react"; 3 | 4 | import { Heading } from "../ui/heading"; 5 | 6 | export default function CommentBox() { 7 | return ( 8 | <> 9 | Comments 10 |
11 | 25 |
26 | 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /src/components/common/cta.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { Icons } from "@/assets/icons"; 4 | import { Heading } from "@/components/ui/heading"; 5 | import { Button } from "@/components/ui/reusables/button"; 6 | import Row from "@/components/ui/row"; 7 | import { siteConfig } from "@/config/site"; 8 | 9 | export default function Cta() { 10 | return ( 11 | 12 | 16 | Interested in
working
with me? 17 |
18 | 19 | 22 | 23 |
24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /src/components/common/dev-tools/breakpoint-viewer.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export function BreakpointViewer() { 4 | return ( 5 |
9 | XS 10 | SM 11 | MD 12 | LG 13 | XL 14 | 2XL 15 |
16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /src/components/common/donation-box.tsx: -------------------------------------------------------------------------------- 1 | import { StaticImage } from "gatsby-plugin-image"; 2 | import React from "react"; 3 | import { toast } from "sonner"; 4 | 5 | import { Icons } from "@/assets/icons"; 6 | import { siteConfig } from "@/config/site"; 7 | 8 | import { Button } from "../ui/reusables/button"; 9 | import { Dialog, DialogContent, DialogTrigger } from "../ui/reusables/dialog"; 10 | import Row from "../ui/row"; 11 | 12 | export default function DonationBox() { 13 | return ( 14 | 15 |

Loved this post?

16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | ); 24 | } 25 | 26 | function DonateViaUPI() { 27 | return ( 28 | 29 | 30 | 39 | 40 | 41 | 46 | 58 | 59 | 60 | ); 61 | } 62 | -------------------------------------------------------------------------------- /src/components/common/footer.tsx: -------------------------------------------------------------------------------- 1 | import { Link, PageProps } from "gatsby"; 2 | import React from "react"; 3 | 4 | import { Icons } from "@/assets/icons"; 5 | 6 | import Col from "../ui/col"; 7 | import Row from "../ui/row"; 8 | import SocialItems from "./social-items"; 9 | import Subscribe from "./subscribe"; 10 | 11 | export default function Footer({ 12 | location, 13 | }: { 14 | location: PageProps["location"]; 15 | }) { 16 | return ( 17 |
18 | 19 |

Let's Connect

20 | 21 | 22 | 27 | 28 | 29 | 30 | 35 |

36 | © 2021 - {new Date().getFullYear()} itsrakesh. v2. 37 |

38 | 39 |
40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /src/components/common/layout.tsx: -------------------------------------------------------------------------------- 1 | import { PageProps } from "gatsby"; 2 | import React from "react"; 3 | 4 | import { cn } from "@/utils/cn"; 5 | 6 | import { Toaster } from "../ui/reusables/sonner"; 7 | import ScrollToTop from "../ui/scroll-to-top"; 8 | import Cta from "./cta"; 9 | import { BreakpointViewer } from "./dev-tools/breakpoint-viewer"; 10 | import Footer from "./footer"; 11 | import Nav from "./nav"; 12 | 13 | interface LayoutProps extends React.HTMLAttributes { 14 | location: PageProps["location"]; 15 | } 16 | 17 | export default function Layout({ 18 | children, 19 | location, 20 | className, 21 | }: Readonly) { 22 | return ( 23 | <> 24 |