├── .babelrc ├── .env.local.example ├── .gitignore ├── README.md ├── assets └── images │ └── logo │ ├── index.js │ └── rocketseat.svg ├── lib └── api-prismic.ts ├── next-env.d.ts ├── package.json ├── pages ├── _app.tsx ├── _document.tsx ├── api │ └── hello.js ├── index.tsx └── posts │ └── [id].tsx ├── public ├── favicon.ico └── vercel.svg ├── styles ├── Home.module.css ├── Home.ts └── globals.css ├── tsconfig.json └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["next/babel"], 3 | "plugins": [["styled-components", { "ssr": true }]] 4 | } -------------------------------------------------------------------------------- /.env.local.example: -------------------------------------------------------------------------------- 1 | PRISMIC_REPOSITORY_NAME= 2 | PRISMIC_API_TOKEN= 3 | PRISMIC_LOCALE= 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/import/git?s=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fhello-world&env=PRISMIC_API_TOKEN,PRISMIC_REPOSITORY_NAME,PRISMIC_LOCALE&envDescription=Reference&envLink=https%3A%2F%2Fgithub.com%2FRocketseat%2Fcontrib-nextjs%2Fblob%2F54881701f7c22cb22751d23dadf12b9cf5ac4231%2Flib%2Fapi-prismic.ts) 4 | 5 | ## Getting Started 6 | 7 | First, run the development server: 8 | 9 | ```bash 10 | npm run dev 11 | # or 12 | yarn dev 13 | ``` 14 | 15 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 16 | 17 | You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. 18 | 19 | ## Learn More 20 | 21 | To learn more about Next.js, take a look at the following resources: 22 | 23 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 24 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 25 | 26 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 27 | 28 | ## Deploy on Vercel 29 | 30 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/import?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 31 | 32 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 33 | -------------------------------------------------------------------------------- /assets/images/logo/index.js: -------------------------------------------------------------------------------- 1 | export {default as RocketLogo} from './rocketseat.svg' -------------------------------------------------------------------------------- /assets/images/logo/rocketseat.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/api-prismic.ts: -------------------------------------------------------------------------------- 1 | import Prismic from 'prismic-javascript' 2 | 3 | const PRISMIC_URL = `https://${process.env.PRISMIC_REPOSITORY_NAME}.prismic.io` 4 | 5 | const PrismicClient = Prismic.client(`${PRISMIC_URL}/api/v2`, { 6 | accessToken: process.env.PRISMIC_API_TOKEN, 7 | }); 8 | 9 | const GRAPHQL_API_URL = `${PRISMIC_URL}/graphql` 10 | 11 | export async function fetchAPI(query, variables): Promise { 12 | const prismicApi = await PrismicClient.getApi(); 13 | 14 | const res = await fetch( 15 | `${GRAPHQL_API_URL}?query=${query}&variables=${JSON.stringify(variables)}`, 16 | { 17 | headers: { 18 | 'Prismic-Ref': prismicApi.masterRef.ref, 19 | 'Content-Type': 'application/json', 20 | 'Accept-Language': process.env.PRISMIC_LOCALE, 21 | Authorization: `Token ${process.env.PRISMIC_API_TOKEN}`, 22 | }, 23 | } 24 | ); 25 | 26 | const { data } = await res.json(); 27 | 28 | return data; 29 | } -------------------------------------------------------------------------------- /next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blogcontrib", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start" 9 | }, 10 | "dependencies": { 11 | "next": "9.5.2", 12 | "prismic-javascript": "^3.0.1", 13 | "prismic-reactjs": "^1.3.2", 14 | "react": "16.13.1", 15 | "react-dom": "16.13.1", 16 | "styled-components": "^5.1.1" 17 | }, 18 | "devDependencies": { 19 | "@types/node": "^14.0.27", 20 | "@types/react": "^16.9.46", 21 | "babel-plugin-styled-components": "^1.11.1", 22 | "typescript": "^3.9.7" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import '../styles/globals.css' 2 | 3 | function MyApp({ Component, pageProps }) { 4 | return 5 | } 6 | 7 | export default MyApp 8 | -------------------------------------------------------------------------------- /pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import Document from 'next/document' 2 | import { ServerStyleSheet } from 'styled-components' 3 | 4 | export default class MyDocument extends Document { 5 | static async getInitialProps(ctx) { 6 | const sheet = new ServerStyleSheet() 7 | const originalRenderPage = ctx.renderPage 8 | 9 | try { 10 | ctx.renderPage = () => 11 | originalRenderPage({ 12 | enhanceApp: (App) => (props) => 13 | sheet.collectStyles(), 14 | }) 15 | 16 | const initialProps = await Document.getInitialProps(ctx) 17 | return { 18 | ...initialProps, 19 | styles: ( 20 | <> 21 | {initialProps.styles} 22 | {sheet.getStyleElement()} 23 | 24 | ), 25 | } 26 | } finally { 27 | sheet.seal() 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /pages/api/hello.js: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | 3 | export default (req, res) => { 4 | res.statusCode = 200 5 | res.json({ name: 'John Doe' }) 6 | } 7 | -------------------------------------------------------------------------------- /pages/index.tsx: -------------------------------------------------------------------------------- 1 | import Head from 'next/head' 2 | import {Container, TitleContainer} from '../styles/Home' 3 | import {RocketLogo} from '../assets/images/logo' 4 | import Link from 'next/link' 5 | 6 | import { fetchAPI } from '../lib/api-prismic'; 7 | 8 | interface Post { 9 | node: { 10 | _meta: { 11 | uid: string; 12 | } 13 | title: string; 14 | thumbnail: { 15 | url: string; 16 | }; 17 | content: string; 18 | } 19 | } 20 | 21 | interface HomeProps { 22 | posts: Post[]; 23 | } 24 | 25 | export default function Home({ posts }: HomeProps) { 26 | return ( 27 | 28 | 29 | Rocketseat | Blog Next.JS 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 49 | 50 | ) 51 | } 52 | 53 | export async function getServerSideProps() { 54 | const posts = await fetchAPI(` 55 | query { 56 | allPosts { 57 | edges { 58 | node{ 59 | _meta { 60 | uid 61 | } 62 | title 63 | thumbnail 64 | content 65 | } 66 | } 67 | } 68 | } 69 | `, {}); 70 | 71 | return { 72 | props: { 73 | posts: posts.allPosts.edges, 74 | } 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /pages/posts/[id].tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { GetStaticPropsContext } from 'next'; 3 | import { RichText, RichTextBlock } from 'prismic-reactjs'; 4 | import { fetchAPI } from '../../lib/api-prismic'; 5 | 6 | interface PostProps { 7 | post: { 8 | title: string; 9 | thumbnail: { 10 | url: string; 11 | }; 12 | content: RichTextBlock[]; 13 | }; 14 | } 15 | 16 | function Post({ post }: PostProps) { 17 | console.log(post); 18 | 19 | return ( 20 |
21 |

