+
+
+
+To get started, you need to create a Capacitor project. You can follow the [official guide](https://capacitorjs.com/docs/getting-started) to create one.
+
+This tutorial is framework-agnostic, so you can use any UI framework you prefer and update the code accordingly.
+
+```bash
+# or yarn, pnpm
+npm install @logto/capacitor
+# Install peer dependencies
+npm install @capacitor/browser @capacitor/app @capacitor/preferences
+```
+
+
+
+
+
+Add the following code to your Capacitor project:
+
+
+
+ {`import LogtoClient from '@logto/capacitor';
+
+const logtoClient = new LogtoClient({
+ endpoint: '${props.endpoint}',${props.alternativeEndpoint ? ` // or '${props.alternativeEndpoint}'` : ''}
+ appId: '${props.app.id}',
+});`}
+
+
+
+
+
+
+
+Now, let's configure the redirect URI. The redirect URI is used to redirect the user back to your application after the authentication flow.
+
+Ensure that the URI redirects to the Capacitor app, for example, `com.example.app://callback`. The value may vary depending on your Capacitor app configuration. For more details, see [Capacitor Deep Links](https://capacitorjs.com/docs/guides/deep-links).
+
+
+
+Remember to click on **Save Changes** after updating the redirect URI. Then, add the following code to the `onClick` handler of the sign-in button:
+
+
+
+ {`const onClick = async () => {
+ await logtoClient.signIn('${props.redirectUris[0] || 'com.example.app://callback'}');
+ console.log(await logtoClient.isAuthenticated()); // true
+ console.log(await logtoClient.getIdTokenClaims()); // { sub: '...', ... }
+};`}
+
+
+
+
+
+
+
+Run the Capacitor app and click the sign-in button. A browser window will open, redirecting to the Logto sign-in page.
+
+
+
+
+
+> If the user closes the browser window without completing the authentication flow, the Capacitor
+> app will receive a `LogtoClientError`.
+
+
+
+
+
+Since Capacitor leverages the Safari View Controller on iOS and Chrome Custom Tabs on Android, the authentication state can be persisted for a while. However, sometimes the user may want to sign out of the application immediately. In this case, we can use the `signOut` method to sign out the user:
+
+```ts
+const onClick = async () => {
+ await logtoClient.signOut();
+ console.log(await logtoClient.isAuthenticated()); // false
+};
+```
+
+The `signOut` method has an optional parameter for the post sign-out redirect URI. If it's not provided, the user will be redirected to the Logto sign-out page:
+
+
+
+
+
+The user needs to click "Done" to close the web view and return to the Capacitor app. If you want to automatically redirect the user back to the Capacitor app, you can provide the post sign-out redirect URI:
+
+
+
+Ensure that the post sign-out redirect URI redirects to the Capacitor app. Then add the following code to the `onClick` handler of the sign-out button:
+
+
+
+ {`const onClick = async () => {
+ await logtoClient.signOut('${props.postLogoutRedirectUris[0] || 'com.example.app://callback/sign-out'}');
+};`}
+
+
+
+
+
+
+
+Run the Capacitor app again and click the sign-in button. If everything goes well, when the authentication flow is completed, the Capacitor app will receive the sign-in result and print the user claims in the console.
+
+
+
+
+
+Then click the sign-out button, and the Capacitor app will be redirected to the Logto sign-out page. It will automatically redirect back to the Capacitor app if the post sign-out redirect URI is configured.
+
+
+
+
diff --git a/packages/console/src/assets/docs/guides/native-capacitor/assets/capacitor-ios.webp b/packages/console/src/assets/docs/guides/native-capacitor/assets/capacitor-ios.webp
new file mode 100644
index 000000000..dbabd8b38
Binary files /dev/null and b/packages/console/src/assets/docs/guides/native-capacitor/assets/capacitor-ios.webp differ
diff --git a/packages/console/src/assets/docs/guides/native-capacitor/assets/logto-sign-in-page.webp b/packages/console/src/assets/docs/guides/native-capacitor/assets/logto-sign-in-page.webp
new file mode 100644
index 000000000..074ccd8ca
Binary files /dev/null and b/packages/console/src/assets/docs/guides/native-capacitor/assets/logto-sign-in-page.webp differ
diff --git a/packages/console/src/assets/docs/guides/native-capacitor/assets/logto-sign-out-page.webp b/packages/console/src/assets/docs/guides/native-capacitor/assets/logto-sign-out-page.webp
new file mode 100644
index 000000000..be2b0c4cb
Binary files /dev/null and b/packages/console/src/assets/docs/guides/native-capacitor/assets/logto-sign-out-page.webp differ
diff --git a/packages/console/src/pages/Applications/components/GuideV2/index.tsx b/packages/console/src/pages/Applications/components/GuideV2/index.tsx
index d6e7b6075..3da4f605e 100644
--- a/packages/console/src/pages/Applications/components/GuideV2/index.tsx
+++ b/packages/console/src/pages/Applications/components/GuideV2/index.tsx
@@ -91,7 +91,14 @@ function GuideV2({ guideId, app, isCompact, onClose }: Props) {
const [, language] = /language-(\w+)/.exec(String(className ?? '')) ?? [];
return language ? (
-