├── .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 |
39 | {name}
40 | >
41 | ) : (
42 | <>
43 |
44 |
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 |
--------------------------------------------------------------------------------
/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 |