Skip to content

Commit

Permalink
Merge branch 'canary' into font-defaults
Browse files Browse the repository at this point in the history
  • Loading branch information
timneutkens authored Nov 24, 2020
2 parents cc1f27d + 21e4c3f commit 67117f7
Show file tree
Hide file tree
Showing 53 changed files with 926 additions and 48 deletions.
2 changes: 1 addition & 1 deletion errors/next-image-unconfigured-host.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ module.exports = {

### Useful Links

- [Image Optimization Documetnation](https://nextjs.org/docs/basic-features/image-optimization)
- [Image Optimization Documentation](https://nextjs.org/docs/basic-features/image-optimization)
4 changes: 2 additions & 2 deletions examples/custom-server-koa/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
"start": "cross-env NODE_ENV=production node server.js"
},
"dependencies": {
"@koa/router": "^8.0.7",
"@koa/router": "^10.0.0",
"cross-env": "^5.2.0",
"koa": "^2.0.1",
"koa": "^2.13.0",
"next": "latest",
"react": "^16.7.0",
"react-dom": "^16.7.0"
Expand Down
2 changes: 1 addition & 1 deletion examples/custom-server-koa/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ app.prepare().then(() => {
ctx.respond = false
})

router.all('*', async (ctx) => {
router.all('(.*)', async (ctx) => {
await handle(ctx.req, ctx.res)
ctx.respond = false
})
Expand Down
6 changes: 6 additions & 0 deletions examples/with-mysql/.env.local.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Example .env.local file for MySQL Database credentials

MYSQL_HOST=
MYSQL_DATABASE=
MYSQL_USERNAME=
MYSQL_PASSWORD=
34 changes: 34 additions & 0 deletions examples/with-mysql/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# 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
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local

# vercel
.vercel
82 changes: 82 additions & 0 deletions examples/with-mysql/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# MySQL Example

This is an example of using [MySQL](https://www.mysql.com/) in a Next.js project.

## Demo

### [https://next-mysql.vercel.app](https://next-mysql.vercel.app/)

## Deploy your own

Once you have access to [the environment variables you'll need](#step-5-set-up-environment-variables), deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example):

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fwith-mysql&env=MYSQL_HOST,MYSQL_DATABASE,MYSQL_USERNAME,MYSQL_PASSWORD&project-name=nextjs-mysql&repo-name=nextjs-mysql&envDescription=Required%20to%20connect%20the%20app%20with%20MySQL&envLink=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fwith-mysql%23step-2-set-up-environment-variables&demo-title=Next.js%20%2B%20MySQL%20Demo&demo-description=A%20simple%20app%20demonstrating%20Next.js%20and%20MySQL%20&demo-url=https%3A%2F%2Fnext-mysql.vercel.app%2F)

## How to use

Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example:

```bash
npx create-next-app --example with-mysql next-mysql-app
# or
yarn create next-app --example with-mysql next-mysql-app
```

## Configuration

### Step 1. Set up a MySQL database

Set up a MySQL server either locally or any cloud provider.

### Step 2. Set up environment variables

Copy the `env.local.example` file in this directory to `.env.local` (which will be ignored by Git):

```bash
cp .env.local.example .env.local
```

Set each variable on `.env.local`:

- `MYSQL_HOST` - Your MySQL host URL.
- `MYSQL_DATABASE` - The name of the MySQL database you want to use.
- `MYSQL_USERNAME` - The name of the MySQL user with access to database.
- `MYSQL_PASSWORD` - The passowrd of the MySQL user.

### Step 3. Run migration script

You'll need to run a migration to create the necessary table for the example.

```bash
npm run migrate
# or
yarn migrate
```

### Step 4. Run Next.js in development mode

```bash
npm install
npm run dev
# or
yarn install
yarn dev
```

Your app should be up and running on [http://localhost:3000](http://localhost:3000)! If it doesn't work, post on [GitHub discussions](https://github.com/zeit/next.js/discussions).

## Deploy on Vercel

You can deploy this app to the cloud with [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).

#### Deploy Your Local Project

To deploy your local project to Vercel, push it to GitHub/GitLab/Bitbucket and [import to Vercel](https://vercel.com/import/git?utm_source=github&utm_medium=readme&utm_campaign=next-example).

**Important**: When you import your project on Vercel, make sure to click on **Environment Variables** and set them to match your `.env.local` file.

#### Deploy from Our Template

Alternatively, you can deploy using our template by clicking on the Deploy button below.

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fwith-mysql&env=MYSQL_HOST,MYSQL_DATABASE,MYSQL_USERNAME,MYSQL_PASSWORD&project-name=nextjs-mysql&repo-name=nextjs-mysql&envDescription=Required%20to%20connect%20the%20app%20with%20MySQL&envLink=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fwith-mysql%23step-2-set-up-environment-variables&demo-title=Next.js%20%2B%20MySQL%20Demo&demo-description=A%20simple%20app%20demonstrating%20Next.js%20and%20MySQL%20&demo-url=https%3A%2F%2Fnext-mysql.vercel.app%2F)
27 changes: 27 additions & 0 deletions examples/with-mysql/components/button-link/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Link from 'next/link'
import cn from 'clsx'

function ButtonLink({ href = '/', className = '', children }) {
return (
<Link href={href}>
<a
className={cn(
'bg-black',
'text-white',
'p-2',
'rounded',
'uppercase',
'text-sm',
'font-bold',
{
[className]: Boolean(className),
}
)}
>
{children}
</a>
</Link>
)
}

export default ButtonLink
33 changes: 33 additions & 0 deletions examples/with-mysql/components/button/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import cn from 'clsx'

function Button({
onClick = console.log,
className = '',
children = null,
type = null,
disabled = false,
}) {
return (
<button
type={type}
onClick={onClick}
disabled={disabled}
className={cn(
'bg-black',
'text-white',
'p-2',
'rounded',
'uppercase',
'text-sm',
'font-bold',
{
[className]: Boolean(className),
}
)}
>
{children}
</button>
)
}

export default Button
5 changes: 5 additions & 0 deletions examples/with-mysql/components/container/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
function Container({ className = '', children }) {
return <div className={'container mx-auto px-8 ' + className}>{children}</div>
}

export default Container
78 changes: 78 additions & 0 deletions examples/with-mysql/components/edit-entry-form/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { useState, useEffect } from 'react'
import Router, { useRouter } from 'next/router'

import Button from '../button'

export default function EntryForm() {
const [_title, setTitle] = useState('')
const [_content, setContent] = useState('')
const [submitting, setSubmitting] = useState(false)
const router = useRouter()
const { id, title, content } = router.query

useEffect(() => {
if (typeof title === 'string') {
setTitle(title)
}
if (typeof content === 'string') {
setContent(content)
}
}, [title, content])

async function submitHandler(e) {
e.preventDefault()
setSubmitting(true)
try {
const res = await fetch('/api/edit-entry', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
id,
title: _title,
content: _content,
}),
})
const json = await res.json()
setSubmitting(false)
if (!res.ok) throw Error(json.message)
Router.push('/')
} catch (e) {
throw Error(e.message)
}
}

return (
<form onSubmit={submitHandler}>
<div className="my-4">
<label htmlFor="title">
<h3 className="font-bold">Title</h3>
</label>
<input
id="title"
className="shadow border rounded w-full"
type="text"
name="title"
value={_title}
onChange={(e) => setTitle(e.target.value)}
/>
</div>
<div className="my-4">
<label htmlFor="content">
<h3 className="font-bold">Content</h3>
</label>
<textarea
className="shadow border resize-none focus:shadow-outline w-full h-48"
id="content"
name="content"
value={_content}
onChange={(e) => setContent(e.target.value)}
/>
</div>
<Button disabled={submitting} type="submit">
{submitting ? 'Saving ...' : 'Save'}
</Button>
</form>
)
}
46 changes: 46 additions & 0 deletions examples/with-mysql/components/entries/entry/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useState } from 'react'
import Link from 'next/link'
import { mutate } from 'swr'

import ButtonLink from '@/components/button-link'
import Button from '@/components/button'

function Entry({ id, title, content }) {
const [deleting, setDeleting] = useState(false)

async function deleteEntry() {
setDeleting(true)
let res = await fetch(`/api/delete-entry?id=${id}`, { method: 'DELETE' })
let json = await res.json()
if (!res.ok) throw Error(json.message)
mutate('/api/get-entries')
setDeleting(false)
}
return (
<div>
<div className="flex items-center">
<Link href={`/entry/${id}`}>
<a className="font-bold py-2">{title}</a>
</Link>
<div className="flex ml-4">
<ButtonLink
href={`/entry/edit/${id}?title=${title}&content=${content}`}
className="h-5 py-0 mx-1"
>
Edit
</ButtonLink>
<Button
disabled={deleting}
onClick={deleteEntry}
className="h-5 py-0 mx-1"
>
{deleting ? 'Deleting ...' : 'Delete'}
</Button>
</div>
</div>
<p>{content}</p>
</div>
)
}

export default Entry
19 changes: 19 additions & 0 deletions examples/with-mysql/components/entries/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Entry from './entry'

function Entries({ entries }) {
if (entries) {
return (
<div>
{entries.map((e) => (
<div key={e.id} className="py-2">
<Entry id={e.id} title={e.title} content={e.content} />
</div>
))}
</div>
)
} else {
return null
}
}

export default Entries
Loading

0 comments on commit 67117f7

Please sign in to comment.