Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add with-xata example #39864

Merged
merged 14 commits into from Sep 29, 2022
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.*
55 changes: 55 additions & 0 deletions examples/with-xata/README.md
@@ -0,0 +1,55 @@
# Next.js + Xata

This example showcases how to use Next.js with [Xata](https://xata.io) as your data layer.
balazsorban44 marked this conversation as resolved.
Show resolved Hide resolved

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

## 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
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'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because OG:Image requires it to be absolute urls, pointing it to localhost on dev makes it easier to test a new image, I thought it was a nice addition to whoever bases on this template to build something.

But absolutely not needed

I can remove it if you prefer.

? '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.
27 changes: 27 additions & 0 deletions examples/with-xata/public/xatafly.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.