├── .eslintrc.js ├── .github ├── dependabot.yml └── workflows │ └── test.yml ├── .gitignore ├── .prettierignore ├── README.md ├── basics ├── README.md ├── api-routes-starter │ ├── .gitignore │ ├── .nvmrc │ ├── README.md │ ├── components │ │ ├── date.js │ │ ├── layout.js │ │ └── layout.module.css │ ├── lib │ │ └── posts.js │ ├── package.json │ ├── pages │ │ ├── _app.js │ │ ├── index.js │ │ └── posts │ │ │ └── [id].js │ ├── posts │ │ ├── pre-rendering.md │ │ └── ssg-ssr.md │ ├── public │ │ ├── favicon.ico │ │ └── images │ │ │ └── profile.jpg │ └── styles │ │ ├── global.css │ │ └── utils.module.css ├── assets-metadata-css-starter │ ├── .gitignore │ ├── .nvmrc │ ├── README.md │ ├── package.json │ ├── pages │ │ ├── index.js │ │ └── posts │ │ │ └── first-post.js │ ├── public │ │ ├── favicon.ico │ │ └── vercel.svg │ └── styles │ │ ├── Home.module.css │ │ └── global.css ├── basics-final │ ├── .gitignore │ ├── .nvmrc │ ├── README.md │ ├── components │ │ ├── date.js │ │ ├── layout.js │ │ └── layout.module.css │ ├── lib │ │ └── posts.js │ ├── package.json │ ├── pages │ │ ├── _app.js │ │ ├── api │ │ │ └── hello.js │ │ ├── index.js │ │ └── posts │ │ │ └── [id].js │ ├── posts │ │ ├── pre-rendering.md │ │ └── ssg-ssr.md │ ├── public │ │ ├── favicon.ico │ │ └── images │ │ │ └── profile.jpg │ └── styles │ │ ├── global.css │ │ └── utils.module.css ├── data-fetching-starter │ ├── .gitignore │ ├── .nvmrc │ ├── README.md │ ├── components │ │ ├── layout.js │ │ └── layout.module.css │ ├── package.json │ ├── pages │ │ ├── _app.js │ │ ├── index.js │ │ └── posts │ │ │ └── first-post.js │ ├── public │ │ ├── favicon.ico │ │ └── images │ │ │ └── profile.jpg │ └── styles │ │ ├── global.css │ │ └── utils.module.css ├── demo │ ├── .gitignore │ ├── .nvmrc │ ├── README.md │ ├── components │ │ ├── date.js │ │ ├── layout.js │ │ └── layout.module.css │ ├── lib │ │ └── posts.js │ ├── package.json │ ├── pages │ │ ├── _app.js │ │ ├── api │ │ │ └── hello.js │ │ ├── index.js │ │ └── posts │ │ │ └── [id].js │ ├── posts │ │ ├── pre-rendering.md │ │ └── ssg-ssr.md │ ├── public │ │ ├── favicon.ico │ │ └── images │ │ │ └── profile.jpg │ └── styles │ │ ├── global.css │ │ └── utils.module.css ├── dynamic-routes-starter │ ├── .gitignore │ ├── .nvmrc │ ├── README.md │ ├── components │ │ ├── layout.js │ │ └── layout.module.css │ ├── lib │ │ └── posts.js │ ├── package.json │ ├── pages │ │ ├── _app.js │ │ ├── index.js │ │ └── posts │ │ │ └── first-post.js │ ├── posts │ │ ├── pre-rendering.md │ │ └── ssg-ssr.md │ ├── public │ │ ├── favicon.ico │ │ └── images │ │ │ └── profile.jpg │ └── styles │ │ ├── global.css │ │ └── utils.module.css ├── dynamic-routes-step-1 │ ├── .gitignore │ ├── .nvmrc │ ├── README.md │ ├── components │ │ ├── layout.js │ │ └── layout.module.css │ ├── lib │ │ └── posts.js │ ├── package.json │ ├── pages │ │ ├── _app.js │ │ ├── index.js │ │ └── posts │ │ │ └── [id].js │ ├── posts │ │ ├── pre-rendering.md │ │ └── ssg-ssr.md │ ├── public │ │ ├── favicon.ico │ │ └── images │ │ │ └── profile.jpg │ └── styles │ │ ├── global.css │ │ └── utils.module.css ├── errors │ └── install.md ├── learn-starter │ ├── .gitignore │ ├── .nvmrc │ ├── README.md │ ├── package.json │ ├── pages │ │ └── index.js │ ├── public │ │ ├── favicon.ico │ │ └── vercel.svg │ └── styles │ │ ├── Home.module.css │ │ └── global.css ├── navigate-between-pages-starter │ ├── .gitignore │ ├── .nvmrc │ ├── README.md │ ├── package.json │ ├── pages │ │ └── index.js │ ├── public │ │ ├── favicon.ico │ │ └── vercel.svg │ └── styles │ │ ├── Home.module.css │ │ └── global.css ├── snippets │ └── link-classname-example.js └── typescript-final │ ├── .gitignore │ ├── .nvmrc │ ├── README.md │ ├── components │ ├── date.tsx │ ├── layout.module.css │ └── layout.tsx │ ├── global.d.ts │ ├── lib │ └── posts.ts │ ├── next-env.d.ts │ ├── package.json │ ├── pages │ ├── _app.tsx │ ├── api │ │ └── hello.ts │ ├── index.tsx │ └── posts │ │ └── [id].tsx │ ├── posts │ ├── pre-rendering.md │ └── ssg-ssr.md │ ├── public │ ├── favicon.ico │ └── images │ │ └── profile.jpg │ ├── styles │ ├── global.css │ └── utils.module.css │ └── tsconfig.json ├── dashboard ├── README.md ├── final-example │ ├── .env.example │ ├── .gitignore │ ├── README.md │ ├── app │ │ ├── dashboard │ │ │ ├── (overview) │ │ │ │ ├── loading.tsx │ │ │ │ └── page.tsx │ │ │ ├── customers │ │ │ │ └── page.tsx │ │ │ ├── invoices │ │ │ │ ├── [id] │ │ │ │ │ └── edit │ │ │ │ │ │ ├── not-found.tsx │ │ │ │ │ │ └── page.tsx │ │ │ │ ├── create │ │ │ │ │ └── page.tsx │ │ │ │ ├── error.tsx │ │ │ │ └── page.tsx │ │ │ └── layout.tsx │ │ ├── favicon.ico │ │ ├── layout.tsx │ │ ├── lib │ │ │ ├── actions.ts │ │ │ ├── data.ts │ │ │ ├── definitions.ts │ │ │ ├── placeholder-data.ts │ │ │ └── utils.ts │ │ ├── login │ │ │ └── page.tsx │ │ ├── opengraph-image.png │ │ ├── page.tsx │ │ ├── query │ │ │ └── route.ts │ │ ├── seed │ │ │ └── route.ts │ │ └── ui │ │ │ ├── acme-logo.tsx │ │ │ ├── button.tsx │ │ │ ├── customers │ │ │ └── table.tsx │ │ │ ├── dashboard │ │ │ ├── cards.tsx │ │ │ ├── latest-invoices.tsx │ │ │ ├── nav-links.tsx │ │ │ ├── revenue-chart.tsx │ │ │ └── sidenav.tsx │ │ │ ├── fonts.ts │ │ │ ├── global.css │ │ │ ├── invoices │ │ │ ├── breadcrumbs.tsx │ │ │ ├── buttons.tsx │ │ │ ├── create-form.tsx │ │ │ ├── edit-form.tsx │ │ │ ├── pagination.tsx │ │ │ ├── status.tsx │ │ │ └── table.tsx │ │ │ ├── login-form.tsx │ │ │ ├── search.tsx │ │ │ └── skeletons.tsx │ ├── auth.config.ts │ ├── auth.ts │ ├── middleware.ts │ ├── next.config.ts │ ├── package.json │ ├── pnpm-lock.yaml │ ├── postcss.config.js │ ├── public │ │ ├── customers │ │ │ ├── amy-burns.png │ │ │ ├── balazs-orban.png │ │ │ ├── delba-de-oliveira.png │ │ │ ├── evil-rabbit.png │ │ │ ├── lee-robinson.png │ │ │ └── michael-novotny.png │ │ ├── hero-desktop.png │ │ └── hero-mobile.png │ ├── tailwind.config.ts │ └── tsconfig.json └── starter-example │ ├── .env.example │ ├── .gitignore │ ├── README.md │ ├── app │ ├── layout.tsx │ ├── lib │ │ ├── data.ts │ │ ├── definitions.ts │ │ ├── placeholder-data.ts │ │ └── utils.ts │ ├── page.tsx │ ├── query │ │ └── route.ts │ ├── seed │ │ └── route.ts │ └── ui │ │ ├── acme-logo.tsx │ │ ├── button.tsx │ │ ├── customers │ │ └── table.tsx │ │ ├── dashboard │ │ ├── cards.tsx │ │ ├── latest-invoices.tsx │ │ ├── nav-links.tsx │ │ ├── revenue-chart.tsx │ │ └── sidenav.tsx │ │ ├── global.css │ │ ├── invoices │ │ ├── breadcrumbs.tsx │ │ ├── buttons.tsx │ │ ├── create-form.tsx │ │ ├── edit-form.tsx │ │ ├── pagination.tsx │ │ ├── status.tsx │ │ └── table.tsx │ │ ├── login-form.tsx │ │ ├── search.tsx │ │ └── skeletons.tsx │ ├── next.config.ts │ ├── package.json │ ├── pnpm-lock.yaml │ ├── postcss.config.js │ ├── public │ ├── customers │ │ ├── amy-burns.png │ │ ├── balazs-orban.png │ │ ├── delba-de-oliveira.png │ │ ├── evil-rabbit.png │ │ ├── lee-robinson.png │ │ └── michael-novotny.png │ ├── favicon.ico │ ├── hero-desktop.png │ ├── hero-mobile.png │ └── opengraph-image.png │ ├── tailwind.config.ts │ └── tsconfig.json ├── license.md ├── package.json ├── pnpm-lock.yaml ├── prettier.config.js └── seo ├── .gitignore ├── README.md ├── components └── CodeSampleModal.js ├── countries.js ├── demo ├── .gitignore ├── README.md ├── components │ └── CodeSampleModal.js ├── countries.js ├── package.json ├── pages │ ├── _app.js │ └── index.js ├── public │ ├── favicon.ico │ ├── large-image.jpg │ └── vercel.svg └── styles │ ├── Home.module.css │ └── global.css ├── package.json ├── pages ├── _app.js └── index.js ├── public ├── favicon.ico ├── large-image.jpg └── vercel.svg └── styles ├── Home.module.css └── global.css /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['next/core-web-vitals', 'prettier'], 3 | ignorePatterns: ['**/.next/**', '**/node_modules/**'], 4 | root: true, 5 | settings: { 6 | next: { 7 | rootDir: ['basics/*/', 'dashboard/*/', 'seo/'], 8 | }, 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: 'github-actions' 4 | directory: '/' 5 | schedule: 6 | interval: 'weekly' 7 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | on: pull_request 3 | jobs: 4 | test: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - name: Cancel running workflows 8 | uses: styfle/cancel-workflow-action@0.12.1 9 | with: 10 | access_token: ${{ github.token }} 11 | - name: Checkout repo 12 | uses: actions/checkout@v4 13 | - name: Setup pnpm 14 | uses: pnpm/action-setup@v3 15 | - name: Set node version 16 | uses: actions/setup-node@v3 17 | with: 18 | cache: 'pnpm' 19 | node-version: '20' 20 | - name: Cache node_modules 21 | id: node-modules-cache 22 | uses: actions/cache@v4 23 | with: 24 | path: '**/node_modules' 25 | key: node-modules-cache-${{ hashFiles('**/pnpm-lock.yaml') }} 26 | - name: Install dependencies 27 | if: steps.node-modules-cache.outputs.cache-hit != 'true' 28 | run: pnpm install 29 | - name: Run tests 30 | run: pnpm test 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | node_modules 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/.next 2 | **/node_modules 3 | **/package-lock.json 4 | **/pnpm-lock.yaml 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Learn Next.js 2 | 3 | This repository contains starter templates and final code for [Learn Next.js](https://nextjs.org/learn) courses: 4 | 5 | - 🆕 [Learn Next.js App Router, Data Fetching, Databases, and Auth](https://nextjs.org/learn) ([demo](https://next-learn-dashboard.vercel.sh)) 6 | - [Learn Basics and TypeScript](https://nextjs.org/learn-pages-router/basics/create-nextjs-app) ([demo](https://next-learn-starter.vercel.app)) 7 | - [Learn SEO](https://nextjs.org/learn-pages-router/seo/introduction-to-seo) ([demo](https://next-seo-starter.vercel.app)) 8 | 9 | ## Contributions 10 | 11 | The code for the example apps you build using Next.js Learn live in this repository and we'd be grateful for your contributions. 12 | 13 | The course curriculum is currently not open sourced, but you can [create an issue](https://github.com/vercel/next-learn/issues/new) if you find a mistake. 14 | -------------------------------------------------------------------------------- /basics/README.md: -------------------------------------------------------------------------------- 1 | # next-learn-starter 2 | 3 | This repository contains starter templates for [Learn Next.js](https://nextjs.org/learn). 4 | 5 | The final result for the basics lesson can be found in the [demo](demo) directory and is available at: [https://next-learn-starter.vercel.app/](https://next-learn-starter.vercel.app/). 6 | -------------------------------------------------------------------------------- /basics/api-routes-starter/.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 | .env* 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | -------------------------------------------------------------------------------- /basics/api-routes-starter/.nvmrc: -------------------------------------------------------------------------------- 1 | 18 2 | -------------------------------------------------------------------------------- /basics/api-routes-starter/README.md: -------------------------------------------------------------------------------- 1 | This is a starter template for [Learn Next.js](https://nextjs.org/learn). 2 | -------------------------------------------------------------------------------- /basics/api-routes-starter/components/date.js: -------------------------------------------------------------------------------- 1 | import { parseISO, format } from 'date-fns'; 2 | 3 | export default function Date({ dateString }) { 4 | const date = parseISO(dateString); 5 | return ; 6 | } 7 | -------------------------------------------------------------------------------- /basics/api-routes-starter/components/layout.js: -------------------------------------------------------------------------------- 1 | import Head from 'next/head'; 2 | import Image from 'next/image'; 3 | import styles from './layout.module.css'; 4 | import utilStyles from '../styles/utils.module.css'; 5 | import Link from 'next/link'; 6 | 7 | const name = '[Your Name]'; 8 | export const siteTitle = 'Next.js Sample Website'; 9 | 10 | export default function Layout({ children, home }) { 11 | return ( 12 |
13 | 14 | 15 | 19 | 25 | 26 | 27 | 28 |
29 | {home ? ( 30 | <> 31 | {name} 39 |

{name}

40 | 41 | ) : ( 42 | <> 43 | 44 | {name} 52 | 53 |

54 | 55 | {name} 56 | 57 |

58 | 59 | )} 60 |
61 |
{children}
62 | {!home && ( 63 |
64 | ← Back to home 65 |
66 | )} 67 |
68 | ); 69 | } 70 | -------------------------------------------------------------------------------- /basics/api-routes-starter/components/layout.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | max-width: 36rem; 3 | padding: 0 1rem; 4 | margin: 3rem auto 6rem; 5 | } 6 | 7 | .header { 8 | display: flex; 9 | flex-direction: column; 10 | align-items: center; 11 | } 12 | 13 | .backToHome { 14 | margin: 3rem 0 0; 15 | } 16 | -------------------------------------------------------------------------------- /basics/api-routes-starter/lib/posts.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import matter from 'gray-matter'; 4 | import { remark } from 'remark'; 5 | import html from 'remark-html'; 6 | 7 | const postsDirectory = path.join(process.cwd(), 'posts'); 8 | 9 | export function getSortedPostsData() { 10 | // Get file names under /posts 11 | const fileNames = fs.readdirSync(postsDirectory); 12 | const allPostsData = fileNames.map((fileName) => { 13 | // Remove ".md" from file name to get id 14 | const id = fileName.replace(/\.md$/, ''); 15 | 16 | // Read markdown file as string 17 | const fullPath = path.join(postsDirectory, fileName); 18 | const fileContents = fs.readFileSync(fullPath, 'utf8'); 19 | 20 | // Use gray-matter to parse the post metadata section 21 | const matterResult = matter(fileContents); 22 | 23 | // Combine the data with the id 24 | return { 25 | id, 26 | ...matterResult.data, 27 | }; 28 | }); 29 | // Sort posts by date 30 | return allPostsData.sort((a, b) => { 31 | if (a.date < b.date) { 32 | return 1; 33 | } else { 34 | return -1; 35 | } 36 | }); 37 | } 38 | 39 | export function getAllPostIds() { 40 | const fileNames = fs.readdirSync(postsDirectory); 41 | return fileNames.map((fileName) => { 42 | return { 43 | params: { 44 | id: fileName.replace(/\.md$/, ''), 45 | }, 46 | }; 47 | }); 48 | } 49 | 50 | export async function getPostData(id) { 51 | const fullPath = path.join(postsDirectory, `${id}.md`); 52 | const fileContents = fs.readFileSync(fullPath, 'utf8'); 53 | 54 | // Use gray-matter to parse the post metadata section 55 | const matterResult = matter(fileContents); 56 | 57 | // Use remark to convert markdown into HTML string 58 | const processedContent = await remark() 59 | .use(html) 60 | .process(matterResult.content); 61 | const contentHtml = processedContent.toString(); 62 | 63 | // Combine the data with the id and contentHtml 64 | return { 65 | id, 66 | contentHtml, 67 | ...matterResult.data, 68 | }; 69 | } 70 | -------------------------------------------------------------------------------- /basics/api-routes-starter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "build": "next build", 5 | "dev": "next dev --turbopack", 6 | "start": "next start" 7 | }, 8 | "dependencies": { 9 | "date-fns": "^2.29.3", 10 | "gray-matter": "^4.0.3", 11 | "next": "latest", 12 | "react": "latest", 13 | "react-dom": "latest", 14 | "remark": "^14.0.2", 15 | "remark-html": "^15.0.1" 16 | }, 17 | "engines": { 18 | "node": ">=18" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /basics/api-routes-starter/pages/_app.js: -------------------------------------------------------------------------------- 1 | import '../styles/global.css'; 2 | 3 | export default function App({ Component, pageProps }) { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /basics/api-routes-starter/pages/index.js: -------------------------------------------------------------------------------- 1 | import Head from 'next/head'; 2 | import Layout, { siteTitle } from '../components/layout'; 3 | import utilStyles from '../styles/utils.module.css'; 4 | import { getSortedPostsData } from '../lib/posts'; 5 | import Link from 'next/link'; 6 | import Date from '../components/date'; 7 | 8 | export default function Home({ allPostsData }) { 9 | return ( 10 | 11 | 12 | {siteTitle} 13 | 14 |
15 |

[Your Self Introduction]

16 |

17 | (This is a sample website - you’ll be building a site like this in{' '} 18 | our Next.js tutorial.) 19 |

20 |
21 |
22 |

Blog

23 |
    24 | {allPostsData.map(({ id, date, title }) => ( 25 |
  • 26 | {title} 27 |
    28 | 29 | 30 | 31 |
  • 32 | ))} 33 |
34 |
35 |
36 | ); 37 | } 38 | 39 | export async function getStaticProps() { 40 | const allPostsData = getSortedPostsData(); 41 | return { 42 | props: { 43 | allPostsData, 44 | }, 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /basics/api-routes-starter/pages/posts/[id].js: -------------------------------------------------------------------------------- 1 | import Layout from '../../components/layout'; 2 | import { getAllPostIds, getPostData } from '../../lib/posts'; 3 | import Head from 'next/head'; 4 | import Date from '../../components/date'; 5 | import utilStyles from '../../styles/utils.module.css'; 6 | 7 | export default function Post({ postData }) { 8 | return ( 9 | 10 | 11 | {postData.title} 12 | 13 |
14 |

{postData.title}

15 |
16 | 17 |
18 |
19 |
20 |
21 | ); 22 | } 23 | 24 | export async function getStaticPaths() { 25 | const paths = getAllPostIds(); 26 | return { 27 | paths, 28 | fallback: false, 29 | }; 30 | } 31 | 32 | export async function getStaticProps({ params }) { 33 | const postData = await getPostData(params.id); 34 | return { 35 | props: { 36 | postData, 37 | }, 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /basics/api-routes-starter/posts/pre-rendering.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Two Forms of Pre-rendering' 3 | date: '2022-01-01' 4 | --- 5 | 6 | Next.js has two forms of pre-rendering: **Static Generation** and **Server-side Rendering**. The difference is in **when** it generates the HTML for a page. 7 | 8 | - **Static Generation** is the pre-rendering method that generates the HTML at **build time**. The pre-rendered HTML is then _reused_ on each request. 9 | - **Server-side Rendering** is the pre-rendering method that generates the HTML on **each request**. 10 | 11 | Importantly, Next.js lets you **choose** which pre-rendering form to use for each page. You can create a "hybrid" Next.js app by using Static Generation for most pages and using Server-side Rendering for others. 12 | -------------------------------------------------------------------------------- /basics/api-routes-starter/posts/ssg-ssr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'When to Use Static Generation v.s. Server-side Rendering' 3 | date: '2022-01-02' 4 | --- 5 | 6 | We recommend using **Static Generation** (with and without data) whenever possible because your page can be built once and served by CDN, which makes it much faster than having a server render the page on every request. 7 | 8 | You can use Static Generation for many types of pages, including: 9 | 10 | - Marketing pages 11 | - Blog posts 12 | - E-commerce product listings 13 | - Help and documentation 14 | 15 | You should ask yourself: "Can I pre-render this page **ahead** of a user's request?" If the answer is yes, then you should choose Static Generation. 16 | 17 | On the other hand, Static Generation is **not** a good idea if you cannot pre-render a page ahead of a user's request. Maybe your page shows frequently updated data, and the page content changes on every request. 18 | 19 | In that case, you can use **Server-Side Rendering**. It will be slower, but the pre-rendered page will always be up-to-date. Or you can skip pre-rendering and use client-side JavaScript to populate data. 20 | -------------------------------------------------------------------------------- /basics/api-routes-starter/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolf620/next-learn/e399cdf4e7e4f401b08ab8b6b454fac2ae8ec958/basics/api-routes-starter/public/favicon.ico -------------------------------------------------------------------------------- /basics/api-routes-starter/public/images/profile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolf620/next-learn/e399cdf4e7e4f401b08ab8b6b454fac2ae8ec958/basics/api-routes-starter/public/images/profile.jpg -------------------------------------------------------------------------------- /basics/api-routes-starter/styles/global.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | font-family: 6 | -apple-system, 7 | BlinkMacSystemFont, 8 | Segoe UI, 9 | Roboto, 10 | Oxygen, 11 | Ubuntu, 12 | Cantarell, 13 | Fira Sans, 14 | Droid Sans, 15 | Helvetica Neue, 16 | sans-serif; 17 | line-height: 1.6; 18 | font-size: 18px; 19 | } 20 | 21 | * { 22 | box-sizing: border-box; 23 | } 24 | 25 | a { 26 | color: #0070f3; 27 | text-decoration: none; 28 | } 29 | 30 | a:hover { 31 | text-decoration: underline; 32 | } 33 | 34 | img { 35 | max-width: 100%; 36 | display: block; 37 | } 38 | -------------------------------------------------------------------------------- /basics/api-routes-starter/styles/utils.module.css: -------------------------------------------------------------------------------- 1 | .heading2Xl { 2 | font-size: 2.5rem; 3 | line-height: 1.2; 4 | font-weight: 800; 5 | letter-spacing: -0.05rem; 6 | margin: 1rem 0; 7 | } 8 | 9 | .headingXl { 10 | font-size: 2rem; 11 | line-height: 1.3; 12 | font-weight: 800; 13 | letter-spacing: -0.05rem; 14 | margin: 1rem 0; 15 | } 16 | 17 | .headingLg { 18 | font-size: 1.5rem; 19 | line-height: 1.4; 20 | margin: 1rem 0; 21 | } 22 | 23 | .headingMd { 24 | font-size: 1.2rem; 25 | line-height: 1.5; 26 | } 27 | 28 | .borderCircle { 29 | border-radius: 9999px; 30 | } 31 | 32 | .colorInherit { 33 | color: inherit; 34 | } 35 | 36 | .padding1px { 37 | padding-top: 1px; 38 | } 39 | 40 | .list { 41 | list-style: none; 42 | padding: 0; 43 | margin: 0; 44 | } 45 | 46 | .listItem { 47 | margin: 0 0 1.25rem; 48 | } 49 | 50 | .lightText { 51 | color: #666; 52 | } 53 | -------------------------------------------------------------------------------- /basics/assets-metadata-css-starter/.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 | .env* 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | -------------------------------------------------------------------------------- /basics/assets-metadata-css-starter/.nvmrc: -------------------------------------------------------------------------------- 1 | 18 2 | -------------------------------------------------------------------------------- /basics/assets-metadata-css-starter/README.md: -------------------------------------------------------------------------------- 1 | This is a starter template for [Learn Next.js](https://nextjs.org/learn). 2 | -------------------------------------------------------------------------------- /basics/assets-metadata-css-starter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "build": "next build", 5 | "dev": "next dev --turbopack", 6 | "start": "next start" 7 | }, 8 | "dependencies": { 9 | "next": "latest", 10 | "react": "latest", 11 | "react-dom": "latest" 12 | }, 13 | "engines": { 14 | "node": ">=18" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /basics/assets-metadata-css-starter/pages/posts/first-post.js: -------------------------------------------------------------------------------- 1 | import Link from 'next/link'; 2 | 3 | export default function FirstPost() { 4 | return ( 5 | <> 6 |

First Post

7 |

8 | Back to home 9 |

10 | 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /basics/assets-metadata-css-starter/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolf620/next-learn/e399cdf4e7e4f401b08ab8b6b454fac2ae8ec958/basics/assets-metadata-css-starter/public/favicon.ico -------------------------------------------------------------------------------- /basics/assets-metadata-css-starter/public/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /basics/assets-metadata-css-starter/styles/Home.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | min-height: 100vh; 3 | padding: 0 0.5rem; 4 | display: flex; 5 | flex-direction: column; 6 | justify-content: center; 7 | align-items: center; 8 | } 9 | 10 | .title a { 11 | color: #0070f3; 12 | text-decoration: none; 13 | } 14 | 15 | .title a:hover, 16 | .title a:focus, 17 | .title a:active { 18 | text-decoration: underline; 19 | } 20 | 21 | .title { 22 | margin: 0 0 1rem; 23 | line-height: 1.15; 24 | font-size: 3.6rem; 25 | } 26 | 27 | .title { 28 | text-align: center; 29 | } 30 | 31 | .title, 32 | .description { 33 | text-align: center; 34 | } 35 | 36 | .description { 37 | line-height: 1.5; 38 | font-size: 1.5rem; 39 | } 40 | 41 | .grid { 42 | display: flex; 43 | align-items: center; 44 | justify-content: center; 45 | flex-wrap: wrap; 46 | 47 | max-width: 800px; 48 | margin-top: 3rem; 49 | } 50 | 51 | .card { 52 | margin: 1rem; 53 | flex-basis: 45%; 54 | padding: 1.5rem; 55 | text-align: left; 56 | color: inherit; 57 | text-decoration: none; 58 | border: 1px solid #eaeaea; 59 | border-radius: 10px; 60 | transition: 61 | color 0.15s ease, 62 | border-color 0.15s ease; 63 | } 64 | 65 | .card:hover, 66 | .card:focus, 67 | .card:active { 68 | color: #0070f3; 69 | border-color: #0070f3; 70 | } 71 | 72 | .card h3 { 73 | margin: 0 0 1rem 0; 74 | font-size: 1.5rem; 75 | } 76 | 77 | .card p { 78 | margin: 0; 79 | font-size: 1.25rem; 80 | line-height: 1.5; 81 | } 82 | 83 | .logo { 84 | height: 1em; 85 | } 86 | 87 | @media (max-width: 600px) { 88 | .grid { 89 | width: 100%; 90 | flex-direction: column; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /basics/assets-metadata-css-starter/styles/global.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | font-family: 6 | Inter, 7 | -apple-system, 8 | BlinkMacSystemFont, 9 | Segoe UI, 10 | Roboto, 11 | Oxygen, 12 | Ubuntu, 13 | Cantarell, 14 | Fira Sans, 15 | Droid Sans, 16 | Helvetica Neue, 17 | sans-serif; 18 | } 19 | 20 | a { 21 | color: inherit; 22 | text-decoration: none; 23 | } 24 | 25 | * { 26 | box-sizing: border-box; 27 | } 28 | 29 | img { 30 | max-width: 100%; 31 | height: auto; 32 | } 33 | -------------------------------------------------------------------------------- /basics/basics-final/.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 | .env* 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | -------------------------------------------------------------------------------- /basics/basics-final/.nvmrc: -------------------------------------------------------------------------------- 1 | 18 2 | -------------------------------------------------------------------------------- /basics/basics-final/README.md: -------------------------------------------------------------------------------- 1 | This is a starter template for [Learn Next.js](https://nextjs.org/learn). 2 | -------------------------------------------------------------------------------- /basics/basics-final/components/date.js: -------------------------------------------------------------------------------- 1 | import { parseISO, format } from 'date-fns'; 2 | 3 | export default function Date({ dateString }) { 4 | const date = parseISO(dateString); 5 | return ; 6 | } 7 | -------------------------------------------------------------------------------- /basics/basics-final/components/layout.js: -------------------------------------------------------------------------------- 1 | import Head from 'next/head'; 2 | import Image from 'next/image'; 3 | import Script from 'next/script'; 4 | 5 | import styles from './layout.module.css'; 6 | import utilStyles from '../styles/utils.module.css'; 7 | import Link from 'next/link'; 8 | 9 | const name = '[Your Name]'; 10 | export const siteTitle = 'Next.js Sample Website'; 11 | 12 | export default function Layout({ children, home }) { 13 | return ( 14 |
15 | 16 | 17 | 21 | 27 | 28 | 29 | 30 |