├── .eslintrc.js ├── .eslintrc.json ├── .gitignore ├── .husky └── pre-commit ├── .prettierignore ├── .prettierrc ├── LICENSE.md ├── README.md ├── components ├── BlogPost.tsx ├── Divider.tsx ├── Footer.tsx ├── Header.tsx ├── Hero.tsx ├── Layout.tsx ├── NavItems.tsx ├── ProjectCard.tsx ├── SubscribeForm.tsx ├── TopBlogPost.tsx ├── TopTweets.tsx └── index.ts ├── contentlayer.config.ts ├── data ├── menus.ts ├── posts │ ├── encode-decode-string-golang.md │ ├── next-js-resources.md │ └── what-is-json-web-token.md ├── projects.ts └── tweets.ts ├── next-env.d.ts ├── next.config.js ├── package-lock.json ├── package.json ├── pages ├── _app.tsx ├── _document.tsx ├── blog │ ├── [slug].tsx │ └── index.tsx ├── contact.tsx ├── index.tsx ├── projects.tsx └── top-tweets.tsx ├── postcss.config.js ├── public ├── developer-avatar.png ├── favicon.ico └── projects │ └── project.png ├── styles └── globals.css ├── tailwind.config.js ├── tsconfig.json └── types.ts /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2021: true, 5 | node: true, 6 | }, 7 | extends: [ 8 | "eslint:recommended", 9 | "plugin:@typescript-eslint/recommended", 10 | "prettier", 11 | "next/core-web-vitals", 12 | ], 13 | parser: "@typescript-eslint/parser", 14 | parserOptions: { 15 | ecmaFeatures: { 16 | jsx: true, 17 | }, 18 | ecmaVersion: "latest", 19 | sourceType: "module", 20 | }, 21 | plugins: ["react", "@typescript-eslint"], 22 | rules: { 23 | "@typescript-eslint/no-explicit-any": "off", 24 | "@typescript-eslint/no-var-requires": "off", 25 | }, 26 | settings: { 27 | react: { 28 | version: "detect", 29 | }, 30 | }, 31 | overrides: [ 32 | { 33 | files: ["*.js"], 34 | }, 35 | ], 36 | }; 37 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | 37 | 38 | # Contentlayer 39 | .contentlayer 40 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | echo '🏗️👷 Styling, testing and building your project before committing' 5 | 6 | # Check Prettier standards 7 | npm run check-format || 8 | ( 9 | echo '🤢🤮🤢🤮 Its F**KING RAW - Your styling looks disgusting. 🤢🤮🤢🤮 10 | Prettier Check Failed. Run npm run format, add changes and try commit again.'; 11 | false; 12 | ) 13 | 14 | # Check ESLint Standards 15 | npm run check-lint || 16 | ( 17 | echo '😤🏀👋😤 Get that weak s**t out of here! 😤🏀👋😤 18 | ESLint Check Failed. Make the required changes listed above, add changes and try to commit again.' 19 | false; 20 | ) 21 | 22 | # Check tsconfig standards 23 | npm run check-types || 24 | ( 25 | echo '🤡😂❌🤡 Failed Type check. 🤡😂❌🤡 26 | Are you seriously trying to write that? Make the changes required above.' 27 | false; 28 | ) 29 | 30 | # If everything passes... Now we can commit 31 | echo '🤔🤔🤔🤔... Alright... Code looks good to me... 🤔🤔🤔🤔' 32 | 33 | # npm run build || 34 | # ( 35 | # echo '❌👷🔨❌ Better call Bob... Because your build failed ❌👷🔨❌ 36 | # Next build failed: View the errors above to see why. 37 | # ' 38 | # false; 39 | # ) 40 | 41 | # If everything passes... Now we can commit 42 | echo '✅✅✅✅ You win this time... I am committing this now. ✅✅✅✅' -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .next 3 | public 4 | **/**/node_modules 5 | **/**/.next 6 | **/**/public 7 | npm/migration/** 8 | 9 | *.lock 10 | *.log 11 | 12 | .gitignore 13 | .npmignore 14 | .prettierignore 15 | .DS_Store 16 | .eslintignore 17 | 18 | out 19 | 20 | .contentlayer 21 | 22 | data/posts/* -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "printWidth": 80, 4 | "tabWidth": 2, 5 | "trailingComma": "es5" 6 | } 7 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Kiran K 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NextJS Blog Template for Developers 2 | 3 | This is a simple NextJS blog template for developers. Still in development. Feel free to contribute! 4 | 5 | ## Pages 6 | 7 | - [x] Home 8 | - [x] Projects 9 | - [x] Blog 10 | - [x] Contact form 11 | - [x] Subscribe to the email form 12 | - [x] Latest Articles & News 13 | - [x] Top Tweets 14 | - [ ] Open Source Contributions 15 | - [ ] Make the header mobile responsive 16 | 17 | ## Demo 18 | 19 | See the [demo](https://nextjs-blog-template-xi.vercel.app/) 20 | 21 | ## How to update the data (Posts, Projects, etc.) 22 | 23 | - Add new posts to the `data/posts` folder. 24 | - Add new projects to the `data/projects.ts` file. 25 | - Add new tweets to the `data/tweets.ts` file. 26 | - Add new menu items to the `data/menus.ts` file. 27 | 28 | ## Development 29 | 30 | First, run the development server: 31 | 32 | ```bash 33 | npm run dev 34 | ``` 35 | 36 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 37 | 38 | You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. 39 | 40 | ## Learn More 41 | 42 | To learn more about Next.js, take a look at the following resources: 43 | 44 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 45 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 46 | 47 | ## Deploy on Vercel 48 | 49 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 50 | 51 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 52 | -------------------------------------------------------------------------------- /components/BlogPost.tsx: -------------------------------------------------------------------------------- 1 | import type { Post } from "contentlayer/generated"; 2 | import Link from "next/link"; 3 | 4 | const BlogPost = ({ post }: { post: Post }) => { 5 | return ( 6 | 7 | 8 |
9 |
10 |

