Skip to content

Commit 2fa33b3

Browse files
Add with-xata example (vercel#39864)
This Pull Request adds a `with-xata` example to use [Xata](https://xata.io) as the data layer of a Next.js app. ## Documentation / Examples - [x] Make sure the linting passes by running `pnpm lint` - [x] The examples guidelines are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing.md#adding-examples) Co-authored-by: Balázs Orbán <[email protected]>
1 parent 06607e3 commit 2fa33b3

16 files changed

+652
-0
lines changed

examples/with-xata/.gitignore

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# See http://help.github.com/ignore-files/ for more about ignoring files.
2+
3+
# compiled output
4+
/build
5+
/out
6+
/dist
7+
/tmp
8+
/out-tsc
9+
10+
# dependencies
11+
/node_modules
12+
13+
# IDEs and editors
14+
/.idea
15+
.project
16+
.classpath
17+
.c9/
18+
*.launch
19+
.settings/
20+
*.sublime-workspace
21+
22+
# IDE - VSCode
23+
.vscode/*
24+
!.vscode/settings.json
25+
!.vscode/tasks.json
26+
!.vscode/launch.json
27+
!.vscode/extensions.json
28+
29+
# misc
30+
/.sass-cache
31+
/connect.lock
32+
/coverage
33+
/libpeerconnection.log
34+
npm-debug.log
35+
yarn-error.log
36+
testem.log
37+
/typings
38+
39+
# System Files
40+
.DS_Store
41+
Thumbs.db
42+
43+
.next
44+
.turbo
45+
node_modules
46+
47+
**/.xatarc
48+
.env
49+
.env.*

examples/with-xata/README.md

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Next.js + Xata
2+
3+
This example showcases how to use Next.js with [Xata](https://xata.io) as your data layer.
4+
5+
With this template you get out-of-the-box:
6+
7+
- API Route to connect to your Xata database
8+
- Type-safe Codegen
9+
- Accessibility-Ready
10+
- Dark/Light mode
11+
- Respects `prefers-reduce-motion` for CSS Transitions
12+
13+
## Deploy your own
14+
15+
Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example) or preview live with [StackBlitz](https://stackblitz.com/github/vercel/next.js/tree/canary/examples/with-xata)
16+
17+
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-xata&project-name=with-xata&repository-name=with-xata)
18+
19+
## Demo
20+
21+
[nextjs-with-xata.vercel.app](https://nextjs-with-xata.vercel.app)
22+
23+
## How to use
24+
25+
Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init), [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/), or [pnpm](https://pnpm.io) to bootstrap the example:
26+
27+
```sh
28+
npx create-next-app --example cms-contentful cms-contentful-app
29+
```
30+
31+
```sh
32+
yarn create next-app --example cms-contentful cms-contentful-app
33+
```
34+
35+
```sh
36+
pnpm create next-app --example cms-contentful cms-contentful-app
37+
```
38+
39+
### Link Your Xata Workspace and Run Codegen
40+
41+
> 💡 consider [installing the Xata CLI globally](https://xata.io/docs/cli/getting-started), it will likely improve your experience managing your databases
42+
43+
```sh
44+
npm run start:xata
45+
```
46+
47+
> ⚠️ once linked, you can just run `xata` to re-generate types.
48+
49+
### Start Coding
50+
51+
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
52+
53+
> 💡 the template will prompt you to create a dummy new table (`nextjs_with_xata_example`) with some useful resources.
54+
55+
## Notes
56+
57+
Some tips that may help you develop your app.
58+
59+
- The Xata [VS Code Extension](https://marketplace.visualstudio.com/items?itemName=xata.xata) will make managing your data more comfortable
60+
- Prefer fetching data from `getServerSideProps()` or `getStaticProps()`
61+
- Create a Serverless Route(s) to handle data mutations
62+
63+
Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).

examples/with-xata/next-env.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/// <reference types="next" />
2+
/// <reference types="next/image-types/global" />
3+
4+
// NOTE: This file should not be edited
5+
// see https://nextjs.org/docs/basic-features/typescript for more information.

examples/with-xata/package.json

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"private": true,
3+
"scripts": {
4+
"dev": "next dev",
5+
"build": "next build",
6+
"start": "next start",
7+
"start:xata": "xata init --schema=schema.template.json --codegen=utils/xata.codegen.ts",
8+
"poststart:xata": "xata codegen",
9+
"xata": "xata codegen"
10+
},
11+
"devDependencies": {
12+
"@types/node": "18.6.5",
13+
"@types/react": "18.0.17",
14+
"@types/react-dom": "18.0.6",
15+
"@xata.io/cli": "0.8.1",
16+
"eslint": "8.21.0",
17+
"eslint-config-next": "latest",
18+
"typescript": "4.7.4"
19+
},
20+
"dependencies": {
21+
"@xata.io/client": "^0.16.1",
22+
"next": "latest",
23+
"react": "^18.2.0",
24+
"react-dom": "^18.2.0"
25+
}
26+
}

examples/with-xata/pages/_app.tsx

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import type { AppProps } from 'next/app'
2+
import Head from 'next/head'
3+
import '../styles/root.css'
4+
5+
const metas = {
6+
title: 'Next.js with-xata',
7+
description: 'Run Next.js with Xata with this awesome template',
8+
image:
9+
process.env.NODE_ENV === 'development'
10+
? 'http://localhost:3000/og.jpg'
11+
: 'https://nextjs-with-xata.vercel.app/og.jpg',
12+
}
13+
14+
export default function App({ Component, pageProps }: AppProps) {
15+
return (
16+
<>
17+
<Head>
18+
<title>{metas.title}</title>
19+
<meta property="og:title" content={metas.title} key="og:title" />
20+
<meta property="og:image" content={metas.image} key="og:image" />
21+
<meta
22+
property="description"
23+
content={metas.description}
24+
key="description"
25+
/>
26+
<meta
27+
property="og:description"
28+
content={metas.description}
29+
key="og:description"
30+
/>
31+
<meta property="og:type" content="website" />
32+
<meta property="twitter:card" content="summary_large_image" />
33+
<meta
34+
property="twitter:title"
35+
content={metas.title}
36+
key="twitter:title"
37+
/>
38+
<meta
39+
property="twitter:description"
40+
content={metas.description}
41+
key="twitter:description"
42+
/>
43+
<meta
44+
property="twitter:image"
45+
content={metas.image}
46+
key="twitter:image"
47+
/>
48+
<meta
49+
name="theme-color"
50+
content="#000"
51+
media="(prefers-color-scheme: dark)"
52+
/>
53+
<meta
54+
name="theme-color"
55+
content="#fff"
56+
media="(prefers-color-scheme: light)"
57+
/>
58+
</Head>
59+
<Component {...pageProps} />
60+
</>
61+
)
62+
}
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import type { NextApiRequest, NextApiResponse } from 'next'
2+
import { getXataClient } from '../../utils/xata.codegen'
3+
4+
const xata = getXataClient()
5+
6+
const deleteItem = async (id: string) => {
7+
return await xata.db.nextjs_with_xata_example.delete(id)
8+
}
9+
10+
export async function cleanDummyDataFromXata(
11+
req: NextApiRequest,
12+
res: NextApiResponse
13+
) {
14+
const { id } = req.body
15+
await deleteItem(id)
16+
17+
res.json({
18+
ok: true,
19+
})
20+
}
21+
22+
export default cleanDummyDataFromXata
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { NextApiRequest, NextApiResponse } from 'next'
2+
import { getXataClient } from '../../utils/xata.codegen'
3+
4+
const LINKS = [
5+
{
6+
description: 'Everything you need to know about Xata APIs and tools.',
7+
title: 'Xata Docs',
8+
url: 'https://xata.io/docs',
9+
},
10+
{
11+
description: 'In case you need to check some Next.js specifics.',
12+
title: 'Next.js Docs',
13+
url: 'https://nextjs.org/docs',
14+
},
15+
{
16+
description:
17+
'Maintain your flow by managing your Xata Workspace without ever leaving VS Code.',
18+
title: 'Xata VS Code Extension',
19+
url: 'https://marketplace.visualstudio.com/items?itemName=xata.xata',
20+
},
21+
{
22+
description: 'Get help. Offer help. Show us what you built!',
23+
title: 'Xata Discord',
24+
url: 'https://xata.io/discord',
25+
},
26+
]
27+
28+
const xata = getXataClient()
29+
30+
export default async function writeLinksToXata(
31+
_req: NextApiRequest,
32+
res: NextApiResponse
33+
) {
34+
await xata.db.nextjs_with_xata_example.create(LINKS)
35+
res.json({
36+
ok: true,
37+
})
38+
}

examples/with-xata/pages/index.tsx

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import type { InferGetServerSidePropsType } from 'next'
2+
import Image from 'next/image'
3+
import { getXataClient } from '../utils/xata.codegen'
4+
import xatafly from '../public/xatafly.gif'
5+
6+
const pushDummyData = async () => {
7+
const response = await fetch('/api/write-links-to-xata')
8+
9+
if (response.ok) {
10+
window?.location.reload()
11+
}
12+
}
13+
14+
const removeDummyItem = async (id: string) => {
15+
const { status } = await fetch('/api/clean-xata', {
16+
method: 'POST',
17+
headers: {
18+
'Content-Type': 'application/json',
19+
},
20+
body: JSON.stringify({ id }),
21+
})
22+
23+
if (status === 200) {
24+
window?.location.reload()
25+
}
26+
}
27+
28+
export default function IndexPage({
29+
links,
30+
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
31+
return (
32+
<main>
33+
<header>
34+
<Image src={xatafly} priority />
35+
<h1>
36+
Next.js with<span aria-hidden>&#8209;</span>xata
37+
</h1>
38+
</header>
39+
<article>
40+
{links.length ? (
41+
<ul>
42+
{links.map(({ id, title, url, description }) => (
43+
<li key={url}>
44+
<a href={url} rel="noopener noreferrer" target="_blank">
45+
{title}
46+
</a>
47+
<p>{description}</p>
48+
49+
<button
50+
type="button"
51+
onClick={() => {
52+
removeDummyItem(id)
53+
}}
54+
>
55+
<span role="img" aria-label="delete item">
56+
🗑
57+
</span>
58+
</button>
59+
</li>
60+
))}
61+
</ul>
62+
) : (
63+
<section>
64+
<h2>No records found.</h2>
65+
<strong>
66+
Create a `nextjs_with_xata_example` and push some useful links to
67+
see them here.
68+
</strong>
69+
<button
70+
type="button"
71+
onClick={() => {
72+
pushDummyData()
73+
}}
74+
>
75+
Push records to Xata
76+
</button>
77+
</section>
78+
)}
79+
</article>
80+
<footer>
81+
<span>
82+
Made by{' '}
83+
<a href="https://xata.io" rel="noopener noreferrer" target="_blank">
84+
<object data="/xatafly.svg" />
85+
</a>
86+
</span>
87+
</footer>
88+
</main>
89+
)
90+
}
91+
92+
export const getServerSideProps = async () => {
93+
const xata = await getXataClient()
94+
const links = await xata.db.nextjs_with_xata_example.getAll()
95+
return {
96+
props: {
97+
links,
98+
},
99+
}
100+
}

examples/with-xata/public/favicon.ico

14.7 KB
Binary file not shown.

examples/with-xata/public/og.jpg

169 KB
Loading

examples/with-xata/public/xatafly.gif

2.57 MB
Loading

0 commit comments

Comments
 (0)