{post.title}

22 | 23 | 24 | {RichText.render(post.content)} 25 |
26 | ); 27 | } 28 | 29 | export async function getStaticProps(ctx: GetStaticPropsContext) { 30 | const post = await fetchAPI( 31 | ` 32 | query($slug: String!, $lang: String!) { 33 | post(uid: $slug, lang: $lang) { 34 | title 35 | thumbnail 36 | content 37 | } 38 | } 39 | `, 40 | { 41 | slug: ctx.params.id, 42 | lang: 'pt-br', 43 | } 44 | ); 45 | 46 | return { 47 | props: { 48 | post: post.post, 49 | }, 50 | revalidate: 1, 51 | }; 52 | } 53 | 54 | export async function getStaticPaths() { 55 | const { 56 | allPosts: { edges }, 57 | } = await fetchAPI( 58 | ` 59 | query { 60 | allPosts { 61 | edges { 62 | node { 63 | _meta { 64 | uid 65 | } 66 | } 67 | } 68 | } 69 | } 70 | `, 71 | {} 72 | ); 73 | 74 | return { 75 | paths: edges.map(({ node }) => `/posts/${node._meta.uid}`) || [], 76 | fallback: false, 77 | }; 78 | } 79 | 80 | export default Post; 81 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rocketseat-content/contrib-nextjs/a6ad30078601a05c4aaf07c45d26672e03b799e0/public/favicon.ico -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /styles/Home.module.css: -------------------------------------------------------------------------------- 1 | .list { 2 | 3 | } 4 | 5 | .image { 6 | 7 | } 8 | 9 | .listItem { 10 | 11 | } 12 | 13 | .listItem + .listItem { 14 | margin-top: 16px; 15 | } 16 | 17 | .listItem:hover { 18 | 19 | } 20 | 21 | .listItem 22 | 23 | .listLink { 24 | 25 | } 26 | 27 | .footer { 28 | width: 100%; 29 | height: 100px; 30 | border-top: 1px solid #eaeaea; 31 | display: flex; 32 | justify-content: center; 33 | align-items: center; 34 | } 35 | 36 | .footer img { 37 | margin-left: 0.5rem; 38 | } -------------------------------------------------------------------------------- /styles/Home.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Container = styled.div` 4 | min-height: 100vh; 5 | padding: 0 0.5rem; 6 | display: flex; 7 | flex-direction: column; 8 | justify-content: center; 9 | align-items: center; 10 | 11 | > ul { 12 | list-style-type: none; 13 | 14 | > li { 15 | padding: 12px 20px; 16 | background: #312e38; 17 | border-radius: 4px; 18 | box-shadow: 0 12px 10px -8px rgba(0,0,0,0.5); 19 | transition: 250ms ease-in-out; 20 | 21 | + li { 22 | margin-top: 16px; 23 | } 24 | 25 | :hover { 26 | background: #3b3843; 27 | color: #fff; 28 | transform: scale(1.01); 29 | box-shadow: 0 16px 16px -8px rgba(0,0,0,0.3); 30 | } 31 | 32 | :active { 33 | background: #27242d; 34 | transform: scale(0.99); 35 | box-shadow: 0 4px 4px -2px rgba(0,0,0,0.8); 36 | color: #d9d9d9; 37 | } 38 | 39 | a { 40 | display: flex; 41 | align-items: center; 42 | } 43 | 44 | img { 45 | filter: invert(1) hue-rotate(108deg) opacity(0.9); 46 | margin-right: 16px; 47 | } 48 | } 49 | 50 | } 51 | `; 52 | 53 | export const TitleContainer = styled.header` 54 | margin-bottom: 40px; 55 | 56 | > h1 { 57 | font-weight: 500; 58 | color: #fff; 59 | } 60 | `; -------------------------------------------------------------------------------- /styles/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 6 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 7 | 8 | background-color: #1a1721; 9 | color: #e6e6e6; 10 | } 11 | 12 | img { 13 | filter: invert(1) hue-rotate(108deg) opacity(0.9); 14 | } 15 | 16 | a { 17 | color: inherit; 18 | text-decoration: none; 19 | } 20 | 21 | * { 22 | box-sizing: border-box; 23 | } 24 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "strict": false, 12 | "forceConsistentCasingInFileNames": true, 13 | "noEmit": true, 14 | "esModuleInterop": true, 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "resolveJsonModule": true, 18 | "isolatedModules": true, 19 | "jsx": "preserve" 20 | }, 21 | "include": [ 22 | "next-env.d.ts", 23 | "**/*.ts", 24 | "**/*.tsx" 25 | ], 26 | "exclude": [ 27 | "node_modules" 28 | ] 29 | } 30 | --------------------------------------------------------------------------------