diff --git a/README.md b/README.md
new file mode 100644
index 0000000..588278e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+# next-learn-starter
+
+This repository contains starter templates for [Learn Next.js](https://nextjs.org/learn).
+
+The final result for the basics lesson can be found in the [basics-final](basics-final) directory and is available at: [https://next-learn-starter.now.sh/](https://next-learn-starter.now.sh/).
\ No newline at end of file
diff --git a/api-routes-starter/.gitignore b/api-routes-starter/.gitignore
new file mode 100644
index 0000000..922d92a
--- /dev/null
+++ b/api-routes-starter/.gitignore
@@ -0,0 +1,25 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+.env*
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
diff --git a/api-routes-starter/README.md b/api-routes-starter/README.md
new file mode 100644
index 0000000..02695bc
--- /dev/null
+++ b/api-routes-starter/README.md
@@ -0,0 +1 @@
+This is a starter template for [Learn Next.js](https://nextjs.org/learn).
\ No newline at end of file
diff --git a/api-routes-starter/components/date.js b/api-routes-starter/components/date.js
new file mode 100644
index 0000000..0ec71d3
--- /dev/null
+++ b/api-routes-starter/components/date.js
@@ -0,0 +1,6 @@
+import { parseISO, format } from 'date-fns'
+
+export default function Date({ dateString }) {
+ const date = parseISO(dateString)
+ return {format(date, 'LLLL d, yyyy')}
+}
diff --git a/api-routes-starter/components/layout.js b/api-routes-starter/components/layout.js
new file mode 100644
index 0000000..cff0cca
--- /dev/null
+++ b/api-routes-starter/components/layout.js
@@ -0,0 +1,64 @@
+import Head from 'next/head'
+import styles from './layout.module.css'
+import utilStyles from '../styles/utils.module.css'
+import Link from 'next/link'
+
+const name = '[Your Name]'
+export const siteTitle = 'Next.js Sample Website'
+
+export default function Layout({ children, home }) {
+ return (
+
+
+
+
+
+
+
+ {home ? (
+ <>
+
+ {name}
+ >
+ ) : (
+ <>
+
+
+
+
+
+
+ >
+ )}
+
+
{children}
+ {!home && (
+
+ )}
+
+ )
+}
diff --git a/api-routes-starter/components/layout.module.css b/api-routes-starter/components/layout.module.css
new file mode 100644
index 0000000..d0e3a8f
--- /dev/null
+++ b/api-routes-starter/components/layout.module.css
@@ -0,0 +1,25 @@
+.container {
+ max-width: 36rem;
+ padding: 0 1rem;
+ margin: 3rem auto 6rem;
+}
+
+.header {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.headerImage {
+ width: 6rem;
+ height: 6rem;
+}
+
+.headerHomeImage {
+ width: 8rem;
+ height: 8rem;
+}
+
+.backToHome {
+ margin: 3rem 0 0;
+}
diff --git a/api-routes-starter/lib/posts.js b/api-routes-starter/lib/posts.js
new file mode 100644
index 0000000..53d8653
--- /dev/null
+++ b/api-routes-starter/lib/posts.js
@@ -0,0 +1,69 @@
+import fs from 'fs'
+import path from 'path'
+import matter from 'gray-matter'
+import remark from 'remark'
+import html from 'remark-html'
+
+const postsDirectory = path.join(process.cwd(), 'posts')
+
+export function getSortedPostsData() {
+ // Get file names under /posts
+ const fileNames = fs.readdirSync(postsDirectory)
+ const allPostsData = fileNames.map(fileName => {
+ // Remove ".md" from file name to get id
+ const id = fileName.replace(/\.md$/, '')
+
+ // Read markdown file as string
+ const fullPath = path.join(postsDirectory, fileName)
+ const fileContents = fs.readFileSync(fullPath, 'utf8')
+
+ // Use gray-matter to parse the post metadata section
+ const matterResult = matter(fileContents)
+
+ // Combine the data with the id
+ return {
+ id,
+ ...matterResult.data
+ }
+ })
+ // Sort posts by date
+ return allPostsData.sort((a, b) => {
+ if (a.date < b.date) {
+ return 1
+ } else {
+ return -1
+ }
+ })
+}
+
+export function getAllPostIds() {
+ const fileNames = fs.readdirSync(postsDirectory)
+ return fileNames.map(fileName => {
+ return {
+ params: {
+ id: fileName.replace(/\.md$/, '')
+ }
+ }
+ })
+}
+
+export async function getPostData(id) {
+ const fullPath = path.join(postsDirectory, `${id}.md`)
+ const fileContents = fs.readFileSync(fullPath, 'utf8')
+
+ // Use gray-matter to parse the post metadata section
+ const matterResult = matter(fileContents)
+
+ // Use remark to convert markdown into HTML string
+ const processedContent = await remark()
+ .use(html)
+ .process(matterResult.content)
+ const contentHtml = processedContent.toString()
+
+ // Combine the data with the id and contentHtml
+ return {
+ id,
+ contentHtml,
+ ...matterResult.data
+ }
+}
diff --git a/api-routes-starter/package.json b/api-routes-starter/package.json
new file mode 100644
index 0000000..b879f50
--- /dev/null
+++ b/api-routes-starter/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "my-app",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start"
+ },
+ "dependencies": {
+ "date-fns": "^2.11.1",
+ "gray-matter": "^4.0.2",
+ "next": "9.3.4",
+ "react": "16.13.1",
+ "react-dom": "16.13.1",
+ "remark": "^12.0.0",
+ "remark-html": "^11.0.1"
+ }
+}
diff --git a/api-routes-starter/pages/_app.js b/api-routes-starter/pages/_app.js
new file mode 100644
index 0000000..7e66efc
--- /dev/null
+++ b/api-routes-starter/pages/_app.js
@@ -0,0 +1,5 @@
+import '../styles/global.css'
+
+export default function App({ Component, pageProps }) {
+ return
+}
diff --git a/api-routes-starter/pages/index.js b/api-routes-starter/pages/index.js
new file mode 100644
index 0000000..0f9494b
--- /dev/null
+++ b/api-routes-starter/pages/index.js
@@ -0,0 +1,48 @@
+import Head from 'next/head'
+import Layout, { siteTitle } from '../components/layout'
+import utilStyles from '../styles/utils.module.css'
+import { getSortedPostsData } from '../lib/posts'
+import Link from 'next/link'
+import Date from '../components/date'
+
+export default function Home({ allPostsData }) {
+ return (
+
+
+ {siteTitle}
+
+
+ [Your Self Introduction]
+
+ (This is a sample website - you’ll be building a site like this on{' '}
+ our Next.js tutorial .)
+
+
+
+ Blog
+
+ {allPostsData.map(({ id, date, title }) => (
+
+
+ {title}
+
+
+
+
+
+
+ ))}
+
+
+
+ )
+}
+
+export async function getStaticProps() {
+ const allPostsData = getSortedPostsData()
+ return {
+ props: {
+ allPostsData
+ }
+ }
+}
diff --git a/api-routes-starter/pages/posts/[id].js b/api-routes-starter/pages/posts/[id].js
new file mode 100644
index 0000000..28faaad
--- /dev/null
+++ b/api-routes-starter/pages/posts/[id].js
@@ -0,0 +1,39 @@
+import Layout from '../../components/layout'
+import { getAllPostIds, getPostData } from '../../lib/posts'
+import Head from 'next/head'
+import Date from '../../components/date'
+import utilStyles from '../../styles/utils.module.css'
+
+export default function Post({ postData }) {
+ return (
+
+
+ {postData.title}
+
+
+ {postData.title}
+
+
+
+
+
+
+ )
+}
+
+export async function getStaticPaths() {
+ const paths = getAllPostIds()
+ return {
+ paths,
+ fallback: false
+ }
+}
+
+export async function getStaticProps({ params }) {
+ const postData = await getPostData(params.id)
+ return {
+ props: {
+ postData
+ }
+ }
+}
diff --git a/api-routes-starter/posts/dps.md b/api-routes-starter/posts/dps.md
new file mode 100644
index 0000000..878a33d
--- /dev/null
+++ b/api-routes-starter/posts/dps.md
@@ -0,0 +1,12 @@
+---
+title: "DPS: Develop, Preview, Ship"
+date: "2020-01-02"
+---
+
+[ZEIT Now](https://zeit.co/) supports the **DPS** workflow: **D**evelop, **P**review, and **S**hip:
+
+- **Develop**: Write code in Next.js. Keep the development server running and take advantage of its hot code reloading feature.
+- **Preview**: Every time you push changes to a branch on GitHub / GitLab / BitBucket, ZEIT Now automatically creates a new deployment with a unique URL.
+- **Ship**: When you’re ready to ship, merge the pull request to your default branch (e.g. `master`). ZEIT Now will automatically create a production deployment.
+
+By using the DPS workflow, in addition to doing code reviews, you can do *deployment previews*. Each deployment creates a unique URL that can be shared or used for integration tests.
\ No newline at end of file
diff --git a/api-routes-starter/posts/pre-rendering.md b/api-routes-starter/posts/pre-rendering.md
new file mode 100644
index 0000000..78cc081
--- /dev/null
+++ b/api-routes-starter/posts/pre-rendering.md
@@ -0,0 +1,11 @@
+---
+title: "Two Forms of Pre-rendering"
+date: "2020-01-01"
+---
+
+[Next.js](https://nextjs.org/) has two forms of pre-rendering: **Static Generation** and **Server-side Rendering**. The difference is in **when** it generates the HTML for a page.
+
+- **Static Generation (Recommended)**: The HTML is generated at **build time** and will be reused on each request.
+- **Server-side Rendering**: The HTML is generated on **each request**.
+
+Importantly, Next.js lets you **choose** which pre-rendering form you'd like 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.
\ No newline at end of file
diff --git a/api-routes-starter/public/favicon.ico b/api-routes-starter/public/favicon.ico
new file mode 100644
index 0000000..4965832
Binary files /dev/null and b/api-routes-starter/public/favicon.ico differ
diff --git a/api-routes-starter/public/images/profile.jpg b/api-routes-starter/public/images/profile.jpg
new file mode 100644
index 0000000..798aba3
Binary files /dev/null and b/api-routes-starter/public/images/profile.jpg differ
diff --git a/api-routes-starter/styles/global.css b/api-routes-starter/styles/global.css
new file mode 100644
index 0000000..9e1b0fb
--- /dev/null
+++ b/api-routes-starter/styles/global.css
@@ -0,0 +1,27 @@
+html,
+body {
+ padding: 0;
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
+ Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+ line-height: 1.6;
+ font-size: 18px;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+a {
+ color: #0070f3;
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+img {
+ max-width: 100%;
+ display: block;
+}
diff --git a/api-routes-starter/styles/utils.module.css b/api-routes-starter/styles/utils.module.css
new file mode 100644
index 0000000..37f545e
--- /dev/null
+++ b/api-routes-starter/styles/utils.module.css
@@ -0,0 +1,52 @@
+.heading2Xl {
+ font-size: 2.5rem;
+ line-height: 1.2;
+ font-weight: 800;
+ letter-spacing: -0.05rem;
+ margin: 1rem 0;
+}
+
+.headingXl {
+ font-size: 2rem;
+ line-height: 1.3;
+ font-weight: 800;
+ letter-spacing: -0.05rem;
+ margin: 1rem 0;
+}
+
+.headingLg {
+ font-size: 1.5rem;
+ line-height: 1.4;
+ margin: 1rem 0;
+}
+
+.headingMd {
+ font-size: 1.2rem;
+ line-height: 1.5;
+}
+
+.borderCircle {
+ border-radius: 9999px;
+}
+
+.colorInherit {
+ color: inherit;
+}
+
+.padding1px {
+ padding-top: 1px;
+}
+
+.list {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.listItem {
+ margin: 0 0 1.25rem;
+}
+
+.lightText {
+ color: #666;
+}
diff --git a/assets-metadata-css-starter/.gitignore b/assets-metadata-css-starter/.gitignore
new file mode 100644
index 0000000..922d92a
--- /dev/null
+++ b/assets-metadata-css-starter/.gitignore
@@ -0,0 +1,25 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+.env*
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
diff --git a/assets-metadata-css-starter/README.md b/assets-metadata-css-starter/README.md
new file mode 100644
index 0000000..02695bc
--- /dev/null
+++ b/assets-metadata-css-starter/README.md
@@ -0,0 +1 @@
+This is a starter template for [Learn Next.js](https://nextjs.org/learn).
\ No newline at end of file
diff --git a/assets-metadata-css-starter/package.json b/assets-metadata-css-starter/package.json
new file mode 100644
index 0000000..899e758
--- /dev/null
+++ b/assets-metadata-css-starter/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "my-app",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start"
+ },
+ "dependencies": {
+ "next": "9.3.4",
+ "react": "16.13.1",
+ "react-dom": "16.13.1"
+ }
+}
diff --git a/assets-metadata-css-starter/pages/index.js b/assets-metadata-css-starter/pages/index.js
new file mode 100644
index 0000000..33a0627
--- /dev/null
+++ b/assets-metadata-css-starter/pages/index.js
@@ -0,0 +1,207 @@
+import Link from 'next/link'
+import Head from 'next/head'
+
+const Home = () => (
+
+
+
Create Next App
+
+
+
+
+
+
+
+ Get started by editing pages/index.js
+
+
+
+
+
+
+
+
+
+
+
+)
+
+export default Home
diff --git a/assets-metadata-css-starter/pages/posts/first-post.js b/assets-metadata-css-starter/pages/posts/first-post.js
new file mode 100644
index 0000000..7f840e5
--- /dev/null
+++ b/assets-metadata-css-starter/pages/posts/first-post.js
@@ -0,0 +1,14 @@
+import Link from 'next/link'
+
+export default function FirstPost() {
+ return (
+ <>
+ First Post
+
+ >
+ )
+}
diff --git a/assets-metadata-css-starter/public/favicon.ico b/assets-metadata-css-starter/public/favicon.ico
new file mode 100644
index 0000000..4965832
Binary files /dev/null and b/assets-metadata-css-starter/public/favicon.ico differ
diff --git a/assets-metadata-css-starter/public/zeit.svg b/assets-metadata-css-starter/public/zeit.svg
new file mode 100644
index 0000000..dd3916c
--- /dev/null
+++ b/assets-metadata-css-starter/public/zeit.svg
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/basics-final/.gitignore b/basics-final/.gitignore
new file mode 100644
index 0000000..922d92a
--- /dev/null
+++ b/basics-final/.gitignore
@@ -0,0 +1,25 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+.env*
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
diff --git a/basics-final/README.md b/basics-final/README.md
new file mode 100644
index 0000000..02695bc
--- /dev/null
+++ b/basics-final/README.md
@@ -0,0 +1 @@
+This is a starter template for [Learn Next.js](https://nextjs.org/learn).
\ No newline at end of file
diff --git a/basics-final/components/date.js b/basics-final/components/date.js
new file mode 100644
index 0000000..0ec71d3
--- /dev/null
+++ b/basics-final/components/date.js
@@ -0,0 +1,6 @@
+import { parseISO, format } from 'date-fns'
+
+export default function Date({ dateString }) {
+ const date = parseISO(dateString)
+ return {format(date, 'LLLL d, yyyy')}
+}
diff --git a/basics-final/components/layout.js b/basics-final/components/layout.js
new file mode 100644
index 0000000..1cf9c69
--- /dev/null
+++ b/basics-final/components/layout.js
@@ -0,0 +1,64 @@
+import Head from 'next/head'
+import styles from './layout.module.css'
+import utilStyles from '../styles/utils.module.css'
+import Link from 'next/link'
+
+const name = 'Shu Uesugi'
+export const siteTitle = 'Next.js Sample Website'
+
+export default function Layout({ children, home }) {
+ return (
+
+
+
+
+
+
+
+ {home ? (
+ <>
+
+ {name}
+ >
+ ) : (
+ <>
+
+
+
+
+
+
+ >
+ )}
+
+
{children}
+ {!home && (
+
+ )}
+
+ )
+}
diff --git a/basics-final/components/layout.module.css b/basics-final/components/layout.module.css
new file mode 100644
index 0000000..d0e3a8f
--- /dev/null
+++ b/basics-final/components/layout.module.css
@@ -0,0 +1,25 @@
+.container {
+ max-width: 36rem;
+ padding: 0 1rem;
+ margin: 3rem auto 6rem;
+}
+
+.header {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.headerImage {
+ width: 6rem;
+ height: 6rem;
+}
+
+.headerHomeImage {
+ width: 8rem;
+ height: 8rem;
+}
+
+.backToHome {
+ margin: 3rem 0 0;
+}
diff --git a/basics-final/lib/posts.js b/basics-final/lib/posts.js
new file mode 100644
index 0000000..53d8653
--- /dev/null
+++ b/basics-final/lib/posts.js
@@ -0,0 +1,69 @@
+import fs from 'fs'
+import path from 'path'
+import matter from 'gray-matter'
+import remark from 'remark'
+import html from 'remark-html'
+
+const postsDirectory = path.join(process.cwd(), 'posts')
+
+export function getSortedPostsData() {
+ // Get file names under /posts
+ const fileNames = fs.readdirSync(postsDirectory)
+ const allPostsData = fileNames.map(fileName => {
+ // Remove ".md" from file name to get id
+ const id = fileName.replace(/\.md$/, '')
+
+ // Read markdown file as string
+ const fullPath = path.join(postsDirectory, fileName)
+ const fileContents = fs.readFileSync(fullPath, 'utf8')
+
+ // Use gray-matter to parse the post metadata section
+ const matterResult = matter(fileContents)
+
+ // Combine the data with the id
+ return {
+ id,
+ ...matterResult.data
+ }
+ })
+ // Sort posts by date
+ return allPostsData.sort((a, b) => {
+ if (a.date < b.date) {
+ return 1
+ } else {
+ return -1
+ }
+ })
+}
+
+export function getAllPostIds() {
+ const fileNames = fs.readdirSync(postsDirectory)
+ return fileNames.map(fileName => {
+ return {
+ params: {
+ id: fileName.replace(/\.md$/, '')
+ }
+ }
+ })
+}
+
+export async function getPostData(id) {
+ const fullPath = path.join(postsDirectory, `${id}.md`)
+ const fileContents = fs.readFileSync(fullPath, 'utf8')
+
+ // Use gray-matter to parse the post metadata section
+ const matterResult = matter(fileContents)
+
+ // Use remark to convert markdown into HTML string
+ const processedContent = await remark()
+ .use(html)
+ .process(matterResult.content)
+ const contentHtml = processedContent.toString()
+
+ // Combine the data with the id and contentHtml
+ return {
+ id,
+ contentHtml,
+ ...matterResult.data
+ }
+}
diff --git a/basics-final/package.json b/basics-final/package.json
new file mode 100644
index 0000000..b879f50
--- /dev/null
+++ b/basics-final/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "my-app",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start"
+ },
+ "dependencies": {
+ "date-fns": "^2.11.1",
+ "gray-matter": "^4.0.2",
+ "next": "9.3.4",
+ "react": "16.13.1",
+ "react-dom": "16.13.1",
+ "remark": "^12.0.0",
+ "remark-html": "^11.0.1"
+ }
+}
diff --git a/basics-final/pages/_app.js b/basics-final/pages/_app.js
new file mode 100644
index 0000000..7e66efc
--- /dev/null
+++ b/basics-final/pages/_app.js
@@ -0,0 +1,5 @@
+import '../styles/global.css'
+
+export default function App({ Component, pageProps }) {
+ return
+}
diff --git a/basics-final/pages/api/hello.js b/basics-final/pages/api/hello.js
new file mode 100644
index 0000000..2e22ab3
--- /dev/null
+++ b/basics-final/pages/api/hello.js
@@ -0,0 +1,3 @@
+export default (req, res) => {
+ res.status(200).json({ text: 'Hello' })
+}
diff --git a/basics-final/pages/index.js b/basics-final/pages/index.js
new file mode 100644
index 0000000..1f4acc0
--- /dev/null
+++ b/basics-final/pages/index.js
@@ -0,0 +1,54 @@
+import Head from 'next/head'
+import Layout, { siteTitle } from '../components/layout'
+import utilStyles from '../styles/utils.module.css'
+import { getSortedPostsData } from '../lib/posts'
+import Link from 'next/link'
+import Date from '../components/date'
+
+export default function Home({ allPostsData }) {
+ return (
+
+
+ {siteTitle}
+
+
+
+ Hello, I’m Shu . I write code at{' '}
+ ZEIT , the team behind{' '}
+ Next.js . You can contact me via{' '}
+ Twitter or{' '}
+ email .
+
+
+ (This is a sample website - you’ll be building a site like this on{' '}
+ our Next.js tutorial .)
+
+
+
+ Blog
+
+ {allPostsData.map(({ id, date, title }) => (
+
+
+ {title}
+
+
+
+
+
+
+ ))}
+
+
+
+ )
+}
+
+export async function getStaticProps() {
+ const allPostsData = getSortedPostsData()
+ return {
+ props: {
+ allPostsData
+ }
+ }
+}
diff --git a/basics-final/pages/posts/[id].js b/basics-final/pages/posts/[id].js
new file mode 100644
index 0000000..28faaad
--- /dev/null
+++ b/basics-final/pages/posts/[id].js
@@ -0,0 +1,39 @@
+import Layout from '../../components/layout'
+import { getAllPostIds, getPostData } from '../../lib/posts'
+import Head from 'next/head'
+import Date from '../../components/date'
+import utilStyles from '../../styles/utils.module.css'
+
+export default function Post({ postData }) {
+ return (
+
+
+ {postData.title}
+
+
+ {postData.title}
+
+
+
+
+
+
+ )
+}
+
+export async function getStaticPaths() {
+ const paths = getAllPostIds()
+ return {
+ paths,
+ fallback: false
+ }
+}
+
+export async function getStaticProps({ params }) {
+ const postData = await getPostData(params.id)
+ return {
+ props: {
+ postData
+ }
+ }
+}
diff --git a/basics-final/posts/dps.md b/basics-final/posts/dps.md
new file mode 100644
index 0000000..878a33d
--- /dev/null
+++ b/basics-final/posts/dps.md
@@ -0,0 +1,12 @@
+---
+title: "DPS: Develop, Preview, Ship"
+date: "2020-01-02"
+---
+
+[ZEIT Now](https://zeit.co/) supports the **DPS** workflow: **D**evelop, **P**review, and **S**hip:
+
+- **Develop**: Write code in Next.js. Keep the development server running and take advantage of its hot code reloading feature.
+- **Preview**: Every time you push changes to a branch on GitHub / GitLab / BitBucket, ZEIT Now automatically creates a new deployment with a unique URL.
+- **Ship**: When you’re ready to ship, merge the pull request to your default branch (e.g. `master`). ZEIT Now will automatically create a production deployment.
+
+By using the DPS workflow, in addition to doing code reviews, you can do *deployment previews*. Each deployment creates a unique URL that can be shared or used for integration tests.
\ No newline at end of file
diff --git a/basics-final/posts/pre-rendering.md b/basics-final/posts/pre-rendering.md
new file mode 100644
index 0000000..78cc081
--- /dev/null
+++ b/basics-final/posts/pre-rendering.md
@@ -0,0 +1,11 @@
+---
+title: "Two Forms of Pre-rendering"
+date: "2020-01-01"
+---
+
+[Next.js](https://nextjs.org/) has two forms of pre-rendering: **Static Generation** and **Server-side Rendering**. The difference is in **when** it generates the HTML for a page.
+
+- **Static Generation (Recommended)**: The HTML is generated at **build time** and will be reused on each request.
+- **Server-side Rendering**: The HTML is generated on **each request**.
+
+Importantly, Next.js lets you **choose** which pre-rendering form you'd like 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.
\ No newline at end of file
diff --git a/basics-final/public/favicon.ico b/basics-final/public/favicon.ico
new file mode 100644
index 0000000..4965832
Binary files /dev/null and b/basics-final/public/favicon.ico differ
diff --git a/basics-final/public/images/profile.jpg b/basics-final/public/images/profile.jpg
new file mode 100644
index 0000000..928d903
Binary files /dev/null and b/basics-final/public/images/profile.jpg differ
diff --git a/basics-final/styles/global.css b/basics-final/styles/global.css
new file mode 100644
index 0000000..9e1b0fb
--- /dev/null
+++ b/basics-final/styles/global.css
@@ -0,0 +1,27 @@
+html,
+body {
+ padding: 0;
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
+ Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+ line-height: 1.6;
+ font-size: 18px;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+a {
+ color: #0070f3;
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+img {
+ max-width: 100%;
+ display: block;
+}
diff --git a/basics-final/styles/utils.module.css b/basics-final/styles/utils.module.css
new file mode 100644
index 0000000..37f545e
--- /dev/null
+++ b/basics-final/styles/utils.module.css
@@ -0,0 +1,52 @@
+.heading2Xl {
+ font-size: 2.5rem;
+ line-height: 1.2;
+ font-weight: 800;
+ letter-spacing: -0.05rem;
+ margin: 1rem 0;
+}
+
+.headingXl {
+ font-size: 2rem;
+ line-height: 1.3;
+ font-weight: 800;
+ letter-spacing: -0.05rem;
+ margin: 1rem 0;
+}
+
+.headingLg {
+ font-size: 1.5rem;
+ line-height: 1.4;
+ margin: 1rem 0;
+}
+
+.headingMd {
+ font-size: 1.2rem;
+ line-height: 1.5;
+}
+
+.borderCircle {
+ border-radius: 9999px;
+}
+
+.colorInherit {
+ color: inherit;
+}
+
+.padding1px {
+ padding-top: 1px;
+}
+
+.list {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.listItem {
+ margin: 0 0 1.25rem;
+}
+
+.lightText {
+ color: #666;
+}
diff --git a/data-fetching-starter/.gitignore b/data-fetching-starter/.gitignore
new file mode 100644
index 0000000..922d92a
--- /dev/null
+++ b/data-fetching-starter/.gitignore
@@ -0,0 +1,25 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+.env*
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
diff --git a/data-fetching-starter/README.md b/data-fetching-starter/README.md
new file mode 100644
index 0000000..02695bc
--- /dev/null
+++ b/data-fetching-starter/README.md
@@ -0,0 +1 @@
+This is a starter template for [Learn Next.js](https://nextjs.org/learn).
\ No newline at end of file
diff --git a/data-fetching-starter/components/layout.js b/data-fetching-starter/components/layout.js
new file mode 100644
index 0000000..cff0cca
--- /dev/null
+++ b/data-fetching-starter/components/layout.js
@@ -0,0 +1,64 @@
+import Head from 'next/head'
+import styles from './layout.module.css'
+import utilStyles from '../styles/utils.module.css'
+import Link from 'next/link'
+
+const name = '[Your Name]'
+export const siteTitle = 'Next.js Sample Website'
+
+export default function Layout({ children, home }) {
+ return (
+
+
+
+
+
+
+
+ {home ? (
+ <>
+
+ {name}
+ >
+ ) : (
+ <>
+
+
+
+
+
+
+ >
+ )}
+
+
{children}
+ {!home && (
+
+ )}
+
+ )
+}
diff --git a/data-fetching-starter/components/layout.module.css b/data-fetching-starter/components/layout.module.css
new file mode 100644
index 0000000..d0e3a8f
--- /dev/null
+++ b/data-fetching-starter/components/layout.module.css
@@ -0,0 +1,25 @@
+.container {
+ max-width: 36rem;
+ padding: 0 1rem;
+ margin: 3rem auto 6rem;
+}
+
+.header {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.headerImage {
+ width: 6rem;
+ height: 6rem;
+}
+
+.headerHomeImage {
+ width: 8rem;
+ height: 8rem;
+}
+
+.backToHome {
+ margin: 3rem 0 0;
+}
diff --git a/data-fetching-starter/package.json b/data-fetching-starter/package.json
new file mode 100644
index 0000000..899e758
--- /dev/null
+++ b/data-fetching-starter/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "my-app",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start"
+ },
+ "dependencies": {
+ "next": "9.3.4",
+ "react": "16.13.1",
+ "react-dom": "16.13.1"
+ }
+}
diff --git a/data-fetching-starter/pages/_app.js b/data-fetching-starter/pages/_app.js
new file mode 100644
index 0000000..a508286
--- /dev/null
+++ b/data-fetching-starter/pages/_app.js
@@ -0,0 +1,7 @@
+import '../styles/global.css'
+
+export default function App({ Component, pageProps }) {
+ return
+}
+
+export default App
diff --git a/data-fetching-starter/pages/index.js b/data-fetching-starter/pages/index.js
new file mode 100644
index 0000000..be1afc7
--- /dev/null
+++ b/data-fetching-starter/pages/index.js
@@ -0,0 +1,20 @@
+import Head from 'next/head'
+import Layout, { siteTitle } from '../components/layout'
+import utilStyles from '../styles/utils.module.css'
+
+export default function Home() {
+ return (
+
+
+ {siteTitle}
+
+
+ [Your Self Introduction]
+
+ (This is a sample website - you’ll be building a site like this on{' '}
+ our Next.js tutorial .)
+
+
+
+ )
+}
diff --git a/data-fetching-starter/pages/posts/first-post.js b/data-fetching-starter/pages/posts/first-post.js
new file mode 100644
index 0000000..887057f
--- /dev/null
+++ b/data-fetching-starter/pages/posts/first-post.js
@@ -0,0 +1,19 @@
+import Head from 'next/head'
+import Link from 'next/link'
+import Layout from '../../components/layout'
+
+export default function FirstPost() {
+ return (
+
+
+ First Post
+
+ First Post
+
+
+ )
+}
diff --git a/data-fetching-starter/public/favicon.ico b/data-fetching-starter/public/favicon.ico
new file mode 100644
index 0000000..4965832
Binary files /dev/null and b/data-fetching-starter/public/favicon.ico differ
diff --git a/data-fetching-starter/public/images/profile.jpg b/data-fetching-starter/public/images/profile.jpg
new file mode 100644
index 0000000..798aba3
Binary files /dev/null and b/data-fetching-starter/public/images/profile.jpg differ
diff --git a/data-fetching-starter/public/zeit.svg b/data-fetching-starter/public/zeit.svg
new file mode 100644
index 0000000..dd3916c
--- /dev/null
+++ b/data-fetching-starter/public/zeit.svg
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/data-fetching-starter/styles/global.css b/data-fetching-starter/styles/global.css
new file mode 100644
index 0000000..9e1b0fb
--- /dev/null
+++ b/data-fetching-starter/styles/global.css
@@ -0,0 +1,27 @@
+html,
+body {
+ padding: 0;
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
+ Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+ line-height: 1.6;
+ font-size: 18px;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+a {
+ color: #0070f3;
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+img {
+ max-width: 100%;
+ display: block;
+}
diff --git a/data-fetching-starter/styles/utils.module.css b/data-fetching-starter/styles/utils.module.css
new file mode 100644
index 0000000..37f545e
--- /dev/null
+++ b/data-fetching-starter/styles/utils.module.css
@@ -0,0 +1,52 @@
+.heading2Xl {
+ font-size: 2.5rem;
+ line-height: 1.2;
+ font-weight: 800;
+ letter-spacing: -0.05rem;
+ margin: 1rem 0;
+}
+
+.headingXl {
+ font-size: 2rem;
+ line-height: 1.3;
+ font-weight: 800;
+ letter-spacing: -0.05rem;
+ margin: 1rem 0;
+}
+
+.headingLg {
+ font-size: 1.5rem;
+ line-height: 1.4;
+ margin: 1rem 0;
+}
+
+.headingMd {
+ font-size: 1.2rem;
+ line-height: 1.5;
+}
+
+.borderCircle {
+ border-radius: 9999px;
+}
+
+.colorInherit {
+ color: inherit;
+}
+
+.padding1px {
+ padding-top: 1px;
+}
+
+.list {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.listItem {
+ margin: 0 0 1.25rem;
+}
+
+.lightText {
+ color: #666;
+}
diff --git a/dynamic-routes-starter/.gitignore b/dynamic-routes-starter/.gitignore
new file mode 100644
index 0000000..922d92a
--- /dev/null
+++ b/dynamic-routes-starter/.gitignore
@@ -0,0 +1,25 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+.env*
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
diff --git a/dynamic-routes-starter/README.md b/dynamic-routes-starter/README.md
new file mode 100644
index 0000000..02695bc
--- /dev/null
+++ b/dynamic-routes-starter/README.md
@@ -0,0 +1 @@
+This is a starter template for [Learn Next.js](https://nextjs.org/learn).
\ No newline at end of file
diff --git a/dynamic-routes-starter/components/layout.js b/dynamic-routes-starter/components/layout.js
new file mode 100644
index 0000000..cff0cca
--- /dev/null
+++ b/dynamic-routes-starter/components/layout.js
@@ -0,0 +1,64 @@
+import Head from 'next/head'
+import styles from './layout.module.css'
+import utilStyles from '../styles/utils.module.css'
+import Link from 'next/link'
+
+const name = '[Your Name]'
+export const siteTitle = 'Next.js Sample Website'
+
+export default function Layout({ children, home }) {
+ return (
+
+
+
+
+
+
+
+ {home ? (
+ <>
+
+ {name}
+ >
+ ) : (
+ <>
+
+
+
+
+
+
+ >
+ )}
+
+
{children}
+ {!home && (
+
+ )}
+
+ )
+}
diff --git a/dynamic-routes-starter/components/layout.module.css b/dynamic-routes-starter/components/layout.module.css
new file mode 100644
index 0000000..d0e3a8f
--- /dev/null
+++ b/dynamic-routes-starter/components/layout.module.css
@@ -0,0 +1,25 @@
+.container {
+ max-width: 36rem;
+ padding: 0 1rem;
+ margin: 3rem auto 6rem;
+}
+
+.header {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.headerImage {
+ width: 6rem;
+ height: 6rem;
+}
+
+.headerHomeImage {
+ width: 8rem;
+ height: 8rem;
+}
+
+.backToHome {
+ margin: 3rem 0 0;
+}
diff --git a/dynamic-routes-starter/lib/posts.js b/dynamic-routes-starter/lib/posts.js
new file mode 100644
index 0000000..46d820c
--- /dev/null
+++ b/dynamic-routes-starter/lib/posts.js
@@ -0,0 +1,35 @@
+import fs from 'fs'
+import path from 'path'
+import matter from 'gray-matter'
+
+const postsDirectory = path.join(process.cwd(), 'posts')
+
+export function getSortedPostsData() {
+ // Get file names under /posts
+ const fileNames = fs.readdirSync(postsDirectory)
+ const allPostsData = fileNames.map(fileName => {
+ // Remove ".md" from file name to get id
+ const id = fileName.replace(/\.md$/, '')
+
+ // Read markdown file as string
+ const fullPath = path.join(postsDirectory, fileName)
+ const fileContents = fs.readFileSync(fullPath, 'utf8')
+
+ // Use gray-matter to parse the post metadata section
+ const matterResult = matter(fileContents)
+
+ // Combine the data with the id
+ return {
+ id,
+ ...matterResult.data
+ }
+ })
+ // Sort posts by date
+ return allPostsData.sort((a, b) => {
+ if (a.date < b.date) {
+ return 1
+ } else {
+ return -1
+ }
+ })
+}
diff --git a/dynamic-routes-starter/package.json b/dynamic-routes-starter/package.json
new file mode 100644
index 0000000..bc4c8b5
--- /dev/null
+++ b/dynamic-routes-starter/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "my-app",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start"
+ },
+ "dependencies": {
+ "gray-matter": "^4.0.2",
+ "next": "9.3.4",
+ "react": "16.13.1",
+ "react-dom": "16.13.1"
+ }
+}
diff --git a/dynamic-routes-starter/pages/_app.js b/dynamic-routes-starter/pages/_app.js
new file mode 100644
index 0000000..a508286
--- /dev/null
+++ b/dynamic-routes-starter/pages/_app.js
@@ -0,0 +1,7 @@
+import '../styles/global.css'
+
+export default function App({ Component, pageProps }) {
+ return
+}
+
+export default App
diff --git a/dynamic-routes-starter/pages/index.js b/dynamic-routes-starter/pages/index.js
new file mode 100644
index 0000000..24ba2c6
--- /dev/null
+++ b/dynamic-routes-starter/pages/index.js
@@ -0,0 +1,40 @@
+import Head from 'next/head'
+import Layout, { siteTitle } from '../components/layout'
+import utilStyles from '../styles/utils.module.css'
+import { getSortedPostsData } from '../lib/posts'
+
+export default function Home({ allPostsData }) {
+ return (
+
+
+ {siteTitle}
+
+
+ [Your Self Introduction]
+
+
+ Blog
+
+ {allPostsData.map(({ id, date, title }) => (
+
+ {title}
+
+ {id}
+
+ {date}
+
+ ))}
+
+
+
+ )
+}
+
+export async function getStaticProps() {
+ const allPostsData = getSortedPostsData()
+ return {
+ props: {
+ allPostsData
+ }
+ }
+}
diff --git a/dynamic-routes-starter/pages/posts/first-post.js b/dynamic-routes-starter/pages/posts/first-post.js
new file mode 100644
index 0000000..887057f
--- /dev/null
+++ b/dynamic-routes-starter/pages/posts/first-post.js
@@ -0,0 +1,19 @@
+import Head from 'next/head'
+import Link from 'next/link'
+import Layout from '../../components/layout'
+
+export default function FirstPost() {
+ return (
+
+
+ First Post
+
+ First Post
+
+
+ )
+}
diff --git a/dynamic-routes-starter/posts/dps.md b/dynamic-routes-starter/posts/dps.md
new file mode 100644
index 0000000..878a33d
--- /dev/null
+++ b/dynamic-routes-starter/posts/dps.md
@@ -0,0 +1,12 @@
+---
+title: "DPS: Develop, Preview, Ship"
+date: "2020-01-02"
+---
+
+[ZEIT Now](https://zeit.co/) supports the **DPS** workflow: **D**evelop, **P**review, and **S**hip:
+
+- **Develop**: Write code in Next.js. Keep the development server running and take advantage of its hot code reloading feature.
+- **Preview**: Every time you push changes to a branch on GitHub / GitLab / BitBucket, ZEIT Now automatically creates a new deployment with a unique URL.
+- **Ship**: When you’re ready to ship, merge the pull request to your default branch (e.g. `master`). ZEIT Now will automatically create a production deployment.
+
+By using the DPS workflow, in addition to doing code reviews, you can do *deployment previews*. Each deployment creates a unique URL that can be shared or used for integration tests.
\ No newline at end of file
diff --git a/dynamic-routes-starter/posts/pre-rendering.md b/dynamic-routes-starter/posts/pre-rendering.md
new file mode 100644
index 0000000..78cc081
--- /dev/null
+++ b/dynamic-routes-starter/posts/pre-rendering.md
@@ -0,0 +1,11 @@
+---
+title: "Two Forms of Pre-rendering"
+date: "2020-01-01"
+---
+
+[Next.js](https://nextjs.org/) has two forms of pre-rendering: **Static Generation** and **Server-side Rendering**. The difference is in **when** it generates the HTML for a page.
+
+- **Static Generation (Recommended)**: The HTML is generated at **build time** and will be reused on each request.
+- **Server-side Rendering**: The HTML is generated on **each request**.
+
+Importantly, Next.js lets you **choose** which pre-rendering form you'd like 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.
\ No newline at end of file
diff --git a/dynamic-routes-starter/public/favicon.ico b/dynamic-routes-starter/public/favicon.ico
new file mode 100644
index 0000000..4965832
Binary files /dev/null and b/dynamic-routes-starter/public/favicon.ico differ
diff --git a/dynamic-routes-starter/public/images/profile.jpg b/dynamic-routes-starter/public/images/profile.jpg
new file mode 100644
index 0000000..798aba3
Binary files /dev/null and b/dynamic-routes-starter/public/images/profile.jpg differ
diff --git a/dynamic-routes-starter/styles/global.css b/dynamic-routes-starter/styles/global.css
new file mode 100644
index 0000000..9e1b0fb
--- /dev/null
+++ b/dynamic-routes-starter/styles/global.css
@@ -0,0 +1,27 @@
+html,
+body {
+ padding: 0;
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
+ Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+ line-height: 1.6;
+ font-size: 18px;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+a {
+ color: #0070f3;
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+img {
+ max-width: 100%;
+ display: block;
+}
diff --git a/dynamic-routes-starter/styles/utils.module.css b/dynamic-routes-starter/styles/utils.module.css
new file mode 100644
index 0000000..37f545e
--- /dev/null
+++ b/dynamic-routes-starter/styles/utils.module.css
@@ -0,0 +1,52 @@
+.heading2Xl {
+ font-size: 2.5rem;
+ line-height: 1.2;
+ font-weight: 800;
+ letter-spacing: -0.05rem;
+ margin: 1rem 0;
+}
+
+.headingXl {
+ font-size: 2rem;
+ line-height: 1.3;
+ font-weight: 800;
+ letter-spacing: -0.05rem;
+ margin: 1rem 0;
+}
+
+.headingLg {
+ font-size: 1.5rem;
+ line-height: 1.4;
+ margin: 1rem 0;
+}
+
+.headingMd {
+ font-size: 1.2rem;
+ line-height: 1.5;
+}
+
+.borderCircle {
+ border-radius: 9999px;
+}
+
+.colorInherit {
+ color: inherit;
+}
+
+.padding1px {
+ padding-top: 1px;
+}
+
+.list {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.listItem {
+ margin: 0 0 1.25rem;
+}
+
+.lightText {
+ color: #666;
+}
diff --git a/license.md b/license.md
new file mode 100644
index 0000000..4a8b342
--- /dev/null
+++ b/license.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016-present ZEIT, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/navigate-between-pages-starter/.gitignore b/navigate-between-pages-starter/.gitignore
new file mode 100644
index 0000000..922d92a
--- /dev/null
+++ b/navigate-between-pages-starter/.gitignore
@@ -0,0 +1,25 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+.env*
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
diff --git a/navigate-between-pages-starter/README.md b/navigate-between-pages-starter/README.md
new file mode 100644
index 0000000..02695bc
--- /dev/null
+++ b/navigate-between-pages-starter/README.md
@@ -0,0 +1 @@
+This is a starter template for [Learn Next.js](https://nextjs.org/learn).
\ No newline at end of file
diff --git a/navigate-between-pages-starter/package.json b/navigate-between-pages-starter/package.json
new file mode 100644
index 0000000..899e758
--- /dev/null
+++ b/navigate-between-pages-starter/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "my-app",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start"
+ },
+ "dependencies": {
+ "next": "9.3.4",
+ "react": "16.13.1",
+ "react-dom": "16.13.1"
+ }
+}
diff --git a/navigate-between-pages-starter/pages/index.js b/navigate-between-pages-starter/pages/index.js
new file mode 100644
index 0000000..25715fb
--- /dev/null
+++ b/navigate-between-pages-starter/pages/index.js
@@ -0,0 +1,203 @@
+import Head from 'next/head'
+
+const Home = () => (
+
+
+
Create Next App
+
+
+
+
+
+
+
+ Get started by editing pages/index.js
+
+
+
+
+
+
+
+
+
+
+
+)
+
+export default Home
diff --git a/navigate-between-pages-starter/public/favicon.ico b/navigate-between-pages-starter/public/favicon.ico
new file mode 100644
index 0000000..4965832
Binary files /dev/null and b/navigate-between-pages-starter/public/favicon.ico differ
diff --git a/navigate-between-pages-starter/public/zeit.svg b/navigate-between-pages-starter/public/zeit.svg
new file mode 100644
index 0000000..dd3916c
--- /dev/null
+++ b/navigate-between-pages-starter/public/zeit.svg
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..7a8dc16
--- /dev/null
+++ b/package.json
@@ -0,0 +1,14 @@
+{
+ "private": true,
+ "license": "MIT",
+ "husky": {
+ "hooks": {
+ "pre-commit": "pretty-quick --staged"
+ }
+ },
+ "devDependencies": {
+ "prettier": "^2.0.2",
+ "pretty-quick": "2.0.1",
+ "husky": "4.2.3"
+ }
+}
diff --git a/typescript-final/.gitignore b/typescript-final/.gitignore
new file mode 100644
index 0000000..922d92a
--- /dev/null
+++ b/typescript-final/.gitignore
@@ -0,0 +1,25 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+.env*
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
diff --git a/typescript-final/README.md b/typescript-final/README.md
new file mode 100644
index 0000000..02695bc
--- /dev/null
+++ b/typescript-final/README.md
@@ -0,0 +1 @@
+This is a starter template for [Learn Next.js](https://nextjs.org/learn).
\ No newline at end of file
diff --git a/typescript-final/components/date.tsx b/typescript-final/components/date.tsx
new file mode 100644
index 0000000..70662ea
--- /dev/null
+++ b/typescript-final/components/date.tsx
@@ -0,0 +1,6 @@
+import { parseISO, format } from 'date-fns'
+
+export default function Date({ dateString }: { dateString: string }) {
+ const date = parseISO(dateString)
+ return {format(date, 'LLLL d, yyyy')}
+}
diff --git a/typescript-final/components/layout.module.css b/typescript-final/components/layout.module.css
new file mode 100644
index 0000000..d0e3a8f
--- /dev/null
+++ b/typescript-final/components/layout.module.css
@@ -0,0 +1,25 @@
+.container {
+ max-width: 36rem;
+ padding: 0 1rem;
+ margin: 3rem auto 6rem;
+}
+
+.header {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.headerImage {
+ width: 6rem;
+ height: 6rem;
+}
+
+.headerHomeImage {
+ width: 8rem;
+ height: 8rem;
+}
+
+.backToHome {
+ margin: 3rem 0 0;
+}
diff --git a/typescript-final/components/layout.tsx b/typescript-final/components/layout.tsx
new file mode 100644
index 0000000..428a0d3
--- /dev/null
+++ b/typescript-final/components/layout.tsx
@@ -0,0 +1,70 @@
+import Head from 'next/head'
+import styles from './layout.module.css'
+import utilStyles from '../styles/utils.module.css'
+import Link from 'next/link'
+
+const name = '[Your Name]'
+export const siteTitle = 'Next.js Sample Website'
+
+export default function Layout({
+ children,
+ home
+}: {
+ children: React.ReactNode
+ home?: boolean
+}) {
+ return (
+
+
+
+
+
+
+
+ {home ? (
+ <>
+
+ {name}
+ >
+ ) : (
+ <>
+
+
+
+
+
+
+ >
+ )}
+
+
{children}
+ {!home && (
+
+ )}
+
+ )
+}
diff --git a/typescript-final/global.d.ts b/typescript-final/global.d.ts
new file mode 100644
index 0000000..b681c31
--- /dev/null
+++ b/typescript-final/global.d.ts
@@ -0,0 +1,4 @@
+declare module 'remark-html' {
+ const html: any
+ export default html
+}
diff --git a/typescript-final/lib/posts.ts b/typescript-final/lib/posts.ts
new file mode 100644
index 0000000..a7d4db7
--- /dev/null
+++ b/typescript-final/lib/posts.ts
@@ -0,0 +1,69 @@
+import fs from 'fs'
+import path from 'path'
+import matter from 'gray-matter'
+import remark from 'remark'
+import html from 'remark-html'
+
+const postsDirectory = path.join(process.cwd(), 'posts')
+
+export function getSortedPostsData() {
+ // Get file names under /posts
+ const fileNames = fs.readdirSync(postsDirectory)
+ const allPostsData = fileNames.map(fileName => {
+ // Remove ".md" from file name to get id
+ const id = fileName.replace(/\.md$/, '')
+
+ // Read markdown file as string
+ const fullPath = path.join(postsDirectory, fileName)
+ const fileContents = fs.readFileSync(fullPath, 'utf8')
+
+ // Use gray-matter to parse the post metadata section
+ const matterResult = matter(fileContents)
+
+ // Combine the data with the id
+ return {
+ id,
+ ...(matterResult.data as { date: string; title: string })
+ }
+ })
+ // Sort posts by date
+ return allPostsData.sort((a, b) => {
+ if (a.date < b.date) {
+ return 1
+ } else {
+ return -1
+ }
+ })
+}
+
+export function getAllPostIds() {
+ const fileNames = fs.readdirSync(postsDirectory)
+ return fileNames.map(fileName => {
+ return {
+ params: {
+ id: fileName.replace(/\.md$/, '')
+ }
+ }
+ })
+}
+
+export async function getPostData(id: string) {
+ const fullPath = path.join(postsDirectory, `${id}.md`)
+ const fileContents = fs.readFileSync(fullPath, 'utf8')
+
+ // Use gray-matter to parse the post metadata section
+ const matterResult = matter(fileContents)
+
+ // Use remark to convert markdown into HTML string
+ const processedContent = await remark()
+ .use(html)
+ .process(matterResult.content)
+ const contentHtml = processedContent.toString()
+
+ // Combine the data with the id and contentHtml
+ return {
+ id,
+ contentHtml,
+ ...(matterResult.data as { date: string; title: string })
+ }
+}
diff --git a/typescript-final/next-env.d.ts b/typescript-final/next-env.d.ts
new file mode 100644
index 0000000..7b7aa2c
--- /dev/null
+++ b/typescript-final/next-env.d.ts
@@ -0,0 +1,2 @@
+///
+///
diff --git a/typescript-final/package.json b/typescript-final/package.json
new file mode 100644
index 0000000..9dace70
--- /dev/null
+++ b/typescript-final/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "my-app",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start"
+ },
+ "dependencies": {
+ "date-fns": "^2.11.1",
+ "gray-matter": "^4.0.2",
+ "next": "9.3.4",
+ "react": "16.13.1",
+ "react-dom": "16.13.1",
+ "remark": "^12.0.0",
+ "remark-html": "^11.0.1"
+ },
+ "devDependencies": {
+ "@types/node": "^13.11.0",
+ "@types/react": "^16.9.32",
+ "typescript": "^3.8.3"
+ }
+}
diff --git a/typescript-final/pages/_app.tsx b/typescript-final/pages/_app.tsx
new file mode 100644
index 0000000..6cdcdc2
--- /dev/null
+++ b/typescript-final/pages/_app.tsx
@@ -0,0 +1,6 @@
+import '../styles/global.css'
+import { AppProps } from 'next/app'
+
+export default function App({ Component, pageProps }: AppProps) {
+ return
+}
diff --git a/typescript-final/pages/api/hello.ts b/typescript-final/pages/api/hello.ts
new file mode 100644
index 0000000..7cf37be
--- /dev/null
+++ b/typescript-final/pages/api/hello.ts
@@ -0,0 +1,5 @@
+import { NextApiRequest, NextApiResponse } from 'next'
+
+export default (_: NextApiRequest, res: NextApiResponse) => {
+ res.status(200).json({ text: 'Hello' })
+}
diff --git a/typescript-final/pages/index.tsx b/typescript-final/pages/index.tsx
new file mode 100644
index 0000000..39d4bd1
--- /dev/null
+++ b/typescript-final/pages/index.tsx
@@ -0,0 +1,57 @@
+import Head from 'next/head'
+import Layout, { siteTitle } from '../components/layout'
+import utilStyles from '../styles/utils.module.css'
+import { getSortedPostsData } from '../lib/posts'
+import Link from 'next/link'
+import Date from '../components/date'
+import { GetStaticProps } from 'next'
+
+export default function Home({
+ allPostsData
+}: {
+ allPostsData: {
+ date: string
+ title: string
+ id: string
+ }[]
+}) {
+ return (
+
+
+ {siteTitle}
+
+
+ [Your Self Introduction]
+
+ (This is a sample website - you’ll be building a site like this on{' '}
+ our Next.js tutorial .)
+
+
+
+ Blog
+
+ {allPostsData.map(({ id, date, title }) => (
+
+
+ {title}
+
+
+
+
+
+
+ ))}
+
+
+
+ )
+}
+
+export const getStaticProps: GetStaticProps = async () => {
+ const allPostsData = getSortedPostsData()
+ return {
+ props: {
+ allPostsData
+ }
+ }
+}
diff --git a/typescript-final/pages/posts/[id].tsx b/typescript-final/pages/posts/[id].tsx
new file mode 100644
index 0000000..ffe4bdd
--- /dev/null
+++ b/typescript-final/pages/posts/[id].tsx
@@ -0,0 +1,48 @@
+import Layout from '../../components/layout'
+import { getAllPostIds, getPostData } from '../../lib/posts'
+import Head from 'next/head'
+import Date from '../../components/date'
+import utilStyles from '../../styles/utils.module.css'
+import { GetStaticProps, GetStaticPaths } from 'next'
+
+export default function Post({
+ postData
+}: {
+ postData: {
+ title: string
+ date: string
+ contentHtml: string
+ }
+}) {
+ return (
+
+
+ {postData.title}
+
+
+ {postData.title}
+
+
+
+
+
+
+ )
+}
+
+export const getStaticPaths: GetStaticPaths = async () => {
+ const paths = getAllPostIds()
+ return {
+ paths,
+ fallback: false
+ }
+}
+
+export const getStaticProps: GetStaticProps = async ({ params }) => {
+ const postData = await getPostData(params.id as string)
+ return {
+ props: {
+ postData
+ }
+ }
+}
diff --git a/typescript-final/posts/dps.md b/typescript-final/posts/dps.md
new file mode 100644
index 0000000..878a33d
--- /dev/null
+++ b/typescript-final/posts/dps.md
@@ -0,0 +1,12 @@
+---
+title: "DPS: Develop, Preview, Ship"
+date: "2020-01-02"
+---
+
+[ZEIT Now](https://zeit.co/) supports the **DPS** workflow: **D**evelop, **P**review, and **S**hip:
+
+- **Develop**: Write code in Next.js. Keep the development server running and take advantage of its hot code reloading feature.
+- **Preview**: Every time you push changes to a branch on GitHub / GitLab / BitBucket, ZEIT Now automatically creates a new deployment with a unique URL.
+- **Ship**: When you’re ready to ship, merge the pull request to your default branch (e.g. `master`). ZEIT Now will automatically create a production deployment.
+
+By using the DPS workflow, in addition to doing code reviews, you can do *deployment previews*. Each deployment creates a unique URL that can be shared or used for integration tests.
\ No newline at end of file
diff --git a/typescript-final/posts/pre-rendering.md b/typescript-final/posts/pre-rendering.md
new file mode 100644
index 0000000..78cc081
--- /dev/null
+++ b/typescript-final/posts/pre-rendering.md
@@ -0,0 +1,11 @@
+---
+title: "Two Forms of Pre-rendering"
+date: "2020-01-01"
+---
+
+[Next.js](https://nextjs.org/) has two forms of pre-rendering: **Static Generation** and **Server-side Rendering**. The difference is in **when** it generates the HTML for a page.
+
+- **Static Generation (Recommended)**: The HTML is generated at **build time** and will be reused on each request.
+- **Server-side Rendering**: The HTML is generated on **each request**.
+
+Importantly, Next.js lets you **choose** which pre-rendering form you'd like 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.
\ No newline at end of file
diff --git a/typescript-final/public/favicon.ico b/typescript-final/public/favicon.ico
new file mode 100644
index 0000000..4965832
Binary files /dev/null and b/typescript-final/public/favicon.ico differ
diff --git a/typescript-final/public/images/profile.jpg b/typescript-final/public/images/profile.jpg
new file mode 100644
index 0000000..798aba3
Binary files /dev/null and b/typescript-final/public/images/profile.jpg differ
diff --git a/typescript-final/styles/global.css b/typescript-final/styles/global.css
new file mode 100644
index 0000000..9e1b0fb
--- /dev/null
+++ b/typescript-final/styles/global.css
@@ -0,0 +1,27 @@
+html,
+body {
+ padding: 0;
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
+ Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+ line-height: 1.6;
+ font-size: 18px;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+a {
+ color: #0070f3;
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+img {
+ max-width: 100%;
+ display: block;
+}
diff --git a/typescript-final/styles/utils.module.css b/typescript-final/styles/utils.module.css
new file mode 100644
index 0000000..37f545e
--- /dev/null
+++ b/typescript-final/styles/utils.module.css
@@ -0,0 +1,52 @@
+.heading2Xl {
+ font-size: 2.5rem;
+ line-height: 1.2;
+ font-weight: 800;
+ letter-spacing: -0.05rem;
+ margin: 1rem 0;
+}
+
+.headingXl {
+ font-size: 2rem;
+ line-height: 1.3;
+ font-weight: 800;
+ letter-spacing: -0.05rem;
+ margin: 1rem 0;
+}
+
+.headingLg {
+ font-size: 1.5rem;
+ line-height: 1.4;
+ margin: 1rem 0;
+}
+
+.headingMd {
+ font-size: 1.2rem;
+ line-height: 1.5;
+}
+
+.borderCircle {
+ border-radius: 9999px;
+}
+
+.colorInherit {
+ color: inherit;
+}
+
+.padding1px {
+ padding-top: 1px;
+}
+
+.list {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.listItem {
+ margin: 0 0 1.25rem;
+}
+
+.lightText {
+ color: #666;
+}
diff --git a/typescript-final/tsconfig.json b/typescript-final/tsconfig.json
new file mode 100644
index 0000000..48ca14a
--- /dev/null
+++ b/typescript-final/tsconfig.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "forceConsistentCasingInFileNames": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve"
+ },
+ "exclude": [
+ "node_modules"
+ ],
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx"
+ ]
+}
diff --git a/typescript-starter/.gitignore b/typescript-starter/.gitignore
new file mode 100644
index 0000000..922d92a
--- /dev/null
+++ b/typescript-starter/.gitignore
@@ -0,0 +1,25 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+.env*
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
diff --git a/typescript-starter/README.md b/typescript-starter/README.md
new file mode 100644
index 0000000..02695bc
--- /dev/null
+++ b/typescript-starter/README.md
@@ -0,0 +1 @@
+This is a starter template for [Learn Next.js](https://nextjs.org/learn).
\ No newline at end of file
diff --git a/typescript-starter/components/date.js b/typescript-starter/components/date.js
new file mode 100644
index 0000000..0ec71d3
--- /dev/null
+++ b/typescript-starter/components/date.js
@@ -0,0 +1,6 @@
+import { parseISO, format } from 'date-fns'
+
+export default function Date({ dateString }) {
+ const date = parseISO(dateString)
+ return {format(date, 'LLLL d, yyyy')}
+}
diff --git a/typescript-starter/components/layout.js b/typescript-starter/components/layout.js
new file mode 100644
index 0000000..cff0cca
--- /dev/null
+++ b/typescript-starter/components/layout.js
@@ -0,0 +1,64 @@
+import Head from 'next/head'
+import styles from './layout.module.css'
+import utilStyles from '../styles/utils.module.css'
+import Link from 'next/link'
+
+const name = '[Your Name]'
+export const siteTitle = 'Next.js Sample Website'
+
+export default function Layout({ children, home }) {
+ return (
+
+
+
+
+
+
+
+ {home ? (
+ <>
+
+ {name}
+ >
+ ) : (
+ <>
+
+
+
+
+
+
+ >
+ )}
+
+
{children}
+ {!home && (
+
+ )}
+
+ )
+}
diff --git a/typescript-starter/components/layout.module.css b/typescript-starter/components/layout.module.css
new file mode 100644
index 0000000..d0e3a8f
--- /dev/null
+++ b/typescript-starter/components/layout.module.css
@@ -0,0 +1,25 @@
+.container {
+ max-width: 36rem;
+ padding: 0 1rem;
+ margin: 3rem auto 6rem;
+}
+
+.header {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.headerImage {
+ width: 6rem;
+ height: 6rem;
+}
+
+.headerHomeImage {
+ width: 8rem;
+ height: 8rem;
+}
+
+.backToHome {
+ margin: 3rem 0 0;
+}
diff --git a/typescript-starter/lib/posts.js b/typescript-starter/lib/posts.js
new file mode 100644
index 0000000..53d8653
--- /dev/null
+++ b/typescript-starter/lib/posts.js
@@ -0,0 +1,69 @@
+import fs from 'fs'
+import path from 'path'
+import matter from 'gray-matter'
+import remark from 'remark'
+import html from 'remark-html'
+
+const postsDirectory = path.join(process.cwd(), 'posts')
+
+export function getSortedPostsData() {
+ // Get file names under /posts
+ const fileNames = fs.readdirSync(postsDirectory)
+ const allPostsData = fileNames.map(fileName => {
+ // Remove ".md" from file name to get id
+ const id = fileName.replace(/\.md$/, '')
+
+ // Read markdown file as string
+ const fullPath = path.join(postsDirectory, fileName)
+ const fileContents = fs.readFileSync(fullPath, 'utf8')
+
+ // Use gray-matter to parse the post metadata section
+ const matterResult = matter(fileContents)
+
+ // Combine the data with the id
+ return {
+ id,
+ ...matterResult.data
+ }
+ })
+ // Sort posts by date
+ return allPostsData.sort((a, b) => {
+ if (a.date < b.date) {
+ return 1
+ } else {
+ return -1
+ }
+ })
+}
+
+export function getAllPostIds() {
+ const fileNames = fs.readdirSync(postsDirectory)
+ return fileNames.map(fileName => {
+ return {
+ params: {
+ id: fileName.replace(/\.md$/, '')
+ }
+ }
+ })
+}
+
+export async function getPostData(id) {
+ const fullPath = path.join(postsDirectory, `${id}.md`)
+ const fileContents = fs.readFileSync(fullPath, 'utf8')
+
+ // Use gray-matter to parse the post metadata section
+ const matterResult = matter(fileContents)
+
+ // Use remark to convert markdown into HTML string
+ const processedContent = await remark()
+ .use(html)
+ .process(matterResult.content)
+ const contentHtml = processedContent.toString()
+
+ // Combine the data with the id and contentHtml
+ return {
+ id,
+ contentHtml,
+ ...matterResult.data
+ }
+}
diff --git a/typescript-starter/package.json b/typescript-starter/package.json
new file mode 100644
index 0000000..b879f50
--- /dev/null
+++ b/typescript-starter/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "my-app",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start"
+ },
+ "dependencies": {
+ "date-fns": "^2.11.1",
+ "gray-matter": "^4.0.2",
+ "next": "9.3.4",
+ "react": "16.13.1",
+ "react-dom": "16.13.1",
+ "remark": "^12.0.0",
+ "remark-html": "^11.0.1"
+ }
+}
diff --git a/typescript-starter/pages/_app.js b/typescript-starter/pages/_app.js
new file mode 100644
index 0000000..7e66efc
--- /dev/null
+++ b/typescript-starter/pages/_app.js
@@ -0,0 +1,5 @@
+import '../styles/global.css'
+
+export default function App({ Component, pageProps }) {
+ return
+}
diff --git a/typescript-starter/pages/api/hello.js b/typescript-starter/pages/api/hello.js
new file mode 100644
index 0000000..2e22ab3
--- /dev/null
+++ b/typescript-starter/pages/api/hello.js
@@ -0,0 +1,3 @@
+export default (req, res) => {
+ res.status(200).json({ text: 'Hello' })
+}
diff --git a/typescript-starter/pages/index.js b/typescript-starter/pages/index.js
new file mode 100644
index 0000000..0f9494b
--- /dev/null
+++ b/typescript-starter/pages/index.js
@@ -0,0 +1,48 @@
+import Head from 'next/head'
+import Layout, { siteTitle } from '../components/layout'
+import utilStyles from '../styles/utils.module.css'
+import { getSortedPostsData } from '../lib/posts'
+import Link from 'next/link'
+import Date from '../components/date'
+
+export default function Home({ allPostsData }) {
+ return (
+
+
+ {siteTitle}
+
+
+ [Your Self Introduction]
+
+ (This is a sample website - you’ll be building a site like this on{' '}
+ our Next.js tutorial .)
+
+
+
+ Blog
+
+ {allPostsData.map(({ id, date, title }) => (
+
+
+ {title}
+
+
+
+
+
+
+ ))}
+
+
+
+ )
+}
+
+export async function getStaticProps() {
+ const allPostsData = getSortedPostsData()
+ return {
+ props: {
+ allPostsData
+ }
+ }
+}
diff --git a/typescript-starter/pages/posts/[id].js b/typescript-starter/pages/posts/[id].js
new file mode 100644
index 0000000..28faaad
--- /dev/null
+++ b/typescript-starter/pages/posts/[id].js
@@ -0,0 +1,39 @@
+import Layout from '../../components/layout'
+import { getAllPostIds, getPostData } from '../../lib/posts'
+import Head from 'next/head'
+import Date from '../../components/date'
+import utilStyles from '../../styles/utils.module.css'
+
+export default function Post({ postData }) {
+ return (
+
+
+ {postData.title}
+
+
+ {postData.title}
+
+
+
+
+
+
+ )
+}
+
+export async function getStaticPaths() {
+ const paths = getAllPostIds()
+ return {
+ paths,
+ fallback: false
+ }
+}
+
+export async function getStaticProps({ params }) {
+ const postData = await getPostData(params.id)
+ return {
+ props: {
+ postData
+ }
+ }
+}
diff --git a/typescript-starter/posts/dps.md b/typescript-starter/posts/dps.md
new file mode 100644
index 0000000..878a33d
--- /dev/null
+++ b/typescript-starter/posts/dps.md
@@ -0,0 +1,12 @@
+---
+title: "DPS: Develop, Preview, Ship"
+date: "2020-01-02"
+---
+
+[ZEIT Now](https://zeit.co/) supports the **DPS** workflow: **D**evelop, **P**review, and **S**hip:
+
+- **Develop**: Write code in Next.js. Keep the development server running and take advantage of its hot code reloading feature.
+- **Preview**: Every time you push changes to a branch on GitHub / GitLab / BitBucket, ZEIT Now automatically creates a new deployment with a unique URL.
+- **Ship**: When you’re ready to ship, merge the pull request to your default branch (e.g. `master`). ZEIT Now will automatically create a production deployment.
+
+By using the DPS workflow, in addition to doing code reviews, you can do *deployment previews*. Each deployment creates a unique URL that can be shared or used for integration tests.
\ No newline at end of file
diff --git a/typescript-starter/posts/pre-rendering.md b/typescript-starter/posts/pre-rendering.md
new file mode 100644
index 0000000..78cc081
--- /dev/null
+++ b/typescript-starter/posts/pre-rendering.md
@@ -0,0 +1,11 @@
+---
+title: "Two Forms of Pre-rendering"
+date: "2020-01-01"
+---
+
+[Next.js](https://nextjs.org/) has two forms of pre-rendering: **Static Generation** and **Server-side Rendering**. The difference is in **when** it generates the HTML for a page.
+
+- **Static Generation (Recommended)**: The HTML is generated at **build time** and will be reused on each request.
+- **Server-side Rendering**: The HTML is generated on **each request**.
+
+Importantly, Next.js lets you **choose** which pre-rendering form you'd like 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.
\ No newline at end of file
diff --git a/typescript-starter/public/favicon.ico b/typescript-starter/public/favicon.ico
new file mode 100644
index 0000000..4965832
Binary files /dev/null and b/typescript-starter/public/favicon.ico differ
diff --git a/typescript-starter/public/images/profile.jpg b/typescript-starter/public/images/profile.jpg
new file mode 100644
index 0000000..798aba3
Binary files /dev/null and b/typescript-starter/public/images/profile.jpg differ
diff --git a/typescript-starter/styles/global.css b/typescript-starter/styles/global.css
new file mode 100644
index 0000000..9e1b0fb
--- /dev/null
+++ b/typescript-starter/styles/global.css
@@ -0,0 +1,27 @@
+html,
+body {
+ padding: 0;
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
+ Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+ line-height: 1.6;
+ font-size: 18px;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+a {
+ color: #0070f3;
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+img {
+ max-width: 100%;
+ display: block;
+}
diff --git a/typescript-starter/styles/utils.module.css b/typescript-starter/styles/utils.module.css
new file mode 100644
index 0000000..37f545e
--- /dev/null
+++ b/typescript-starter/styles/utils.module.css
@@ -0,0 +1,52 @@
+.heading2Xl {
+ font-size: 2.5rem;
+ line-height: 1.2;
+ font-weight: 800;
+ letter-spacing: -0.05rem;
+ margin: 1rem 0;
+}
+
+.headingXl {
+ font-size: 2rem;
+ line-height: 1.3;
+ font-weight: 800;
+ letter-spacing: -0.05rem;
+ margin: 1rem 0;
+}
+
+.headingLg {
+ font-size: 1.5rem;
+ line-height: 1.4;
+ margin: 1rem 0;
+}
+
+.headingMd {
+ font-size: 1.2rem;
+ line-height: 1.5;
+}
+
+.borderCircle {
+ border-radius: 9999px;
+}
+
+.colorInherit {
+ color: inherit;
+}
+
+.padding1px {
+ padding-top: 1px;
+}
+
+.list {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.listItem {
+ margin: 0 0 1.25rem;
+}
+
+.lightText {
+ color: #666;
+}