Skip to content

Commit

Permalink
refactor: update nuxt guide
Browse files Browse the repository at this point in the history
  • Loading branch information
gao-sun committed Jun 26, 2024
1 parent 8fcb747 commit d93ea0d
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 45 deletions.
1 change: 1 addition & 0 deletions packages/console/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
"react-syntax-highlighter": "^15.5.0",
"react-timer-hook": "^3.0.5",
"recharts": "^2.1.13",
"rehype-mdx-code-props": "^3.0.1",
"remark-gfm": "^4.0.0",
"stylelint": "^15.0.0",
"swr": "^2.2.0",
Expand Down
2 changes: 2 additions & 0 deletions packages/console/parcel-transformer-mdx2.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { compile } from '@mdx-js/mdx';
import { default as ThrowableDiagnostic } from '@parcel/diagnostic';
import { Transformer } from '@parcel/plugin';
import rehypeMdxCodeProps from 'rehype-mdx-code-props';

export default new Transformer({
async transform({ asset }) {
Expand All @@ -15,6 +16,7 @@ export default new Transformer({
development: true,
jsx: true,
providerImportSource: '@mdx-js/react',
rehypePlugins: [[rehypeMdxCodeProps, { tagName: 'code' }]],
});
} catch (error) {
const { start, end } = error.position;
Expand Down
20 changes: 20 additions & 0 deletions packages/console/src/assets/docs/fragments/_sign_in_explanation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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
graph LR
A[Your app] -->|1. Invoke sign-in| B[Logto]
B -->|2. Finish sign-in| A
```

1. Your app invokes the sign-in method.
2. The user is redirected to the Logto sign-in page. For native apps, the system browser is opened.
3. The user signs in and is redirected back to your app (configured as the redirect URI).

Regarding redirect-based sign-in:

1. This authentication process follows the [OpenID Connect (OIDC)](https://openid.net/specs/openid-connect-core-1_0.html) protocol, and Logto enforces the Authorization Code Flow with PKCE to ensure the security of the authentication process.
2. If you have multiple apps, you can use the same authentication server (Logto), and the user only needs to sign in once.

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).

---
57 changes: 22 additions & 35 deletions packages/console/src/assets/docs/guides/web-nuxt/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,22 @@ 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 { generateStandardSecret } from '@logto/shared/universal';

export const cookieEncryptionKey = generateStandardSecret();

<Steps>

<InlineNotification severity="alert">
Logto Nuxt SDK only works with Nuxt 3.
</InlineNotification>

<Step
title="Installation"
subtitle="Install Logto SDK"
>

<InlineNotification severity="alert">
Logto Nuxt SDK only works with Nuxt 3.
</InlineNotification>

<Tabs>
<TabItem value="npm" label="npm">

Expand Down Expand Up @@ -46,18 +48,9 @@ pnpm add @logto/nuxt

<Step title="Register Logto module">

In your Nuxt config file (`nuxt.config.ts`), add the Logto module:
In your Nuxt config file, add the Logto module and configure it:

```ts
export default defineNuxtConfig({
modules: ['@logto/nuxt'],
// ...other configurations
});
```

The minimal configuration for the module is as follows:

<Code className="language-tsx">
<Code title="nuxt.config.ts" className="language-tsx">
{`export default defineNuxtConfig({
modules: ['@logto/nuxt'],
runtimeConfig: {
Expand All @@ -74,7 +67,7 @@ The minimal configuration for the module is as follows:

Since these information are sensitive, it's recommended to use environment variables (`.env`):

<Code className="language-bash">
<Code title=".env" className="language-bash">
{`NUXT_LOGTO_ENDPOINT=${props.endpoint}
NUXT_LOGTO_APP_ID=${props.app.id}
NUXT_LOGTO_APP_SECRET=${props.app.secret}
Expand All @@ -88,15 +81,17 @@ See [runtime config](https://nuxt.com/docs/guide/going-further/runtime-config) f

<Step title="Configure your app">

<SignInExplanation />

<InlineNotification>
In the following steps, we assume your app is running on <code>http://localhost:3000</code>.
</InlineNotification>

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.
Now, let's enter your redirect URI. E.g. `http://localhost:3000/callback`.

<UriInputField name="redirectUris" />

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.
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.

<UriInputField name="postLogoutRedirectUris" />

Expand All @@ -107,7 +102,7 @@ When registering `@logto/nuxt` module, it will do the following:

These routes are configurable via `logto.pathnames` in the module options, for example:

```ts
```ts title="nuxt.config.ts"
export default defineNuxtConfig({
logto: {
pathnames: {
Expand All @@ -122,32 +117,24 @@ export default defineNuxtConfig({

Check out the [type definition file](https://github.com/logto-io/js/blob/HEAD/packages/nuxt/src/runtime/utils/types.ts) in the `@logto/nuxt` package for more information.

Note: If you configure the callback route to a different path, you need to update the redirect URI in Logto accordingly.
<InlineNotification>
If you configure the callback route to a different path, you need to update the redirect URI in Logto accordingly.
</InlineNotification>

</Step>

<Step title="Implement sign-in and sign-out">

Since Nuxt pages will be hydrated and become a single-page application (SPA) after the initial load, we need to redirect the user to the sign-in or sign-out route when needed.

```html
<a :href="/sign-in">Sign in</a>
<br />
<a :href="/sign-out">Sign out</a>
```

</Step>

<Step title="Display user information">

To display the user's information, you can use the `useLogtoUser()` composable, which is available on both server and client side:
Since Nuxt pages will be hydrated and become a single-page application (SPA) after the initial load, we need to redirect the user to the sign-in or sign-out route when needed. To help with this, our SDK provides the `useLogtoUser()` composable, which can be used in both server and client side.

```html
```html title="index.vue"
<script setup lang="ts">
import { useLogtoUser } from '#imports'; // Add this line if auto-import is disabled
const user = useLogtoUser();
</script>
<template>
<ul v-if="Boolean(user)">
<!-- Display user information when signed in -->
<ul v-if="Boolean(user)">
<li v-for="(value, key) in user"><b>{{ key }}:</b> {{ value }}</li>
</ul>
<!-- Simplified button for sign-in and sign-out -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
position: relative;
overflow-y: auto;

.title {
margin-top: _.unit(-2);
padding-bottom: _.unit(2);
margin-bottom: _.unit(3);
border-bottom: 1px solid var(--color-border);
}

.placeholder {
position: absolute;
inset: _.unit(6);
Expand Down
3 changes: 3 additions & 0 deletions packages/console/src/ds-components/CodeEditor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { lineNumberContainerStyle, lineNumberStyle, customStyle } from './utils'

type Props = {
readonly className?: string;
readonly title?: string;
readonly language?: string;
readonly isReadonly?: boolean;
readonly value?: string;
Expand All @@ -23,6 +24,7 @@ type Props = {

function CodeEditor({
className,
title,
language,
isReadonly = false,
value,
Expand Down Expand Up @@ -85,6 +87,7 @@ function CodeEditor({
return (
<>
<div className={classNames(styles.container, className)}>
{title && <pre className={styles.title}>{title}</pre>}
{isShowingPlaceholder && <div className={styles.placeholder}>{placeholder}</div>}
<CopyToClipboard value={value ?? ''} variant="icon" className={styles.copy} />
<div ref={editorRef} className={classNames(styles.editor, isReadonly && styles.readonly)}>
Expand Down
3 changes: 2 additions & 1 deletion packages/console/src/mdx-components/Code/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import CodeEditor from '@/ds-components/CodeEditor';

import Mermaid from '../Mermaid';

export default function Code({ className, children }: JSX.IntrinsicElements['code']) {
export default function Code({ className, children, title }: JSX.IntrinsicElements['code']) {
const [, language] = /language-(\w+)/.exec(String(className ?? '')) ?? [];

if (language === 'mermaid') {
Expand All @@ -17,6 +17,7 @@ export default function Code({ className, children }: JSX.IntrinsicElements['cod
// To be investigated.
language={language === 'ts' ? 'typescript' : language}
value={String(children).trimEnd()}
title={title}
/>
) : (
<code>{String(children).trimEnd()}</code>
Expand Down
7 changes: 5 additions & 2 deletions packages/console/src/mdx-components/Steps/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { onKeyDownHandler } from '@/utils/a11y';

import Sample from '../Sample';
import { type Props as StepProps } from '../Step';
import type Step from '../Step';
import Step from '../Step';

import FurtherReadings from './FurtherReadings';
import * as styles from './index.module.scss';
Expand Down Expand Up @@ -47,7 +47,10 @@ export default function Steps({ children: reactChildren }: Props) {
[metadata.fullGuide]
);
const children: Array<ReactElement<StepProps, typeof Step>> = useMemo(() => {
const steps = Array.isArray(reactChildren) ? reactChildren : [reactChildren];
const steps = (Array.isArray(reactChildren) ? reactChildren : [reactChildren]).filter(
(child) => child.type === Step
);

return isApiResourceGuide ? steps : steps.concat(furtherReadings);
}, [isApiResourceGuide, furtherReadings, reactChildren]);

Expand Down
Loading

0 comments on commit d93ea0d

Please sign in to comment.