From bd0487ecc34b5eab23b87041092335198b54a6f2 Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Thu, 27 Jun 2024 14:11:06 +0800 Subject: [PATCH] refactor(console): update ruby guide (#6116) * refactor(console): update ruby guide * refactor(console): support further readings * refactor(console): reorg docs --- ...n_in_explanation.md => _redirect_uris.mdx} | 15 +++++++ .../assets/docs/guides/m2m-general/index.ts | 5 +-- .../docs/guides/native-android/index.ts | 5 +-- .../assets/docs/guides/native-expo/index.ts | 5 +-- .../assets/docs/guides/spa-angular/index.ts | 5 +-- .../src/assets/docs/guides/spa-react/index.ts | 5 +-- .../assets/docs/guides/spa-vanilla/index.ts | 5 +-- .../src/assets/docs/guides/spa-vue/index.ts | 5 +-- .../console/src/assets/docs/guides/types.ts | 11 +++-- .../web-dotnet-core-blazor-server/index.ts | 5 +-- .../web-dotnet-core-blazor-wasm/index.ts | 5 +-- .../docs/guides/web-dotnet-core-mvc/index.ts | 5 +-- .../assets/docs/guides/web-express/index.ts | 5 +-- .../src/assets/docs/guides/web-go/index.ts | 5 +-- .../docs/guides/web-next-app-router/index.ts | 5 +-- .../src/assets/docs/guides/web-next/index.ts | 5 +-- .../assets/docs/guides/web-nuxt/README.mdx | 21 +++------ .../src/assets/docs/guides/web-nuxt/index.ts | 5 +-- .../src/assets/docs/guides/web-php/index.ts | 5 +-- .../assets/docs/guides/web-python/index.ts | 5 +-- .../assets/docs/guides/web-ruby/README.mdx | 44 +++++++++---------- .../src/assets/docs/guides/web-ruby/index.ts | 4 ++ .../assets/docs/guides/web-sveltekit/index.ts | 5 +-- .../assets/docs/guides/web-wordpress/index.ts | 10 +++-- .../mdx-components/Steps/FurtherReadings.tsx | 17 +++++-- .../src/mdx-components/Steps/index.tsx | 10 ++++- 26 files changed, 98 insertions(+), 124 deletions(-) rename packages/console/src/assets/docs/fragments/{_sign_in_explanation.md => _redirect_uris.mdx} (61%) diff --git a/packages/console/src/assets/docs/fragments/_sign_in_explanation.md b/packages/console/src/assets/docs/fragments/_redirect_uris.mdx similarity index 61% rename from packages/console/src/assets/docs/fragments/_sign_in_explanation.md rename to packages/console/src/assets/docs/fragments/_redirect_uris.mdx index df8616a98..780f4f97e 100644 --- a/packages/console/src/assets/docs/fragments/_sign_in_explanation.md +++ b/packages/console/src/assets/docs/fragments/_redirect_uris.mdx @@ -1,3 +1,6 @@ +import InlineNotification from '@/ds-components/InlineNotification'; +import UriInputField from '@/mdx-components/UriInputField'; + Before we dive into the details, here's a quick overview of the end-user experience. The sign-in process can be simplified as follows: ```mermaid @@ -18,3 +21,15 @@ Regarding redirect-based sign-in: To learn more about the rationale and benefits of redirect-based sign-in, see [Logto sign-in experience explained](https://docs.logto.io/docs/tutorials/get-started/sign-in-experience). --- + + + In the following steps, we assume your app is running on http://localhost:3000. + + +Now, let's enter your redirect URI. E.g. `http://localhost:3000/callback`. + + + +Just like signing in, users should be redirected to Logto for signing out of the shared session. Once finished, it would be great to redirect the user back to your website. For example, add `http://localhost:3000` as the post sign-out redirect URI below. + + diff --git a/packages/console/src/assets/docs/guides/m2m-general/index.ts b/packages/console/src/assets/docs/guides/m2m-general/index.ts index 00c1a10c6..4ad62a3e5 100644 --- a/packages/console/src/assets/docs/guides/m2m-general/index.ts +++ b/packages/console/src/assets/docs/guides/m2m-general/index.ts @@ -7,10 +7,7 @@ const metadata: Readonly = Object.freeze({ description: 'Enables direct communication between machines.', target: ApplicationType.MachineToMachine, isFeatured: true, - fullGuide: { - title: 'Full machine-to-machine integration tutorial', - url: 'https://docs.logto.io/quick-starts/m2m', - }, + fullGuide: 'm2m', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/native-android/index.ts b/packages/console/src/assets/docs/guides/native-android/index.ts index de711ff81..a248a0d35 100644 --- a/packages/console/src/assets/docs/guides/native-android/index.ts +++ b/packages/console/src/assets/docs/guides/native-android/index.ts @@ -10,10 +10,7 @@ const metadata: Readonly = Object.freeze({ repo: 'kotlin', path: 'android-sample-kotlin', }, - fullGuide: { - title: 'Full Android SDK tutorial', - url: 'https://docs.logto.io/quick-starts/android', - }, + fullGuide: 'android', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/native-expo/index.ts b/packages/console/src/assets/docs/guides/native-expo/index.ts index 2ea3ef262..353c64cc6 100644 --- a/packages/console/src/assets/docs/guides/native-expo/index.ts +++ b/packages/console/src/assets/docs/guides/native-expo/index.ts @@ -10,10 +10,7 @@ const metadata: Readonly = Object.freeze({ repo: 'react-native', path: 'packages/rn-sample', }, - fullGuide: { - title: 'Full Expo (React Native) guide', - url: 'https://docs.logto.io/quick-starts/expo', - }, + fullGuide: 'expo', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/spa-angular/index.ts b/packages/console/src/assets/docs/guides/spa-angular/index.ts index ef02c1ced..3073c73b7 100644 --- a/packages/console/src/assets/docs/guides/spa-angular/index.ts +++ b/packages/console/src/assets/docs/guides/spa-angular/index.ts @@ -10,10 +10,7 @@ const metadata: Readonly = Object.freeze({ repo: 'js', path: 'packages/angular-sample', }, - fullGuide: { - title: 'Full Angular guide', - url: 'https://docs.logto.io/quick-starts/angular', - }, + fullGuide: 'angular', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/spa-react/index.ts b/packages/console/src/assets/docs/guides/spa-react/index.ts index 53fdeeff5..b560d8dd4 100644 --- a/packages/console/src/assets/docs/guides/spa-react/index.ts +++ b/packages/console/src/assets/docs/guides/spa-react/index.ts @@ -11,10 +11,7 @@ const metadata: Readonly = Object.freeze({ path: 'packages/react-sample', }, isFeatured: true, - fullGuide: { - title: 'Full React SDK tutorial', - url: 'https://docs.logto.io/quick-starts/react', - }, + fullGuide: 'react', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/spa-vanilla/index.ts b/packages/console/src/assets/docs/guides/spa-vanilla/index.ts index 48198f3cc..a75ff94be 100644 --- a/packages/console/src/assets/docs/guides/spa-vanilla/index.ts +++ b/packages/console/src/assets/docs/guides/spa-vanilla/index.ts @@ -10,10 +10,7 @@ const metadata: Readonly = Object.freeze({ repo: 'js', path: 'packages/browser-sample', }, - fullGuide: { - title: 'Full vanilla JS SDK tutorial', - url: 'https://docs.logto.io/quick-starts/vanilla-js', - }, + fullGuide: 'vanilla-js', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/spa-vue/index.ts b/packages/console/src/assets/docs/guides/spa-vue/index.ts index 71f6553bc..195ceebed 100644 --- a/packages/console/src/assets/docs/guides/spa-vue/index.ts +++ b/packages/console/src/assets/docs/guides/spa-vue/index.ts @@ -12,10 +12,7 @@ const metadata: Readonly = Object.freeze({ path: 'packages/vue-sample', }, isFeatured: true, - fullGuide: { - title: 'Full Vue SDK tutorial', - url: 'https://docs.logto.io/quick-starts/vue', - }, + fullGuide: 'vue', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/types.ts b/packages/console/src/assets/docs/guides/types.ts index 7f0f60cc5..0b18523c9 100644 --- a/packages/console/src/assets/docs/guides/types.ts +++ b/packages/console/src/assets/docs/guides/types.ts @@ -31,11 +31,14 @@ export type GuideMetadata = { /** Indicate whether the application is for third-party use */ isThirdParty?: boolean; - /** The related complete guide for this guide which will be displayed in the 'Further readings' section. */ - fullGuide?: { + /** The related complete guide url relative to the quick starts page (https://docs.logto.io/quick-starts). */ + fullGuide?: string; + + /** The related URLs to add to the further readings section. */ + furtherReadings?: Array<{ title: string; - url: string; - }; + url: URL; + }>; }; /** The guide instance to build in the console. */ diff --git a/packages/console/src/assets/docs/guides/web-dotnet-core-blazor-server/index.ts b/packages/console/src/assets/docs/guides/web-dotnet-core-blazor-server/index.ts index 9deb50ecb..1e01259c3 100644 --- a/packages/console/src/assets/docs/guides/web-dotnet-core-blazor-server/index.ts +++ b/packages/console/src/assets/docs/guides/web-dotnet-core-blazor-server/index.ts @@ -10,10 +10,7 @@ const metadata: Readonly = Object.freeze({ repo: 'csharp', path: '/', }, - fullGuide: { - title: 'Full .NET Core (Blazor Server) integration tutorial', - url: 'https://docs.logto.io/quick-starts/dotnet-core/blazor-server', - }, + fullGuide: 'dotnet-core/blazor-server', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/web-dotnet-core-blazor-wasm/index.ts b/packages/console/src/assets/docs/guides/web-dotnet-core-blazor-wasm/index.ts index 55770849b..1ad19eeee 100644 --- a/packages/console/src/assets/docs/guides/web-dotnet-core-blazor-wasm/index.ts +++ b/packages/console/src/assets/docs/guides/web-dotnet-core-blazor-wasm/index.ts @@ -10,10 +10,7 @@ const metadata: Readonly = Object.freeze({ repo: 'csharp', path: '/', }, - fullGuide: { - title: 'Full .NET Core (Blazor WASM) integration tutorial', - url: 'https://docs.logto.io/quick-starts/dotnet-core/blazor-wasm', - }, + fullGuide: 'dotnet-core/blazor-wasm', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/web-dotnet-core-mvc/index.ts b/packages/console/src/assets/docs/guides/web-dotnet-core-mvc/index.ts index 315a8943e..ac60c2b40 100644 --- a/packages/console/src/assets/docs/guides/web-dotnet-core-mvc/index.ts +++ b/packages/console/src/assets/docs/guides/web-dotnet-core-mvc/index.ts @@ -10,10 +10,7 @@ const metadata: Readonly = Object.freeze({ repo: 'csharp', path: '/', }, - fullGuide: { - title: 'Full .NET Core (MVC) integration tutorial', - url: 'https://docs.logto.io/quick-starts/dotnet-core/mvc', - }, + fullGuide: 'dotnet-core/mvc', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/web-express/index.ts b/packages/console/src/assets/docs/guides/web-express/index.ts index 6c22e22b2..1f3ac22b3 100644 --- a/packages/console/src/assets/docs/guides/web-express/index.ts +++ b/packages/console/src/assets/docs/guides/web-express/index.ts @@ -11,10 +11,7 @@ const metadata: Readonly = Object.freeze({ repo: 'js', path: 'packages/express-sample', }, - fullGuide: { - title: 'Full Express SDK tutorial', - url: 'https://docs.logto.io/quick-starts/express', - }, + fullGuide: 'express', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/web-go/index.ts b/packages/console/src/assets/docs/guides/web-go/index.ts index 6bd10eae3..e7190d030 100644 --- a/packages/console/src/assets/docs/guides/web-go/index.ts +++ b/packages/console/src/assets/docs/guides/web-go/index.ts @@ -11,10 +11,7 @@ const metadata: Readonly = Object.freeze({ repo: 'go', path: 'gin-sample', }, - fullGuide: { - title: 'Full Go SDK tutorial', - url: 'https://docs.logto.io/quick-starts/go', - }, + fullGuide: 'go', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/web-next-app-router/index.ts b/packages/console/src/assets/docs/guides/web-next-app-router/index.ts index 01aa12154..492ee0515 100644 --- a/packages/console/src/assets/docs/guides/web-next-app-router/index.ts +++ b/packages/console/src/assets/docs/guides/web-next-app-router/index.ts @@ -11,10 +11,7 @@ const metadata: Readonly = Object.freeze({ path: 'packages/next-server-actions-sample', }, isFeatured: true, - fullGuide: { - title: 'Full Next.js SDK tutorial', - url: 'https://docs.logto.io/sdk/next-app-router/', - }, + fullGuide: 'next-app-router', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/web-next/index.ts b/packages/console/src/assets/docs/guides/web-next/index.ts index 703b36bae..e705492dc 100644 --- a/packages/console/src/assets/docs/guides/web-next/index.ts +++ b/packages/console/src/assets/docs/guides/web-next/index.ts @@ -11,10 +11,7 @@ const metadata: Readonly = Object.freeze({ repo: 'js', path: 'packages/next-sample', }, - fullGuide: { - title: 'Full Next.js SDK tutorial', - url: 'https://docs.logto.io/quick-starts/next', - }, + fullGuide: 'next', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/web-nuxt/README.mdx b/packages/console/src/assets/docs/guides/web-nuxt/README.mdx index 13d70bebe..70c8ee3ed 100644 --- a/packages/console/src/assets/docs/guides/web-nuxt/README.mdx +++ b/packages/console/src/assets/docs/guides/web-nuxt/README.mdx @@ -5,7 +5,7 @@ import InlineNotification from '@/ds-components/InlineNotification'; import Steps from '@/mdx-components/Steps'; import Step from '@/mdx-components/Step'; import Checkpoint from '../../fragments/_checkpoint.md'; -import SignInExplanation from '../../fragments/_sign_in_explanation.md'; +import RedirectUris from '../../fragments/_redirect_uris.mdx'; import { generateStandardSecret } from '@logto/shared/universal'; export const cookieEncryptionKey = generateStandardSecret(); @@ -79,21 +79,12 @@ See [runtime config](https://nuxt.com/docs/guide/going-further/runtime-config) f - + - - - - In the following steps, we assume your app is running on http://localhost:3000. - - -Now, let's enter your redirect URI. E.g. `http://localhost:3000/callback`. - - - -Just like signing in, users should be redirected to Logto for signing out of the shared session. Once finished, it would be great to redirect the user back to your website. For example, add `http://localhost:3000` as the post sign-out redirect URI below. - - + When registering `@logto/nuxt` module, it will do the following: diff --git a/packages/console/src/assets/docs/guides/web-nuxt/index.ts b/packages/console/src/assets/docs/guides/web-nuxt/index.ts index 00953f2e6..062dcfa66 100644 --- a/packages/console/src/assets/docs/guides/web-nuxt/index.ts +++ b/packages/console/src/assets/docs/guides/web-nuxt/index.ts @@ -11,10 +11,7 @@ const metadata: Readonly = Object.freeze({ repo: 'js', path: 'packages/nuxt', }, - fullGuide: { - title: 'Full Nuxt guide', - url: 'https://docs.logto.io/quick-starts/nuxt', - }, + fullGuide: 'nuxt', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/web-php/index.ts b/packages/console/src/assets/docs/guides/web-php/index.ts index c3bbccb0a..8fa0568ca 100644 --- a/packages/console/src/assets/docs/guides/web-php/index.ts +++ b/packages/console/src/assets/docs/guides/web-php/index.ts @@ -10,10 +10,7 @@ const metadata: Readonly = Object.freeze({ repo: 'php', path: 'samples', }, - fullGuide: { - title: 'Full PHP SDK tutorial', - url: 'https://docs.logto.io/quick-starts/php', - }, + fullGuide: 'php', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/web-python/index.ts b/packages/console/src/assets/docs/guides/web-python/index.ts index 8840be3d4..ffb9766a3 100644 --- a/packages/console/src/assets/docs/guides/web-python/index.ts +++ b/packages/console/src/assets/docs/guides/web-python/index.ts @@ -10,10 +10,7 @@ const metadata: Readonly = Object.freeze({ repo: 'python', path: 'samples', }, - fullGuide: { - title: 'Full Python SDK tutorial', - url: 'https://docs.logto.io/quick-starts/python', - }, + fullGuide: 'python', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/web-ruby/README.mdx b/packages/console/src/assets/docs/guides/web-ruby/README.mdx index 0f19d4387..22f9fedd9 100644 --- a/packages/console/src/assets/docs/guides/web-ruby/README.mdx +++ b/packages/console/src/assets/docs/guides/web-ruby/README.mdx @@ -1,6 +1,8 @@ import UriInputField from '@/mdx-components/UriInputField'; import InlineNotification from '@/ds-components/InlineNotification'; import { generateStandardSecret } from '@logto/shared/universal'; +import RedirectUris from '../../fragments/_redirect_uris.mdx'; +import Checkpoint from '../../fragments/_checkpoint.md'; import Steps from '@/mdx-components/Steps'; import Step from '@/mdx-components/Step'; @@ -49,9 +51,8 @@ end`} For instance, in a Rails controller, the code might look like this: - - {`# app/controllers/sample_controller.rb -require "logto/client" + + {`require "logto/client" class SampleController < ApplicationController before_action :initialize_logto_client @@ -81,13 +82,7 @@ end`} subtitle="2 URIs" > -First, let's enter your redirect URI. E.g. `http://localhost:3000/callback`. [Redirect URI](https://www.oauth.com/oauth2-servers/redirect-uris/) is an OAuth 2.0 concept which implies the location should redirect after authentication. - - - -After signing out, it'll be great to redirect user back to your website. For example, add `http://localhost:3000` as the post sign-out redirect URI below. - - + @@ -100,18 +95,17 @@ After signing out, it'll be great to redirect user back to your website. For exa Since the redirect URI has been set to {props.redirectUris[0] || 'http://localhost:3000/callback'}, it needs to be handled it in our application. In a Rails controller, you can add the following code:

- - {`# app/controllers/sample_controller.rb -class SampleController < ApplicationController + + {`class SampleController < ApplicationController def ${props.redirectUris[0]?.split('/').pop() || 'callback'} @client.handle_sign_in_callback(url: request.original_url) end end`} -And configure the route in `config/routes.rb`: +And configure the route: - + {`Rails.application.routes.draw do get "${new URL(props.redirectUris[0] || 'http://localhost:3000/callback').pathname}", to: "sample#${props.redirectUris[0]?.split('/').pop() || 'callback'}" end`} @@ -125,9 +119,8 @@ end`} There are various ways to invoke sign-in and sign-out in your application. For example, you can implement two routes in your Rails application: - - {`# app/controllers/sample_controller.rb -class SampleController < ApplicationController + + {`class SampleController < ApplicationController def sign_in @client.sign_in(redirect_uri: request.base_url + "${new URL(props.redirectUris[0] || 'http://localhost:3000/callback').pathname}") end @@ -140,8 +133,7 @@ class SampleController < ApplicationController end`} -```ruby -# config/routes.rb +```ruby title="config/routes.rb" Rails.application.routes.draw do get "/sign_in", to: "sample#sign_in" get "/sign_out", to: "sample#sign_out" @@ -152,8 +144,7 @@ end Then you can create buttons or links in your views to trigger these actions. For example: -```erb - +```erb title="app/views/sample/index.html.erb" <% if @client.is_authenticated? %> Sign out <% else %> @@ -163,12 +154,17 @@ Then you can create buttons or links in your views to trigger these actions. For
+ + + + + + To display the user's information, you can use the `@client.id_token_claims` method. For example, in a view: -```erb - +```erb title="app/views/sample/index.html.erb" <% if @client.is_authenticated? %>

Welcome, <%= @client.id_token_claims["name"] %>

<% else %> diff --git a/packages/console/src/assets/docs/guides/web-ruby/index.ts b/packages/console/src/assets/docs/guides/web-ruby/index.ts index 150b32006..37b0f04ef 100644 --- a/packages/console/src/assets/docs/guides/web-ruby/index.ts +++ b/packages/console/src/assets/docs/guides/web-ruby/index.ts @@ -8,6 +8,10 @@ const metadata: Readonly = Object.freeze({ 'Ruby is a dynamic, open-source programming language with a focus on simplicity and productivity.', target: ApplicationType.Traditional, isFeatured: true, + sample: { + repo: 'ruby', + path: 'logto-sample', + }, }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/web-sveltekit/index.ts b/packages/console/src/assets/docs/guides/web-sveltekit/index.ts index 7b429bbbf..1460ca86b 100644 --- a/packages/console/src/assets/docs/guides/web-sveltekit/index.ts +++ b/packages/console/src/assets/docs/guides/web-sveltekit/index.ts @@ -11,10 +11,7 @@ const metadata: Readonly = Object.freeze({ repo: 'js', path: 'packages/sveltekit-sample', }, - fullGuide: { - title: 'Full SvelteKit guide', - url: 'https://docs.logto.io/quick-starts/sveltekit', - }, + fullGuide: 'sveltekit', }); export default metadata; diff --git a/packages/console/src/assets/docs/guides/web-wordpress/index.ts b/packages/console/src/assets/docs/guides/web-wordpress/index.ts index 53ca03b17..8cd5fcd23 100644 --- a/packages/console/src/assets/docs/guides/web-wordpress/index.ts +++ b/packages/console/src/assets/docs/guides/web-wordpress/index.ts @@ -6,10 +6,12 @@ const metadata: Readonly = Object.freeze({ name: 'WordPress', description: 'Integrate Logto into your WordPress app.', target: ApplicationType.Traditional, - fullGuide: { - title: 'Authorization and role mapping in WordPress', - url: 'https://blog.logto.io/integrate-with-wordpress-authorization/', - }, + furtherReadings: [ + { + title: 'Authorization and role mapping in WordPress', + url: new URL('https://blog.logto.io/integrate-with-wordpress-authorization/'), + }, + ], }); export default metadata; diff --git a/packages/console/src/mdx-components/Steps/FurtherReadings.tsx b/packages/console/src/mdx-components/Steps/FurtherReadings.tsx index 852b7e9d5..a2961402a 100644 --- a/packages/console/src/mdx-components/Steps/FurtherReadings.tsx +++ b/packages/console/src/mdx-components/Steps/FurtherReadings.tsx @@ -1,3 +1,4 @@ +import { appendPath } from '@silverhand/essentials'; import { type Ref, forwardRef } from 'react'; import { type GuideMetadata } from '@/assets/docs/guides/types'; @@ -7,20 +8,30 @@ import Step, { type Props as StepProps } from '../Step'; type Props = Omit & { readonly fullGuide: GuideMetadata['fullGuide']; + readonly furtherReadings: GuideMetadata['furtherReadings']; }; +const quickStartsUrl = new URL('https://docs.logto.io/quick-starts/'); + function FurtherReadings(props: Props, ref?: Ref) { - const { fullGuide, ...stepProps } = props; + const { fullGuide, furtherReadings, ...stepProps } = props; return (
    {fullGuide && (
  • - - {fullGuide.title} + + Complete guide
  • )} + {furtherReadings?.map(({ title, url }) => ( +
  • + + {title} + +
  • + ))}
  • Customize sign-in experience diff --git a/packages/console/src/mdx-components/Steps/index.tsx b/packages/console/src/mdx-components/Steps/index.tsx index 4776a1e51..0f60f779e 100644 --- a/packages/console/src/mdx-components/Steps/index.tsx +++ b/packages/console/src/mdx-components/Steps/index.tsx @@ -43,8 +43,14 @@ export default function Steps({ children: reactChildren }: Props) { const isApiResourceGuide = metadata.target === 'API'; const furtherReadings = useMemo( - () => , - [metadata.fullGuide] + () => ( + + ), + [metadata.fullGuide, metadata.furtherReadings] ); const children: Array> = useMemo(() => { const steps = (Array.isArray(reactChildren) ? reactChildren : [reactChildren]).filter(