Skip to content

Commit

Permalink
Add example for Next 13 app directory and Keystone getContext (#8371
Browse files Browse the repository at this point in the history
)

Co-authored-by: Daniel Cousens <[email protected]>
Co-authored-by: Daniel Cousens <[email protected]>
  • Loading branch information
3 people authored Apr 13, 2023
1 parent 5575bbd commit 0f99cf1
Show file tree
Hide file tree
Showing 30 changed files with 824 additions and 327 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/tests_api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,16 @@ jobs:
- name: Example unit tests
run: cd examples/testing; pnpm test

examples_next_app_build:
name: Ensure Nest in App directory builds
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@main
- uses: ./.github/actions/ci-setup

- name: Example Next in app direcroty build
run: cd examples/nextjs-keystone-app-directory; pnpm build

examples_smoke_tests:
name: Smoke Tests For Examples
runs-on: ubuntu-latest
Expand Down
45 changes: 45 additions & 0 deletions examples/nextjs-keystone-app-directory/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
node_modules
.keystone
.keystone/admin
*.log
*.env
# making sure demo db is committed to repo so
# one click deploy to vercel will work
!keystone.db

# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
38 changes: 38 additions & 0 deletions examples/nextjs-keystone-app-directory/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Next.js + Keystone

Keystone can be used as a data engine in Next.js applications without having to host a separate Keystone server.
This is made possible by Keystone's `getContext` API.

- **CRUD data within your Next.js server**: You can use Keystone data APIs directly in Next.js `getStaticProps` or `getServerSideProps` to CRUD data. ⚡️
- **CRUD data from browser**: You can use the generated Keystone GraphQL schema to setup your own GraphQL server in a Next.js route. This enables you to send GraphQL requests from the browser. 🤯 (refer to [/pages/api/graphql.ts](/pages/api/graphql.ts) for implementation details)
- You don't have to start the Keystone server at all.

_Note: Since you are not starting the keystone server, the Admin UI will not be available. You can host Keystone as a separate server if you need Admin UI._

## Notes

- This example is setup with seed data. Demo user email is `[email protected]`, password is `passw0rd`.
- `pnpm next:dev` is all you need to develop your Next.js app. You don't need to start the keystone server since `getContext` will work without starting the Keystone server.
- However when you make changes to your keystone lists, the schema files need to be regenerated. So you'll either have to run `pnpm keystone:dev` or `pnpm keystone:build` just once after making changes to your lists. Alternatively you can open two terminal tabs and run both `pnpm keystone:dev` and `pnpm next:dev` concurrently during development.
- When you deploy your Next.js app, remember to run `pnpm keystone:build` once to make sure you have the latest schema files built for `getContext` API.

## FAQ

### 1. Why won't Admin UI work?

Admin UI needs the Keystone server to run. Your Next.js app runs on a Next.js server. Keystone's Admin UI runs on Keystone server. You can't have two servers running in a Next.js production environment. Since we are not starting the Keystone server in production builds, we won't have access to Keystone's Admin UI. You can access it in local (use the command `pnpm keystone:dev`) because you can easily start two servers in your local but once you deploy your Next.js app you won't have access to the Admin UI.

### 2. What should I do to both use Keystone in my Next.js app and have a fully functioning Admin UI?

Easy. Deploy twice to two different servers.

1. Deploy your Next.js app to one instance (Eg. Vercel).
2. Deploy the Keystone server (commands in package.json) to another instance (Eg. Digital Ocean).

Both these apps connect to the same database and are built with the same source code so everything will work as you expect it to.

## Give it a try

Deploy this example to Vercel and see it for yourself.

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fkeystonejs%2Fkeystone%2Ftree%2Fmain%2Fexamples%2Fnextjs-keystone-app-directory)
Binary file not shown.
18 changes: 18 additions & 0 deletions examples/nextjs-keystone-app-directory/keystone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { config } from '@keystone-6/core';
import { lists } from './src/keystone/schema';
import { seedDemoData } from './src/keystone/seed';
import type { Context } from '.keystone/types';

export default config({
db: {
provider: 'sqlite',
url: `file:${process.cwd()}/keystone.db`, // next.js requires an absolute path for sqlite
onConnect: async (context: Context) => {
await seedDemoData(context);
},

// WARNING: this is only needed for our monorepo examples, dont do this
prismaClientPath: 'node_modules/.myprisma/client',
},
lists,
});
17 changes: 17 additions & 0 deletions examples/nextjs-keystone-app-directory/next.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// you don't need this if you're building something outside of the Keystone repo
import withPreconstruct from '@preconstruct/next';

export default withPreconstruct({
experimental: {
appDir: true,

// without this, 'Error: Expected Upload to be a GraphQL nullable type.'
serverComponentsExternalPackages: ['graphql'],
},
eslint: {
ignoreDuringBuilds: true,
},
typescript: {
ignoreBuildErrors: true,
},
});
38 changes: 38 additions & 0 deletions examples/nextjs-keystone-app-directory/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "@keystone-6/example-nextjs-keystone-app-directory",
"version": "0.0.2",
"private": true,
"license": "MIT",
"scripts": {
"keystone:dev": "keystone dev",
"keystone:build": "keystone build",
"keystone:start": "keystone start",
"next:dev": "next dev -p 4000",
"next:build": "next build",
"build": "pnpm keystone build --no-ui && pnpm next build",
"postinstall": "keystone postinstall",
"start": "next start"
},
"dependencies": {
"@keystone-6/auth": "^7.0.0",
"@keystone-6/core": "^5.0.0",
"@keystone-6/document-renderer": "^1.0.0",
"@keystone-6/fields-document": "^7.0.0",
"@preconstruct/next": "^4.0.0",
"@prisma/client": "^4.12.0",
"graphql": "^16.6.0",
"graphql-request": "^5.0.0",
"graphql-yoga": "^3.1.0",
"next": "^13.3.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/node": "^18.11.14",
"@types/react": "^18.0.9",
"@types/react-dom": "^18.0.4",
"prisma": "^4.12.0",
"typescript": "~5.0.0"
},
"repository": "https://github.com/keystonejs/keystone/tree/main/examples/nextjs-keystone-app-directory"
}
Binary file not shown.
Loading

0 comments on commit 0f99cf1

Please sign in to comment.