├── .env.local.sample ├── .gitignore ├── @types └── remark-html.d.ts ├── README.md ├── _posts ├── dynamic-routing.md ├── hello-world.md ├── last-post.md └── preview.md ├── components ├── alert.tsx ├── avatar.tsx ├── container.tsx ├── cover-image.tsx ├── date-formatter.tsx ├── footer.tsx ├── header.tsx ├── hero-post.tsx ├── intro.tsx ├── layout.tsx ├── markdown-styles.module.css ├── meta.tsx ├── more-stories.tsx ├── post-body.tsx ├── post-header.tsx ├── post-preview.tsx ├── post-title.tsx ├── post-views.tsx └── section-separator.tsx ├── config └── mongodb.ts ├── lib ├── api.ts ├── constants.ts ├── fetcher.ts └── markdownToHtml.ts ├── next-env.d.ts ├── package.json ├── pages ├── _app.tsx ├── _document.tsx ├── api │ ├── page-views-preview.ts │ └── page-views.ts ├── index.tsx └── posts │ └── [slug].tsx ├── postcss.config.js ├── public ├── assets │ └── blog │ │ ├── authors │ │ ├── jj.jpeg │ │ ├── joe.jpeg │ │ └── tim.jpeg │ │ ├── dynamic-routing │ │ └── cover.jpg │ │ ├── hello-world │ │ └── cover.jpg │ │ ├── last-post │ │ └── cover.jpeg │ │ └── preview │ │ └── cover.jpg └── favicon │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── browserconfig.xml │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── mstile-150x150.png │ ├── safari-pinned-tab.svg │ └── site.webmanifest ├── styles └── index.css ├── tailwind.config.js ├── tsconfig.json ├── types ├── author.ts └── post.ts └── yarn.lock /.env.local.sample: -------------------------------------------------------------------------------- 1 | ## pegue esses dados no Mongo Atlas ;) 2 | MONGODB_URI= 3 | MONGODB_DB= 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 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | -------------------------------------------------------------------------------- /@types/remark-html.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'remark-html' 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Next.js](https://assets.vercel.com/image/upload/v1538361091/repositories/next-js/next-js.png)](https://nextjs.org) 2 | 3 |

4 | Projeto   |    5 | Tecnologias   |    6 | Hospedagem   |    7 | Playground   |    8 |

9 | 10 |

11 | License 12 | 13 | Stars 14 |

15 | 16 |
17 | 18 | 19 | ## 💻 Projeto 20 | 21 | Criamos um Blog com NextJS e fizemos um post no [blog da Rocketseat](http://blog.rocketseat.com.br/) 💜 22 | 23 | 24 | ## 🚀 Tecnologias 25 | 26 | Esse projeto foi desenvolvido utilizando as seguintes tecnologias: 27 | 28 | - [NextJS](https://nextjs.org/) 29 | - [MongoDB](https://expressjs.com/pt-br/) 30 | - [React](https://reactjs.org/) 31 | 32 | ## 🌐 Hospedagem 33 | 34 | - [Mongo Atlas](https://cloud.mongodb.com/) 35 | - [Vercel](https://vercel.com/dashboard) 36 | 37 | ## 🎮 Playground 38 | 39 | - [Site](http://blog-rocketseat.vercel.app/) 40 | - [API](https://blog-rocketseat.vercel.app/api/page-views-preview?id=1) 41 | 42 | 43 | ## 📝 Licença 44 | 45 | Fique a vontade <3 46 | 47 | --- 48 | 49 |

Desenvolvido com 💜 por Thiago Marinho | AX @ Rocketseat

