Skip to content

Commit

Permalink
Add with-xata example (#39864)
Browse files Browse the repository at this point in the history
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 <18369201+balazsorban44@users.noreply.github.com>
  • Loading branch information
atilafassina and balazsorban44 committed Sep 29, 2022
1 parent 06607e3 commit 2fa33b3
Show file tree
Hide file tree
Showing 16 changed files with 652 additions and 0 deletions.
49 changes: 49 additions & 0 deletions examples/with-xata/.gitignore
@@ -0,0 +1,49 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.

# compiled output
/build
/out
/dist
/tmp
/out-tsc

# dependencies
/node_modules

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings

# System Files
.DS_Store
Thumbs.db

.next
.turbo
node_modules

**/.xatarc
.env
.env.*
63 changes: 63 additions & 0 deletions examples/with-xata/README.md
@@ -0,0 +1,63 @@
# Next.js + Xata

This example showcases how to use Next.js with [Xata](https://xata.io) as your data layer.

With this template you get out-of-the-box:

- API Route to connect to your Xata database
- Type-safe Codegen
- Accessibility-Ready
- Dark/Light mode
- Respects `prefers-reduce-motion` for CSS Transitions

## Deploy your own

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)

[![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)

## Demo

[nextjs-with-xata.vercel.app](https://nextjs-with-xata.vercel.app)

## 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), [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/), or [pnpm](https://pnpm.io) to bootstrap the example:

```sh
npx create-next-app --example cms-contentful cms-contentful-app
```

```sh
yarn create next-app --example cms-contentful cms-contentful-app
```

```sh
pnpm create next-app --example cms-contentful cms-contentful-app
```

### Link Your Xata Workspace and Run Codegen

> 💡 consider [installing the Xata CLI globally](https://xata.io/docs/cli/getting-started), it will likely improve your experience managing your databases
```sh
npm run start:xata
```

> ⚠️ once linked, you can just run `xata` to re-generate types.
### Start Coding

Open [http://localhost:3000](http://localhost:3000) to view it in the browser.

> 💡 the template will prompt you to create a dummy new table (`nextjs_with_xata_example`) with some useful resources.
## Notes

Some tips that may help you develop your app.

- The Xata [VS Code Extension](https://marketplace.visualstudio.com/items?itemName=xata.xata) will make managing your data more comfortable
- Prefer fetching data from `getServerSideProps()` or `getStaticProps()`
- Create a Serverless Route(s) to handle data mutations

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)).
5 changes: 5 additions & 0 deletions examples/with-xata/next-env.d.ts
@@ -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.
26 changes: 26 additions & 0 deletions examples/with-xata/package.json
@@ -0,0 +1,26 @@
{
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"start:xata": "xata init --schema=schema.template.json --codegen=utils/xata.codegen.ts",
"poststart:xata": "xata codegen",
"xata": "xata codegen"
},
"devDependencies": {
"@types/node": "18.6.5",
"@types/react": "18.0.17",
"@types/react-dom": "18.0.6",
"@xata.io/cli": "0.8.1",
"eslint": "8.21.0",
"eslint-config-next": "latest",
"typescript": "4.7.4"
},
"dependencies": {
"@xata.io/client": "^0.16.1",
"next": "latest",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}
62 changes: 62 additions & 0 deletions examples/with-xata/pages/_app.tsx
@@ -0,0 +1,62 @@
import type { AppProps } from 'next/app'
import Head from 'next/head'
import '../styles/root.css'

const metas = {
title: 'Next.js with-xata',
description: 'Run Next.js with Xata with this awesome template',
image:
process.env.NODE_ENV === 'development'
? 'http://localhost:3000/og.jpg'
: 'https://nextjs-with-xata.vercel.app/og.jpg',
}

export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Head>
<title>{metas.title}</title>
<meta property="og:title" content={metas.title} key="og:title" />
<meta property="og:image" content={metas.image} key="og:image" />
<meta
property="description"
content={metas.description}
key="description"
/>
<meta
property="og:description"
content={metas.description}
key="og:description"
/>
<meta property="og:type" content="website" />
<meta property="twitter:card" content="summary_large_image" />
<meta
property="twitter:title"
content={metas.title}
key="twitter:title"
/>
<meta
property="twitter:description"
content={metas.description}
key="twitter:description"
/>
<meta
property="twitter:image"
content={metas.image}
key="twitter:image"
/>
<meta
name="theme-color"
content="#000"
media="(prefers-color-scheme: dark)"
/>
<meta
name="theme-color"
content="#fff"
media="(prefers-color-scheme: light)"
/>
</Head>
<Component {...pageProps} />
</>
)
}
22 changes: 22 additions & 0 deletions examples/with-xata/pages/api/clean-xata.ts
@@ -0,0 +1,22 @@
import type { NextApiRequest, NextApiResponse } from 'next'
import { getXataClient } from '../../utils/xata.codegen'

const xata = getXataClient()

const deleteItem = async (id: string) => {
return await xata.db.nextjs_with_xata_example.delete(id)
}

export async function cleanDummyDataFromXata(
req: NextApiRequest,
res: NextApiResponse
) {
const { id } = req.body
await deleteItem(id)

res.json({
ok: true,
})
}

export default cleanDummyDataFromXata
38 changes: 38 additions & 0 deletions examples/with-xata/pages/api/write-links-to-xata.ts
@@ -0,0 +1,38 @@
import type { NextApiRequest, NextApiResponse } from 'next'
import { getXataClient } from '../../utils/xata.codegen'

const LINKS = [
{
description: 'Everything you need to know about Xata APIs and tools.',
title: 'Xata Docs',
url: 'https://xata.io/docs',
},
{
description: 'In case you need to check some Next.js specifics.',
title: 'Next.js Docs',
url: 'https://nextjs.org/docs',
},
{
description:
'Maintain your flow by managing your Xata Workspace without ever leaving VS Code.',
title: 'Xata VS Code Extension',
url: 'https://marketplace.visualstudio.com/items?itemName=xata.xata',
},
{
description: 'Get help. Offer help. Show us what you built!',
title: 'Xata Discord',
url: 'https://xata.io/discord',
},
]

const xata = getXataClient()

export default async function writeLinksToXata(
_req: NextApiRequest,
res: NextApiResponse
) {
await xata.db.nextjs_with_xata_example.create(LINKS)
res.json({
ok: true,
})
}
100 changes: 100 additions & 0 deletions examples/with-xata/pages/index.tsx
@@ -0,0 +1,100 @@
import type { InferGetServerSidePropsType } from 'next'
import Image from 'next/image'
import { getXataClient } from '../utils/xata.codegen'
import xatafly from '../public/xatafly.gif'

const pushDummyData = async () => {
const response = await fetch('/api/write-links-to-xata')

if (response.ok) {
window?.location.reload()
}
}

const removeDummyItem = async (id: string) => {
const { status } = await fetch('/api/clean-xata', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ id }),
})

