Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: update nuxt guide #6114

Merged
merged 2 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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.
simeng-li marked this conversation as resolved.
Show resolved Hide resolved
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 strict security measures to protect user sign-in.
2. If you have multiple apps, you can use the same identity provider (Logto). Once the user signs in to one app, Logto will automatically complete the sign-in process when the user accesses another app.

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).
gao-sun marked this conversation as resolved.
Show resolved Hide resolved

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