Skip to content

Commit b4d57f2

Browse files
authored
docs: add webflow full integration guide (#670)
1 parent bafb2ab commit b4d57f2

21 files changed

+327
-0
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
---
2+
slug: /quick-starts/webflow
3+
sidebar_label: Webflow
4+
sidebar_custom_props:
5+
description: Webflow is a SaaS platform for website building and hosting.
6+
---
7+
8+
import FurtherReadings from '../../fragments/_further-readings.md';
9+
10+
import Checkpoint from './_checkpoint-test-your-webflow-site.md';
11+
import GetUserInformation from './_get-user-information.mdx';
12+
import GuideTip from './_guide-tip.mdx';
13+
import HandleAuthenticationStatus from './_handle-authentication-status.mdx';
14+
import ImplementSignIn from './_implement-sign-in.mdx';
15+
import ImplementSignOut from './_implement-sign-out.mdx';
16+
import InitClient from './_init-client.mdx';
17+
import ApiResources from './api-resources/_index.mdx';
18+
19+
# Webflow integration guide
20+
21+
This guide will show you how to integrate Logto into your Webflow sites.
22+
23+
<GuideTip />
24+
25+
## Prerequisits
26+
27+
1. Integrating Logto with Webflow requires the "Custom code" feature of Webflow, which requires at least the "Basic" plan.
28+
2. A Webflow site, either use an existing site or create a new one.
29+
30+
## Integration
31+
32+
### Init Logto provider
33+
34+
<InitClient />
35+
36+
### Implement sign-in
37+
38+
<ImplementSignIn />
39+
40+
### Implement sign-out
41+
42+
<ImplementSignOut />
43+
44+
### Handle authentication status
45+
46+
<HandleAuthenticationStatus />
47+
48+
<Checkpoint />
49+
50+
## Get user information
51+
52+
<GetUserInformation />
53+
54+
## API resources
55+
56+
<ApiResources />
57+
58+
## Further readings
59+
60+
<FurtherReadings />
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
### Checkpoint: Test your Webflow site
2+
3+
Now, test your site:
4+
5+
1. Deploy and visit your site URL, the sign-in button should be visible.
6+
2. Click the sign-in button, the SDK will initiate the sign-in process, redirecting you to the Logto sign-in page.
7+
3. After signing in, you will be redirected back to your site, seeing the username and the sign-out button.
8+
4. Click the sign-out button to sign-out.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import GetUserInfoApis from '../../fragments/_get-user-info-apis.mdx';
2+
import ScopesAndClaims from '../../fragments/_scopes-and-claims.mdx';
3+
4+
import ScopesAndClaimsCode from './_scopes-and-claims-code.mdx';
5+
6+
<GetUserInfoApis getIdTokenClaimsApi="getIdTokenClaims" fetchUserInfoApi="fetchUserInfo" />
7+
8+
<ScopesAndClaims configScopesCode={<ScopesAndClaimsCode />} />
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
:::tip
2+
3+
- The sample project is available at [Webflow project preview](https://preview.webflow.com/preview/charless-trendy-site-f191c0?utm_medium=preview_link&utm_source=designer&utm_content=charless-trendy-site-f191c0&preview=0eae5f73661a8a5791787f0438bc29de&workflow=preview).
4+
- A live demo is deployed at https://charless-trendy-site-f191c0.webflow.io/.
5+
:::
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
In Logto SDK, generally we can use `logtoClient.isAuthenticated()` method to check the authentication status, if the user is signed in, the value will be `true`; otherwise, it will be `false`.
2+
3+
In your Webflow site, you can also use it to programmatically show and hide the sign-in and sign-out buttons. Apply the following custom code to adjust button CSS accordingly.
4+
5+
```js
6+
const isAuthenticated = await logtoClient.isAuthenticated();
7+
8+
signInButton.style.display = isAuthenticated ? 'none' : 'block';
9+
signOutButton.style.display = isAuthenticated ? 'block' : 'none';
10+
```
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
We're almost there! In the last step, we use `https://your-awesome-site.webflow.io/callback` as the Redirect URI, and now we need to handle it properly.
2+
3+
First let's create a "Callback" page in Webflow, and simply put some static text "Redirecting..." on it. Then add the following page-level custom code to "Callback" page.
4+
5+
```html
6+
<script type="module">
7+
(async () => {
8+
// Handle sign-in callback logic by calling the SDK method
9+
await logtoClient.handleSignInCallback(window.location.href);
10+
11+
// Redirect back to the home page when the handling is done
12+
window.location.assign('https://your-awesome-site.webflow.io');
13+
})();
14+
</script>
15+
```
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import redirectUriFigure from '../../assets/web-redirect-uri.png';
2+
import ConfigureRedirectUri from '../../fragments/_configure-redirect-uri.mdx';
3+
import SignInFlowSummary from '../../fragments/_web-sign-in-flow-summary.mdx';
4+
5+
import HandleRedirect from './_handle-redirect.mdx';
6+
7+
<SignInFlowSummary />
8+
9+
#### Configure sign-in redirect URI
10+
11+
<ConfigureRedirectUri
12+
figureSrc={redirectUriFigure}
13+
redirectUri="https://your-awesome-site.webflow.io/callback"
14+
/>
15+
16+
#### Implement a sign-in button
17+
18+
Return to your Webflow designer, drag and drop a "Sign in" button to the home page, and assign it an ID “sign-in” for later reference using `getElementById()`.
19+
20+
```html
21+
<script type="module">
22+
const signInButton = document.getElementById('sign-in');
23+
const onClickSignIn = () => logtoClient.signIn('https://your-awesome-site.webflow.io/callback');
24+
signInButton.addEventListener('click', onClickSignIn);
25+
</script>
26+
```
27+
28+
#### Handle redirect
29+
30+
<HandleRedirect />
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Calling `.signOut()` will clear all the Logto data in memory and localStorage if they exist.
2+
3+
After signing out, it'll be great to redirect your user back to your website. Let's add `https://your-awesome-site.webflow.io` as one of the Post Sign-out URIs in Admin Console (shows under Redirect URIs), and use the URL as the parameter when calling `.signOut()`.
4+
5+
#### Implement a sign-out button
6+
7+
Return to the Webflow designer, and add a “Sign out” button on your home page. Similarly, assign an ID “sign-out” to the button, and add the following code to the page-level custom code.
8+
9+
```js
10+
const signOutButton = document.getElementById('sign-out');
11+
const onClickSignOut = () => logtoClient.signOut('https://your-awesome-site.webflow.io');
12+
signOutButton.addEventListener('click', onClickSignOut);
13+
```
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
:::note
2+
In the following steps, we assume your Webflow site is running on `https://your-awesome-site.webflow.io`.
3+
:::
4+
5+
In this step, we'll add global-level custom code to your Webflow site. Since NPM is not supported in Webflow, we'll use the [jsdelivr.com](https://www.jsdelivr.com/) CDN service to import the Logto SDK.
6+
7+
Open the "Site settings" page, and navigate to the "Custom code" section. Add the following code to the "Head code" section.
8+
9+
```html
10+
<script type="module">
11+
// Import \`@logto/browser\` SDK from the jsdelivr CDN
12+
import LogtoClient from 'https://esm.run/@logto/browser';
13+
14+
// Assign the \`logtoClient\` instance to window object,
15+
// enabling global usage in other pages
16+
window.logtoClient = new LogtoClient({
17+
endpoint: '<your-logto-endpoint>', // E.g. http://localhost:3001
18+
appId: '<your-application-id>',
19+
});
20+
</script>
21+
```
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
```html
2+
<script type="module">
3+
// Import \`@logto/browser\` SDK from the jsdelivr CDN
4+
import LogtoClient from 'https://esm.run/@logto/browser';
5+
6+
// Assign the \`logtoClient\` instance to window object,
7+
// enabling global usage in other pages
8+
window.logtoClient = new LogtoClient({
9+
endpoint: '<your-logto-endpoint>', // E.g. http://localhost:3001
10+
appId: '<your-application-id>',
11+
scopes: [
12+
UserScope.Email,
13+
UserScope.Phone,
14+
UserScope.CustomData,
15+
UserScope.Identities,
16+
UserScope.Organizations,
17+
],
18+
});
19+
</script>
20+
```
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import ConfigApiResources from '../../../fragments/_config-api-resources.mdx';
2+
3+
import ConfigResourcesCode from './code/_config-resources-code.md';
4+
import ConfigResourcesWithScopesCode from './code/_config-resources-with-scopes-code.md';
5+
import ConfigResourcesWithSharedScopesCode from './code/_config-resources-with-shared-scopes-code.md';
6+
7+
<ConfigApiResources
8+
configResourcesCode={<ConfigResourcesCode />}
9+
configResourcesWithScopesCode={<ConfigResourcesWithScopesCode />}
10+
configResourcesWithSharedScopesCode={<ConfigResourcesWithSharedScopesCode />}
11+
/>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import FetchAccessTokenForApiResources from '../../../fragments/_fetch-access-token-for-api-resources.mdx';
2+
3+
import GetAccessTokenCode from './code/_get-access-token-code.md';
4+
5+
<FetchAccessTokenForApiResources
6+
getAccessTokenApi="getAccessToken"
7+
getAccessTokenCode={<GetAccessTokenCode />}
8+
/>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import FetchOrganizationTokenForUser from '../../../fragments/_fetch-organization-token-for-user.mdx';
2+
3+
import ConfigOrganizationCode from './code/_config-organization-code.md';
4+
import GetOrganizationAccessTokenCode from './code/_get-organization-access-token-code.md';
5+
6+
<FetchOrganizationTokenForUser
7+
organizationScope="UserScope.Organizations"
8+
configOrganizationCode={<ConfigOrganizationCode />}
9+
getOrganizationAccessTokenCode={<GetOrganizationAccessTokenCode />}
10+
/>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import ApiResourcesDescription from '../../../fragments/_api-resources-description.md';
2+
3+
import ConfigApiResources from './_config-api-resources.mdx';
4+
import FetchAccessTokenForApiResources from './_fetch-access-token-for-api-resources.mdx';
5+
import FetchOrganizationTokenForUser from './_fetch-organization-token-for-user.mdx';
6+
7+
<ApiResourcesDescription />
8+
9+
### Configure Logto client
10+
11+
<ConfigApiResources />
12+
13+
### Fetch access token for the API resource
14+
15+
<FetchAccessTokenForApiResources />
16+
17+
### Fetch organization token for user
18+
19+
<FetchOrganizationTokenForUser />
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
```js
2+
import LogtoClient, { UserScope } from 'https://esm.run/@logto/browser';
3+
4+
window.logtoClient = new LogtoClient({
5+
// ...other configs
6+
scopes: [UserScope.Organizations],
7+
});
8+
```
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
```html
2+
<script type="module">
3+
// Import \`@logto/browser\` SDK from the jsdelivr CDN
4+
import LogtoClient from 'https://esm.run/@logto/browser';
5+
6+
// Assign the \`logtoClient\` instance to window object,
7+
// enabling global usage in other pages
8+
window.logtoClient = new LogtoClient({
9+
endpoint: '<your-logto-endpoint>', // E.g. http://localhost:3001
10+
appId: '<your-application-id>',
11+
resources: ['https://shopping.your-app.com/api', 'https://store.your-app.com/api'], // Add API resources
12+
});
13+
</script>
14+
```
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
```html
2+
<script type="module">
3+
// Import \`@logto/browser\` SDK from the jsdelivr CDN
4+
import LogtoClient from 'https://esm.run/@logto/browser';
5+
6+
window.logtoClient = new LogtoClient({
7+
endpoint: '<your-logto-endpoint>',
8+
appId: '<your-application-id>',
9+
scopes: ['shopping:read', 'shopping:write', 'store:read', 'store:write'],
10+
resources: ['https://shopping.your-app.com/api', 'https://store.your-app.com/api'],
11+
});
12+
</script>
13+
```
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
```html
2+
<script type="module">
3+
// Import \`@logto/browser\` SDK from the jsdelivr CDN
4+
import LogtoClient from 'https://esm.run/@logto/browser';
5+
6+
window.logtoClient = new LogtoClient({
7+
endpoint: '<your-logto-endpoint>',
8+
appId: '<your-application-id>',
9+
scopes: ['read', 'write'],
10+
resources: ['https://shopping.your-app.com/api', 'https://store.your-app.com/api'],
11+
});
12+
</script>
13+
```
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
```js
2+
const isAuthenticated = await logtoClient.isAuthenticated();
3+
4+
if (isAuthenticated) {
5+
(async () => {
6+
const token = await logtoClient.getAccessToken();
7+
console.log(token);
8+
})();
9+
}
10+
```
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
```js
2+
import { UserScope } from 'https://esm.run/@logto/browser';
3+
4+
const isAuthenticated = await logtoClient.isAuthenticated();
5+
6+
(async () => {
7+
if (!isAuthenticated) {
8+
return;
9+
}
10+
const claims = await logtoClient.getIdTokenClaims();
11+
12+
console.log('ID token claims:', claims);
13+
console.log('Organization IDs:', claims.organizations);
14+
15+
// Assuming there's at least one organization, let's take the first one
16+
const organizationId = claims.organizations[0];
17+
const token = await logtoClient.getOrganizationToken(organizationId);
18+
19+
console.log('Organization access token:', token);
20+
})();
21+
```

static/img/logo/webflow.svg

Lines changed: 10 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)