if (status === 200) {
window?.location.reload()
}
}

export default function IndexPage({
links,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
return (
<main>
<header>
<Image src={xatafly} priority />
<h1>
Next.js with<span aria-hidden>&#8209;</span>xata
</h1>
</header>
<article>
{links.length ? (
<ul>
{links.map(({ id, title, url, description }) => (
<li key={url}>
<a href={url} rel="noopener noreferrer" target="_blank">
{title}
</a>
<p>{description}</p>

<button
type="button"
onClick={() => {
removeDummyItem(id)
}}
>
<span role="img" aria-label="delete item">
🗑
</span>
</button>
</li>
))}
</ul>
) : (
<section>
<h2>No records found.</h2>
<strong>
Create a `nextjs_with_xata_example` and push some useful links to
see them here.
</strong>
<button
type="button"
onClick={() => {
pushDummyData()
}}
>
Push records to Xata
</button>
</section>
)}
</article>
<footer>
<span>
Made by{' '}
<a href="https://xata.io" rel="noopener noreferrer" target="_blank">
<object data="/xatafly.svg" />
</a>
</span>
</footer>
</main>
)
}

export const getServerSideProps = async () => {
const xata = await getXataClient()
const links = await xata.db.nextjs_with_xata_example.getAll()
return {
props: {
links,
},
}
}
Binary file added examples/with-xata/public/favicon.ico
Binary file not shown.
Binary file added examples/with-xata/public/og.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/with-xata/public/xatafly.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 2fa33b3

Please sign in to comment.