From 29977d2778a748cf693364573294022c21ca475c Mon Sep 17 00:00:00 2001 From: mitchellhamilton Date: Fri, 12 Aug 2022 15:17:16 +1000 Subject: [PATCH] Run migration script --- .../{access-control.mdx => access-control.md} | 68 +++++++++++---- docs/pages/docs/apis/{auth.mdx => auth.md} | 25 +++--- .../pages/docs/apis/{config.mdx => config.md} | 26 +++--- .../docs/apis/{context.mdx => context.md} | 39 ++++----- .../docs/apis/{db-items.mdx => db-items.md} | 39 ++++----- .../pages/docs/apis/{fields.mdx => fields.md} | 48 +++++----- .../docs/apis/{filters.mdx => filters.md} | 29 +++---- .../docs/apis/{graphql.mdx => graphql.md} | 43 +++++---- docs/pages/docs/apis/{hooks.mdx => hooks.md} | 25 +++--- docs/pages/docs/apis/{query.mdx => query.md} | 38 ++++---- .../pages/docs/apis/{schema.mdx => schema.md} | 52 +++++------ .../docs/apis/{session.mdx => session.md} | 41 ++++----- ...control.mdx => auth-and-access-control.md} | 72 ++++++++------- ...-a-database.mdx => choosing-a-database.md} | 46 +++++----- docs/pages/docs/guides/{cli.mdx => cli.md} | 49 ++++++----- .../pages/docs/guides/custom-admin-ui-logo.md | 71 +++++++++++++++ .../docs/guides/custom-admin-ui-logo.mdx | 77 ---------------- ...tion.mdx => custom-admin-ui-navigation.md} | 87 +++++++++++-------- ...-ui-pages.mdx => custom-admin-ui-pages.md} | 70 +++++++-------- docs/pages/docs/guides/custom-field-views.md | 7 ++ docs/pages/docs/guides/custom-field-views.mdx | 8 -- .../{custom-fields.mdx => custom-fields.md} | 35 ++++---- ...document-fields.mdx => document-fields.md} | 70 ++++++++------- .../docs/guides/{filters.mdx => filters.md} | 33 +++---- .../pages/docs/guides/{hooks.mdx => hooks.md} | 28 +++--- ...ages-and-files.mdx => images-and-files.md} | 56 ++++++------ docs/pages/docs/guides/internal-items.md | 7 ++ docs/pages/docs/guides/internal-items.mdx | 8 -- .../{relationships.mdx => relationships.md} | 66 ++++++++------ docs/pages/docs/guides/schema-extension.md | 7 ++ docs/pages/docs/guides/schema-extension.mdx | 8 -- .../docs/guides/{testing.mdx => testing.md} | 65 +++++++------- .../{virtual-fields.mdx => virtual-fields.md} | 45 +++++----- ...dx => embedded-mode-with-sqlite-nextjs.md} | 53 +++++------ ...tting-started-with-create-keystone-app.md} | 76 ++++++++-------- .../{lesson-1.mdx => lesson-1.md} | 44 ++++++---- .../{lesson-2.mdx => lesson-2.md} | 41 ++++----- .../{lesson-3.mdx => lesson-3.md} | 25 +++--- .../{lesson-4.mdx => lesson-4.md} | 24 +++-- .../{lesson-5.mdx => lesson-5.md} | 27 +++--- 40 files changed, 855 insertions(+), 823 deletions(-) rename docs/pages/docs/apis/{access-control.mdx => access-control.md} (79%) rename docs/pages/docs/apis/{auth.mdx => auth.md} (96%) rename docs/pages/docs/apis/{config.mdx => config.md} (96%) rename docs/pages/docs/apis/{context.mdx => context.md} (85%) rename docs/pages/docs/apis/{db-items.mdx => db-items.md} (72%) rename docs/pages/docs/apis/{fields.mdx => fields.md} (97%) rename docs/pages/docs/apis/{filters.mdx => filters.md} (89%) rename docs/pages/docs/apis/{graphql.mdx => graphql.md} (90%) rename docs/pages/docs/apis/{hooks.mdx => hooks.md} (96%) rename docs/pages/docs/apis/{query.mdx => query.md} (76%) rename docs/pages/docs/apis/{schema.mdx => schema.md} (90%) rename docs/pages/docs/apis/{session.mdx => session.md} (87%) rename docs/pages/docs/guides/{auth-and-access-control.mdx => auth-and-access-control.md} (91%) rename docs/pages/docs/guides/{choosing-a-database.mdx => choosing-a-database.md} (70%) rename docs/pages/docs/guides/{cli.mdx => cli.md} (83%) create mode 100644 docs/pages/docs/guides/custom-admin-ui-logo.md delete mode 100644 docs/pages/docs/guides/custom-admin-ui-logo.mdx rename docs/pages/docs/guides/{custom-admin-ui-navigation.mdx => custom-admin-ui-navigation.md} (79%) rename docs/pages/docs/guides/{custom-admin-ui-pages.mdx => custom-admin-ui-pages.md} (78%) create mode 100644 docs/pages/docs/guides/custom-field-views.md delete mode 100644 docs/pages/docs/guides/custom-field-views.mdx rename docs/pages/docs/guides/{custom-fields.mdx => custom-fields.md} (85%) rename docs/pages/docs/guides/{document-fields.mdx => document-fields.md} (92%) rename docs/pages/docs/guides/{filters.mdx => filters.md} (89%) rename docs/pages/docs/guides/{hooks.mdx => hooks.md} (90%) rename docs/pages/docs/guides/{images-and-files.mdx => images-and-files.md} (84%) create mode 100644 docs/pages/docs/guides/internal-items.md delete mode 100644 docs/pages/docs/guides/internal-items.mdx rename docs/pages/docs/guides/{relationships.mdx => relationships.md} (80%) create mode 100644 docs/pages/docs/guides/schema-extension.md delete mode 100644 docs/pages/docs/guides/schema-extension.mdx rename docs/pages/docs/guides/{testing.mdx => testing.md} (83%) rename docs/pages/docs/guides/{virtual-fields.mdx => virtual-fields.md} (91%) rename docs/pages/docs/walkthroughs/{embedded-mode-with-sqlite-nextjs.mdx => embedded-mode-with-sqlite-nextjs.md} (88%) rename docs/pages/docs/walkthroughs/{getting-started-with-create-keystone-app.mdx => getting-started-with-create-keystone-app.md} (71%) rename docs/pages/docs/walkthroughs/{lesson-1.mdx => lesson-1.md} (74%) rename docs/pages/docs/walkthroughs/{lesson-2.mdx => lesson-2.md} (85%) rename docs/pages/docs/walkthroughs/{lesson-3.mdx => lesson-3.md} (91%) rename docs/pages/docs/walkthroughs/{lesson-4.mdx => lesson-4.md} (93%) rename docs/pages/docs/walkthroughs/{lesson-5.mdx => lesson-5.md} (91%) diff --git a/docs/pages/docs/apis/access-control.mdx b/docs/pages/docs/apis/access-control.md similarity index 79% rename from docs/pages/docs/apis/access-control.mdx rename to docs/pages/docs/apis/access-control.md index 0eb868ae858..47d7f1b91f1 100644 --- a/docs/pages/docs/apis/access-control.mdx +++ b/docs/pages/docs/apis/access-control.md @@ -1,8 +1,11 @@ -import { Markdown } from '../../../components/Markdown'; +--- +title: "Access Control API" +description: "Complete reference docs for Keystone’s Access Control API. Configure who can read, create, update, and delete items in your Keystone system." +--- -# Access Control API - -?> We recently improved this API so it’s easier to program, and makes it harder to introduce security gaps in your system. If you were using it prior to September 6th 2021, [read this guide](/updates/new-access-control) for info on how to upgrade. +{% hint kind="warn" %} +We recently improved this API so it’s easier to program, and makes it harder to introduce security gaps in your system. If you were using it prior to September 6th 2021, [read this guide](/updates/new-access-control) for info on how to upgrade. +{% /hint %} The `access` property of the [list configuration](./schema) object configures who can query, create, update, and delete items in your Keystone system. The `access` property of the [field configuration](./fields) object configures who can read, create, and update specific field values of an item. @@ -36,9 +39,13 @@ There are three types of access control that can be configured on the `access` o Each of these types of access control are applied before [hooks](./hooks). -?> Please note that Keystone does not automatically configure nor leverage database row security policies or row level security +{% hint kind="warn" %} +Please note that Keystone does not automatically configure nor leverage database row security policies or row level security +{% /hint %} -!> **Access denied:** **Mutations** return `null` data with an access denied error. **Queries** never return access denied errors, and instead treat items as if they didn't exist. +{% hint kind="tip" %} +**Access denied:** **Mutations** return `null` data with an access denied error. **Queries** never return access denied errors, and instead treat items as if they didn't exist. +{% /hint %} If access is **denied** due to any of the access control methods, the following responses will be returned from the GraphQL API: @@ -56,9 +63,13 @@ If access is **denied** due to any of the access control methods, the following Operation-level access control lets you control which operations can be accessed by a user based on the `session` and `context`. Individual functions can be provided for each of the operations. -?> Each operation type _defaults to public_ unless configured. +{% hint kind="warn" %} +Each operation type _defaults to public_ unless configured. +{% /hint %} -!> These functions must return `true` if the operation is allowed, or `false` if it is not allowed. +{% hint kind="tip" %} +These functions must return `true` if the operation is allowed, or `false` if it is not allowed. +{% /hint %} ```typescript import { config, list } from '@keystone-6/core'; @@ -79,9 +90,11 @@ export default config({ }); ``` -?> The `query` access control is applied only when running GraphQL query operations. +{% hint kind="warn" %} +The `query` access control is applied only when running GraphQL query operations. A user can still **read** fields as part of a return query when using a mutation `operation` (`create`, `update` or `delete`). If you want to limit access to fields, use [field access control](https://keystonejs.com/docs/apis/access-control#field-access-control). +{% /hint %} ### Filter @@ -93,7 +106,9 @@ Filter-level access control lets you restrict which items can be operated on by In general, the filter access control functions will return GraphQL filters. They can also return boolean values `true` or `false` to match or exclude all items. -?> Each `filter` type _defaults to an empty filter_, unless configured. +{% hint kind="warn" %} +Each `filter` type _defaults to an empty filter_, unless configured. +{% /hint %} ```typescript import { config, list } from '@keystone-6/core'; @@ -125,10 +140,14 @@ export default config({ }); ``` -!> Filter based access control cannot be used for `create` operations. +{% hint kind="tip" %} +Filter based access control cannot be used for `create` operations. If you want to limit `create` operations, use either `access.operation.create` or `access.item.create`. +{% /hint %} -?> Filter based access control can impact the performance of your database queries. +{% hint kind="warn" %} +Filter based access control can impact the performance of your database queries. +{% /hint %} ### Item (mutations only) @@ -138,9 +157,13 @@ Individual functions can be provided for each of the operations, with each funct - the **input data** of the mutation (for `create` and `update` operations), and/or - the **existing item** in the database (for `update` and `delete` operations). -?> Each `item` access type _defaults to public_ unless configured. +{% hint kind="warn" %} +Each `item` access type _defaults to public_ unless configured. +{% /hint %} -!> These functions must return `true` if the operation is allowed, or `false` if it is not allowed. +{% hint kind="tip" %} +These functions must return `true` if the operation is allowed, or `false` if it is not allowed. +{% /hint %} ```typescript import { config, list } from '@keystone-6/core'; @@ -161,8 +184,10 @@ export default config({ }); ``` -?> Item-level access control is not available for `query` operations. +{% hint kind="warn" %} +Item-level access control is not available for `query` operations. Applying access control after fetching items would lead to inconsistent pagination behaviour and incorrect `count` results. +{% /hint %} ### Function Arguments @@ -182,7 +207,9 @@ List-level access control functions are passed a collection of arguments which c Keystone also allows you to set up access control on a per-field basis. Rules can be set for `read`, `create` and `update` operations. -!> Each operation is defined by a function which returns `true` if access is allowed and `false` if access is not allowed. +{% hint kind="tip" %} +Each operation is defined by a function which returns `true` if access is allowed and `false` if access is not allowed. +{% /hint %} ### Mutations @@ -197,7 +224,9 @@ Field-level access control rules are applied when trying to resolve a field on t If access is denied then the query will still return an item object, but the specific field will return `null`. No errors will be returned for `read` access denied. -!> The `read` access control is applied to fields returned from both **queries** and **mutations**. +{% hint kind="tip" %} +The `read` access control is applied to fields returned from both **queries** and **mutations**. +{% /hint %} ```typescript import { config, list } from '@keystone-6/core'; @@ -220,7 +249,9 @@ export default config({ }); ``` -!> Field-level access control is not available for `delete` operations. Restrict `delete` operations at the List-level instead with `access.operation.delete`, `access.filter.delete` or `access.item.delete`. +{% hint kind="tip" %} +Field-level access control is not available for `delete` operations. Restrict `delete` operations at the List-level instead with `access.operation.delete`, `access.filter.delete` or `access.item.delete`. +{% /hint %} ### Function Arguments @@ -236,4 +267,3 @@ Field-level access control functions are passed a collection of arguments which | `inputData` | For `create` and `update` operations, this is the value of `data` passed into the mutation. | | `item` | The existing item being read/updated in `read` and `update` operations. | -export default ({ children }) => {children}; diff --git a/docs/pages/docs/apis/auth.mdx b/docs/pages/docs/apis/auth.md similarity index 96% rename from docs/pages/docs/apis/auth.mdx rename to docs/pages/docs/apis/auth.md index b313ed334c6..b462530eee9 100644 --- a/docs/pages/docs/apis/auth.mdx +++ b/docs/pages/docs/apis/auth.md @@ -1,8 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; - -# Authentication API +--- +title: "Authentication API" +description: "API reference for supporting authentication against a password field using the createAuth() function in the `@keystone-6/auth` package." +--- Keystone allows you to extend your Keystone system to support authentication against a `password` field using the `createAuth()` function in the `@keystone-6/auth` package. Additional options to this function provide support for creating an initial item in your database, sending password reset tokens, and sending one-time authentication tokens. @@ -457,13 +456,11 @@ The authenticated item will be returned as `item`. ## Related resources - - - Adds password-based authentication to the Task Manager starter project. - - +{% related-content %} +{% well +heading="Example Project: Authentication" +href="https://github.com/keystonejs/keystone/tree/main/examples/with-auth" %} +Adds password-based authentication to the Task Manager starter project. +{% /well %} +{% /related-content %} -export default ({ children }) => {children}; diff --git a/docs/pages/docs/apis/config.mdx b/docs/pages/docs/apis/config.md similarity index 96% rename from docs/pages/docs/apis/config.mdx rename to docs/pages/docs/apis/config.md index ad0b1b71a50..585961ccfe4 100644 --- a/docs/pages/docs/apis/config.mdx +++ b/docs/pages/docs/apis/config.md @@ -1,9 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; -import { InlineCode } from '../../../components/primitives/Code'; - -# System Configuration API +--- +title: "System Configuration API" +description: "API reference for configuring your Keystone system: Lists, Database, Admin UI, Server, Sessions, GraphQl, Files, Images, and experimental options." +--- The `keystone` [CLI](../guides/cli) expects to find a module named `keystone.ts` with a default export of a Keystone system configuration returned from the function `config()`. @@ -517,13 +515,11 @@ Options: ## Related resources - - - The API to configure your options used with the list function. - - +{% related-content %} +{% well +heading="Schema API Reference" +href="/docs/apis/schema" %} +The API to configure your options used with the `list` function. +{% /well %} +{% /related-content %} -export default ({ children }) => {children}; diff --git a/docs/pages/docs/apis/context.mdx b/docs/pages/docs/apis/context.md similarity index 85% rename from docs/pages/docs/apis/context.mdx rename to docs/pages/docs/apis/context.md index 947bcab3447..d750682d984 100644 --- a/docs/pages/docs/apis/context.mdx +++ b/docs/pages/docs/apis/context.md @@ -1,9 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; -import { InlineCode } from '../../../components/primitives/Code'; - -# Context API +--- +title: "Context API" +description: "The KeystoneContext object is the primary API entry point for all of the run-time functionality of your system. It's APIs can be used to write things like access control, hooks, testing and GraphQL schema extensions." +--- The `KeystoneContext` object is the primary API entry point for all of the run-time functionality of your Keystone system. In GraphQL, a [`context`](https://graphql.org/learn/execution/#root-fields-resolvers) is a value which is provided to every resolver and holds important contextual information such as the currently logged in user, or access to a database. @@ -161,19 +159,16 @@ They will be removed in future releases. ## Related resources - - - A programmatic API for running CRUD operations against your GraphQL API. For each list in your system you get an API at context.query.<listName> - - - The API for running CRUD operations against the internal GraphQL resolvers in your system. It returns internal item objects, which can be returned from GraphQL resolvers. - - - -export default ({ children }) => {children}; +{% related-content %} +{% well +heading="Query API Reference" +href="/docs/apis/query" %} +A programmatic API for running CRUD operations against your GraphQL API. For each list in your system you get an API at `context.query.` +{% /well %} +{% well +heading="DB API Reference" +href="/docs/apis/db-items" %} +The API for running CRUD operations against the internal GraphQL resolvers in your system. It returns internal item objects, which can be returned from GraphQL resolvers. +{% /well %} +{% /related-content %} + diff --git a/docs/pages/docs/apis/db-items.mdx b/docs/pages/docs/apis/db-items.md similarity index 72% rename from docs/pages/docs/apis/db-items.mdx rename to docs/pages/docs/apis/db-items.md index 0028738312e..6e79d2f28fb 100644 --- a/docs/pages/docs/apis/db-items.mdx +++ b/docs/pages/docs/apis/db-items.md @@ -1,9 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; -import { InlineCode } from '../../../components/primitives/Code'; - -# Database API +--- +title: "Database API" +description: "Keystone’s database API is a programmatic API for running CRUD operations against the internal GraphQL resolvers in your system. It bypasses the GraphQL Server itself, invoking resolver functions directly." +--- The database API provides a programmatic API for running CRUD operations against the internal GraphQL resolvers in your system. Importantly, this API bypasses the GraphQL Server itself, instead invoking the resolver functions directly. @@ -145,19 +143,16 @@ const users = await context.db.User.deleteMany({ ## Related resources - - - A programmatic API for running CRUD operations against your GraphQL API. For each list in your system you get an API at context.query.<listName>. - - - The API for run-time functionality in your Keystone system. Use it to write business logic for access control, hooks, testing, GraphQL schema extensions, and more. - - - -export default ({ children }) => {children}; +{% related-content %} +{% well +heading="Query API Reference" +href="/docs/apis/query" %} +A programmatic API for running CRUD operations against your GraphQL API. For each list in your system you get an API at `context.query.`. +{% /well %} +{% well +heading="Context API Reference" +href="/docs/apis/context" %} +The API for run-time functionality in your Keystone system. Use it to write business logic for access control, hooks, testing, GraphQL schema extensions, and more. +{% /well %} +{% /related-content %} + diff --git a/docs/pages/docs/apis/fields.mdx b/docs/pages/docs/apis/fields.md similarity index 97% rename from docs/pages/docs/apis/fields.mdx rename to docs/pages/docs/apis/fields.md index d816583f478..0a4660ada4c 100644 --- a/docs/pages/docs/apis/fields.mdx +++ b/docs/pages/docs/apis/fields.md @@ -1,11 +1,11 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; -import { InlineCode } from '../../../components/primitives/Code'; +--- +title: "Fields API" +description: "A reference of Keystone’s field types, and the configuration options they accept." +--- -# Fields API - -?> We recently improved this API. If you were using it prior to October 5th 2021, [read this guide](/releases/2021-10-05#upgrade-guide) for details on how to upgrade. +{% hint kind="warn" %} +We recently improved this API. If you were using it prior to October 5th 2021, [read this guide](/releases/2021-10-05#upgrade-guide) for details on how to upgrade. +{% /hint %} The `fields` option of a [list configuration](./schema) defines the names, types, and configuration of the fields in the list. This configuration option takes an object with field names as keys, and configured field types as values. @@ -241,7 +241,7 @@ export default config({ A `bigInt` field represents a 64 bit signed integer value. When interacting with the field with GraphQL, values will be strings. When interacting with the field in hooks, values will be [Javascript `BigInt`s](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#bigint_type). -Javascript `BigInt`s are used since [integers in Javascript are unsafe beyond 253](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER). +Javascript `BigInt`s are used since [integers in Javascript are unsafe beyond 2{% sup %}53{% /sup %}](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER). Options: @@ -629,10 +629,12 @@ Options: This is only allowed when you have no create access control because otherwise, the item will always fail access control if a user doesn't have access to create the particular field regardless of whether or not they specify the field in the create. -!> **\*Warning** Unlike with other `keystone` fields, `db.isNullable` is defaulted to `false` for the text field. +{% hint kind="tip" %} +**\*Warning** Unlike with other `keystone` fields, `db.isNullable` is defaulted to `false` for the text field. This is primarily in the interest of not having to make assumptions about how a `null` value can be represented in a text field in the Admin-UI in the default case. These differences, and the rationale for them, are examined in detail [on GitHub](https://github.com/keystonejs/keystone/discussions/7158). You can opt into this behaviour by explicitly setting `isNullable: true`. +{% /hint %} ```typescript import { config, list } from '@keystone-6/core'; @@ -1022,19 +1024,15 @@ export default config({ ## Related resources - - - The API to configure your options used with the list() function. - - - A complete CRUD (create, read, update, delete) GraphQL API derived from the list and field names you configure in your system. - - - -export default ({ children }) => {children} +{% related-content %} +{% well +heading="Schema API Reference" +href="/docs/apis/schema" %} +The API to configure your options used with the `list()` function. +{% /well %} +{% well +heading="GraphQL API Reference" +href="/docs/apis/graphql" %} +A complete CRUD (create, read, update, delete) GraphQL API derived from the list and field names you configure in your system. +{% /well %} +{% /related-content %} diff --git a/docs/pages/docs/apis/filters.mdx b/docs/pages/docs/apis/filters.md similarity index 89% rename from docs/pages/docs/apis/filters.mdx rename to docs/pages/docs/apis/filters.md index d7dcfd988ea..f9c28d1195f 100644 --- a/docs/pages/docs/apis/filters.mdx +++ b/docs/pages/docs/apis/filters.md @@ -1,10 +1,11 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; +--- +title: "Query Filter API" +description: "A reference list of every filters available for every Keystone field type. Keystone filters are typically named after the field they are filtering." +--- -# Query Filter API - -?> We recently improved this API so it’s easier to program and reason about. If you were using it prior to August 17th 2021, [read this guide](/updates/new-graphql-api) for info on how to upgrade. +{% hint kind="warn" %} +We recently improved this API so it’s easier to program and reason about. If you were using it prior to August 17th 2021, [read this guide](/updates/new-graphql-api) for info on how to upgrade. +{% /hint %} Each field type provides its own set of filters which can be used with [queries](./graphql#all-users). This page lists all the filters available for each field type. @@ -151,13 +152,11 @@ The `image` field type does not support filters. ## Related resources - - - Query filters are an integral part of Keystone’s powerful GraphQL APIs. This guide will show you how to use filters to get the data you need from your system. - - +{% related-content %} +{% well +heading="Query Filters Guide" +href="/docs/guides/filters" %} +Query filters are an integral part of Keystone’s powerful GraphQL APIs. This guide will show you how to use filters to get the data you need from your system. +{% /well %} +{% /related-content %} -export default ({ children }) => {children}; diff --git a/docs/pages/docs/apis/graphql.mdx b/docs/pages/docs/apis/graphql.md similarity index 90% rename from docs/pages/docs/apis/graphql.mdx rename to docs/pages/docs/apis/graphql.md index 89e2f173d08..326cd604cf0 100644 --- a/docs/pages/docs/apis/graphql.mdx +++ b/docs/pages/docs/apis/graphql.md @@ -1,11 +1,11 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; -import { InlineCode } from '../../../components/primitives/Code'; +--- +title: "GraphQL API" +description: "Reference docs for Keystone’s CRUD (create, read, update, delete) GraphQL API. Based on the schema definitions outlined in your system config." +--- -# GraphQL API - -?> We recently improved this API so it’s easier to program and reason about. If you were using it prior to August 17th 2021, [read this guide](/updates/new-graphql-api) for info on how to upgrade. +{% hint kind="warn" %} +We recently improved this API so it’s easier to program and reason about. If you were using it prior to August 17th 2021, [read this guide](/updates/new-graphql-api) for info on how to upgrade. +{% /hint %} Keystone generates a CRUD (create, read, update, delete) GraphQL API based on the [schema](./schema) definition provided in the system [config](./config). @@ -461,19 +461,16 @@ The following error codes can be returned from the Keystone GraphQL API. ## Related resources - - - The API to configure your options used with the list() function. - - - The API to configure all the parts parts of your Keystone system. - - - -export default ({ children }) => {children}; +{% related-content %} +{% well +heading="Schema API Reference" +href="/docs/apis/schema" %} +The API to configure your options used with the `list()` function. +{% /well %} +{% well +heading="Config API Reference" +href="/docs/apis/config" %} +The API to configure all the parts parts of your Keystone system. +{% /well %} +{% /related-content %} + diff --git a/docs/pages/docs/apis/hooks.mdx b/docs/pages/docs/apis/hooks.md similarity index 96% rename from docs/pages/docs/apis/hooks.mdx rename to docs/pages/docs/apis/hooks.md index 22af22e1c3f..cebd74e16ec 100644 --- a/docs/pages/docs/apis/hooks.mdx +++ b/docs/pages/docs/apis/hooks.md @@ -1,8 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; - -# Hooks API +--- +title: "Hooks API" +description: "Hooks let you to execute code at different stages of the mutation lifecycle when performing create, update, and delete operations." +--- Hooks allow you to execute code at different stages of the mutation lifecycle when performing create, update, and delete operations. Lists and fields both support the same set of hook functions, with some slight differences in the arguments they accept. @@ -351,13 +350,11 @@ The data resolving steps are applied in the following order: ## Related resources - - - Learn how to use Hooks within your schema to extend Keystone’s powerful CRUD GraphQL APIs with your own business logic. - - +{% related-content %} +{% well +heading="Hooks Guide" +href="/docs/guides/hooks" %} +Learn how to use Hooks within your schema to extend Keystone’s powerful CRUD GraphQL APIs with your own business logic. +{% /well %} +{% /related-content %} -export default ({ children }) => {children}; diff --git a/docs/pages/docs/apis/query.mdx b/docs/pages/docs/apis/query.md similarity index 76% rename from docs/pages/docs/apis/query.mdx rename to docs/pages/docs/apis/query.md index daeda462a26..264ceee1ca9 100644 --- a/docs/pages/docs/apis/query.mdx +++ b/docs/pages/docs/apis/query.md @@ -1,8 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; - -# Query API +--- +title: "Query API" +description: "Reference docs for Keystone‘s Query API: a programmatic API for running CRUD operations against your GraphQL API." +--- The Query API provides a programmatic API for running CRUD operations against your GraphQL API. For each list in your system the following API is available at `context.query.`. @@ -148,19 +147,16 @@ const users = await context.query.User.deleteMany({ ## Related resources - - - The API for run-time functionality in your Keystone system. Use it to write business logic for access control, hooks, testing, GraphQL schema extensions, and more. - - - The API for running CRUD operations against the internal GraphQL resolvers in your system. It returns internal item objects, which can be returned from GraphQL resolvers. - - - -export default ({ children }) => {children}; +{% related-content %} +{% well +heading="Context API Reference" +href="/docs/apis/context" %} +The API for run-time functionality in your Keystone system. Use it to write business logic for access control, hooks, testing, GraphQL schema extensions, and more. +{% /well %} +{% well +heading="DB API Reference" +href="/docs/apis/db-items" %} +The API for running CRUD operations against the internal GraphQL resolvers in your system. It returns internal item objects, which can be returned from GraphQL resolvers. +{% /well %} +{% /related-content %} + diff --git a/docs/pages/docs/apis/schema.mdx b/docs/pages/docs/apis/schema.md similarity index 90% rename from docs/pages/docs/apis/schema.mdx rename to docs/pages/docs/apis/schema.md index d0e970788f5..fad316590b5 100644 --- a/docs/pages/docs/apis/schema.mdx +++ b/docs/pages/docs/apis/schema.md @@ -1,8 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; - -# Schema API +--- +title: "Schema API" +description: "Reference docs for Keystone’s Schema API, which defines the data model of your system." +--- The `lists` property of the [system configuration](./config) object is where you define the data model, or schema, of your Keystone system. It accepts an object with list names as keys, and `list()` configurations as values. @@ -233,27 +232,22 @@ This option can be individually overridden by the `graphql.description` or `ui.d ## Related resources - - - Defines the names, types, and configuration of Keystone fields. See all the fields and the configuration options they accept. - - - The API to configure all the parts parts of your Keystone system. - - - A basic Blog schema with Posts and Authors. Use this as a starting place for learning how to use Keystone. It’s also a starter for other feature projects. - - - -export default ({ children }) => {children}; +{% related-content %} +{% well +heading="Fields API Reference" +href="/docs/apis/fields" %} +Defines the names, types, and configuration of Keystone fields. See all the fields and the configuration options they accept. +{% /well %} +{% well +heading="Config API Reference" +href="/docs/apis/config" %} +The API to configure all the parts parts of your Keystone system. +{% /well %} +{% well +heading="Example Project: Blog" +href="https://github.com/keystonejs/keystone/tree/main/examples/blog" +target="_blank" %} +A basic Blog schema with Posts and Authors. Use this as a starting place for learning how to use Keystone. It’s also a starter for other feature projects. +{% /well %} +{% /related-content %} + diff --git a/docs/pages/docs/apis/session.mdx b/docs/pages/docs/apis/session.md similarity index 87% rename from docs/pages/docs/apis/session.mdx rename to docs/pages/docs/apis/session.md index ff86e292b65..26b6075fffd 100644 --- a/docs/pages/docs/apis/session.mdx +++ b/docs/pages/docs/apis/session.md @@ -1,8 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; - -# Session API +--- +title: "Session API" +description: "Reference docs for the session property of Keystone’s system configuration object." +--- The `session` property of the [system configuration](./config) object allows you to configure session management of your Keystone system. It has a TypeScript type of `SessionStrategy`. @@ -126,21 +125,17 @@ These mutations will set the value of `session` to include the values `{ listKey ## Related resources - - - The API to configure all the parts parts of your Keystone system. - - - Adds password-based authentication to the Task Manager starter project. - - - -export default ({ children }) => {children}; +{% related-content %} +{% well +heading="Config API Reference" +href="/docs/apis/config" %} +The API to configure all the parts parts of your Keystone system. +{% /well %} +{% well +heading="Example Project: Authentication" +href="https://github.com/keystonejs/keystone/tree/main/examples/with-auth" +target="_blank" %} +Adds password-based authentication to the Task Manager starter project. +{% /well %} +{% /related-content %} + diff --git a/docs/pages/docs/guides/auth-and-access-control.mdx b/docs/pages/docs/guides/auth-and-access-control.md similarity index 91% rename from docs/pages/docs/guides/auth-and-access-control.mdx rename to docs/pages/docs/guides/auth-and-access-control.md index cfbad0950de..c75e3df57ee 100644 --- a/docs/pages/docs/guides/auth-and-access-control.mdx +++ b/docs/pages/docs/guides/auth-and-access-control.md @@ -1,8 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; - -# Authentication and Access Control +--- +title: "Authentication and Access Control" +description: "Learn how to use Keystone's built-in Authentication and Access Control systems." +--- Keystone comes with several features that work together to control access to the Admin UI and GraphQL API: @@ -38,7 +37,9 @@ const Person = list({ }); ``` -!> Read more about creating lists in the [schema](../apis/schema) and [fields](../apis/schema) API Docs. +{% hint kind="tip" %} +Read more about creating lists in the [schema](../apis/schema) and [fields](../apis/schema) API Docs. +{% /hint %} ### Configure authentication @@ -56,7 +57,9 @@ const { withAuth } = createAuth({ The `createAuth` function returns another function called `withAuth` that will automatically extend Keystone's config to set up everything we need. Behind the scenes, the `auth` package is just using lower-level Keystone APIs to do everything, which means if you want to do something differently, you can fork our implementation of `auth` and build your own (this is true for session management as well) -!> Read more about `createAuth` in the [Auth API Docs](../apis/auth). +{% hint kind="tip" %} +Read more about `createAuth` in the [Auth API Docs](../apis/auth). +{% /hint %} ### Configure sessions @@ -70,7 +73,9 @@ const session = statelessSessions({ Keystone also comes with a Redis session adapter, which uses a cookie to store a session ID that is looked up in a Redis database; or you can use your own session adapter (for example, if you are using OAuth sessions). -!> Read more about [Session Stores in the Session API Docs](../apis/session#session-stores). +{% hint kind="tip" %} +Read more about [Session Stores in the Session API Docs](../apis/session#session-stores). +{% /hint %} ### Putting it all together @@ -162,7 +167,9 @@ The way to think about access control is – - With **Session Data**, you know who the user is, and what they should have access to (whether that's permissions granted by a role, or items related to them) - For each **List** you can restrict which operations they can perform, filter the items they have access to, and control which fields they can read and update. -!> In other words: **Step 1** load data about the current user; **Step 2** use that data to limit what they can do. +{% hint kind="tip" %} +In other words: **Step 1** load data about the current user; **Step 2** use that data to limit what they can do. +{% /hint %} You define access control for each List (and field) individually; the rules you specify will always be run, even when the list is being queried or mutated through a relationship. @@ -247,7 +254,9 @@ query { } ``` -!> An easy way to set up Access Control filters is to write them as queries in the GraphQL Playground, then test them to make sure they return the results you expect. When you're happy, copy and paste the `where` input into your access control function. +{% hint kind="tip" %} +An easy way to set up Access Control filters is to write them as queries in the GraphQL Playground, then test them to make sure they return the results you expect. When you're happy, copy and paste the `where` input into your access control function. +{% /hint %} These filters are **combined** with any filters provided through the GraphQL API, and there's no way to circumvent them when making HTTP Requests. @@ -313,7 +322,9 @@ mutation { } ``` -!> Note: this is different to **field** access control, where the `read` access control rule will affect a user's ability to retrieve the value for that field regardless of the query or mutation. +{% hint kind="tip" %} +Note: this is different to **field** access control, where the `read` access control rule will affect a user's ability to retrieve the value for that field regardless of the query or mutation. +{% /hint %} ### Different levels of Access Control @@ -342,7 +353,9 @@ type Access = { }; ``` -!> We'll cover field access control separately below. +{% hint kind="tip" %} +We'll cover field access control separately below. +{% /hint %} You'll generally only need to use a subset of the available options: @@ -360,7 +373,9 @@ In addition to returning filters, you can return a boolean where: - `true` effectively means match _all_ records (no filter is applied) - `false` effectively means match _no_ records (the operation will be blocked) -!> Returning a boolean from filter access control is functionally the same as using operation access control, so if you specify filter access control, you rarely also need to specify operation access control. +{% hint kind="tip" %} +Returning a boolean from filter access control is functionally the same as using operation access control, so if you specify filter access control, you rarely also need to specify operation access control. +{% /hint %} Query filters are also applied to count operations, so you can paginate items predictably without revealing the existence of items the user does not have access to. @@ -455,7 +470,6 @@ const extendGraphqlSchema = graphQLSchemaExtension({ }); ``` -export default ({ children }) => {children}; ## Field Access Control @@ -467,7 +481,9 @@ You can provide field-level rules for: - Create – applied when items are being created - Update – applied when items are being updated -!> If you want to completely block users from setting a field's value, make sure you set both the `create` and `update` rules. +{% hint kind="tip" %} +If you want to completely block users from setting a field's value, make sure you set both the `create` and `update` rules. +{% /hint %} For more information about the arguments provided to field rules, see the [Access Control API Docs](../apis/access-control#field-access-control) @@ -540,17 +556,15 @@ const Person = list({ ## Related resources - - - Documentation for the Auth Package API - - - Documentation for the Access Control API - - +{% related-content %} +{% well +heading="Authentication" +href="../apis/auth" %} +Documentation for the Auth Package API +{% /well %} +{% well +heading="Access Control" +href="../apis/access-control" %} +Documentation for the Access Control API +{% /well %} +{% /related-content %} diff --git a/docs/pages/docs/guides/choosing-a-database.mdx b/docs/pages/docs/guides/choosing-a-database.md similarity index 70% rename from docs/pages/docs/guides/choosing-a-database.mdx rename to docs/pages/docs/guides/choosing-a-database.md index a5e8c1fb555..dbce5c064d1 100644 --- a/docs/pages/docs/guides/choosing-a-database.mdx +++ b/docs/pages/docs/guides/choosing-a-database.md @@ -1,12 +1,13 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; - -# Choosing the right Database +--- +title: "Choosing the right Database" +description: "How to choose the right database for your Keystone project" +--- Keystone supports [Postgres](https://www.postgresql.org), [MySQL](https://www.mysql.com) and [SQLite](https://www.sqlite.org/index.html) database [providers](../apis.config#db). This guide highlights the differences between these providers to help you choose the right one for your project. -!> **Note:** SQLite is not recommended in production except for scenarios like the [Embedded Keystone](../walkthroughs/embedded-mode-with-sqlite-nextjs) example +{% hint kind="tip" %} +**Note:** SQLite is not recommended in production except for scenarios like the [Embedded Keystone](../walkthroughs/embedded-mode-with-sqlite-nextjs) example +{% /hint %} ## Case Sensitivity @@ -15,7 +16,9 @@ When using `StringFilter` in a GraphQL query the `mode` defaults to case sensiti See the [Case Sensitivity Prisma Docs](https://www.prisma.io/docs/concepts/components/prisma-client/case-sensitivity) for more information. -!> **Note:** `mode: insensitive` is not supported in MySQL or SQLite +{% hint kind="tip" %} +**Note:** `mode: insensitive` is not supported in MySQL or SQLite +{% /hint %} ## Default Types @@ -35,19 +38,16 @@ For supported database provider versions for Postgres and MySQL see [Prisma Supp ## Related resources - - - Documentation for the Fields API - - - Documentation for the DB Config API - - - -export default ({ children }) => {children}; +{% related-content %} +{% well +heading="Fields API" +href="../apis/fields" %} +Documentation for the Fields API +{% /well %} +{% well +heading="DB Config API" +href="../apis/config#db" %} +Documentation for the DB Config API +{% /well %} +{% /related-content %} + diff --git a/docs/pages/docs/guides/cli.mdx b/docs/pages/docs/guides/cli.md similarity index 83% rename from docs/pages/docs/guides/cli.mdx rename to docs/pages/docs/guides/cli.md index f0f30fc853c..8859bfca79f 100644 --- a/docs/pages/docs/guides/cli.mdx +++ b/docs/pages/docs/guides/cli.md @@ -1,8 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; - -# Command Line +--- +title: "Command Line" +description: "Learn how to use Keystone's command line interface (CLI) to develop, build, and deploy your Keystone projects." +--- Keystone's command line interface (CLI) has been designed to help you develop, build, and deploy your Keystone project. @@ -21,7 +20,9 @@ Commands prisma run Prisma CLI commands safely ``` -!> All the commands expect to find a module called `keystone.js` (or `.ts`) with a default export that returns a Keystone System `config()` from `@keystone-6/core`. See [System Configuration](../apis/config) for details. +{% hint kind="tip" %} +All the commands expect to find a module called `keystone.js` (or `.ts`) with a default export that returns a Keystone System `config()` from `@keystone-6/core`. See [System Configuration](../apis/config) for details. +{% /hint %} ## Setting up package.json @@ -38,7 +39,9 @@ We recommend adding the following scripts to your project's `package.json` file: } ``` -!> Note: the deploy script above assumes you are using migrations +{% hint kind="tip" %} +Note: the deploy script above assumes you are using migrations +{% /hint %} Read on below for more details about each command, and see [bringing it all together](#bringing-it-all-together) for more details (including some important caveats) about how that "deploy" command works. @@ -54,7 +57,9 @@ This is the command you use to start Keystone for local development. It will: - Generate and apply database migrations based on your Keystone Schema - Start the local dev server, which hosts the GraphQL API and Admin UI -?> Keystone does not currently watch your local files for changes. If you update the config, schema or any other files in your keystone project you'll need to restart the server. +{% hint kind="warn" %} +Keystone does not currently watch your local files for changes. If you update the config, schema or any other files in your keystone project you'll need to restart the server. +{% /hint %} ### About database migrations @@ -67,7 +72,9 @@ When you are using migrations, the recommended workflow is to have `keystone dev Commit the migration files to source control, then when you are hosting your app in production, use the `keystone prisma migrate deploy` command (see below) to deploy your migrations before starting Keystone. -!> We strongly recommend enabling migrations if you are going to run your app in production. Not doing so risks data loss. +{% hint kind="tip" %} +We strongly recommend enabling migrations if you are going to run your app in production. Not doing so risks data loss. +{% /hint %} ### Resetting the database @@ -77,7 +84,9 @@ From time to time, in development you may want to reset the database and recreat $ keystone dev --reset-db ``` -x> Doing this will destroy your database, including all data +{% hint kind="error" %} +Doing this will destroy your database, including all data +{% /hint %} This is mainly useful early in a project's development lifecycle, when you want to test database initialisation scripts or create a fresh set of test data. @@ -171,7 +180,9 @@ Install the project dependencies, generate the build and deploy migrations: yarn && yarn keystone build && yarn keystone prisma migrate deploy ``` -x> Note: it is only safe to run migrations in the build step if deploys are built synchronously by your hosting provider. Make sure you don't run migrations against your production database from staging / preview builds. +{% hint kind="error" %} +Note: it is only safe to run migrations in the build step if deploys are built synchronously by your hosting provider. Make sure you don't run migrations against your production database from staging / preview builds. +{% /hint %} #### Start Script @@ -190,13 +201,11 @@ yarn keystone start ## Related resources - - - How to use Keystone's CLI app to standup a new local project with an Admin UI & the GraphQL Playground. - - +{% related-content %} +{% well +heading="Getting Started with create-keystone-app" +href="/docs/walkthroughs/getting-started-with-create-keystone-app" %} +How to use Keystone's CLI app to standup a new local project with an Admin UI & the GraphQL Playground. +{% /well %} +{% /related-content %} -export default ({ children }) => {children}; diff --git a/docs/pages/docs/guides/custom-admin-ui-logo.md b/docs/pages/docs/guides/custom-admin-ui-logo.md new file mode 100644 index 00000000000..9da2426db9d --- /dev/null +++ b/docs/pages/docs/guides/custom-admin-ui-logo.md @@ -0,0 +1,71 @@ +--- +title: "Custom Admin UI Logo" +description: "Learn how to customize Keystone’s Admin UI with your own logo." +--- + +In this guide we'll show you how to add a custom logo to the Keystone Admin UI. + +{% hint kind="tip" %} +Presently the only replaceable component in the Admin UI is the logo. If you have suggestions as to other components you would like to be able to customise, let us know on [Slack](https://community.keystonejs.com) +{% /hint %} + +To import a custom component for rendering within the Admin UI, ensure that the `admin/config.tsx` file exists in the root of your Keystone project. +This file expects a named export `components`. + +```tsx +// admin/config.tsx +function CustomLogo () { + return

