Skip to content

Commit

Permalink
Merge pull request #8938 from marmelab/update-next-tutorial
Browse files Browse the repository at this point in the history
[Doc] Fix NextJS tutorial for the latest version of create-next-app
  • Loading branch information
fzaninotto authored May 26, 2023
2 parents 0c8976b + 72b27eb commit 83aa214
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 11 deletions.
27 changes: 16 additions & 11 deletions docs/NextJs.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ React-admin runs seamlessly on [Next.js](https://nextjs.org/), with minimal conf
Let's start by creating a new Next.js project called `nextjs-react-admin`.

```bash
npx create-next-app --ts nextjs-react-admin --use-yarn
npx create-next-app@latest next-admin --ts --use-yarn --eslint --no-tailwind --no-src-dir --no-app --import-alias "@/*"
```

![Setup Next.js](./img/nextjs-setup.webp)
Expand Down Expand Up @@ -126,21 +126,23 @@ SUPABASE_SERVICE_ROLE="MY_SERVICE_ROLE_KEY"

Create [a "catch-all" API route](https://nextjs.org/docs/api-routes/dynamic-api-routes#optional-catch-all-api-routes) in the Next.js app by adding a `pages/api/admin/[[...slug]].ts` file. This API route redirects all calls from the react-admin app to the Supabase CRUD API:

```jsx
```tsx
// in pages/api/admin/[[...slug]].ts
export default async function handler(req, res) {
import { NextApiRequest, NextApiResponse } from "next";

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
// get the incoming request URL, e.g. 'posts?limit=10&offset=0&order=id.asc'
const requestUrl = req.url.substring("/api/admin/".length);
const requestUrl = req.url?.substring("/api/admin/".length);
// build the CRUD request based on the incoming request
const url = `${process.env.SUPABASE_URL}/rest/v1/${requestUrl}`;
const options = {
const options: RequestInit = {
method: req.method,
headers: {
prefer: req.headers["prefer"] ?? "",
prefer: req.headers["prefer"] as string ?? "",
accept: req.headers["accept"] ?? "application/json",
["content-type"]: req.headers["content-type"] ?? "application/json",
// supabase authentication
apiKey: process.env.SUPABASE_SERVICE_ROLE,
apiKey: process.env.SUPABASE_SERVICE_ROLE ?? '',
},
};
if (req.body) {
Expand All @@ -149,24 +151,27 @@ export default async function handler(req, res) {
// call the CRUD API
const response = await fetch(url, options);
// send the response back to the client
res.setHeader("Content-Range", response.headers.get("content-range"));
const contentRange = response.headers.get("content-range");
if (contentRange) {
res.setHeader("Content-Range", contentRange);
}
res.end(await response.text());
}
```

**Tip**: Some of this code is really PostgREST-specific. The `prefer` header is required to let PostgREST return one record instead of an array containing one record in response to `getOne` requests. The `Content-Range` header is returned by PostgREST and must be passed down to the client. A proxy for another CRUD API will require different parameters.

Finally, update the react-admin data provider to use the Supabase adapter instead of the JSON Server one. As Supabase provides a PostgREST endpoint, we'll use [`ra-data-postgrest`](https://github.com/promitheus7/ra-data-postgrest):
Finally, update the react-admin data provider to use the Supabase adapter instead of the JSON Server one. As Supabase provides a PostgREST endpoint, we'll use [`ra-data-postgrest`](https://github.com/raphiniert-com/ra-data-postgrest):

```sh
yarn add @promitheus/ra-data-postgrest
yarn add @raphiniert/ra-data-postgrest
```

```jsx
// in src/admin/App.jsx
import * as React from "react";
import { Admin, Resource, ListGuesser } from 'react-admin';
import postgrestRestProvider from "@promitheus/ra-data-postgrest";
import postgrestRestProvider from "@raphiniert/ra-data-postgrest";

const dataProvider = postgrestRestProvider("/api/admin");

Expand Down
Binary file modified docs/img/nextjs-setup.webp
Binary file not shown.

0 comments on commit 83aa214

Please sign in to comment.