From 2fa33b351b0df93da7b62761e998823f228cc71c Mon Sep 17 00:00:00 2001 From: Atila Fassina Date: Fri, 30 Sep 2022 00:37:28 +0200 Subject: [PATCH] Add `with-xata` example (#39864) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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> --- examples/with-xata/.gitignore | 49 +++++ examples/with-xata/README.md | 63 +++++++ examples/with-xata/next-env.d.ts | 5 + examples/with-xata/package.json | 26 +++ examples/with-xata/pages/_app.tsx | 62 +++++++ examples/with-xata/pages/api/clean-xata.ts | 22 +++ .../pages/api/write-links-to-xata.ts | 38 ++++ examples/with-xata/pages/index.tsx | 100 ++++++++++ examples/with-xata/public/favicon.ico | Bin 0 -> 15086 bytes examples/with-xata/public/og.jpg | Bin 0 -> 172552 bytes examples/with-xata/public/xatafly.gif | Bin 0 -> 2698486 bytes examples/with-xata/public/xatafly.svg | 27 +++ examples/with-xata/schema.template.json | 22 +++ examples/with-xata/styles/root.css | 174 ++++++++++++++++++ examples/with-xata/tsconfig.json | 21 +++ examples/with-xata/utils/xata.codegen.ts | 43 +++++ 16 files changed, 652 insertions(+) create mode 100644 examples/with-xata/.gitignore create mode 100644 examples/with-xata/README.md create mode 100644 examples/with-xata/next-env.d.ts create mode 100644 examples/with-xata/package.json create mode 100644 examples/with-xata/pages/_app.tsx create mode 100644 examples/with-xata/pages/api/clean-xata.ts create mode 100644 examples/with-xata/pages/api/write-links-to-xata.ts create mode 100644 examples/with-xata/pages/index.tsx create mode 100644 examples/with-xata/public/favicon.ico create mode 100644 examples/with-xata/public/og.jpg create mode 100644 examples/with-xata/public/xatafly.gif create mode 100644 examples/with-xata/public/xatafly.svg create mode 100644 examples/with-xata/schema.template.json create mode 100644 examples/with-xata/styles/root.css create mode 100644 examples/with-xata/tsconfig.json create mode 100644 examples/with-xata/utils/xata.codegen.ts diff --git a/examples/with-xata/.gitignore b/examples/with-xata/.gitignore new file mode 100644 index 000000000000..f97181c4cb4c --- /dev/null +++ b/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.* \ No newline at end of file diff --git a/examples/with-xata/README.md b/examples/with-xata/README.md new file mode 100644 index 000000000000..f6eecbc2c430 --- /dev/null +++ b/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)). diff --git a/examples/with-xata/next-env.d.ts b/examples/with-xata/next-env.d.ts new file mode 100644 index 000000000000..4f11a03dc6cc --- /dev/null +++ b/examples/with-xata/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/examples/with-xata/package.json b/examples/with-xata/package.json new file mode 100644 index 000000000000..761098f5dc61 --- /dev/null +++ b/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" + } +} diff --git a/examples/with-xata/pages/_app.tsx b/examples/with-xata/pages/_app.tsx new file mode 100644 index 000000000000..a3828c69101f --- /dev/null +++ b/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 ( + <> + + {metas.title} + + + + + + + + + + + + + + + ) +} diff --git a/examples/with-xata/pages/api/clean-xata.ts b/examples/with-xata/pages/api/clean-xata.ts new file mode 100644 index 000000000000..a5836cbe2c15 --- /dev/null +++ b/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 diff --git a/examples/with-xata/pages/api/write-links-to-xata.ts b/examples/with-xata/pages/api/write-links-to-xata.ts new file mode 100644 index 000000000000..a0b94d2667cb --- /dev/null +++ b/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, + }) +} diff --git a/examples/with-xata/pages/index.tsx b/examples/with-xata/pages/index.tsx new file mode 100644 index 000000000000..0aaa079fde26 --- /dev/null +++ b/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) { + return ( +
+
+ +

+ Next.js withxata +

+
+
+ {links.length ? ( +
    + {links.map(({ id, title, url, description }) => ( +
  • + + {title} + +

    {description}

    + + +
  • + ))} +
+ ) : ( +
+

No records found.

+ + Create a `nextjs_with_xata_example` and push some useful links to + see them here. + + +
+ )} +
+