Custom Logo here

+} + +export const components = { + Logo: CustomLogo +} +``` + +If you have styling constraints, we recommend using the jsx export from the `@keystone-ui/core` package, as this will ensure that the version of emotion you're using conforms with the version of emotion used internally within Keystone. + +```tsx +// admin/config.tsx +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@keystone-ui/core'; + +function CustomLogo () { + return

Custom Logo here

+} + +export const components = { + Logo: CustomLogo +} +``` + +Of course this is purely a recommendation, if you would prefer to roll your own css-in-js solution in with your custom component please feel free to! Although this may require additional configuration outside of the scope of this guide. + +Once you've added your custom logo component you should see it rendered out in the Admin UI. +![image of Admin UI with custom logo](/assets/guides/custom-admin-ui-logo/custom-logo-result.png) + +## Related resources + +{% related-content %} +{% well +heading="Example: Custom Admin UI Logo" +href="https://github.com/keystonejs/keystone/tree/main/examples/custom-admin-ui-logo" +target="_blank" %} +Adds a custom logo component in the Admin UI. Builds on the Task Manager starter project. +{% /well %} +{% well +heading="Custom Admin UI Navigation Guide" +href="/docs/guides/custom-admin-ui-navigation" %} +Learn how to create your own custom Navigation components in Keytone’s Admin UI. +{% /well %} +{% well +heading="Custom Admin UI Pages Guide" +href="/docs/guides/custom-admin-ui-pages" %} +Learn how to add your own custom pages to Keystone’s Admin UI. +{% /well %} + +{% /related-content %} + diff --git a/docs/pages/docs/guides/custom-admin-ui-logo.mdx b/docs/pages/docs/guides/custom-admin-ui-logo.mdx deleted file mode 100644 index f8f536b3186..00000000000 --- a/docs/pages/docs/guides/custom-admin-ui-logo.mdx +++ /dev/null @@ -1,77 +0,0 @@ -import { ComingSoon } from '../../../components/docs/ComingSoon'; -import { Markdown } from '../../../components/Markdown'; -import { Alert } from '../../../components/primitives/Alert' -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; - -# Custom Admin UI Logo - -In this guide we'll show you how to add a custom logo to the Keystone Admin UI. - -!> Presently the only replaceable component in the Admin UI is the logo. If you have suggestions as to other components you would like to be able to customise, let us know on [Slack](https://community.keystonejs.com) - -To import a custom component for rendering within the Admin UI, ensure that the `admin/config.tsx` file exists in the root of your Keystone project. -This file expects a named export `components`. - -```tsx -// admin/config.tsx -function CustomLogo () { - return