50 | 51 | 52 | -------------------------------------------------------------------------------- /_posts/dynamic-routing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Dynamic Routing and Static Generation' 3 | excerpt: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus.' 4 | coverImage: '/assets/blog/dynamic-routing/cover.jpg' 5 | date: '2020-03-16T05:35:07.322Z' 6 | author: 7 | name: JJ Kasper 8 | picture: '/assets/blog/authors/jj.jpeg' 9 | ogImage: 10 | url: '/assets/blog/dynamic-routing/cover.jpg' 11 | --- 12 | 13 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus. Praesent elementum facilisis leo vel fringilla. Congue mauris rhoncus aenean vel. Egestas sed tempus urna et pharetra pharetra massa massa ultricies. 14 | 15 | Venenatis cras sed felis eget velit. Consectetur libero id faucibus nisl tincidunt. Gravida in fermentum et sollicitudin ac orci phasellus egestas tellus. Volutpat consequat mauris nunc congue nisi vitae. Id aliquet risus feugiat in ante metus dictum at tempor. Sed blandit libero volutpat sed cras. Sed odio morbi quis commodo odio aenean sed adipiscing. Velit euismod in pellentesque massa placerat. Mi bibendum neque egestas congue quisque egestas diam in arcu. Nisi lacus sed viverra tellus in. Nibh cras pulvinar mattis nunc sed. Luctus accumsan tortor posuere ac ut consequat semper viverra. Fringilla ut morbi tincidunt augue interdum velit euismod. 16 | 17 | ## Lorem Ipsum 18 | 19 | Tristique senectus et netus et malesuada fames ac turpis. Ridiculous mus mauris vitae ultricies leo integer malesuada nunc vel. In mollis nunc sed id semper. Egestas tellus rutrum tellus pellentesque. Phasellus vestibulum lorem sed risus ultricies tristique nulla. Quis blandit turpis cursus in hac habitasse platea dictumst quisque. Eros donec ac odio tempor orci dapibus ultrices. Aliquam sem et tortor consequat id porta nibh. Adipiscing elit duis tristique sollicitudin nibh sit amet commodo nulla. Diam vulputate ut pharetra sit amet. Ut tellus elementum sagittis vitae et leo. Arcu non odio euismod lacinia at quis risus sed vulputate. 20 | -------------------------------------------------------------------------------- /_posts/hello-world.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Learn How to Pre-render Pages Using Static Generation with Next.js' 3 | excerpt: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus.' 4 | coverImage: '/assets/blog/hello-world/cover.jpg' 5 | date: '2020-03-16T05:35:07.322Z' 6 | author: 7 | name: Tim Neutkens 8 | picture: '/assets/blog/authors/tim.jpeg' 9 | ogImage: 10 | url: '/assets/blog/hello-world/cover.jpg' 11 | --- 12 | 13 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus. Praesent elementum facilisis leo vel fringilla. Congue mauris rhoncus aenean vel. Egestas sed tempus urna et pharetra pharetra massa massa ultricies. 14 | 15 | Venenatis cras sed felis eget velit. Consectetur libero id faucibus nisl tincidunt. Gravida in fermentum et sollicitudin ac orci phasellus egestas tellus. Volutpat consequat mauris nunc congue nisi vitae. Id aliquet risus feugiat in ante metus dictum at tempor. Sed blandit libero volutpat sed cras. Sed odio morbi quis commodo odio aenean sed adipiscing. Velit euismod in pellentesque massa placerat. Mi bibendum neque egestas congue quisque egestas diam in arcu. Nisi lacus sed viverra tellus in. Nibh cras pulvinar mattis nunc sed. Luctus accumsan tortor posuere ac ut consequat semper viverra. Fringilla ut morbi tincidunt augue interdum velit euismod. 16 | 17 | ## Lorem Ipsum 18 | 19 | Tristique senectus et netus et malesuada fames ac turpis. Ridiculous mus mauris vitae ultricies leo integer malesuada nunc vel. In mollis nunc sed id semper. Egestas tellus rutrum tellus pellentesque. Phasellus vestibulum lorem sed risus ultricies tristique nulla. Quis blandit turpis cursus in hac habitasse platea dictumst quisque. Eros donec ac odio tempor orci dapibus ultrices. Aliquam sem et tortor consequat id porta nibh. Adipiscing elit duis tristique sollicitudin nibh sit amet commodo nulla. Diam vulputate ut pharetra sit amet. Ut tellus elementum sagittis vitae et leo. Arcu non odio euismod lacinia at quis risus sed vulputate. 20 | -------------------------------------------------------------------------------- /_posts/last-post.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Last post for demonstration' 3 | excerpt: 'Last Post is ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus.' 4 | coverImage: '/assets/blog/last-post/cover.jpeg' 5 | date: '2020-10-22T06:35:07.322Z' 6 | author: 7 | name: JJ Kasper 8 | picture: '/assets/blog/authors/jj.jpeg' 9 | ogImage: 10 | url: '/assets/blog/last-post/cover.jpeg' 11 | --- 12 | 13 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus. Praesent elementum facilisis leo vel fringilla. Congue mauris rhoncus aenean vel. Egestas sed tempus urna et pharetra pharetra massa massa ultricies. 14 | 15 | Venenatis cras sed felis eget velit. Consectetur libero id faucibus nisl tincidunt. Gravida in fermentum et sollicitudin ac orci phasellus egestas tellus. Volutpat consequat mauris nunc congue nisi vitae. Id aliquet risus feugiat in ante metus dictum at tempor. Sed blandit libero volutpat sed cras. Sed odio morbi quis commodo odio aenean sed adipiscing. Velit euismod in pellentesque massa placerat. Mi bibendum neque egestas congue quisque egestas diam in arcu. Nisi lacus sed viverra tellus in. Nibh cras pulvinar mattis nunc sed. Luctus accumsan tortor posuere ac ut consequat semper viverra. Fringilla ut morbi tincidunt augue interdum velit euismod. 16 | 17 | ## Lorem Ipsum 18 | 19 | Tristique senectus et netus et malesuada fames ac turpis. Ridiculous mus mauris vitae ultricies leo integer malesuada nunc vel. In mollis nunc sed id semper. Egestas tellus rutrum tellus pellentesque. Phasellus vestibulum lorem sed risus ultricies tristique nulla. Quis blandit turpis cursus in hac habitasse platea dictumst quisque. Eros donec ac odio tempor orci dapibus ultrices. Aliquam sem et tortor consequat id porta nibh. Adipiscing elit duis tristique sollicitudin nibh sit amet commodo nulla. Diam vulputate ut pharetra sit amet. Ut tellus elementum sagittis vitae et leo. Arcu non odio euismod lacinia at quis risus sed vulputate. 20 | 21 | 22 | Thank you for reading! -------------------------------------------------------------------------------- /_posts/preview.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Preview Mode for Static Generation' 3 | excerpt: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus.' 4 | coverImage: '/assets/blog/preview/cover.jpg' 5 | date: '2020-03-16T05:35:07.322Z' 6 | author: 7 | name: Joe Haddad 8 | picture: '/assets/blog/authors/joe.jpeg' 9 | ogImage: 10 | url: '/assets/blog/preview/cover.jpg' 11 | --- 12 | 13 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus. Praesent elementum facilisis leo vel fringilla. Congue mauris rhoncus aenean vel. Egestas sed tempus urna et pharetra pharetra massa massa ultricies. 14 | 15 | Venenatis cras sed felis eget velit. Consectetur libero id faucibus nisl tincidunt. Gravida in fermentum et sollicitudin ac orci phasellus egestas tellus. Volutpat consequat mauris nunc congue nisi vitae. Id aliquet risus feugiat in ante metus dictum at tempor. Sed blandit libero volutpat sed cras. Sed odio morbi quis commodo odio aenean sed adipiscing. Velit euismod in pellentesque massa placerat. Mi bibendum neque egestas congue quisque egestas diam in arcu. Nisi lacus sed viverra tellus in. Nibh cras pulvinar mattis nunc sed. Luctus accumsan tortor posuere ac ut consequat semper viverra. Fringilla ut morbi tincidunt augue interdum velit euismod. 16 | 17 | ## Lorem Ipsum 18 | 19 | Tristique senectus et netus et malesuada fames ac turpis. Ridiculous mus mauris vitae ultricies leo integer malesuada nunc vel. In mollis nunc sed id semper. Egestas tellus rutrum tellus pellentesque. Phasellus vestibulum lorem sed risus ultricies tristique nulla. Quis blandit turpis cursus in hac habitasse platea dictumst quisque. Eros donec ac odio tempor orci dapibus ultrices. Aliquam sem et tortor consequat id porta nibh. Adipiscing elit duis tristique sollicitudin nibh sit amet commodo nulla. Diam vulputate ut pharetra sit amet. Ut tellus elementum sagittis vitae et leo. Arcu non odio euismod lacinia at quis risus sed vulputate. 20 | -------------------------------------------------------------------------------- /components/alert.tsx: -------------------------------------------------------------------------------- 1 | import Container from './container' 2 | import cn from 'classnames' 3 | import { EXAMPLE_PATH } from '../lib/constants' 4 | 5 | type Props = { 6 | preview?: boolean 7 | } 8 | 9 | const Alert = ({ preview }: Props) => { 10 | return ( 11 |
17 | 18 |
19 | {preview ? ( 20 | <> 21 | This page is a preview.{' '} 22 | 26 | Click here 27 | {' '} 28 | to exit preview mode. 29 | 30 | ) : ( 31 | <> 32 | The source code for this blog is{' '} 33 | 37 | available on GitHub 38 | 39 | . 40 | 41 | )} 42 |
43 |
44 |
45 | ) 46 | } 47 | 48 | export default Alert 49 | -------------------------------------------------------------------------------- /components/avatar.tsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | 3 | type Props = { 4 | name: string; 5 | picture: string; 6 | }; 7 | 8 | const Avatar = ({ name, picture }: Props) => { 9 | return ( 10 |
11 | {name} 19 |
{name}
20 |
21 | ); 22 | }; 23 | 24 | export default Avatar; 25 | -------------------------------------------------------------------------------- /components/container.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode, FunctionComponent } from 'react' 2 | 3 | type Props = { 4 | children?: ReactNode 5 | } 6 | 7 | const Container: FunctionComponent = ({ children }: Props) => { 8 | return
{children}
9 | } 10 | 11 | export default Container 12 | -------------------------------------------------------------------------------- /components/cover-image.tsx: -------------------------------------------------------------------------------- 1 | import cn from "classnames"; 2 | import Link from "next/link"; 3 | import Image from "next/image"; 4 | 5 | type Props = { 6 | title: string; 7 | src: string; 8 | slug?: string; 9 | }; 10 | 11 | const CoverImage = ({ title, src, slug }: Props) => { 12 | const image = ( 13 | {`Cover 23 | ); 24 | return ( 25 |
26 | {slug ? ( 27 | 28 | {image} 29 | 30 | ) : ( 31 | image 32 | )} 33 |
34 | ); 35 | }; 36 | 37 | export default CoverImage; 38 | -------------------------------------------------------------------------------- /components/date-formatter.tsx: -------------------------------------------------------------------------------- 1 | import { parseISO, format } from 'date-fns' 2 | 3 | type Props = { 4 | dateString: string 5 | } 6 | 7 | const DateFormatter = ({ dateString }: Props) => { 8 | const date = parseISO(dateString) 9 | return 10 | } 11 | 12 | export default DateFormatter 13 | -------------------------------------------------------------------------------- /components/footer.tsx: -------------------------------------------------------------------------------- 1 | import Container from "./container"; 2 | import { EXAMPLE_PATH } from "../lib/constants"; 3 | 4 | const Footer = () => { 5 | return ( 6 | 29 | ); 30 | }; 31 | 32 | export default Footer; 33 | -------------------------------------------------------------------------------- /components/header.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | 3 | const Header = () => { 4 | return ( 5 |

6 | 7 | Blog da Rocketseat 8 | 9 | . 10 |

11 | ); 12 | }; 13 | 14 | export default Header; 15 | -------------------------------------------------------------------------------- /components/hero-post.tsx: -------------------------------------------------------------------------------- 1 | import Avatar from "./avatar"; 2 | import DateFormatter from "./date-formatter"; 3 | import CoverImage from "./cover-image"; 4 | import Link from "next/link"; 5 | import Author from "../types/author"; 6 | import { useFetch } from "@/lib/fetcher"; 7 | import PostViews from "./post-views"; 8 | 9 | type Props = { 10 | title: string; 11 | coverImage: string; 12 | date: string; 13 | excerpt: string; 14 | author: Author; 15 | slug: string; 16 | }; 17 | 18 | const HeroPost = ({ 19 | title, 20 | coverImage, 21 | date, 22 | excerpt, 23 | author, 24 | slug, 25 | }: Props) => { 26 | const { data } = useFetch(`/api/page-views-preview?id=${slug}`, true); 27 | 28 | const views = data?.total; 29 | console.log(views); 30 | 31 | return ( 32 |
33 |
34 | 35 |
36 |
37 |
38 |

39 | 40 | {title} 41 | 42 |

43 |
44 | -{" "} 45 | {`${views >= 0 ? views : "..."} views`} 46 |
47 |
48 |
49 |

{excerpt}

50 | 51 |
52 |
53 |
54 | ); 55 | }; 56 | 57 | export default HeroPost; 58 | -------------------------------------------------------------------------------- /components/intro.tsx: -------------------------------------------------------------------------------- 1 | import { CMS_NAME } from "../lib/constants"; 2 | 3 | const Intro = () => { 4 | return ( 5 |
6 |

7 | Blog da Rocketseat. 8 |

9 |

10 | A statically generated blog example using{" "} 11 | 15 | Next.js 16 | {" "} 17 | and {CMS_NAME}. 18 |

19 |
20 | ); 21 | }; 22 | 23 | export default Intro; 24 | -------------------------------------------------------------------------------- /components/layout.tsx: -------------------------------------------------------------------------------- 1 | import Alert from './alert' 2 | import Footer from './footer' 3 | import Meta from './meta' 4 | 5 | type Props = { 6 | preview?: boolean 7 | children: React.ReactNode 8 | } 9 | 10 | const Layout = ({ preview, children }: Props) => { 11 | return ( 12 | <> 13 | 14 |
15 | 16 |
{children}
17 |
18 |