├── .gitignore ├── README.md ├── src ├── data │ └── data.js └── components │ └── nav.jsx ├── next.config.js ├── pages ├── api │ └── note │ │ ├── index.js │ │ └── [id].js ├── _app.jsx ├── index.jsx └── notes │ ├── [id].jsx │ └── index.jsx ├── theme.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | public 4 | .next 5 | .env 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Next.js course 2 | > Learn Next.js 3 | 4 | Follow along with [the course](https://hendrixer.github.io/nextjs-course/) 5 | -------------------------------------------------------------------------------- /src/data/data.js: -------------------------------------------------------------------------------- 1 | const notes = new Array(15) 2 | .fill(1) 3 | .map((_, i) => ({ 4 | id: Date.now() + i, 5 | title: `Note ${i}` 6 | })) 7 | 8 | module.exports = notes 9 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | const nextEnv = require('next-env') 2 | const dotenvLoad = require('dotenv-load') 3 | 4 | dotenvLoad() 5 | 6 | const withNextEnv = nextEnv() 7 | module.exports = withNextEnv() 8 | -------------------------------------------------------------------------------- /pages/api/note/index.js: -------------------------------------------------------------------------------- 1 | import nc from 'next-connect' 2 | import notes from '../../../src/data/data' 3 | 4 | const handler = nc() 5 | .get((req, res) => { 6 | res.json({data: notes}) 7 | }) 8 | .post((req, res) => { 9 | const id = Date.now() 10 | const note = {...req.body, id} 11 | 12 | notes.push(note) 13 | res.json({data: note}) 14 | }) 15 | 16 | 17 | export default handler 18 | -------------------------------------------------------------------------------- /pages/_app.jsx: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx } from 'theme-ui' 3 | import { ThemeProvider } from 'theme-ui' 4 | import theme from '../theme' 5 | import Nav from '../src/components/nav' 6 | 7 | export default function App({ Component, pageProps }) { 8 | return ( 9 | 10 |
11 |
14 |
15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /theme.js: -------------------------------------------------------------------------------- 1 | import { roboto } from '@theme-ui/presets' 2 | 3 | const theme = { 4 | ...roboto, 5 | containers: { 6 | card: { 7 | boxShadow: '0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24)', 8 | border: '1px solid', 9 | borderColor: 'muted', 10 | borderRadius: '4px', 11 | p: 2, 12 | }, 13 | page: { 14 | width: '100%', 15 | maxWidth: '960px', 16 | m: 0, 17 | mx: 'auto', 18 | } 19 | }, 20 | styles: { 21 | ...roboto.styles 22 | } 23 | } 24 | 25 | export default theme 26 | -------------------------------------------------------------------------------- /pages/index.jsx: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx } from 'theme-ui' 3 | import Link from 'next/link' 4 | 5 | export default ({content}) => ( 6 |
7 |
8 |

{content.title}

9 |
10 |
11 | ) 12 | 13 | 14 | export async function getStaticProps() { 15 | return { 16 | props: { 17 | content: { 18 | title: 'Look at my note app tho' 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "author": "Scott Moss ", 6 | "license": "MIT", 7 | "dependencies": { 8 | "@theme-ui/presets": "^0.3.0", 9 | "body-parser": "^1.19.0", 10 | "dotenv-load": "^2.0.0", 11 | "next": "^9.5.0", 12 | "next-connect": "^0.8.1", 13 | "next-env": "^1.1.1", 14 | "react": "^16.13.1", 15 | "react-dom": "^16.13.1", 16 | "theme-ui": "^0.3.1" 17 | }, 18 | "scripts": { 19 | "dev": "next", 20 | "build": "next build", 21 | "start": "next start" 22 | }, 23 | "devDependencies": {} 24 | } 25 | -------------------------------------------------------------------------------- /src/components/nav.jsx: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx } from 'theme-ui' 3 | import Link from 'next/link' 4 | 5 | const Nav = () => ( 6 |
7 | 18 |
19 | ) 20 | 21 | export default Nav 22 | -------------------------------------------------------------------------------- /pages/notes/[id].jsx: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx } from 'theme-ui' 3 | import { useRouter } from 'next/router' 4 | import Link from 'next/link' 5 | 6 | const Note = () => { 7 | const router = useRouter() 8 | const { id }= router.query 9 | 10 | return ( 11 |
12 |

Note: {id}

13 |
14 | ) 15 | } 16 | 17 | export default Note 18 | 19 | export async function getServerSideProps({params, req, res}) { 20 | const response = await fetch(`http://localhost:3000/api/note/${params.id}`) 21 | 22 | if (!response.ok) { 23 | res.writeHead(302, { Location: '/notes' }) 24 | res.end() 25 | return {props: {}} 26 | } 27 | 28 | const {data} = await response.json() 29 | 30 | 31 | if (data) { 32 | return { 33 | props: {note: data} 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /pages/notes/index.jsx: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx } from 'theme-ui' 3 | import Link from 'next/link' 4 | 5 | export default ({notes}) => { 6 | return ( 7 |
8 |

My Notes

9 | 10 |
11 | {notes.map(note => ( 12 |
13 | 14 | 15 |
16 | {note.title} 17 |
18 |
19 | 20 |
21 | ))} 22 |
23 |
24 | ) 25 | } 26 | 27 | 28 | export async function getServerSideProps() { 29 | const res = await fetch(`http://localhost:3000/api/note`) 30 | const {data} = await res.json() 31 | 32 | return { 33 | props: {notes: data} 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /pages/api/note/[id].js: -------------------------------------------------------------------------------- 1 | import nc from 'next-connect' 2 | import notes from '../../../src/data/data' 3 | 4 | const getNote = id => notes.find(n => n.id === parseInt(id)) 5 | 6 | const handler = nc() 7 | .get((req, res) => { 8 | 9 | const note = getNote(req.query.id) 10 | 11 | if (!note) { 12 | res.status(404) 13 | res.end() 14 | return 15 | } 16 | 17 | res.json({data: note}) 18 | }) 19 | .patch((req, res) => { 20 | const note = getNote(req.query.id) 21 | 22 | if (!note) { 23 | res.status(404) 24 | res.end() 25 | return 26 | } 27 | 28 | const i = notes.findIndex(n => n.id === parseInt(req.query.id)) 29 | const updated = {...note, ...req.body} 30 | 31 | notes[i] = updated 32 | res.json({data: updated}) 33 | }) 34 | .delete((req, res) => { 35 | const note = getNote(req.query.id) 36 | 37 | if (!note) { 38 | res.status(404) 39 | res.end() 40 | return 41 | } 42 | const i = notes.findIndex(n => n.id === parseInt(req.query.id)) 43 | 44 | notes.splice(i, 1) 45 | 46 | res.json({data: req.query.id}) 47 | }) 48 | 49 | 50 | export default handler 51 | --------------------------------------------------------------------------------