Custom Logo here

-} - -export const components = { - Logo: CustomLogo -} -``` - -If you have styling constraints, we recommend using the jsx export from the `@keystone-ui/core` package, as this will ensure that the version of emotion you're using conforms with the version of emotion used internally within Keystone. - -```tsx -// admin/config.tsx -/** @jsxRuntime classic */ -/** @jsx jsx */ -import { jsx } from '@keystone-ui/core'; - -function CustomLogo () { - return

Custom Logo here

-} - -export const components = { - Logo: CustomLogo -} -``` - -Of course this is purely a recommendation, if you would prefer to roll your own css-in-js solution in with your custom component please feel free to! Although this may require additional configuration outside of the scope of this guide. - -Once you've added your custom logo component you should see it rendered out in the Admin UI. -![image of Admin UI with custom logo](/assets/guides/custom-admin-ui-logo/custom-logo-result.png) - -## Related resources - - - - Adds a custom logo component in the Admin UI. Builds on the Task Manager starter project. - - - Learn how to create your own custom Navigation components in Keytone’s Admin UI. - - - Learn how to add your own custom pages to Keystone’s Admin UI. - - - - -export default ({ children }) => {children}; diff --git a/docs/pages/docs/guides/custom-admin-ui-navigation.mdx b/docs/pages/docs/guides/custom-admin-ui-navigation.md similarity index 79% rename from docs/pages/docs/guides/custom-admin-ui-navigation.mdx rename to docs/pages/docs/guides/custom-admin-ui-navigation.md index 64c30dac214..edebf129a9e 100644 --- a/docs/pages/docs/guides/custom-admin-ui-navigation.mdx +++ b/docs/pages/docs/guides/custom-admin-ui-navigation.md @@ -1,13 +1,14 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; - -# Custom Admin UI Navigation +--- +title: "Custom Admin UI Navigation" +description: "In this guide, we'll show you how to create a custom Navigation component to be rendered in the Admin UI." +--- In this guide, we'll show you how to create a custom Navigation component to be rendered in the Admin UI. -!> By the end of this guide you should have a custom Navigation component rendering in the Admin UI with a custom route pointing to the KeystoneJS docs. +{% hint kind="tip" %} +By the end of this guide you should have a custom Navigation component rendering in the Admin UI with a custom route pointing to the KeystoneJS docs. ![finished custom navigation example](/assets/guides/custom-admin-ui-navigation/final-result.png) +{% /hint %} ## Adding the custom navigation component to the Admin UI @@ -52,7 +53,9 @@ type NavigationProps = { } ``` -!> For more information on the props, please see the [Navigation Props](#navigation-props) section of this guide. +{% hint kind="tip" %} +For more information on the props, please see the [Navigation Props](#navigation-props) section of this guide. +{% /hint %} ### Setting up the layout @@ -80,7 +83,9 @@ export function CustomNavigation({ authenticatedItem, lists }: NavigationProps) } ``` -!> For more information on the `NavigationContainer` see the [NavigationContainer](#navigation-container) section of the [component docs](#components) below. +{% hint kind="tip" %} +For more information on the `NavigationContainer` see the [NavigationContainer](#navigation-container) section of the [component docs](#components) below. +{% /hint %} ### Rendering NavItems for Keystone lists @@ -100,7 +105,9 @@ export function CustomNavigation({ authenticatedItem, lists }: NavigationProps) } ``` -!> For more information on the `ListNavItems` component, see the [ListNavItems](#list-nav-items) section of the [component docs](#components) below. +{% hint kind="tip" %} +For more information on the `ListNavItems` component, see the [ListNavItems](#list-nav-items) section of the [component docs](#components) below. +{% /hint %} ### Adding additional routes @@ -123,9 +130,13 @@ export function CustomNavigation({ authenticatedItem, lists }: NavigationProps) } ``` -!> For more information on the `NavItem` component, see the [NavItem](#nav-item) section of the [component docs](#components) below. +{% hint kind="tip" %} +For more information on the `NavItem` component, see the [NavItem](#nav-item) section of the [component docs](#components) below. +{% /hint %} -?> **Note** When opting into a custom Navigation component you will need to specify a NavItem for the `Dashboard` page (the `/` route). +{% hint kind="warn" %} +**Note** When opting into a custom Navigation component you will need to specify a NavItem for the `Dashboard` page (the `/` route). +{% /hint %} ### Putting it all together @@ -160,7 +171,9 @@ export const components: AdminConfig['components'] = { Start up your Keystone project, and you should see Custom Navigation with a route to the KeystoneJS docs in the Admin UI. ![finished custom navigation example](/assets/guides/custom-admin-ui-navigation/final-result.png) -!> The rest of this guide will elaborate on some of the details around the helper components Keystone provides and the Navigation props that we glossed over in the main guide. +{% hint kind="tip" %} +The rest of this guide will elaborate on some of the details around the helper components Keystone provides and the Navigation props that we glossed over in the main guide. +{% /hint %} ## Navigation props @@ -207,7 +220,9 @@ type AuthenticatedItem = The `authenticatedItem` props is rendered automatically when you pass it into the `NavigationContainer` component. -?> If you render the `authenticatedItem` yourself, make sure you handle all of the possible states. +{% hint kind="warn" %} +If you render the `authenticatedItem` yourself, make sure you handle all of the possible states. +{% /hint %} ## Components @@ -227,7 +242,9 @@ type NavigationContainerProps = { } ``` -!> For the shape of the `authenticatedItem` prop, please see the [Navigation Props](#navigation-props) section above. +{% hint kind="tip" %} +For the shape of the `authenticatedItem` prop, please see the [Navigation Props](#navigation-props) section above. +{% /hint %} ```tsx import { NavigationContainer} from '@keystone-6/core/admin-ui/components' @@ -308,27 +325,21 @@ Pass in `isSelected` if you have a custom condition or would like more granular ## Related resources - - - Adds a custom navigation component to the Admin UI. Builds on the Task Manager starter project. - - - Learn how to add your own custom logo to Keystone’s Admin UI. - - - Learn how to add your own custom pages to Keystone’s Admin UI. - - - -export default ({ children }) => {children} +{% related-content %} +{% well +heading="Example: Custom Admin UI Navigation" +href="https://github.com/keystonejs/keystone/tree/main/examples/custom-admin-ui-navigation" +target="_blank" %} +Adds a custom navigation component to the Admin UI. Builds on the Task Manager starter project. +{% /well %} +{% well +heading="Custom Admin UI Logo Guide" +href="/docs/guides/custom-admin-ui-logo" %} +Learn how to add your own custom logo to Keystone’s Admin UI. +{% /well %} +{% well +heading="Custom Admin UI Pages Guide" +href="/docs/guides/custom-admin-ui-pages" %} +Learn how to add your own custom pages to Keystone’s Admin UI. +{% /well %} +{% /related-content %} diff --git a/docs/pages/docs/guides/custom-admin-ui-pages.mdx b/docs/pages/docs/guides/custom-admin-ui-pages.md similarity index 78% rename from docs/pages/docs/guides/custom-admin-ui-pages.mdx rename to docs/pages/docs/guides/custom-admin-ui-pages.md index 2cb0ca687e2..60218e95d4b 100644 --- a/docs/pages/docs/guides/custom-admin-ui-pages.mdx +++ b/docs/pages/docs/guides/custom-admin-ui-pages.md @@ -1,10 +1,7 @@ -import { ComingSoon } from '../../../components/docs/ComingSoon'; -import { Markdown } from '../../../components/Markdown'; -import { Alert } from '../../../components/primitives/Alert'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; - -# Custom Admin UI Pages +--- +title: "Custom Admin UI Pages" +description: "Learn how to add custom pages to the Keystone Admin UI." +--- ## Getting Started @@ -29,7 +26,9 @@ export default function CustomPage () { } ``` -x> **Not all Next.js exports are available:** Keystone **only** supports the page component as a default export in the pages directory. This means that unlike with Next, auxillary exports such as `getStaticProps` and `getServerProps` are not supported. +{% hint kind="error" %} +**Not all Next.js exports are available:** Keystone **only** supports the page component as a default export in the pages directory. This means that unlike with Next, auxillary exports such as `getStaticProps` and `getServerProps` are not supported. +{% /hint %} With this in place, we now have a nice simple custom Admin UI page at `http://localhost:3000/custom-page`. ![example of a simple custom-page in the Admin UI](/assets/guides/custom-admin-ui-pages/simple-custom-page.png) @@ -111,9 +110,13 @@ export function CustomNavigation({ lists, authenticatedItem }: NavigationProps) } ``` -!> You will need to restart your Keystone system after adding `admin/config.ts` for the custom Navigation component to be loaded. +{% hint kind="tip" %} +You will need to restart your Keystone system after adding `admin/config.ts` for the custom Navigation component to be loaded. +{% /hint %} -!> If you're interested in more details on creating a custom Navigation component check out the [Custom Admin UI Navigation](/docs/guides/custom-admin-ui-navigation) guide. +{% hint kind="tip" %} +If you're interested in more details on creating a custom Navigation component check out the [Custom Admin UI Navigation](/docs/guides/custom-admin-ui-navigation) guide. +{% /hint %} Lastly we'll add our new route to the newly created `CustomNavigation` component. @@ -132,7 +135,9 @@ export function CustomNavigation({ lists, authenticatedItem }: NavigationProps) } ``` -!> Under the hood Keystone's Admin UI is powered by Next.js, so the route to our custom page is the filename of our custom page component. In this case it's `/custom-page`. +{% hint kind="tip" %} +Under the hood Keystone's Admin UI is powered by Next.js, so the route to our custom page is the filename of our custom page component. In this case it's `/custom-page`. +{% /hint %} With all that in place, our custom Admin UI page is now navigable from the Admin UI Navigation component, and we can access it from other pages in the Admin UI. ![completed custom Admin UI page](/assets/guides/custom-admin-ui-pages/custom-page-completed.png) @@ -180,27 +185,22 @@ Using `emotion` for styling is purely a recommendation, if you would prefer to u ## Related resources - - - Adds a custom page in the Admin UI. Builds on the Task Manager starter project. - - - Learn how to add your own custom logo to Keystone’s Admin UI. - - - Learn how to create your own custom Navigation components in Keytone’s Admin UI. - - - -export default ({ children }) => {children}; +{% related-content %} +{% well +heading="Example: Custom Admin UI Pages" +href="https://github.com/keystonejs/keystone/tree/main/examples/custom-admin-ui-pages" +target="_blank" %} +Adds a custom page in the Admin UI. Builds on the Task Manager starter project. +{% /well %} +{% well +heading="Custom Admin UI Logo Guide" +href="/docs/guides/custom-admin-ui-logo" %} +Learn how to add your own custom logo to Keystone’s Admin UI. +{% /well %} +{% well +heading="Custom Admin UI Navigation Guide" +href="/docs/guides/custom-admin-ui-navigation" %} +Learn how to create your own custom Navigation components in Keytone’s Admin UI. +{% /well %} +{% /related-content %} + diff --git a/docs/pages/docs/guides/custom-field-views.md b/docs/pages/docs/guides/custom-field-views.md new file mode 100644 index 00000000000..d4d6d5dfdf4 --- /dev/null +++ b/docs/pages/docs/guides/custom-field-views.md @@ -0,0 +1,7 @@ +--- +title: "Custom Field Views" +description: "We've planned this page but not had a chance to write it yet." +--- + +{% coming-soon /%} + diff --git a/docs/pages/docs/guides/custom-field-views.mdx b/docs/pages/docs/guides/custom-field-views.mdx deleted file mode 100644 index 20df8bc5885..00000000000 --- a/docs/pages/docs/guides/custom-field-views.mdx +++ /dev/null @@ -1,8 +0,0 @@ -import { ComingSoon } from '../../../components/docs/ComingSoon'; -import { Markdown } from '../../../components/Markdown'; - -# Custom Field Views - - - -export default ({ children }) => {children}; diff --git a/docs/pages/docs/guides/custom-fields.mdx b/docs/pages/docs/guides/custom-fields.md similarity index 85% rename from docs/pages/docs/guides/custom-fields.mdx rename to docs/pages/docs/guides/custom-fields.md index 0f1e5b36f1c..271e6b3085a 100644 --- a/docs/pages/docs/guides/custom-fields.mdx +++ b/docs/pages/docs/guides/custom-fields.md @@ -1,9 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; -import { InlineCode } from '../../../components/primitives/Code'; - -# Custom Fields +--- +title: "Custom Fields" +description: "Learn how to expand Keystone with your own custom fields. Guidance on backend setup, and frontend implementation in Keystone‘s Admin UI." +--- Keystone provides a collection of [field types](../apis/fields) which you can use to build your system. If you need a field type which isn't provided, or you need a specialised version of an existing field type, you can define your own custom field type. @@ -16,7 +14,9 @@ There are two parts to a field type: The general approach to creating a custom field type is to take an existing field type and make the appropriate changes for your use case. In this guide we're going to create a field type `myInt` which recreates the [`integer`](https://github.com/keystonejs/keystone/tree/main/packages/core/src/fields/types/integer) field type. -!> For inspiration, see [the source for the fields that Keystone provides](https://github.com/keystonejs/keystone/tree/main/packages/core/src/fields/types) and the [Custom Fields](https://github.com/keystonejs/keystone/tree/main/examples/custom-field) example project. +{% hint kind="tip" %} +For inspiration, see [the source for the fields that Keystone provides](https://github.com/keystonejs/keystone/tree/main/packages/core/src/fields/types) and the [Custom Fields](https://github.com/keystonejs/keystone/tree/main/examples/custom-field) example project. +{% /hint %} ## Backend @@ -216,15 +216,12 @@ export const CardValue: CardValueComponent = ({ item, field }) => { ## Related resources - - - Adds a custom field type based on the integer field type which lets users rate items on a 5-star scale. Builds on the Blog starter project. - - - -export default ({ children }) => {children}; +{% related-content %} +{% well +heading="Example Project: Custom Fields" +href="https://github.com/keystonejs/keystone/tree/main/examples/custom-field" +target="_blank" %} +Adds a custom field type based on the `integer` field type which lets users rate items on a 5-star scale. Builds on the Blog starter project. +{% /well %} +{% /related-content %} + diff --git a/docs/pages/docs/guides/document-fields.mdx b/docs/pages/docs/guides/document-fields.md similarity index 92% rename from docs/pages/docs/guides/document-fields.mdx rename to docs/pages/docs/guides/document-fields.md index c4c42133488..daba8da579b 100644 --- a/docs/pages/docs/guides/document-fields.mdx +++ b/docs/pages/docs/guides/document-fields.md @@ -1,9 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; -import { InlineCode } from '../../../components/primitives/Code'; - -# How To Use Document Fields +--- +title: "How To Use Document Fields" +description: "Learn how to configure Keystone’s highly customizable Rich Text editor. The Document field is built with Slate and stores your content as JSON-structured data." +--- The [`document`](../apis/fields#document) field type is a highly customizable rich text editor that lets content creators quickly and easily edit content in your system. @@ -202,8 +200,10 @@ You can then select an item from the list specified by `listKey` from the inline ![The Admin UI showing the select field used to choose a related item](/assets/guides/document-fields/inline-relationship-select.png) -!> **Tip**: The select component will use the [`ui.labelField`](../apis/schema#ui) of the related list in its options list. +{% hint kind="tip" %} +**Tip**: The select component will use the [`ui.labelField`](../apis/schema#ui) of the related list in its options list. Make sure you have this value configured to make finding related items easier for your users. +{% /hint %} ### Querying inline relationships @@ -256,12 +256,16 @@ This will add a `data.label` value, based on the related item's label field, and ... ``` -?> **Null data:** It is possible to add an inline relationship in the document editor without actually selecting a related item. In these cases, the value of `data` will be `null`. +{% hint kind="warn" %} +**Null data:** It is possible to add an inline relationship in the document editor without actually selecting a related item. In these cases, the value of `data` will be `null`. +{% /hint %} -?> **Dangling references:** The data for relationships are stored as IDs within the JSON data structure of the document. +{% hint kind="warn" %} +**Dangling references:** The data for relationships are stored as IDs within the JSON data structure of the document. If an item in your database is deleted, the document field will not have any knowledge of this, and you will be left with a dangling reference in your document data. In other instances the person querying for the document may not have read access to the related item. In both these cases the `data.label` and `data.data` values will be `undefined`. +{% /hint %} ### Rendering inline relationships @@ -294,7 +298,9 @@ const renderers: DocumentRendererProps['renderers'] = { The `relationship` argument lets you write renderers for each of the different relationships defined in your document. The `data` argument is provided directly from the query, and we can use the properies of `data.data` to render our mentions as links to the author's page. -?> **Missing data:** Make sure your renderer checks for `data === null` (no item selected) and `data.data === undefined` (selected item not found) and handles these cases appropriately. +{% hint kind="warn" %} +**Missing data:** Make sure your renderer checks for `data === null` (no item selected) and `data.data === undefined` (selected item not found) and handles these cases appropriately. +{% /hint %} ## Component Blocks @@ -368,12 +374,12 @@ export default config({ }); ``` -
+{% details %} - +{% summary %} In the [document editor demo](/docs/guides/document-field-demo), the insertable Quote, Notice, Hero and Checkbox List items are implemented as component blocks, see the implementation for Notice, Hero and Checkbox List by expanding this. - +{% /summary %} ```tsx /** @jsx */ @@ -615,7 +621,7 @@ export const componentBlocks = { }; ``` -
+{% /details %} ### Fields @@ -740,7 +746,9 @@ To use relationship fields on component blocks, you need to add a relationship f In the form, it will render a relationship select like the relationship field on lists. Similarly to inline relationships, they will be hydrated with this selection if `hydrateRelationships: true` is provided when fetching. -?> We recently updated the config API for inline relationships in component blocks. If you’re using a version prior to 2022-03-25 please [read this](https://github.com/keystonejs/keystone/releases/tag/2022-03-25) upgrade guidance. +{% hint kind="warn" %} +We recently updated the config API for inline relationships in component blocks. If you’re using a version prior to 2022-03-25 please [read this](https://github.com/keystonejs/keystone/releases/tag/2022-03-25) upgrade guidance. +{% /hint %} ```tsx import { fields } from '@keystone-6/fields-document/component-blocks'; @@ -846,21 +854,17 @@ const componentBlockRenderers: InferRenderersForComponentBlocks - - Illustrates how to configure document fields in your Keystone system and render their data in a frontend application. Builds on the Blog starter project. - - - Test drive the many features of Keystone’s Document field on this website. - - - -export default ({ children }) => {children}; +{% related-content %} +{% well +heading="Example Project: Document Field" +href="https://github.com/keystonejs/keystone/tree/main/examples/document-field" +target="_blank" %} +Illustrates how to configure `document` fields in your Keystone system and render their data in a frontend application. Builds on the Blog starter project. +{% /well %} +{% well +heading="Document Field Demo" +href="/docs/guides/document-field-demo" %} +Test drive the many features of Keystone’s Document field on this website. +{% /well %} +{% /related-content %} + diff --git a/docs/pages/docs/guides/filters.mdx b/docs/pages/docs/guides/filters.md similarity index 89% rename from docs/pages/docs/guides/filters.mdx rename to docs/pages/docs/guides/filters.md index 571dd63161e..a8024b81295 100644 --- a/docs/pages/docs/guides/filters.mdx +++ b/docs/pages/docs/guides/filters.md @@ -1,16 +1,19 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; +--- +title: "GraphQL Queries - Filters" +description: "Learn how to use query filters get the data you need from Keystone’s powerful GraphQL API." +--- -# GraphQL Queries - Filters - -?> We recently improved our GraphQL API so it’s easier to program and reason about. If you were using it prior to August 17th 2021, [read this guide](/updates/new-graphql-api) for info on how to upgrade. +{% hint kind="warn" %} +We recently improved our GraphQL API so it’s easier to program and reason about. If you were using it prior to August 17th 2021, [read this guide](/updates/new-graphql-api) for info on how to upgrade. +{% /hint %} Keystone provides a powerful GraphQL API for querying the data in your system. At the core of this API are **query filters**. This guide will show you how to use filters to get data you need. -!> The filter references in this guide are based on the schema defined in the [Task Manager](https://github.com/keystonejs/keystone/tree/main/examples/task-manager) example project. +{% hint kind="tip" %} +The filter references in this guide are based on the schema defined in the [Task Manager](https://github.com/keystonejs/keystone/tree/main/examples/task-manager) example project. +{% /hint %} ## Scalar Filters @@ -334,13 +337,11 @@ that should be ## Related resources - - - The complete list of filters available to Keystone field types. - - +{% related-content %} +{% well +heading="Query Filters API Reference" +href="/docs/apis/filters" %} +The complete list of filters available to Keystone field types. +{% /well %} +{% /related-content %} -export default ({ children }) => {children}; diff --git a/docs/pages/docs/guides/hooks.mdx b/docs/pages/docs/guides/hooks.md similarity index 90% rename from docs/pages/docs/guides/hooks.mdx rename to docs/pages/docs/guides/hooks.md index 6f933e23161..d27a5d6fbe9 100644 --- a/docs/pages/docs/guides/hooks.mdx +++ b/docs/pages/docs/guides/hooks.md @@ -1,8 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; - -# Hooks +--- +title: "Hooks" +description: "Learn how to use Keystone’s Hooks API to enhance your core operations with custome business logic." +--- Keystone provides a powerful CRUD GraphQL API which lets you perform basic operations on your data. As your system evolves you'll find that you need to include business logic alongside these operations. @@ -83,7 +82,9 @@ export default config({ }); ``` -!> We must always return the modified `resolvedData` value from our hook, even if we didn't end up changing it. +{% hint kind="tip" %} +We must always return the modified `resolvedData` value from our hook, even if we didn't end up changing it. +{% /hint %} The `resolveInput` hook is called whenever we update or create an item. The value of `resolvedData` will contain the input provided to the mutation itself, with any field type input resolvers applied. @@ -137,7 +138,9 @@ Keystone will abort the operation and convert these error messages into GraphQL The `validateInput` hook also receives the `operation`, `inputData`, `item` and `context` arguments if you want to perform more advanced checks. -?> Don't confuse data **validation** with **access control**. If you want to check whether a user is **allowed** to do something, you should set up [access control rules](./access-control). +{% hint kind="warn" %} +Don't confuse data **validation** with **access control**. If you want to check whether a user is **allowed** to do something, you should set up [access control rules](./access-control). +{% /hint %} ## Triggering side-effects @@ -219,10 +222,9 @@ See the [Hooks API](../apis/hooks) for the details of all the arguments availabl ## Related resources - - - The complete reference for executing code at different stages of the mutation lifecycle - - +{% related-content %} +{% well heading="Hooks API Reference" href="/docs/apis/hooks" %} +The complete reference for executing code at different stages of the mutation lifecycle +{% /well %} +{% /related-content %} -export default ({ children }) => {children}; diff --git a/docs/pages/docs/guides/images-and-files.mdx b/docs/pages/docs/guides/images-and-files.md similarity index 84% rename from docs/pages/docs/guides/images-and-files.mdx rename to docs/pages/docs/guides/images-and-files.md index 2945f349f39..0dd7d71c970 100644 --- a/docs/pages/docs/guides/images-and-files.mdx +++ b/docs/pages/docs/guides/images-and-files.md @@ -1,8 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; - -# Images and Files +--- +title: "Images and Files" +description: "Learn how to add Images and Files to your project using Keystone’s Storage configuration" +--- Keystone [fields](../apis/fields) include the `image` and `file` types. You can use them to reference and (if required) serve images and/or files from Keystone. This guide will show you how to configure images and files in your Keystone system so you can store assets either locally or [Amazon S3 storage](https://aws.amazon.com/s3/). @@ -186,7 +185,9 @@ export default config({ }); ``` -!> You can define as many stores as required for your use case +{% hint kind="tip" %} +You can define as many stores as required for your use case +{% /hint %} ## Using Images and Files in Lists @@ -206,7 +207,9 @@ lists: { } ``` -!> The `storage` name here relates to the `storage` defined in your `keystone.ts` +{% hint kind="tip" %} +The `storage` name here relates to the `storage` defined in your `keystone.ts` +{% /hint %} ## Relationships example @@ -251,24 +254,21 @@ This means that for images the extension can be trusted, but for files, it can n ## Related Resources - - - The complete reference for the base keystone configuration - - - The complete reference for Field configuration - - - Learn how to reason about and configure relationships in Keystone so you can bring value to your project through structured content. - - - A full keystone project illustrating how to configure `storage` using `kind: 's3'` and then uses both an `image` and `file` field types within a list. - - - A full keystone project illustrating how to configure `storage` using `kind: 'local'` and then uses both an `image` and `file` field types within a list. - - - -export default ({ children }) => {children} - -; +{% related-content %} +{% well heading="Config API Reference" href="/docs/apis/config" %} +The complete reference for the base keystone configuration +{% /well %} +{% well heading="Fields API Reference" href="/docs/apis/fields" %} +The complete reference for Field configuration +{% /well %} +{% well heading="Relationship Guide" href="/docs/apis/fields" %} +Learn how to reason about and configure relationships in Keystone so you can bring value to your project through structured content. +{% /well %} +{% well heading="Example Project: S3 Assets" href="https://github.com/keystonejs/keystone/tree/main/examples/assets-s3" %} +A full keystone project illustrating how to configure `storage` using `kind: 's3'` and then uses both an `image` and `file` field types within a list. +{% /well %} +{% well heading="Example Project: Local Assets" href="https://github.com/keystonejs/keystone/tree/main/examples/assets-local" %} +A full keystone project illustrating how to configure `storage` using `kind: 'local'` and then uses both an `image` and `file` field types within a list. +{% /well %} +{% /related-content %} + diff --git a/docs/pages/docs/guides/internal-items.md b/docs/pages/docs/guides/internal-items.md new file mode 100644 index 00000000000..8a4c60139da --- /dev/null +++ b/docs/pages/docs/guides/internal-items.md @@ -0,0 +1,7 @@ +--- +title: "Internal Items" +description: "We've planned this page but not had a chance to write it yet." +--- + +{% coming-soon /%} + diff --git a/docs/pages/docs/guides/internal-items.mdx b/docs/pages/docs/guides/internal-items.mdx deleted file mode 100644 index d840175e9b3..00000000000 --- a/docs/pages/docs/guides/internal-items.mdx +++ /dev/null @@ -1,8 +0,0 @@ -import { ComingSoon } from '../../../components/docs/ComingSoon'; -import { Markdown } from '../../../components/Markdown'; - -# Internal Items - - - -export default ({ children }) => {children}; diff --git a/docs/pages/docs/guides/relationships.mdx b/docs/pages/docs/guides/relationships.md similarity index 80% rename from docs/pages/docs/guides/relationships.mdx rename to docs/pages/docs/guides/relationships.md index 70a46ee9d54..4abc17848a5 100644 --- a/docs/pages/docs/guides/relationships.mdx +++ b/docs/pages/docs/guides/relationships.md @@ -1,9 +1,7 @@ -import { Emoji } from '../../../components/primitives/Emoji'; -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; - -# Understanding Relationships +--- +title: "Understanding Relationships" +description: "Learn how to reason about and configure relationships in Keystone so you can bring value to your project through structured content." +--- Relationships are the connections you make between different lists of content in Keystone. What you build depends a great deal on what you need. This guide will show you how to reason about, and configure relationships in Keystone so you can bring value to your project through structured content. @@ -45,7 +43,9 @@ export default config({ }); ``` -!> The `many` config option relates to _cardinality_ which we explore later +{% hint kind="tip" %} +The `many` config option relates to _cardinality_ which we explore later +{% /hint %} ## One-sided & two-sided relationships @@ -98,7 +98,9 @@ export default config({ In the example above we added a `posts` field to the `User` list, and changed the `ref` config of the `authors` field to be `User.posts`. -!> In a two-sided relationship the `ref` config must be formatted as `.` and both sides must refer to each other. +{% hint kind="tip" %} +In a two-sided relationship the `ref` config must be formatted as `.` and both sides must refer to each other. +{% /hint %} Now that our relationship is two-sided we can query all the posts written by each user like so: @@ -114,7 +116,13 @@ query { } ``` -?> **Things to keep in mind:**

Two-sided relationships are declared in two places, but **there is only one relationship between both lists**.

**Both fields share the same data**. If you change the author of a post, that post will no longer show up in the original author’s posts. +{% hint kind="warn" %} +**Things to keep in mind:** + +Two-sided relationships are declared in two places, but **there is only one relationship between both lists**. + +**Both fields share the same data**. If you change the author of a post, that post will no longer show up in the original author’s posts. +{% /hint %} ### Self-referencing relationships @@ -155,7 +163,9 @@ export default config({ }); ``` -!> The only relationship configuration not currently supported is having a field reference itself, e.g. `friends: relationship({ ref: 'User.friends', many: true })`. +{% hint kind="tip" %} +The only relationship configuration not currently supported is having a field reference itself, e.g. `friends: relationship({ ref: 'User.friends', many: true })`. +{% /hint %} ## Establishing cardinality @@ -163,8 +173,8 @@ _Cardinality_ is a term used to describe how many items can exist on either side | Relationship type | One to one | One to many | Many to many | | ----------------- | ---------------------------------------- | ------------------------------------ | ------------------------------------ | -| One-sided | | | | -| Two-sided | | | | +| One-sided | {% emoji symbol="❌" alt="Not supported" /%} | {% emoji symbol="✅" alt="Supported" /%} | {% emoji symbol="✅" alt="Supported" /%} | +| Two-sided | {% emoji symbol="✅" alt="Supported" /%} | {% emoji symbol="✅" alt="Supported" /%} | {% emoji symbol="✅" alt="Supported" /%} | Cardinality is defined through the `relationship` field’s `many` configuration option. It’s a boolean where: @@ -172,7 +182,9 @@ Cardinality is defined through the `relationship` field’s `many` configuration - `true` = many -!> `false` is the default state for the many config option. +{% hint kind="tip" %} +`false` is the default state for the many config option. +{% /hint %} Let’s explore how to set up each type of cardinality in the context of our blog: @@ -234,7 +246,9 @@ export default config({ ### Two-sided cardinalities -?> In two-sided relationships the `many` option on both sides must be considered. +{% hint kind="warn" %} +In two-sided relationships the `many` option on both sides must be considered. +{% /hint %} #### One-to-one @@ -292,7 +306,9 @@ export default config({ }); ``` -!> Note that we’ve used `many: false` in the author field and `many: true` in the posts field. +{% hint kind="tip" %} +Note that we’ve used `many: false` in the author field and `many: true` in the posts field. +{% /hint %} #### Many-to-many @@ -322,7 +338,9 @@ export default config({ }); ``` -!> Note that we have used `many: true` in both the authors and posts fields. +{% hint kind="tip" %} +Note that we have used `many: true` in both the authors and posts fields. +{% /hint %} ## Summary @@ -330,13 +348,11 @@ Keystone relationships are managed using the [relationship](../apis/fields#relat ## Related resources - - - Defines the names, types, and configuration of Keystone fields. See all the fields and the configuration options they accept. - - +{% related-content %} +{% well +heading="Relationship Field API Reference" +href="/docs/apis/fields#relationship" %} +Defines the names, types, and configuration of Keystone fields. See all the fields and the configuration options they accept. +{% /well %} +{% /related-content %} -export default ({ children }) => {children}; diff --git a/docs/pages/docs/guides/schema-extension.md b/docs/pages/docs/guides/schema-extension.md new file mode 100644 index 00000000000..e877b8b9074 --- /dev/null +++ b/docs/pages/docs/guides/schema-extension.md @@ -0,0 +1,7 @@ +--- +title: "Schema Extension" +description: "We've planned this page but not had a chance to write it yet." +--- + +{% coming-soon /%} + diff --git a/docs/pages/docs/guides/schema-extension.mdx b/docs/pages/docs/guides/schema-extension.mdx deleted file mode 100644 index d5942131334..00000000000 --- a/docs/pages/docs/guides/schema-extension.mdx +++ /dev/null @@ -1,8 +0,0 @@ -import { ComingSoon } from '../../../components/docs/ComingSoon'; -import { Markdown } from '../../../components/Markdown'; - -# Schema Extension - - - -export default ({ children }) => {children}; diff --git a/docs/pages/docs/guides/testing.mdx b/docs/pages/docs/guides/testing.md similarity index 83% rename from docs/pages/docs/guides/testing.mdx rename to docs/pages/docs/guides/testing.md index 55fb1c8bd05..ed0d872d4a8 100644 --- a/docs/pages/docs/guides/testing.mdx +++ b/docs/pages/docs/guides/testing.md @@ -1,9 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; -import { InlineCode } from '../../../components/primitives/Code'; - -# Testing +--- +title: "Testing" +description: "Learn how to use the `@keystone-6/testing` package and Jest to write tests that check the behaviour of your GraphQL API." +--- When building a web application it's important to be able to test the behaviour of your system to ensure it does what you expect. In this guide we'll show you how to use `@keystone-6/core/testing` and [Jest](https://jestjs.io/) to write tests to check the behaviour of your GraphQL API. @@ -24,8 +22,10 @@ This will let you run your tests with the command yarn test ``` -?> It is important to use [`--runInBand`](https://jestjs.io/docs/cli#--runinband) when running your tests. This tells Jest not to run your tests in parallel. +{% hint kind="warn" %} +It is important to use [`--runInBand`](https://jestjs.io/docs/cli#--runinband) when running your tests. This tells Jest not to run your tests in parallel. Each test shares the same database, so it's important that multiple tests aren't trying to manipulate the data at the same time. +{% /hint %} ## Test runner @@ -57,7 +57,9 @@ Finally, the runner sets up three APIs for you to use in your test. The first is The second is a `graphQLRequest` function, which lets you run GraphQL requests over HTTP using the [`supertest`](https://github.com/visionmedia/supertest) library. The third is an [`express.Express`](https://expressjs.com/) value named `app` which lets you access any of the endpoints of the Express server using `supertest`. -x> The test runner will drop all data in your database on each run. Make sure you do not run your tests against a system with live data. +{% hint kind="error" %} +The test runner will drop all data in your database on each run. Make sure you do not run your tests against a system with live data. +{% /hint %} ## Writing tests @@ -206,7 +208,9 @@ It also returns `testArgs`, which contains the same arguments provided to tests The context API can be used after calling `connect()` in the `beforeAll()` block to initialise the database into a state which will then be used by all the tests in the test block. -x> Be careful of sharing database state across tests. Avoid relying on changes of state from one test in subsequent tests. +{% hint kind="error" %} +Be careful of sharing database state across tests. Avoid relying on changes of state from one test in subsequent tests. +{% /hint %} ``` import { setupTestEnv, TestEnv } from '@keystone-6/core/testing'; @@ -241,27 +245,22 @@ describe('Example tests using test environment', () => { ## Related resources - - - Shows you how to write tests against the GraphQL API to your Keystone system. Builds on the Authentication example project. - - - The API for run-time functionality in your Keystone system. Use it to write business logic for access control, hooks, testing, GraphQL schema extensions, and more. - - - A programmatic API for running CRUD operations against your GraphQL API. For each list in your system you get an API at context.query.<listName>. - - - -export default ({ children }) => {children}; +{% related-content %} +{% well +heading="Example Project: Testing" +href="https://github.com/keystonejs/keystone/tree/main/examples/testing" +target="_blank" %} +Shows you how to write tests against the GraphQL API to your Keystone system. Builds on the Authentication example project. +{% /well %} +{% well +heading="Context API Reference" +href="/docs/apis/context" %} +The API for run-time functionality in your Keystone system. Use it to write business logic for access control, hooks, testing, GraphQL schema extensions, and more. +{% /well %} +{% well +heading="Query API Reference" +href="/docs/apis/query" %} +A programmatic API for running CRUD operations against your GraphQL API. For each list in your system you get an API at `context.query.`. +{% /well %} +{% /related-content %} + diff --git a/docs/pages/docs/guides/virtual-fields.mdx b/docs/pages/docs/guides/virtual-fields.md similarity index 91% rename from docs/pages/docs/guides/virtual-fields.mdx rename to docs/pages/docs/guides/virtual-fields.md index b0c385dea9f..d7218235cd1 100644 --- a/docs/pages/docs/guides/virtual-fields.mdx +++ b/docs/pages/docs/guides/virtual-fields.md @@ -1,8 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; - -# Virtual Fields +--- +title: "Virtual Fields" +description: "Learn how to extend your GraphQL API in powerful ways with the Virtual Fields feature." +--- Keystone lets you define your data model in terms of `lists`, which have `fields`. Most lists will have some [scalar fields](../apis/fields#scalar-types), such as `text` and `integer` fields, which are stored in your database. @@ -236,7 +235,9 @@ This fragment tells the Keystone Admin UI which values to show in the item page #### Self-referencing objects -!> This information is specifically for TypeScript users of the `graphql.object()` function with a self-referential GraphQL type. +{% hint kind="tip" %} +This information is specifically for TypeScript users of the `graphql.object()` function with a self-referential GraphQL type. +{% /hint %} GraphQL types will often contain references to themselves and to make TypeScript allow that, you need have an explicit type annotation of `graphql.ObjectType` along with making `fields` a function that returns the object. @@ -318,21 +319,17 @@ Using a pre-calculated scalar field is the best solution to use if you need filt ## Related resources - - - A demo project that shows you how to add virtual fields to a Keystone list. - - - A virtual field represents a value which is computed a read time, rather than stored in the database. - - - -export default ({ children }) => {children}; +{% related-content %} +{% well +heading="Virtual fields example" +href="https://github.com/keystonejs/keystone/tree/main/examples/virtual-field" +target="_blank" %} +A demo project that shows you how to add virtual fields to a Keystone list. +{% /well %} +{% well +heading="Virtual Fields: API Reference" +href="/docs/apis/fields#virtual-type" %} +A virtual field represents a value which is computed a read time, rather than stored in the database. +{% /well %} +{% /related-content %} + diff --git a/docs/pages/docs/walkthroughs/embedded-mode-with-sqlite-nextjs.mdx b/docs/pages/docs/walkthroughs/embedded-mode-with-sqlite-nextjs.md similarity index 88% rename from docs/pages/docs/walkthroughs/embedded-mode-with-sqlite-nextjs.mdx rename to docs/pages/docs/walkthroughs/embedded-mode-with-sqlite-nextjs.md index 84699e4cc62..69b35375a8d 100644 --- a/docs/pages/docs/walkthroughs/embedded-mode-with-sqlite-nextjs.mdx +++ b/docs/pages/docs/walkthroughs/embedded-mode-with-sqlite-nextjs.md @@ -1,8 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; - -# How to embed Keystone + SQLite in a Next.js app +--- +title: "How to embed Keystone + SQLite in a Next.js app" +description: "Learn how to embed Keystone and an SQLite database into a Next.js app to get a queryable GraphQL endpoint, based on your Keystone schema, running live on Vercel." +--- In this tutorial, we're going to show you how to embed Keystone and an SQLite database into a **Next.js app**. By the end, your app will have a queryable GraphQL endpoint, based on your Keystone schema, running live on Vercel (for free!). @@ -22,9 +21,13 @@ As a Headless CMS, by default Keystone works in **Standalone** mode. Where you h Keystone 6 also introduces SQLite support – giving you the option to store your files and database content _within_ your local Keystone repo instead of an external host. -!> **Note:** Modes is conceptual framework. It has no dedicated APIs, and there are no mentions of modes in the API docs. +{% hint kind="tip" %} +**Note:** Modes is conceptual framework. It has no dedicated APIs, and there are no mentions of modes in the API docs. +{% /hint %} -?> **Embedded** mode comes with some [limitations](#standalone-vs-embedded-modes) that we explore later on. +{% hint kind="warn" %} +**Embedded** mode comes with some [limitations](#standalone-vs-embedded-modes) that we explore later on. +{% /hint %} --- @@ -47,7 +50,9 @@ yarn create next-app --typescript my-project cd my-project ``` -!> Keystone 6 has great TypeScript support. Including it in your project will make it easier to use Keystone’s APIs later. +{% hint kind="tip" %} +Keystone 6 has great TypeScript support. Including it in your project will make it easier to use Keystone’s APIs later. +{% /hint %} Delete the `/pages/api` directory. We’ll add a GraphQL API later in the tutorial. Your `/pages` directory should now look like this: @@ -94,7 +99,9 @@ Add the `.keystone` directory to your `.gitignore` file. The contents of `.keyst To create and edit blog records in Keystone’s Admin UI, add a `keystone.ts` [configuration file](/apis/config) to your project root with a simple `Post` [list](/apis/schema) containing fields for a Title, Slug, and some Content. -?> **Note:** We're enabling experimental features to generate the APIs that make embedded mode work. These may change in future versions. +{% hint kind="warn" %} +**Note:** We're enabling experimental features to generate the APIs that make embedded mode work. These may change in future versions. +{% /hint %} ```tsx // keystone.ts @@ -121,7 +128,9 @@ export default config({ }); ``` -!> For simplicity we set all Post fields as [`text`](/apis/fields#text) above. For a highly customisable rich text editor use the [`document`](/guides/document-fields) field type. +{% hint kind="tip" %} +For simplicity we set all Post fields as [`text`](/apis/fields#text) above. For a highly customisable rich text editor use the [`document`](/guides/document-fields) field type. +{% /hint %} ### Add Keystone to Next.js config @@ -341,18 +350,12 @@ Keystone’s Embedded mode and SQLite support gives you the option to run a self ## Related resources - - - How to use Keystone's CLI app to standup a new local project with an Admin UI & the GraphQL - Playground. - - - -export default ({ children }) => ( - - {children} - -); +{% related-content %} +{% well +heading="Getting Started with create-keystone-app" +href="/docs/walkthroughs/getting-started-with-create-keystone-app" %} +How to use Keystone's CLI app to standup a new local project with an Admin UI & the GraphQL +Playground. +{% /well %} +{% /related-content %} + diff --git a/docs/pages/docs/walkthroughs/getting-started-with-create-keystone-app.mdx b/docs/pages/docs/walkthroughs/getting-started-with-create-keystone-app.md similarity index 71% rename from docs/pages/docs/walkthroughs/getting-started-with-create-keystone-app.mdx rename to docs/pages/docs/walkthroughs/getting-started-with-create-keystone-app.md index c1240671b19..7656157ad66 100644 --- a/docs/pages/docs/walkthroughs/getting-started-with-create-keystone-app.mdx +++ b/docs/pages/docs/walkthroughs/getting-started-with-create-keystone-app.md @@ -1,11 +1,9 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; -import { InlineCode } from '../../../components/primitives/Code'; - +--- +title: "Getting started" +description: "Learn how to get your first Keystone project up and running using the `create-keystone-app` Command Line Interface." +--- ![A terminal with the output of create-keystone-app](/assets/walkthroughs/getting-started/cover.svg) -# Getting started [`create-keystone-app`](https://github.com/keystonejs/create-keystone-app) is a CLI app that makes it easier for you initiate a Keystone project. It generates some files for you and installs all the dependencies you need to run the Admin UI and start using the [GraphQL API](/docs/apis/graphql). @@ -41,7 +39,9 @@ cd your/path/ npm init keystone-app ``` -?> `npm init ""` is available in npm 6+ +{% hint kind="warn" %} +`npm init ""` is available in npm 6+ +{% /hint %} ### npx @@ -52,13 +52,17 @@ cd your/path/ npx create-keystone-app ``` -?> `npx` comes with npm 5.2+ +{% hint kind="warn" %} +`npx` comes with npm 5.2+ +{% /hint %} ## Naming your app The CLI will ask you to name your app. Once named, it will create a new SQLite database. -?> You can switch to another database such as PostgreSQL once your project is created, check out the docs on [Database Setup](https://keystonejs.com/docs/apis/config#db). +{% hint kind="warn" %} +You can switch to another database such as PostgreSQL once your project is created, check out the docs on [Database Setup](https://keystonejs.com/docs/apis/config#db). +{% /hint %} ## Opening your shiny new Admin UI @@ -105,7 +109,9 @@ Keytone creates the following files in your newly generated folder. The most imp - [`build`](/docs/guides/cli#build) will build the project and is required to be run before `start`. - [`postinstall`](/docs/guides/cli#postinstall) ensures files that Keystone generates exist and are kept up to date. -!> Read more about the CLI in our [command line guides](/guides/cli). +{% hint kind="tip" %} +Read more about the CLI in our [command line guides](/guides/cli). +{% /hint %} ## Where to next? @@ -115,31 +121,25 @@ Keytone creates the following files in your newly generated folder. The most imp ## Related resources - - - Keystone’s CLI helps you develop, build, and deploy projects. This guide explains all you need to standup a new backend in the terminal. - - - The API to configure your options used with the list() function. - - - The API to configure all the parts parts of your Keystone system. - - - Configure Keystone to use another database to store data in your system. - - - -export default ({ children }) => {children} +{% related-content %} +{% well +heading="Keystone CLI Guide" +href="/docs/guides/cli" %} +Keystone’s CLI helps you develop, build, and deploy projects. This guide explains all you need to standup a new backend in the terminal. +{% /well %} +{% well +heading="Schema API Reference" +href="/docs/apis/schema" %} +The API to configure your options used with the `list()` function. +{% /well %} +{% well +heading="Config API Reference" +href="/docs/apis/config" %} +The API to configure all the parts parts of your Keystone system. +{% /well %} +{% well +heading="DB API Reference" +href="/docs/apis/config#db" %} +Configure Keystone to use another database to store data in your system. +{% /well %} +{% /related-content %} diff --git a/docs/pages/docs/walkthroughs/lesson-1.mdx b/docs/pages/docs/walkthroughs/lesson-1.md similarity index 74% rename from docs/pages/docs/walkthroughs/lesson-1.mdx rename to docs/pages/docs/walkthroughs/lesson-1.md index 65fa3575b69..03d7914e6cf 100644 --- a/docs/pages/docs/walkthroughs/lesson-1.mdx +++ b/docs/pages/docs/walkthroughs/lesson-1.md @@ -1,9 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Emoji } from '../../../components/primitives/Emoji'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; - -# Lesson 1: Installing Keystone +--- +title: "Lesson 1: Installing Keystone" +description: "Learn Keystone: Lesson 1" +--- Learn how to install Keystone, create your first content type, and get an app up and running with an intuitive editing environment. @@ -13,7 +11,9 @@ Welcome to the Keystone getting started series! Together we’ll learn how to turn an empty folder into a database-backed Keystone instance with related content types, publishing workflows, password protection, an editing interface, and more. -!> Looking to demo Keystone in under 5 minutes? [Try the quick-start CLI](/docs/walkthroughs/getting-started-with-create-keystone-app) +{% hint kind="tip" %} +Looking to demo Keystone in under 5 minutes? [Try the quick-start CLI](/docs/walkthroughs/getting-started-with-create-keystone-app) +{% /hint %} This series assumes you have some basic familiarity with: @@ -32,7 +32,9 @@ cd keystone-learning yarn init ``` -!> We’ll be using `yarn` for installing packages, but you can use `npm` or any other package manager you prefer. +{% hint kind="tip" %} +We’ll be using `yarn` for installing packages, but you can use `npm` or any other package manager you prefer. +{% /hint %} Now add the Keystone package: @@ -56,7 +58,9 @@ And add TypeScript as a dependency: yarn add typescript ``` -!> If you’d rather use JavaScript, make a `keystone.js` file and skip the TypeScript installation step above. +{% hint kind="tip" %} +If you’d rather use JavaScript, make a `keystone.js` file and skip the TypeScript installation step above. +{% /hint %} Your folder structure should now look like this: @@ -90,7 +94,9 @@ export default config({ This will use the local path `./keystone.db` for your database storage. -!> Keystone uses [Prisma](https://www.prisma.io/) to take care of database admin including [migrations](/docs/guides/cli#working-with-migrations). Keystone owns the Prisma workflow so you can focus on building apps instead of DB admin chores. +{% hint kind="tip" %} +Keystone uses [Prisma](https://www.prisma.io/) to take care of database admin including [migrations](/docs/guides/cli#working-with-migrations). Keystone owns the Prisma workflow so you can focus on building apps instead of DB admin chores. +{% /hint %} ### Create your first List @@ -126,7 +132,9 @@ This key will be used in Admin UI for the list’s default display name, and in Like lists, they’ll be used in Admin UI for field label defaults, and in the GraphQL API. We've added validation to both our fields to say that they are required, and declared that emails must be unique, so there can only be one user with each email. -!> **Admin UI** is the name of Keystone’s user friendly editing environment. Accessible from a browser, it’s the place where we’ll add and update content that will be stored in the database. +{% hint kind="tip" %} +**Admin UI** is the name of Keystone’s user friendly editing environment. Accessible from a browser, it’s the place where we’ll add and update content that will be stored in the database. +{% /hint %} ## Run Keystone @@ -144,16 +152,14 @@ Head on over to [http://localhost:3000/users](http://localhost:3000/users) where ![Adding a user record in Keystone Admin UI](https://keystonejs.s3.amazonaws.com/framework-assets/assets/walkthroughs/lesson-1/first-user-creation.gif) -**Hurrah! You now have Keystone up and running** +**Hurrah! You now have Keystone up and running** {% emoji symbol="🎉" alt="Party Popper" /%} Next up, we’ll level-up our blog starter with a `post` list and connect it to our users. ## Next lesson - - - Connect two content types and learn how to configure the appearance of field inputs - - - -export default ({ children }) => {children} +{% related-content %} +{% well heading="Lesson 2: Relating things" href="/docs/walkthroughs/lesson-2" %} +Connect two content types and learn how to configure the appearance of field inputs +{% /well %} +{% /related-content %} diff --git a/docs/pages/docs/walkthroughs/lesson-2.mdx b/docs/pages/docs/walkthroughs/lesson-2.md similarity index 85% rename from docs/pages/docs/walkthroughs/lesson-2.mdx rename to docs/pages/docs/walkthroughs/lesson-2.md index a395c300533..0cf1cc12084 100644 --- a/docs/pages/docs/walkthroughs/lesson-2.mdx +++ b/docs/pages/docs/walkthroughs/lesson-2.md @@ -1,9 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { Well } from '../../../components/primitives/Well'; -import { RelatedContent } from '../../../components/RelatedContent'; -import { InlineCode } from '../../../components/primitives/Code'; - -# Lesson 2: Creating relationships +--- +title: "Lesson 2: Creating relationships" +description: "Learn Keystone: Lesson 2" +--- Learn how to connect two content types to each another and configure how you make those connections in Admin UI. @@ -60,7 +58,9 @@ export default config({ }); ``` -!> **Protip**: you could also move lists into its own file, and import it into `keystone.ts` +{% hint kind="tip" %} +**Protip**: you could also move lists into its own file, and import it into `keystone.ts` +{% /hint %} ## Create a Post list @@ -97,7 +97,9 @@ Let's check that this works. Boot up our Keystone app and have a look: ![Admin UI showing create screen for a blog post](https://keystonejs.s3.amazonaws.com/framework-assets/assets/walkthroughs/lesson-2/my-first-post.png) -?> We’re skipping over the "content" field for the time being to keep this lesson focused on relationships. We’ll come back to it in [Lesson 5](/docs/walkthroughs/lesson-5). +{% hint kind="warn" %} +We’re skipping over the "content" field for the time being to keep this lesson focused on relationships. We’ll come back to it in [Lesson 5](/docs/walkthroughs/lesson-5). +{% /hint %} ## Connect Users with Posts @@ -140,7 +142,9 @@ export default config({ The `relationship` references the name for the `field` of the list it is relating to make it [two-sided](/docs/guides/relationships#two-sided), so the `author` field relates to `User.posts`, while the `posts` field relates to `Post.author`. -!> Naming relationships can be important if lists have multiple relationships. If, for example, we wanted to let users also 'like' posts, we could add a second differently named relationship field between `User` and `Post` called 'likes'. +{% hint kind="tip" %} +Naming relationships can be important if lists have multiple relationships. If, for example, we wanted to let users also 'like' posts, we could add a second differently named relationship field between `User` and `Post` called 'likes'. +{% /hint %} Let's open the Admin UI and create a post: @@ -245,14 +249,11 @@ export default config({ ## Next lesson - - - Support publishing needs with Keystone's select and{' '} - timestamp fields - - - -export default ({ children }) => {children} +{% related-content %} +{% well +heading="Lesson 3: Publishing workflows" +href="/docs/walkthroughs/lesson-3" %} +Support publishing needs with Keystone's `select` and +`timestamp` fields +{% /well %} +{% /related-content %} diff --git a/docs/pages/docs/walkthroughs/lesson-3.mdx b/docs/pages/docs/walkthroughs/lesson-3.md similarity index 91% rename from docs/pages/docs/walkthroughs/lesson-3.mdx rename to docs/pages/docs/walkthroughs/lesson-3.md index 6720c78ffba..1a676c7c3f8 100644 --- a/docs/pages/docs/walkthroughs/lesson-3.mdx +++ b/docs/pages/docs/walkthroughs/lesson-3.md @@ -1,8 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { RelatedContent } from '../../../components/RelatedContent'; -import { Well } from '../../../components/primitives/Well'; - -# Lesson 3: Publishing workflows +--- +title: "Lesson 3: Publishing workflows" +description: "Learn Keystone: Lesson 3" +--- Learn how to create a publishing workflow to your app using Keystons’s `select` and `timestamp` fields. @@ -223,7 +222,9 @@ Let's put it all together to see the changes: ![Post list type showing "status" select input as segmented control type with default value of "draft"](https://keystonejs.s3.amazonaws.com/framework-assets/assets/walkthroughs/lesson-3/status-segmented-control.png) -!> **Protip**: To take the editing experience even farther you can use [hooks](/docs/apis/hooks) to automatically update `publishedAt` when a post’s status moves from `draft` to `published`. +{% hint kind="tip" %} +**Protip**: To take the editing experience even farther you can use [hooks](/docs/apis/hooks) to automatically update `publishedAt` when a post’s status moves from `draft` to `published`. +{% /hint %} ## Looking at the GraphQL API @@ -292,10 +293,8 @@ export default config({ ## Next lesson - - - Add sessions, password protection, and a sign-in screen to your Keystone app - - - -export default ({ children }) => {children} +{% related-content %} +{% well heading="Lesson 4: Auth & Sessions" href="/docs/walkthroughs/lesson-4" %} +Add sessions, password protection, and a sign-in screen to your Keystone app +{% /well %} +{% /related-content %} diff --git a/docs/pages/docs/walkthroughs/lesson-4.mdx b/docs/pages/docs/walkthroughs/lesson-4.md similarity index 93% rename from docs/pages/docs/walkthroughs/lesson-4.mdx rename to docs/pages/docs/walkthroughs/lesson-4.md index 8e571d5fa52..dd0d69f55e2 100644 --- a/docs/pages/docs/walkthroughs/lesson-4.mdx +++ b/docs/pages/docs/walkthroughs/lesson-4.md @@ -1,9 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { RelatedContent } from '../../../components/RelatedContent'; -import { Well } from '../../../components/primitives/Well'; -import { InlineCode } from '../../../components/primitives/Code'; - -# Lesson 4: Auth & Sessions +--- +title: "Lesson 4: Auth & Sessions" +description: "Learn Keystone: Lesson 4" +--- Learn how to add passwords, session data and authentication to your Keystone app. @@ -331,11 +329,9 @@ export default config( ## Next lesson - - - Add a powerful document field to your app and learn how to - configure it to meet your needs - - - -export default ({ children }) => {children} +{% related-content %} +{% well heading="Lesson 5: Rich Text" href="/docs/walkthroughs/lesson-5" %} +Add a powerful `document` field to your app and learn how to +configure it to meet your needs +{% /well %} +{% /related-content %} diff --git a/docs/pages/docs/walkthroughs/lesson-5.mdx b/docs/pages/docs/walkthroughs/lesson-5.md similarity index 91% rename from docs/pages/docs/walkthroughs/lesson-5.mdx rename to docs/pages/docs/walkthroughs/lesson-5.md index 59cd2c1826e..5b822af98d1 100644 --- a/docs/pages/docs/walkthroughs/lesson-5.mdx +++ b/docs/pages/docs/walkthroughs/lesson-5.md @@ -1,8 +1,7 @@ -import { Markdown } from '../../../components/Markdown'; -import { RelatedContent } from '../../../components/RelatedContent'; -import { Well } from '../../../components/primitives/Well'; - -# Lesson 5: Document field +--- +title: "Lesson 5: Document field" +description: "Learn Keystone: Lesson 5" +--- Learn how to implement a powerful and customisable Rich Text editing experience with Keystone’s `document` field. @@ -261,13 +260,11 @@ Congratulations! You've now built a Keystone app from an empty folder and have t This lesson marks the end of this learning series. To dive deeper into Keystone's capabilities take a look at the following: - - - A growing collection of projects you can run locally to learn more about Keystone’s capabilities - - - Practical explanations of Keystone’s fundamental building blocks - - - -export default ({ children }) => {children} +{% related-content %} +{% well heading="Examples" href="/docs/examples" %} +A growing collection of projects you can run locally to learn more about Keystone’s capabilities +{% /well %} +{% well heading="Guides" href="/docs/guides/" %} +Practical explanations of Keystone’s fundamental building blocks +{% /well %} +{% /related-content %}