-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 7fc5078
Showing
19 changed files
with
3,435 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,2 @@ | ||
UPSTASH_REDIS_REST_URL= | ||
UPSTASH_REDIS_REST_TOKEN= |
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,41 @@ | ||
# 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 | ||
.env.local | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
|
||
# Vercel | ||
.vercel | ||
|
||
# Turborepo | ||
.turbo | ||
|
||
# typescript | ||
*.tsbuildinfo |
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 @@ | ||
--- | ||
name: Vercel Cron Job Example | ||
slug: vercel-cron | ||
description: A Next.js app that uses Vercel Cron Jobs to update data at different intervals. | ||
framework: Next.js | ||
useCase: | ||
- Cron | ||
- Edge Functions | ||
css: Tailwind | ||
database: Vercel KV | ||
deployUrl: https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fexamples%2Ftree%2Fmain%2Fsolutions%2Fcron&project-name=cron&repository-name=cron&demo-title=Vercel%20Cron%20Job%20Example&demo-description=A%20Next.js%20app%20that%20uses%20Vercel%20Cron%20Jobs%20to%20update%20data%20at%20different%20intervals.&demo-url=https%3A%2F%2Fcron-template.vercel.app%2F&demo-image=https%3A%2F%2Fcron-template.vercel.app%2Fthumbnail.png&stores=%5B%7B"type"%3A"kv"%7D%5D | ||
demoUrl: https://cron-template.vercel.app/ | ||
relatedTemplates: | ||
- hacker-news-slack-bot | ||
- cron-og | ||
--- | ||
|
||
# Vercel Cron Job Example | ||
|
||
A Next.js app that uses [Vercel Cron Jobs](https://vercel.com/docs/cron-jobs) to update data at different intervals. | ||
|
||
## Demo | ||
|
||
https://cron-template.vercel.app/ | ||
|
||
## How to Use | ||
|
||
You can choose from one of the following two methods to use this repository: | ||
|
||
### One-Click Deploy | ||
|
||
Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=examples-repo): | ||
|
||
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fexamples%2Ftree%2Fmain%2Fsolutions%2Fcron&project-name=cron&repository-name=cron&demo-title=Vercel%20Cron%20Job%20Example&demo-description=A%20Next.js%20app%20that%20uses%20Vercel%20Cron%20Jobs%20to%20update%20data%20at%20different%20intervals.&demo-url=https%3A%2F%2Fcron-template.vercel.app%2F&demo-image=https%3A%2F%2Fcron-template.vercel.app%2Fthumbnail.png&stores=%5B%7B"type"%3A"kv"%7D%5D) | ||
|
||
Don't forget to set the required environment variables that you got from the previous step. | ||
|
||
### Clone and Deploy | ||
|
||
Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [pnpm](https://pnpm.io/installation) to bootstrap the example: | ||
|
||
```bash | ||
pnpm create next-app --example https://github.com/vercel/examples/tree/main/solutions/cron cron | ||
``` | ||
|
||
Next, run Next.js in development mode: | ||
|
||
```bash | ||
pnpm dev | ||
``` | ||
|
||
Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=examples-repo) ([Documentation](https://nextjs.org/docs/deployment)). |
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,81 @@ | ||
import ms from 'ms' | ||
import useSWR from 'swr' | ||
|
||
interface DataProps { | ||
id: number | ||
title: string | ||
by: string | ||
time: number | ||
score: number | ||
descendants: number | ||
fetchedAt: number | ||
} | ||
|
||
export default function Post({ interval }: { interval: string }) { | ||
const { data } = useSWR<DataProps>(`/api/data/${interval}`, (url) => | ||
fetch(url).then((res) => res.json()) | ||
) | ||
|
||
if (!data) | ||
return ( | ||
<div className="flex justify-between items-center border border-gray-100 shadow-md rounded-lg p-5"> | ||
<div className="grid gap-3"> | ||
<div className="bg-gray-200 animate-pulse rounded-md w-96 h-6" /> | ||
<div className="bg-gray-200 animate-pulse rounded-md w-60 h-4" /> | ||
</div> | ||
<div className="bg-gray-200 animate-pulse rounded-md w-28 h-4" /> | ||
</div> | ||
) | ||
|
||
const { id, title, by, time, score, descendants, fetchedAt } = data || {} | ||
return ( | ||
<div className="flex justify-between items-center border border-gray-100 shadow-md rounded-lg p-5"> | ||
<div className="grid gap-2"> | ||
<a | ||
href={`https://news.ycombinator.com/item?id=${id}`} | ||
target="_blank" | ||
rel="noreferrer noopener" | ||
> | ||
<h3 className="text-gray-600 hover:text-black font-semibold transition-all"> | ||
{title} | ||
</h3> | ||
</a> | ||
<div className="flex space-x-1 text-gray-500 text-sm"> | ||
<a | ||
href={`https://news.ycombinator.com/item?id=${id}`} | ||
target="_blank" | ||
rel="noreferrer noopener" | ||
className="hover:underline hover:text-gray-800 transition-all" | ||
> | ||
{score} {score === 1 ? 'point' : 'points'} | ||
</a> | ||
<p>by</p> | ||
<a | ||
href={`https://news.ycombinator.com/user?id=${by}/`} | ||
target="_blank" | ||
rel="noreferrer noopener" | ||
className="hover:underline hover:text-gray-800 transition-all" | ||
> | ||
{by} | ||
</a> | ||
<p>{timeAgo(time * 1000)}</p> | ||
<p>|</p> | ||
<a | ||
href={`https://news.ycombinator.com/item?id=${id}`} | ||
target="_blank" | ||
rel="noreferrer noopener" | ||
className="hover:underline hover:text-gray-800 transition-all" | ||
> | ||
{descendants} {descendants === 1 ? 'comment' : 'comments'} | ||
</a> | ||
</div> | ||
</div> | ||
<p className="text-gray-500 text-sm">fetched {timeAgo(fetchedAt)}</p> | ||
</div> | ||
) | ||
} | ||
|
||
const timeAgo = (time: number): string => { | ||
if (!time) return 'Never' | ||
return `${ms(Date.now() - new Date(time).getTime())} ago` | ||
} |
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 @@ | ||
/// <reference types="next" /> | ||
/// <reference types="next/image-types/global" /> | ||
|
||
// NOTE: This file should not be edited | ||
// see https://nextjs.org/docs/basic-features/typescript for more information. |
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 @@ | ||
{ | ||
"name": "cron", | ||
"repository": "https://github.com/vercel/examples.git", | ||
"license": "MIT", | ||
"private": true, | ||
"scripts": { | ||
"dev": "next dev", | ||
"build": "next build", | ||
"start": "next start", | ||
"lint": "next lint" | ||
}, | ||
"dependencies": { | ||
"@vercel/analytics": "^0.1.11", | ||
"@vercel/examples-ui": "^1.0.5", | ||
"@vercel/kv": "^0.2.1", | ||
"ms": "^2.1.3", | ||
"next": "canary", | ||
"react": "latest", | ||
"react-dom": "latest", | ||
"swr": "^2.1.0" | ||
}, | ||
"devDependencies": { | ||
"@types/ms": "^0.7.31", | ||
"@types/node": "^17.0.45", | ||
"@types/react": "18.0.27", | ||
"autoprefixer": "^10.4.14", | ||
"eslint": "^8.36.0", | ||
"eslint-config-next": "canary", | ||
"postcss": "^8.4.21", | ||
"tailwindcss": "^3.2.7", | ||
"turbo": "^1.8.3", | ||
"typescript": "4.9.5" | ||
} | ||
} |
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,27 @@ | ||
import type { AppProps } from 'next/app' | ||
import type { LayoutProps } from '@vercel/examples-ui/layout' | ||
import { Analytics } from '@vercel/analytics/react' | ||
|
||
import { getLayout } from '@vercel/examples-ui' | ||
import '@vercel/examples-ui/globals.css' | ||
|
||
function App({ Component, pageProps }: AppProps) { | ||
const Layout = getLayout<LayoutProps>(Component) | ||
|
||
return ( | ||
<Layout | ||
title="Vercel Cron Job Example" | ||
deployButton={{ | ||
customDeployUrl: | ||
'https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fexamples%2Ftree%2Fmain%2Fsolutions%2Fcron&project-name=cron&repository-name=cron&demo-title=Vercel%20Cron%20Job%20Example&demo-description=A%20Next.js%20app%20that%20uses%20Vercel%20Cron%20Jobs%20to%20update%20data%20at%20different%20intervals.&demo-url=https%3A%2F%2Fcron-template.vercel.app%2F&demo-image=https%3A%2F%2Fcron-template.vercel.app%2Fthumbnail.png&integration-ids=oac_V3R1GIpkoJorr6fqyiwdhl17', | ||
}} | ||
path="solutions/cron" | ||
description="How to use Vercel Cron Jobs to update data at different intervals" | ||
> | ||
<Component {...pageProps} /> | ||
<Analytics /> | ||
</Layout> | ||
) | ||
} | ||
|
||
export default App |
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,13 @@ | ||
import { Head, Html, Main, NextScript } from 'next/document' | ||
|
||
export default function Document() { | ||
return ( | ||
<Html lang="en"> | ||
<Head /> | ||
<body className="bg-white dark:bg-black"> | ||
<Main /> | ||
<NextScript /> | ||
</body> | ||
</Html> | ||
) | ||
} |
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,29 @@ | ||
import { NextRequest, NextResponse } from 'next/server' | ||
import { kv } from '@vercel/kv' | ||
|
||
export const config = { | ||
runtime: 'edge', | ||
} | ||
|
||
export default async function handler(req: NextRequest) { | ||
const cron = req.nextUrl.pathname.split('/')[3] | ||
console.log(cron) | ||
if (!cron) return new Response('No cron provided', { status: 400 }) | ||
const response = await update(cron) | ||
return new NextResponse(JSON.stringify(response), { | ||
status: 200, | ||
}) | ||
} | ||
|
||
async function update(interval: string) { | ||
const topstories = await fetch( | ||
'https://hacker-news.firebaseio.com/v0/newstories.json?print=pretty' | ||
).then((res) => res.json()) | ||
|
||
const response = await kv.set(interval, { | ||
fetchedAt: Date.now(), | ||
id: topstories[0], | ||
}) | ||
|
||
return response | ||
} |
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,28 @@ | ||
import { NextRequest, NextResponse } from 'next/server' | ||
import { kv } from '@vercel/kv' | ||
|
||
export const config = { | ||
runtime: 'edge', | ||
} | ||
|
||
export default async function handler(req: NextRequest) { | ||
const interval = req.nextUrl.searchParams.get('interval') | ||
if (!interval) return new Response('No interval provided', { status: 400 }) | ||
const { id, fetchedAt } = | ||
(await kv.get<{ | ||
id: string | ||
fetchedAt: string | ||
} | null>(interval)) || {} | ||
const res = await fetch( | ||
`https://hacker-news.firebaseio.com/v0/item/${id}.json?print=pretty` | ||
).then((res) => res.json()) | ||
return new NextResponse( | ||
JSON.stringify({ | ||
fetchedAt, | ||
...res, | ||
}), | ||
{ | ||
status: 200, | ||
} | ||
) | ||
} |
Oops, something went wrong.