11 | {post.title} 12 |

13 |

14 | {post.description} 15 |

16 |

{post.publishedAt}

17 |
18 |
19 |
20 | 21 | ); 22 | }; 23 | 24 | export default BlogPost; 25 | -------------------------------------------------------------------------------- /components/Divider.tsx: -------------------------------------------------------------------------------- 1 | const Divider = () => { 2 | return
; 3 | }; 4 | 5 | export default Divider; 6 | -------------------------------------------------------------------------------- /components/Footer.tsx: -------------------------------------------------------------------------------- 1 | const Footer = () => { 2 | return ( 3 | 13 | ); 14 | }; 15 | 16 | export default Footer; 17 | -------------------------------------------------------------------------------- /components/Header.tsx: -------------------------------------------------------------------------------- 1 | import NavItems from "./NavItems"; 2 | 3 | const Header = () => { 4 | return ( 5 |
6 |

Kiran K

7 | 8 |
9 | ); 10 | }; 11 | 12 | export default Header; 13 | -------------------------------------------------------------------------------- /components/Hero.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | 3 | const Hero = () => { 4 | return ( 5 |
6 |

Kiran Krishnan

7 |

8 | Software Engineer (Open Source, Dev Tools) @ BoxyHQ 9 |

10 |

11 | Sharing my journey in tech. Open source contributor. I'm excited to 12 | learn new languages and contribute to OSS. 13 |

14 |
15 | 16 | Contact Me 17 | 18 |
19 |
20 | ); 21 | }; 22 | 23 | export default Hero; 24 | -------------------------------------------------------------------------------- /components/Layout.tsx: -------------------------------------------------------------------------------- 1 | import Header from "./Header"; 2 | import Footer from "./Footer"; 3 | import React from "react"; 4 | 5 | const Layout = ({ children }: { children: React.ReactElement }) => { 6 | return ( 7 |
8 |
9 |
{children}
10 |
12 | ); 13 | }; 14 | 15 | export default Layout; 16 | -------------------------------------------------------------------------------- /components/NavItems.tsx: -------------------------------------------------------------------------------- 1 | import type { Menu } from "types"; 2 | import Link from "next/link"; 3 | import menus from "data/menus"; 4 | import { useRouter } from "next/router"; 5 | 6 | const Nav = () => { 7 | return ( 8 | 20 | ); 21 | }; 22 | 23 | const NavItem = ({ menu }: { menu: Menu }) => { 24 | const router = useRouter(); 25 | 26 | const { asPath } = router; 27 | 28 | return ( 29 | 30 | 33 | {menu.title} 34 | 35 | 36 | ); 37 | }; 38 | 39 | export default Nav; 40 | -------------------------------------------------------------------------------- /components/ProjectCard.tsx: -------------------------------------------------------------------------------- 1 | import type { Project } from "types"; 2 | import Link from "next/link"; 3 | 4 | const ProjectCard = ({ project }: { project: Project; key: string }) => { 5 | return ( 6 |
7 | 8 | 9 |
10 | {project.name} 15 |

{project.name}

16 |

{project.description}

17 |
18 |
19 | 20 |
21 | ); 22 | }; 23 | 24 | export default ProjectCard; 25 | -------------------------------------------------------------------------------- /components/SubscribeForm.tsx: -------------------------------------------------------------------------------- 1 | const SubscribeForm = () => { 2 | return ( 3 |
4 |
5 |

6 | Subscribe to the email newsletter 7 |

8 |

9 | Join 5,000+ others and never miss out on new tips, tutorials, and 10 | more. 11 |

12 |
13 |
14 | 21 |
22 | 23 |
24 |
25 |
26 | ); 27 | }; 28 | 29 | export default SubscribeForm; 30 | -------------------------------------------------------------------------------- /components/TopBlogPost.tsx: -------------------------------------------------------------------------------- 1 | import { BlogPost } from "components"; 2 | import type { Post } from "contentlayer/generated"; 3 | 4 | const TopBlogPost = ({ posts }: { posts: Post[] | null }) => { 5 | return ( 6 | <> 7 |

8 | Latest Articles & News 9 |

10 |
11 | {posts && 12 | posts.map((post) => )} 13 |
14 | 15 | ); 16 | }; 17 | 18 | export default TopBlogPost; 19 | -------------------------------------------------------------------------------- /components/TopTweets.tsx: -------------------------------------------------------------------------------- 1 | import { TwitterTweetEmbed } from "react-twitter-embed"; 2 | import tweets from "data/tweets"; 3 | 4 | const TopTweets = () => { 5 | return ( 6 | <> 7 |
8 | {tweets.map((tweetId) => ( 9 | 10 | ))} 11 |
12 | 13 | ); 14 | }; 15 | 16 | export default TopTweets; 17 | -------------------------------------------------------------------------------- /components/index.ts: -------------------------------------------------------------------------------- 1 | export { default as BlogPost } from "./BlogPost"; 2 | export { default as Footer } from "./Footer"; 3 | export { default as Header } from "./Header"; 4 | export { default as Hero } from "./Hero"; 5 | export { default as Layout } from "./Layout"; 6 | export { default as NavItems } from "./NavItems"; 7 | export { default as ProjectCard } from "./ProjectCard"; 8 | export { default as SubscribeForm } from "./SubscribeForm"; 9 | export { default as TopTweets } from "./TopTweets"; 10 | export { default as TopBlogPost } from "./TopBlogPost"; 11 | export { default as Divider } from "./Divider"; 12 | -------------------------------------------------------------------------------- /contentlayer.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ComputedFields, 3 | defineDocumentType, 4 | makeSource, 5 | } from "contentlayer/source-files"; 6 | 7 | const computedFields: ComputedFields = { 8 | slug: { 9 | type: "string", 10 | resolve: (doc) => doc._raw.sourceFileName.replace(/\.md$/, ""), 11 | }, 12 | }; 13 | 14 | const Post = defineDocumentType(() => ({ 15 | name: "Post", 16 | filePathPattern: "**/*.md", 17 | contentType: "markdown", 18 | fields: { 19 | title: { type: "string", required: true }, 20 | publishedAt: { type: "string", required: true }, 21 | description: { type: "string", required: true }, 22 | image: { type: "string", required: false }, 23 | }, 24 | computedFields, 25 | })); 26 | 27 | export default makeSource({ 28 | contentDirPath: "data/posts", 29 | documentTypes: [Post], 30 | }); 31 | -------------------------------------------------------------------------------- /data/menus.ts: -------------------------------------------------------------------------------- 1 | const menus = [ 2 | { 3 | title: "Home", 4 | path: "/", 5 | }, 6 | { 7 | title: "Projects", 8 | path: "/projects", 9 | }, 10 | { 11 | title: "Blog", 12 | path: "/blog", 13 | }, 14 | { 15 | title: "Top Tweets", 16 | path: "/top-tweets", 17 | }, 18 | { 19 | title: "Contact", 20 | path: "/contact", 21 | }, 22 | ]; 23 | 24 | export default menus; 25 | -------------------------------------------------------------------------------- /data/posts/encode-decode-string-golang.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How to Base64 encode and decode data in Golang 3 | publishedAt: '2022-03-03' 4 | description: In this article, I'll show you Base64 encoding and decoding in Golang. 5 | --- 6 | 7 | In this post, I'll show you Base64 encoding and decoding in Golang. 8 | 9 | Base64 encoding schemes are commonly used when there is a need to encode binary data that needs to be stored and transferred over media that are designed to deal with ASCII. 10 | 11 | This is to ensure that the data remain intact without modification during transport. 12 | 13 | Read more about the Base64 encoding scheme [here](https://developer.mozilla.org/en-US/docs/Glossary/Base64). 14 | 15 | Golang provides built-in support for base64 encoding and decoding with a package `encoding/base64`. 16 | 17 | Let's see the code for base64 encoding and decoding in Golang. 18 | 19 | Create a new folder called `base64-encode-decode`. 20 | 21 | ```bash 22 | mkdir base64-encode-decode 23 | 24 | cd base64-encode-decode 25 | 26 | touch main.go 27 | ``` 28 | 29 | Open the `main.go` and import the necessary packages. 30 | 31 | ```go 32 | package main 33 | 34 | import ( 35 | "encoding/base64" 36 | "fmt" 37 | ) 38 | ``` 39 | 40 | The package `encoding/base64` provides 2 functions for encoding and decoding data in Base64 format. 41 | 42 | `EncodeToString` encodes the passed data in Base64 format and returns the encoded data as a string. 43 | 44 | ```go 45 | func (enc *Encoding) EncodeToString(src []byte) string 46 | ``` 47 | 48 | `DecodeString` decodes the passed data (string) and returns the decoded data as a byte slice. 49 | 50 | ```go 51 | func (enc *Encoding) DecodeString(s string) ([]byte, error) 52 | ``` 53 | 54 | Let's add the code to encode and print the encoded data. 55 | 56 | ```go 57 | func main() { 58 | text := "Hello World - Go!" 59 | 60 | encodedText := base64.StdEncoding.EncodeToString([]byte(text)); 61 | 62 | fmt.Printf("Encoded Text: %s\n", encodedText) 63 | } 64 | ``` 65 | 66 | The above code will print the following output: 67 | 68 | ```go 69 | Encoded Text: SGVsbG8gV29ybGQgLSBHbyE= 70 | ``` 71 | 72 | Now, let's add the code to decode the encoded data and print the decoded data. 73 | 74 | ```go 75 | decodedText, err := base64.StdEncoding.DecodeString(encodedText); 76 | if err != nil { 77 | panic(err) 78 | } 79 | 80 | fmt.Printf("Decoded Text: %s\n", decodedText) 81 | ``` 82 | 83 | The above code will print the following output: 84 | 85 | ``` 86 | Decoded Text: Hello World - Go! 87 | ``` 88 | 89 | Here is the complete working code. 90 | 91 | ```go 92 | package main 93 | 94 | import ( 95 | "encoding/base64" 96 | "fmt" 97 | ) 98 | 99 | func main() { 100 | text := "Hello World - Go!" 101 | 102 | encodedText := base64.StdEncoding.EncodeToString([]byte(text)); 103 | 104 | fmt.Printf("Encoded Text: %s\n", encodedText) 105 | 106 | decodedText, err := base64.StdEncoding.DecodeString(encodedText); 107 | if err != nil { 108 | panic(err) 109 | } 110 | 111 | fmt.Printf("Decoded Text: %s\n", decodedText) 112 | } 113 | ``` 114 | -------------------------------------------------------------------------------- /data/posts/next-js-resources.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 25 Resources to Learn Next.js in 2022 3 | publishedAt: '2022-03-04' 4 | description: I've curated 25 online resources to learn Next.js in 2022. 5 | --- 6 | 7 | I've curated 25 online resources to learn Next.js in 2022. I hope you find these resources useful and interesting. I'll keep updating the below list as I discover new resources. 8 | 9 | 1. [Next.js documentation](https://nextjs.org/docs) 10 | 11 | 2. [The Next.js Handbook](https://www.freecodecamp.org/news/the-next-js-handbook/) 12 | 13 | 3. [Awesome Next.js](https://awesomenextjs.com/) 14 | 15 | 4. [Complete Next.js Developer in 2022: Zero to Mastery](https://academy.zerotomastery.io/p/learn-next-js) 16 | 17 | 5. [Next.js Crash Course for Beginners 2021 - Learn NextJS from Scratch](https://www.youtube.com/watch?v=MFuwkrseXVE) 18 | 19 | 6. [Mastering Next.js](https://masteringnextjs.com/) 20 | 21 | 7. [Getting started with Next.js](https://flaviocopes.com/nextjs/) 22 | 23 | 8. [Explore all the official Next.js examples](https://nextexamples.vercel.app/) 24 | 25 | 9. [Complete Next.js with React & Node - Beautiful Portfolio App](https://academy.eincode.com/courses/complete-next-js-with-react-node-beautiful-portfolio-app) 26 | 27 | 10. [Universal React with Next.js - The Ultimate Guide](https://www.udemy.com/course/universal-react-with-nextjs-the-ultimate-guide/) 28 | 29 | 11. [Building Server-side Rendered React Apps for Beginners](https://www.pluralsight.com/courses/building-server-side-rendered-react-apps-beginners) 30 | 31 | 12. [Next.js - The ultimate way to build React apps](https://www.educative.io/courses/next-js-build-react-apps) 32 | 33 | 13. [This Mission: Next.js from the Ground Up](https://explorers.netlify.com/learn/nextjs) 34 | 35 | 14. [Learn Next.js 11 - Build Modern Next.js Applications](https://codedamn.com/learn/nextjs-fundamentals) 36 | 37 | 15. [Build a Fullstack App With Strapi and Next.js](https://www.digitalocean.com/community/tech_talks/build-a-fullstack-app-with-strapi-and-next-js) 38 | 39 | 16. [Next.js Crash Course](https://www.youtube.com/watch?v=mTz0GXj8NN0) 40 | 41 | 17. [Next.js Tutorial from The Net Ninja](https://youtube.com/playlist?list=PL4cUxeGkcC9g9gP2onazU5-2M-AzA8eBw) 42 | 43 | 18. [From Design to Development Crash Course - Full Stack Next.js Tutorial](https://www.youtube.com/watch?v=QjZIeA952jE&t=402s) 44 | 45 | 19. [Using Next.js - React Resources](https://reactresources.com/topics/nextjs) 46 | 47 | 20. [Next.js Tutorial - tutorialspoint.com](https://www.tutorialspoint.com/nextjs/index.htm) 48 | 49 | 21. [Production-Ready Next.js](https://frontendmasters.com/workshops/production-next-js/) 50 | 51 | 22. [Getting Started with Next.js](https://teacode.io/blog/getting-started-next-js) 52 | 53 | 23. [Next.js Conf 2020](https://www.youtube.com/playlist?list=PLBnKlKpPeagnT2Cmv4giCbosfrbKnuYTD) 54 | 55 | 24. [Next.js - egghead.io](https://egghead.io/q/next) 56 | 57 | 25. [Using NextJS With Wordpress Headless CMS](https://academind.com/tutorials/nextjs-wordpress-headless-cms) 58 | -------------------------------------------------------------------------------- /data/posts/what-is-json-web-token.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: What is JSON Web Token? 3 | publishedAt: '2021-11-16' 4 | description: JWT or JSON Web Token is an open standard that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. 5 | --- 6 | 7 | JWT or **JSON Web Token** is an open standard that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. 8 | 9 | The main purpose of JWTs is to transfer claims between two parties. 10 | 11 | The claims in a JWT are encoded as a JSON object that is digitally signed using JSON Web Signature (JWS) and/or encrypted using JSON Web Encryption (JWE). 12 | 13 | **JWS** - Signatures are useful to validate the data against tampering. 14 | 15 | **JWT** - Encryption is useful to protect the data from being read by third parties. 16 | 17 | Signed JWTs have 3 different parts. These three elements are separated by dots. 18 | 19 | 1. Header 20 | 21 | 2. Payload 22 | 23 | 3. Signature 24 | 25 | **Header** 26 | 27 | The header typically consists of two parts: the type of the token, which is JWT, and the signing algorithm being used, such as HMAC SHA256 or RSA. 28 | 29 | ![1.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1637080958800/tgQlAtwyq.png) 30 | 31 | **Payload** 32 | 33 | The second part of the token is the payload, which contains the claims. As a developer, you can include information about the user in the payload. 34 | 35 | ![2.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1637080970907/nhMuyiFvl.png) 36 | 37 | **Signature** 38 | 39 | The signature will be created in the following way. 40 | 41 | ![3.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1637080983709/KoswiHsLG.png) 42 | 43 | **Final JWT** 44 | 45 | The output is three Base64-URL strings separated by dots. 46 | 47 | [header].[payload].[signature] 48 | 49 | ![4.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1637081000479/UbQ8NF2qt.png) 50 | -------------------------------------------------------------------------------- /data/projects.ts: -------------------------------------------------------------------------------- 1 | const projects = [ 2 | { 3 | name: "Supabase", 4 | description: 5 | "Supabase is an open source Firebase alternative. Start your project with a Postgres Database, Authentication, instant APIs, Realtime subscriptions and Storage.", 6 | image: "/projects/project.png", 7 | url: "http://localhost:3000/", 8 | }, 9 | { 10 | name: "SAML Jackson", 11 | description: 12 | "A SAML SSO service designed as an OAuth 2.0 flow. Integrate SAML with just a few lines of code.", 13 | image: "/projects/project.png", 14 | url: "http://localhost:3000/", 15 | }, 16 | { 17 | name: "Nhost", 18 | description: 19 | "Nhost is an open source Firebase alternative with GraphQL, built with the following things in mind: Open Source, GraphQL, SQL, Great Developer Experience.", 20 | image: "/projects/project.png", 21 | url: "http://localhost:3000/", 22 | }, 23 | { 24 | name: "Jitsu", 25 | description: 26 | "Jitsu is a fully-scriptable data ingestion engine for modern data teams. Set-up a real-time data pipeline in minutes, not days.", 27 | image: "/projects/project.png", 28 | url: "http://localhost:3000/", 29 | }, 30 | { 31 | name: "PostHog", 32 | description: 33 | "PostHog is the all-in-one platform for building better products - with product analytics, feature flags, session recordings, a/b testing, heatmaps.", 34 | image: "/projects/project.png", 35 | url: "http://localhost:3000/", 36 | }, 37 | ]; 38 | 39 | export default projects; 40 | -------------------------------------------------------------------------------- /data/tweets.ts: -------------------------------------------------------------------------------- 1 | // Add the tweet id to the list of tweets 2 | const tweets = [ 3 | "1477614047268802561", 4 | "1477614047268802561", 5 | "1477614047268802561", 6 | "1477614047268802561", 7 | ]; 8 | 9 | export default tweets; 10 | -------------------------------------------------------------------------------- /next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | const { withContentlayer } = require("next-contentlayer"); 2 | 3 | /** 4 | * @type {import('next').NextConfig} 5 | */ 6 | module.exports = withContentlayer({ 7 | swcMinify: true, 8 | reactStrictMode: true, 9 | images: { 10 | domains: [], 11 | }, 12 | }); 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs-blog-template", 3 | "author": { 4 | "name": "Kiran K", 5 | "email": "kiran@boxyhq.com" 6 | }, 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/devkiran/nextjs-blog-template" 10 | }, 11 | "version": "1.0.0", 12 | "private": true, 13 | "scripts": { 14 | "dev": "next dev", 15 | "build": "next build", 16 | "start": "next start", 17 | "lint": "next lint", 18 | "check-types": "tsc --pretty --noEmit", 19 | "check-format": "prettier --check .", 20 | "check-lint": "eslint . --ext ts --ext tsx --ext js", 21 | "format": "prettier --write .", 22 | "test-all": "npm run check-format && npm run check-lint && npm run check-types && npm run build", 23 | "prepare": "husky install" 24 | }, 25 | "dependencies": { 26 | "@heroicons/react": "^1.0.6", 27 | "contentlayer": "^0.2.6", 28 | "daisyui": "^2.19.0", 29 | "next": "12.2.2", 30 | "next-contentlayer": "^0.2.6", 31 | "next-seo": "^5.4.0", 32 | "react": "18.2.0", 33 | "react-dom": "18.2.0", 34 | "react-markdown": "^8.0.3", 35 | "react-twitter-embed": "^4.0.4", 36 | "rehype-highlight": "^5.0.2", 37 | "rehype-prism-plus": "^1.4.2" 38 | }, 39 | "devDependencies": { 40 | "@tailwindcss/typography": "^0.5.4", 41 | "@types/node": "18.0.5", 42 | "@types/react": "18.0.15", 43 | "@types/react-dom": "18.0.6", 44 | "@typescript-eslint/eslint-plugin": "^5.30.6", 45 | "autoprefixer": "^10.4.7", 46 | "eslint": "^8.19.0", 47 | "eslint-config-next": "^12.2.2", 48 | "eslint-config-prettier": "^8.5.0", 49 | "eslint-plugin-react": "^7.30.1", 50 | "husky": "^8.0.1", 51 | "lint-staged": "^13.0.3", 52 | "postcss": "^8.4.14", 53 | "prettier": "^2.7.1", 54 | "prettier-plugin-tailwindcss": "^0.1.12", 55 | "tailwindcss": "^3.1.6", 56 | "typescript": "4.7.4" 57 | }, 58 | "husky": { 59 | "hooks": { 60 | "pre-commit": "lint-staged" 61 | } 62 | }, 63 | "lint-staged": { 64 | "*.{js,ts}": "eslint --cache --fix", 65 | "*.{js,ts,css,md}": "prettier --write" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import type { AppProps } from "next/app"; 2 | import Head from "next/head"; 3 | 4 | import "../styles/globals.css"; 5 | 6 | function MyApp({ Component, pageProps }: AppProps) { 7 | return ( 8 | <> 9 | 10 | Freelance Template 11 | 12 |
13 | 14 |
15 | 16 | ); 17 | } 18 | 19 | export default MyApp; 20 | -------------------------------------------------------------------------------- /pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import { Head, Html, Main, NextScript } from "next/document"; 2 | 3 | export default function Document() { 4 | return ( 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /pages/blog/[slug].tsx: -------------------------------------------------------------------------------- 1 | import type { NextPage } from "next"; 2 | import type { Post } from "contentlayer/generated"; 3 | import { allPosts } from "contentlayer/generated"; 4 | import ReactMarkdown from "react-markdown"; 5 | import rehypeHighlight from "rehype-highlight"; 6 | import { Layout } from "components"; 7 | import { NextSeo } from "next-seo"; 8 | 9 | const Post: NextPage<{ post: Post }> = ({ post }) => { 10 | return ( 11 | 12 | <> 13 | 14 |
15 |

{post.title}

16 | 20 | {post.body.raw} 21 | 22 |
23 | 24 |
25 | ); 26 | }; 27 | 28 | export function getStaticPaths() { 29 | return { 30 | paths: allPosts.map((p) => ({ params: { slug: p.slug } })), 31 | fallback: false, 32 | }; 33 | } 34 | 35 | export function getStaticProps({ params }: { params: { slug: string } }) { 36 | const post = allPosts.find((post) => post.slug === params?.slug); 37 | 38 | return { props: { post } }; 39 | } 40 | 41 | export default Post; 42 | -------------------------------------------------------------------------------- /pages/blog/index.tsx: -------------------------------------------------------------------------------- 1 | import type { NextPage } from "next"; 2 | import type { Post } from "contentlayer/generated"; 3 | import { allPosts } from "contentlayer/generated"; 4 | import { BlogPost, Layout } from "components"; 5 | import { NextSeo } from "next-seo"; 6 | 7 | const Posts: NextPage<{ posts: Post[] | null }> = ({ posts }) => { 8 | return ( 9 | 10 | <> 11 | 12 |
13 |

All Posts

14 |

15 | Lorem Ipsum has been the industrys standard dummy text ever since 16 | the 1500s, when an unknown printer took a galley of type and 17 | scrambled it to make a type specimen book 18 |

19 |
20 | {posts && 21 | posts.map((post) => )} 22 |
23 |
24 | 25 |
26 | ); 27 | }; 28 | 29 | export function getStaticProps() { 30 | const posts = allPosts.map((post) => { 31 | return { 32 | title: post.title, 33 | description: post.description, 34 | content: post.body, 35 | publishedAt: post.publishedAt, 36 | slug: post.slug, 37 | }; 38 | }); 39 | 40 | return { props: { posts: posts } }; 41 | } 42 | 43 | export default Posts; 44 | -------------------------------------------------------------------------------- /pages/contact.tsx: -------------------------------------------------------------------------------- 1 | import type { NextPage } from "next"; 2 | import { Layout } from "components"; 3 | import { NextSeo } from "next-seo"; 4 | 5 | const Contact: NextPage = () => { 6 | return ( 7 | 8 | <> 9 | 10 |
11 |
12 |

Get in touch

13 |

14 | Lorem Ipsum is simply dummy text of the printing and typesetting 15 | industry. 16 |

17 |
18 |

kiran@boxyhq.com

19 |
20 |
21 |

22 | Website: 23 |  kirandev.com 24 |

25 |
26 |
27 |

28 | Twitter: 29 | 30 |  @tokirankrishnan 31 | 32 |

33 |
34 |
35 |

36 | GitHub: 37 |  @devkiran 38 |

39 |
40 |
41 |
42 |
43 |
44 | 49 |
50 |
51 | 56 |
57 |
58 | 63 |
64 |
65 | 69 |
70 | 71 |
72 |
73 |
74 | 75 |
76 | ); 77 | }; 78 | 79 | export default Contact; 80 | -------------------------------------------------------------------------------- /pages/index.tsx: -------------------------------------------------------------------------------- 1 | import type { NextPage } from "next"; 2 | import type { Post } from "contentlayer/generated"; 3 | import { Layout, Hero, SubscribeForm, TopBlogPost, Divider } from "components"; 4 | import { NextSeo } from "next-seo"; 5 | import { allPosts } from "contentlayer/generated"; 6 | 7 | const Home: NextPage<{ posts: Post[] | null }> = ({ posts }) => { 8 | return ( 9 | 10 | <> 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | ); 20 | }; 21 | 22 | export function getStaticProps() { 23 | const posts = allPosts.map((post) => { 24 | return { 25 | title: post.title, 26 | description: post.description, 27 | publishedAt: post.publishedAt, 28 | slug: post.slug, 29 | }; 30 | }); 31 | 32 | return { props: { posts: posts } }; 33 | } 34 | 35 | export default Home; 36 | -------------------------------------------------------------------------------- /pages/projects.tsx: -------------------------------------------------------------------------------- 1 | import type { NextPage } from "next"; 2 | import projects from "data/projects"; 3 | import { ProjectCard, Layout } from "components"; 4 | import { NextSeo } from "next-seo"; 5 | 6 | const Projects: NextPage = () => { 7 | return ( 8 | 9 | <> 10 | 11 |
12 |

Projects

13 |

14 | Lorem Ipsum has been the industrys standard dummy text ever since 15 | the 1500s, when an unknown printer took a galley of type and 16 | scrambled it to make a type specimen book 17 |

18 |
19 | {projects.map((project) => ( 20 | 21 | ))} 22 |
23 |
24 | 25 |
26 | ); 27 | }; 28 | 29 | export default Projects; 30 | -------------------------------------------------------------------------------- /pages/top-tweets.tsx: -------------------------------------------------------------------------------- 1 | import type { NextPage } from "next"; 2 | import { Layout, TopTweets } from "components"; 3 | import { NextSeo } from "next-seo"; 4 | 5 | const Posts: NextPage = () => { 6 | return ( 7 | 8 | <> 9 | 10 | 11 |
12 |

Top Tweets

13 |

14 | Top tweets from the past week. Follow me on Twitter to hear more 15 | about what I share. 16 |

17 |
18 | 19 |
20 |
21 | 22 |
23 | ); 24 | }; 25 | 26 | export default Posts; 27 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /public/developer-avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devkiran/nextjs-blog-template/e3295b3bd1c7e2a2fb6169a034c20b2033fd8b4d/public/developer-avatar.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devkiran/nextjs-blog-template/e3295b3bd1c7e2a2fb6169a034c20b2033fd8b4d/public/favicon.ico -------------------------------------------------------------------------------- /public/projects/project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devkiran/nextjs-blog-template/e3295b3bd1c7e2a2fb6169a034c20b2033fd8b4d/public/projects/project.png -------------------------------------------------------------------------------- /styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | html, 6 | body { 7 | padding: 0; 8 | margin: 0; 9 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 10 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 11 | } 12 | 13 | a { 14 | color: inherit; 15 | text-decoration: none; 16 | } 17 | 18 | * { 19 | box-sizing: border-box; 20 | } 21 | 22 | .prose .anchor { 23 | @apply invisible absolute no-underline; 24 | 25 | margin-left: -1em; 26 | padding-right: 0.5em; 27 | width: 80%; 28 | max-width: 700px; 29 | cursor: pointer; 30 | } 31 | 32 | .anchor:hover { 33 | @apply visible; 34 | } 35 | 36 | .prose > :first-child { 37 | margin-top: 1.25em !important; 38 | margin-bottom: 1.25em !important; 39 | } 40 | 41 | .prose a { 42 | @apply text-cyan-500; 43 | } 44 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | "./pages/**/*.{js,ts,jsx,tsx}", 5 | "./components/**/*.{js,ts,jsx,tsx}", 6 | ], 7 | theme: { 8 | extend: {}, 9 | }, 10 | plugins: [require("daisyui"), require(`@tailwindcss/typography`)], 11 | }; 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true, 17 | "baseUrl": ".", 18 | "paths": { 19 | "contentlayer/generated": ["./.contentlayer/generated"], 20 | "components/*": ["components/*"] 21 | } 22 | }, 23 | "include": [ 24 | "next-env.d.ts", 25 | "**/*.ts", 26 | "**/*.tsx", 27 | ".contentlayer/generated" 28 | ], 29 | "exclude": ["node_modules"] 30 | } 31 | -------------------------------------------------------------------------------- /types.ts: -------------------------------------------------------------------------------- 1 | export type Project = { 2 | name: string; 3 | description: string; 4 | image: string; 5 | url: string; 6 | }; 7 | 8 | export type Menu = { 9 | title: string; 10 | path: string; 11 | }; 12 | --------------------------------------------------------------------------------