> Portal Navigation: > > - Append `.md` to any URL under `https://dev.wix.com/docs/` to get its markdown version. > - Pages are either content pages (article or reference text) or menu pages (a list of links to child pages). > - To get a menu page, truncate any URL to a parent path and append `.md` (e.g. `https://dev.wix.com/docs/sdk.md`, `https://dev.wix.com/docs/sdk/core-modules.md`). > - Top-level index of all portals: https://dev.wix.com/docs/llms.txt > - Full concatenated docs: https://dev.wix.com/docs/llms-full.txt ## Resource: Quick Start ## Article: Quick Start ## Article Link: https://dev.wix.com/docs/go-headless/get-started/tutorials/self-managed-headless/java-script-sdk-tutorials/quick-start.md ## Article Content: # Quick Start Follow this quick start tutorial to get up and running with your first headless project. This tutorial walks you through the project setup process and builds a simple site that uses tokens to maintain persistent visitor sessions and to authenticate site members. You can use the code described here as a springboard for your own project. After building the foundation here to handle visitors and members, you can continue your development by making use of the various modules in the [Wix Javascript SDK](https://dev.wix.com/docs/sdk.md). For detailed instructions for managing visitors and members, see [Handle Visitors](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/visitors/handle-visitors-using-the-js-sdk.md), [Handle Members with Managed Login](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/members/wix-login-page/wix-managed-login-using-the-js-sdk.md), [Handle Members with a Custom Login Page](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/members/custom-login-page/custom-login/custom-login-using-the-js-sdk.md), and [Handle Members with Externally-Managed Login](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/members/externally-managed-login-page/handle-members-with-externally-managed-login.md). > **Note:** If you're using the [Wix CLI](https://dev.wix.com/docs/go-headless/develop-your-project/wix-managed-headless/about-the-wix-cli-for-headless.md), you don't need to handle OAuth setup or create a client because it's done automatically. This tutorial shows you how to implement: - A React component that handles login and logout by redirecting the visitor to a Wix-managed page. - A callback page that verifies login and saves member tokens in a cookie. - [Next.js middleware](https://nextjs.org/docs/14/app/building-your-application/routing/middleware) that checks for an existing member or visitor token and generates a new visitor token if one is not found. The tutorial is based on this [example site](https://wix-headless-example.vercel.app). To get the code, fork the [Headless Templates repo](https://github.com/wix/headless-templates). The site code is under [minimal examples](https://github.com/wix/headless-templates/tree/main/nextjs/minimal-examples). The site focuses on simplicity and understandability, rather than feature richness, performance or completeness. Looking for a more comprehensive example site integrating Wix Headless APIs? Check out our [starter templates](https://dev.wix.com/docs/go-headless/get-started/templates/self-managed-templates/next-js-templates.md). > **Note:** The code in this tutorial is written in [JSX](https://react.dev/learn/writing-markup-with-jsx), but you can use the SDK in any JavaScript environment. Implementing the session management flow includes the following steps: 1. Set up the Wix Headless environment. 1. Create a login component. 1. Create a callback page. 1. Create middleware for managing tokens. ## Step 1: Set up the Wix Headless environment Before using the SDK, there are a few things you need to set up on your Wix account and in your external site or app's coding environment. To set up the Wix Headless environment, follow these steps: 1. If you haven't already, [create a project](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/create-a-project.md). When prompted to add functionalities to your new project, select whichever business solutions your project needs. 2. Set up authorization for your site by [creating and configuring](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/about-authentication.md) an OAuth app: a. Create an OAuth app in your project's [Headless Settings](https://www.wix.com/my-account/site-selector/?buttonText=Select%20Site&title=Select%20a%20Site&autoSelectOnSingleSite=true&actionUrl=https:%2F%2Fwww.wix.com%2Fdashboard%2F%7B%7BmetaSiteId%7D%7D%2Foauth-apps-settings). Copy your Client ID - you'll need it later. b. Configure Wix-managed login URLs as [allowed redirect domains](https://dev.wix.com/docs/go-headless/develop-your-project/wix-managed-business-flows/add-allowed-redirect-domains.md) in your site dashboard. 3. Install the SDK client and relevant SDK module packages by running the following commands: For NPM: ```console npm install @wix/sdk npm install @wix/members ``` For Yarn: ```console yarn add @wix/sdk yarn add @wix/members ``` 4. Install the `react` package to handle UI rendering, the `js-cookie` package to handle session cookies, and the `next/server` package with helper functions for [Next.js middleware](https://nextjs.org/docs/14/app/building-your-application/routing/middleware). For NPM: ```console npm install react npm install js-cookie npm install next/server ``` For Yarn: ```console yarn add react yarn add js-cookie yarn add next/server ``` ## Step 2: Create a login component Follow these steps to create a React component that handles login and logout by redirecting the visitor to a Wix-managed page. ### 1. Import the SDK modules and create an SDK client To set up the code file for the login component, follow these steps: 1. Add the following import statements to the top of your code file: ```jsx import { createClient, OAuthStrategy } from '@wix/sdk'; import { members } from '@wix/members'; import { useEffect, useState } from 'react'; import Cookies from 'js-cookie'; ``` 1. Create an SDK client by adding the following code to your code file. Replace the value for `clientId` with your OAuth app's client ID. You can find the ID in your project's [**Headless Settings**](https://www.wix.com/my-account/site-selector/?buttonText=Select%20Site&title=Select%20a%20Site&autoSelectOnSingleSite=true&actionUrl=https:%2F%2Fwww.wix.com%2Fdashboard%2F%7B%7BmetaSiteId%7D%7D%2Foauth-apps-settings). The value for `tokens` is the `'session'` cookie on the visitor's browser. It's used to make calls to the Wix API. This way, you can maintain previous visitor sessions. If a token has already been generated for the visitor, this token is used. ```jsx const myWixClient = createClient({ modules: { members }, auth: OAuthStrategy({ clientId: ``, tokens: JSON.parse(Cookies.get('session') || null), }), }); ``` ### 2. Create a React component and a state variable The logic for our example login request flow is contained in a React component called `LoginBar`. To create the component, follow these steps: 1. Define the component function as a default export in your code file: ```jsx export default function LoginBar() {} ``` 1. Define a state variable by adding the following code in the component function: ```jsx const [member, setMember] = useState([]); ``` In the steps that follow, the `member` state variable stores a visitor's data if they are a logged-in site member. ### 3. Define functions to handle member sessions Add the following 3 functions for handling member sessions to the `LoginBar` component: 1. `fetchMember()` - Uses the SDK client's `auth.loggedIn()` function to check if the current site visitor is a logged-in site member. If they are, the rendered UI is updated with the member's details. This function runs when the component is mounted. ```jsx async function fetchMember() { const { member } = myWixClient.auth.loggedIn() ? await myWixClient.members.getCurrentMember() : {}; setMember(member || undefined); } ``` 1. `login()` - Uses the SDK client's `auth.generateOAuthData()` and `auth.getAuthUrl()` functions to log in a site visitor. This function runs when a **Login** button in the rendered UI is clicked. ```jsx async function login() { const data = myWixClient.auth.generateOAuthData( `${window.location.origin}/login-callback`, window.location.href ); localStorage.setItem('oauthRedirectData', JSON.stringify(data)); const { authUrl } = await myWixClient.auth.getAuthUrl(data); window.location = authUrl; } ``` The SDK client's `auth.generateOAuthData()` function generates the data needed for authorization, which is saved in local storage with the key `oauthRedirectData`. When the Wix-managed authentication process is over, Wix redirects the visitor to the URL provided in `redirectUri`. The `auth.getAuthUrl()` function returns a URL for a Wix-managed authentication page called `authUrl`. 1. `logout()` - Uses the SDK client's `auth.logout()` function to log out a site member and remove the session cookie from their browser. This function runs when a **Logout** button in the rendered UI is clicked. ```jsx async function logout() { const { logoutUrl } = await myWixClient.auth.logout(window.location.href); Cookies.remove('session'); window.location = logoutUrl; } ``` ### 4. Add the `useEffect` hook Add the following code to the `LoginBar` component to run the `fetchMember()` function after the component is rendered. This ensures that member data is retrieved when the component mounts. ```jsx useEffect(() => { fetchMember(); }, []); ``` ### 5. Render the UI Add the following code to the `LoginBar` component function's `return` statement to render the UI. ```jsx return (
{member !== null && (
(myWixClient.auth.loggedIn() ? logout() : login())} >

Hello{' '} {myWixClient.auth.loggedIn() ? member.profile?.nickname || member.profile?.slug || '' : 'visitor'} ,

{myWixClient.auth.loggedIn() ? 'Logout' : 'Login'}
)}
); ``` The UI displays the following: - If no member is logged in: **Hello visitor** and a **Login** link. - If a member is logged in: **Hello, ** and a **Logout** link. ## Step 3: Create a callback page Follow these steps to create a callback page for Wix to redirect the visitor to after handling authentication. ### 1. Import the SDK modules and create an SDK client To set up the code file for the callback page, follow these steps: 1. Add the following import statements to the top of your code file: ```jsx import Cookies from 'js-cookie'; import { useEffect, useState } from 'react'; import { createClient, OAuthStrategy } from '@wix/sdk'; ``` 1. Create an SDK client by adding the following code to your code file: ```jsx const myWixClient = createClient({ auth: OAuthStrategy({ clientId: ``, tokens: JSON.parse(Cookies.get('session') || null), }), }); ``` ### 2. Create a React component and state variables The logic for our example login request flow is contained in a React component called `LoginCallback`. To create the component, follow these steps: 1. Define the component function as a default export in your code file: ```jsx export default function LoginCallback() {} ``` 1. Define state variables by adding the following code in the component function: ```jsx const [nextPage, setNextPage] = useState(null); const [errorMessage, setErrorMessage] = useState(null); ``` In the steps that follow, the `nextPage` state variable stores the URL of the page to redirect the visitor to, and the `errorMessage` state variable stores the error received if there is an error generating a member token. ### 3. Define a function to verify login Add the following function to the `LoginCallback` component. This function first retrieves the authorization data saved in local storage by the `Login` component. Then it retrieves the authorization code and state from the callback page's URL using `auth.parseFromUrl()`. Using this data, it calls `auth.getMemberTokens()` to generate access and refresh tokens, which it stores in the `'session'` cookie. It then redirects the visitor to the page specified in `data.originalUri` if it exists, or otherwise to `/`. ```jsx async function verifyLogin() { const data = JSON.parse(localStorage.getItem('oauthRedirectData')); localStorage.removeItem('oauthRedirectData'); try { const { code, state } = myWixClient.auth.parseFromUrl(); let tokens = await myWixClient.auth.getMemberTokens(code, state, data); while (!tokens?.refreshToken?.value) { tokens = await myWixClient.auth.getMemberTokens(code, state, data); } Cookies.set('session', JSON.stringify(tokens)); window.location = data?.originalUri || '/'; } catch (e) { setNextPage(data?.originalUri || '/'); setErrorMessage(e.toString()); } } ``` ### 4. Add the `useEffect` hook Add the following code to the `LoginCallback` component to run the `verifyLogin()` function after the component is rendered. This ensures that tokens are stored when the component mounts. ```jsx useEffect(() => { verifyLogin(); }, []); ``` ### 5. Render the UI Add the following code to the `LoginCallback` component function's `return` statement to render the UI. ```jsx return (
{errorMessage && ( <> {errorMessage}

)} {nextPage ? Continue : <>Loading...}
); ``` The UI displays the following before redirecting the visitor: - If there was an error, `errorMessage` is displayed. - If login was verified, a link to the next page with the text **Continue** is rendered, along with the text **Loading...**. ## Step 4: Create middleware for managing tokens Once you've implemented a login component and a callback page, follow these steps to create [Next.js middleware](https://nextjs.org/docs/14/app/building-your-application/routing/middleware) to check a visitor's session status when loading every page. ### 1. Import the SDK modules To set up the code file for the session management middleware, follow these steps: 1. Add the following import statements to the top of your code file: ```jsx import { createClient, OAuthStrategy } from '@wix/sdk'; import { NextResponse } from '/next/server'; ``` ### 2. Create a middleware function The logic for our middleware is contained in a function called `middleware()`. This function checks if a `'session'` cookie already exists in the page request. If the cookie isn't found, it generates new visitor tokens using `auth.generateVisitorTokens()` and stores them in a `'session'` cookie to create a new anonymous session which persists when the visitor uses the site from the same browser. Implement this function as follows: ```js export async function middleware(request) { if (!request.cookies.get('session')) { const response = NextResponse.next(); const myWixClient = createClient({ auth: OAuthStrategy({ clientId: `` }), }); response.cookies.set( 'session', JSON.stringify(await myWixClient.auth.generateVisitorTokens()) ); return response; } } ``` ## Complete code examples You can use the following full code examples as a starting point for developing your own site: ### Login component ```jsx import Cookies from 'js-cookie'; import { useEffect, useState } from 'react'; import { createClient, OAuthStrategy } from '@wix/sdk'; import { members } from '@wix/members'; const myWixClient = createClient({ modules: { members }, auth: OAuthStrategy({ clientId: ``, tokens: JSON.parse(Cookies.get('session') || null), }), }); export default function LoginBar() { const [member, setMember] = useState(null); async function fetchMember() { const { member } = myWixClient.auth.loggedIn() ? await myWixClient.members.getCurrentMember() : {}; setMember(member || undefined); } async function login() { const data = myWixClient.auth.generateOAuthData( `${window.location.origin}/login-callback`, window.location.href ); localStorage.setItem('oauthRedirectData', JSON.stringify(data)); const { authUrl } = await myWixClient.auth.getAuthUrl(data); window.location = authUrl; // wix auth will send the user back to the callback page (login-callback.js) } async function logout() { const { logoutUrl } = await myWixClient.auth.logout(window.location.href); Cookies.remove('session'); window.location = logoutUrl; } useEffect(() => { fetchMember(); }, []); return (
{member !== null && (
(myWixClient.auth.loggedIn() ? logout() : login())} >

Hello{' '} {myWixClient.auth.loggedIn() ? member.profile?.nickname || member.profile?.slug || '' : 'visitor'} ,

{myWixClient.auth.loggedIn() ? 'Logout' : 'Login'}
)}
); } ``` ### Callback page ```jsx import Cookies from 'js-cookie'; import { useEffect, useState } from 'react'; import { createClient, OAuthStrategy } from '@wix/sdk'; const myWixClient = createClient({ auth: OAuthStrategy({ clientId: ``, tokens: JSON.parse(Cookies.get('session') || null), }), }); export default function LoginCallback() { const [nextPage, setNextPage] = useState(null); const [errorMessage, setErrorMessage] = useState(null); async function verifyLogin() { const data = JSON.parse(localStorage.getItem('oauthRedirectData')); localStorage.removeItem('oauthRedirectData'); try { const { code, state } = myWixClient.auth.parseFromUrl(); let tokens = await myWixClient.auth.getMemberTokens(code, state, data); while (!tokens?.refreshToken?.value) { // temporary workaround tokens = await myWixClient.auth.getMemberTokens(code, state, data); } Cookies.set('session', JSON.stringify(tokens)); window.location = data?.originalUri || '/'; } catch (e) { setNextPage(data?.originalUri || '/'); setErrorMessage(e.toString()); } } useEffect(() => { verifyLogin(); }, []); return (
{errorMessage && ( <> {errorMessage}

)} {nextPage ? Continue : <>Loading...}
); } ``` ### Middleware ```js import { createClient, OAuthStrategy } from '@wix/sdk'; import { NextResponse } from 'next/server'; export async function middleware(request) { // generate a session for the visitor if no session exists if (!request.cookies.get('session')) { const response = NextResponse.next(); const myWixClient = createClient({ auth: OAuthStrategy({ clientId: `` }), }); response.cookies.set( 'session', JSON.stringify(await myWixClient.auth.generateVisitorTokens()) ); return response; } } ```