-
Notifications
You must be signed in to change notification settings - Fork 27.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* initial commit * delete comment * env name fix * Update README.md * remove hapi-boom * use next-image * fix alt attr * date fix for blog posts * reset gitignore * fix react best-practices * prettier * mdx to md * fix prettier config. lint 👍 * Update examples/blog-with-comment/components/comment/list.js Co-authored-by: Lee Robinson <me@leerob.io> * refactor api methods * fix: blog title * fix: html lang * next-mdx to gray-matter Co-authored-by: Noah Fischer <78238464+noahfschr@users.noreply.github.com> Co-authored-by: Lee Robinson <me@leerob.io> Co-authored-by: Enes Akar <enesakar@gmail.com>
- Loading branch information
1 parent
8227973
commit 5142c0e
Showing
32 changed files
with
842 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
REDIS_URL= | ||
NEXT_PUBLIC_AUTH0_CLIENT_ID= | ||
NEXT_PUBLIC_AUTH0_DOMAIN= | ||
NEXT_PUBLIC_AUTH0_ADMIN_EMAIL= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"singleQuote": true, | ||
"semi": false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# Blog with Comment | ||
|
||
This project adds commenting functionality to [Next.js blog application](https://github.com/vercel/next.js/tree/canary/examples/blog) using Upstash and Auth0. | ||
|
||
The comment box requires Auth0 authentication for users to add new comments. A user can delete their own comment. Also admin user can delete any comment. | ||
|
||
Comments are stored in Serverless Redis ([Upstash](http://upstash.com/)). | ||
|
||
### Demo | ||
|
||
[https://blog-with-comment.vercel.app/](https://blog-with-comment.vercel.app/) | ||
|
||
## `1` Project set up | ||
|
||
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 blog-with-comment blog-with-comment-app | ||
``` | ||
|
||
## `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 | ||
``` | ||
|
||
## `3` Configuring Upstash | ||
|
||
Go to the [Upstash Console](https://console.upstash.com/) and create a new database | ||
|
||
#### Upstash environment | ||
|
||
- `REDIS_URL`: Find the URL in the database details page in Upstash Console clicking on **Redis Connect** button. | ||
|
||
## `4` Configuring Auth0 | ||
|
||
1. Go to the [Auth0 dashboard](https://manage.auth0.com/) and create a new application of type **Single Page Web | ||
Applications**. | ||
2. Go to the settings page of the application | ||
3. Configure the following settings: | ||
- **Allowed Callback URLs**: Should be set to `http://localhost:3000/` when testing locally or typically | ||
to `https://myapp.com/` when deploying your application. | ||
- **Allowed Logout URLs**: Should be set to `http://localhost:3000/` when testing locally or typically | ||
to `https://myapp.com/` when deploying your application. | ||
4. Save the settings. | ||
|
||
#### Auth0 environment | ||
|
||
- `NEXT_PUBLIC_AUTH0_DOMAIN`: Can be found in the Auth0 dashboard under `settings`. | ||
- `NEXT_PUBLIC_AUTH0_CLIENT_ID`: Can be found in the Auth0 dashboard under `settings`. | ||
- `NEXT_PUBLIC_AUTH0_ADMIN_EMAIL`: This is the email of the admin user which you use while singing in Auth0. Admin is able to delete any comment. | ||
|
||
## Deploy Your Local Project | ||
|
||
To deploy your local project to Vercel, push it to GitHub/GitLab/Bitbucket | ||
and [import to Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=upstash-roadmap). | ||
|
||
**Important**: When you import your project on Vercel, make sure to click on **Environment Variables** and set them to | ||
match your `.env.local` file. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
--- | ||
title: "A Long-expected Party" | ||
excerpt: "Gandalf arrives in the Shire for Bilbo's Farewell Birthday Party. | ||
Bilbo leaves the Shire permanently." | ||
date: "2021-03-02" | ||
--- | ||
|
||
Placeat consequuntur ullam aut sapiente illo velit. Eius facere ut molestias | ||
totam laborum pariatur quam. Praesentium quo veritatis expedita animi. | ||
|
||
Quite anything glass benefit. Such form clearly top tend can require my. Federal | ||
degree sort performance region maintain. | ||
|
||
Ut dignissimos sapiente culpa rerum pariatur consequatur. Corporis suscipit ad | ||
corrupti aut. Expedita culpa aut deleniti officiis. | ||
|
||
Porro eum id sit quia expedita. Alias expedita asperiores. Corporis ex eum atque | ||
cum ea. |
18 changes: 18 additions & 0 deletions
18
examples/blog-with-comment/_posts/passing-of-grey-company.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
--- | ||
title: "The Passing of the Grey Company" | ||
excerpt: "Aragorn, Legolas, and Gimli are accompanied by the Grey Company as | ||
they pass through the Paths of the Dead between Rohan and Gondor." | ||
date: "2021-01-22" | ||
--- | ||
|
||
Placeat consequuntur ullam aut sapiente illo velit. Eius facere ut molestias | ||
totam laborum pariatur quam. Praesentium quo veritatis expedita animi. | ||
|
||
Quite anything glass benefit. Such form clearly top tend can require my. Federal | ||
degree sort performance region maintain. | ||
|
||
Ut dignissimos sapiente culpa rerum pariatur consequatur. Corporis suscipit ad | ||
corrupti aut. Expedita culpa aut deleniti officiis. | ||
|
||
Porro eum id sit quia expedita. Alias expedita asperiores. Corporis ex eum atque | ||
cum ea. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
--- | ||
title: "At the Sign of the Prancing Pony" | ||
excerpt: "The Hobbits reach the The Prancing Pony inn at Bree, where Frodo uses | ||
a false name, Underhill." | ||
date: "2021-03-03" | ||
--- | ||
|
||
Placeat consequuntur ullam aut sapiente illo velit. Eius facere ut molestias | ||
totam laborum pariatur quam. Praesentium quo veritatis expedita animi. | ||
|
||
Quite anything glass benefit. Such form clearly top tend can require my. Federal | ||
degree sort performance region maintain. | ||
|
||
Ut dignissimos sapiente culpa rerum pariatur consequatur. Corporis suscipit ad | ||
corrupti aut. Expedita culpa aut deleniti officiis. | ||
|
||
Porro eum id sit quia expedita. Alias expedita asperiores. Corporis ex eum atque | ||
cum ea. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
--- | ||
title: "The Riders of Rohan" | ||
excerpt: "Aragorn, Legolas, and Gimli follow the trail of the Orcs and find | ||
several clues as to what happened with Merry and Pippin." | ||
date: "2021-02-01" | ||
--- | ||
|
||
Placeat consequuntur ullam aut sapiente illo velit. Eius facere ut molestias | ||
totam laborum pariatur quam. Praesentium quo veritatis expedita animi. | ||
|
||
Quite anything glass benefit. Such form clearly top tend can require my. Federal | ||
degree sort performance region maintain. | ||
|
||
Ut dignissimos sapiente culpa rerum pariatur consequatur. Corporis suscipit ad | ||
corrupti aut. Expedita culpa aut deleniti officiis. | ||
|
||
Porro eum id sit quia expedita. Alias expedita asperiores. Corporis ex eum atque | ||
cum ea. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { useAuth0 } from '@auth0/auth0-react' | ||
|
||
function CommentForm({ text, setText, onSubmit }) { | ||
const { isAuthenticated, logout, loginWithPopup } = useAuth0() | ||
|
||
return ( | ||
<form onSubmit={onSubmit}> | ||
<textarea | ||
className="flex w-full max-h-40 p-3 rounded resize-y bg-gray-200 text-gray-900 placeholder-gray-500" | ||
rows="2" | ||
placeholder={ | ||
isAuthenticated | ||
? `What are your thoughts?` | ||
: 'Please login to leave a comment' | ||
} | ||
onChange={(e) => setText(e.target.value)} | ||
value={text} | ||
disabled={!isAuthenticated} | ||
/> | ||
|
||
<div className="flex items-center mt-4"> | ||
{isAuthenticated ? ( | ||
<div className="flex items-center space-x-6"> | ||
<button className="py-2 px-4 rounded bg-blue-600 text-white disabled:opacity-40 hover:bg-blue-700"> | ||
Send | ||
</button> | ||
<button className="text-gray-500" onClick={() => logout()}> | ||
Log out | ||
</button> | ||
</div> | ||
) : ( | ||
<button | ||
type="button" | ||
className="py-2 px-4 rounded bg-blue-600 text-white disabled:opacity-40 hover:bg-blue-700" | ||
onClick={() => loginWithPopup()} | ||
> | ||
Log In | ||
</button> | ||
)} | ||
</div> | ||
</form> | ||
) | ||
} | ||
|
||
export default CommentForm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import CommentForm from './form' | ||
import CommentList from './list' | ||
import useComments from '../../hooks/useComment' | ||
|
||
function Comment() { | ||
const { text, setText, comments, onSubmit, onDelete } = useComments() | ||
|
||
return ( | ||
<div className="mt-20"> | ||
<CommentForm onSubmit={onSubmit} text={text} setText={setText} /> | ||
<CommentList comments={comments} onDelete={onDelete} /> | ||
</div> | ||
) | ||
} | ||
|
||
export default Comment |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import distanceToNow from '../../lib/dateRelative' | ||
import { useAuth0 } from '@auth0/auth0-react' | ||
|
||
function CommentList({ comments, onDelete }) { | ||
const { user } = useAuth0() | ||
|
||
return ( | ||
<div className="space-y-6 mt-10"> | ||
{comments.map((comment) => { | ||
const isAuthor = user && user.sub === comment.user.sub | ||
const isAdmin = | ||
user && user.email === process.env.NEXT_PUBLIC_AUTH0_ADMIN_EMAIL | ||
|
||
return ( | ||
<div key={comment.created_at} className="flex space-x-4"> | ||
<div className="flex-shrink-0"> | ||
<img | ||
src={comment.user.picture} | ||
alt={comment.user.name} | ||
width={40} | ||
height={40} | ||
className="rounded-full" | ||
/> | ||
</div> | ||
|
||
<div className="flex-grow"> | ||
<div className="flex space-x-2"> | ||
<b>{comment.user.name}</b> | ||
<time className="text-gray-400"> | ||
{distanceToNow(comment.created_at)} | ||
</time> | ||
{(isAdmin || isAuthor) && ( | ||
<button | ||
className="text-gray-400 hover:text-red-500" | ||
onClick={() => onDelete(comment)} | ||
aria-label="Close" | ||
> | ||
x | ||
</button> | ||
)} | ||
</div> | ||
|
||
<div>{comment.text}</div> | ||
</div> | ||
</div> | ||
) | ||
})} | ||
</div> | ||
) | ||
} | ||
|
||
export default CommentList |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
function Container({ children }) { | ||
return <div className="container max-w-2xl m-auto px-4">{children}</div> | ||
} | ||
|
||
export default Container |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import Link from 'next/link' | ||
import Container from '../components/container' | ||
|
||
function Header() { | ||
return ( | ||
<header className="py-6"> | ||
<Container> | ||
<nav className="flex space-x-4"> | ||
<Link href="/"> | ||
<a>About</a> | ||
</Link> | ||
<Link href="/posts"> | ||
<a>Posts</a> | ||
</Link> | ||
</nav> | ||
</Container> | ||
</header> | ||
) | ||
} | ||
|
||
export default Header |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { useState, useEffect } from 'react' | ||
import useSWR from 'swr' | ||
import { useAuth0 } from '@auth0/auth0-react' | ||
|
||
export default function useComments() { | ||
const { getAccessTokenSilently } = useAuth0() | ||
const [text, setText] = useState('') | ||
const [url, setUrl] = useState(null) | ||
|
||
const { data: comments, mutate } = useSWR( | ||
() => { | ||
const query = new URLSearchParams({ url }) | ||
return `/api/comment?${query.toString()}` | ||
}, | ||
{ | ||
initialData: [], | ||
} | ||
) | ||
|
||
useEffect(() => { | ||
const url = window.location.origin + window.location.pathname | ||
setUrl(url) | ||
}, []) | ||
|
||
const onSubmit = async (e) => { | ||
e.preventDefault() | ||
const token = await getAccessTokenSilently() | ||
|
||
try { | ||
await fetch('/api/comment', { | ||
method: 'POST', | ||
body: JSON.stringify({ url, text }), | ||
headers: { | ||
Authorization: token, | ||
'Content-Type': 'application/json', | ||
}, | ||
}) | ||
setText('') | ||
await mutate() | ||
} catch (err) { | ||
console.log(err) | ||
} | ||
} | ||
|
||
const onDelete = async (comment) => { | ||
const token = await getAccessTokenSilently() | ||
|
||
try { | ||
await fetch('/api/comment', { | ||
method: 'DELETE', | ||
body: JSON.stringify({ url, comment }), | ||
headers: { | ||
Authorization: token, | ||
'Content-Type': 'application/json', | ||
}, | ||
}) | ||
await mutate() | ||
} catch (err) { | ||
console.log(err) | ||
} | ||
} | ||
|
||
return { text, setText, comments, onSubmit, onDelete } | ||
} |
Oops, something went wrong.