diff --git a/boilerplate/frontend/react-multitenancy/.gitignore b/boilerplate/frontend/react-multitenancy/.gitignore
new file mode 100644
index 00000000..a547bf36
--- /dev/null
+++ b/boilerplate/frontend/react-multitenancy/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/LICENSE.md b/boilerplate/frontend/react-multitenancy/LICENSE.md
similarity index 100%
rename from boilerplate/frontend/supertokens-react-multitenancy/LICENSE.md
rename to boilerplate/frontend/react-multitenancy/LICENSE.md
diff --git a/boilerplate/frontend/react-multitenancy/README.md b/boilerplate/frontend/react-multitenancy/README.md
new file mode 100644
index 00000000..d209064b
--- /dev/null
+++ b/boilerplate/frontend/react-multitenancy/README.md
@@ -0,0 +1,120 @@
+# SuperTokens + React
+
+A demo implementation of [SuperTokens](https://supertokens.com/) with [React](https://react.dev/). Based on [Vite](https://vite.dev/).
+
+## General Info
+
+This project aims to demonstrate how to integrate SuperTokens into a React application. Its primary purpose is to serve as an educational tool, but it can also be used as a starting point for your own project.
+
+## Repo Structure
+
+### Source
+
+```
+📦src
+┣ 📂assets
+┃ ┣ 📂fonts
+┃ ┃ ┗ 📜MenloRegular.ttf
+┃ ┗ 📂images
+┃ ┣ 📜arrow-right-icon.svg
+┃ ┣ 📜background.png
+┃ ┣ 📜blogs-icon.svg
+┃ ┣ 📜celebrate-icon.svg
+┃ ┣ 📜guide-icon.svg
+┃ ┣ 📜separator-line.svg
+┃ ┗ 📜signout-icon.svg
+┣ 📂Home --> "Dashboard" component, accessible only via the logged-in state of the app
+┃ ┣ 📜CallAPIView.tsx
+┃ ┣ 📜Home.css
+┃ ┣ 📜SuccessView.tsx
+┃ ┗ 📜index.tsx
+┣ 📂Auth --> Log in page, customized to allow for choosing tenants
+┃ ┣ 📜Auth.css
+┃ ┣ 📜TenantSelector.tsx
+┃ ┗ 📜index.tsx
+┣ 📜App.css
+┣ 📜App.tsx --> Root component of the app
+┗ 📜main.tsx --> Entry point of the app
+```
+
+### Config
+
+#### Vite
+
+Given that the project is a standard Vite project, everything available in the [Vite configuration docs](https://vite.dev/config/) is available to use here (refer to the `vite.config.ts` file). The only customization we've done is changing the port to `3000`.
+
+#### SuperTokens
+
+The full configuration needed for SuperTokens (the frontend part) to work is in the `src/config.tsx` file. This file will differ based on the [auth recipe](https://supertokens.com/docs/guides) you choose.
+
+If you choose to use this as a starting point for your own project, you can further customize the options and config in the `src/config.tsx` file. Refer to our [docs](https://supertokens.com/docs) (and make sure to choose the correct recipe) for more details.
+
+## Application Flow
+
+The application uses [React Router](https://reactrouter.com/) for routing and consists of four main parts:
+
+1. **Entry Point (`main.tsx`)**
+
+ - Initializes the React application using `createRoot`
+ - Renders the main `App` component within React's `StrictMode`
+
+2. **Root Component (`App.tsx`)**
+
+ - Initializes SuperTokens with the provided configuration (generated by the CLI)
+ - Sets up the routing structure using `react-router-dom`
+ - Wraps the application with necessary providers:
+ - `SuperTokensWrapper`: Manages auth state and session
+ - `ComponentWrapper`: Provides auth UI customization for specific auth recipes. For example, if you choose to use the `ThirdPartyPasswordless` recipe, the `ComponentWrapper` will provide the UI customization for the passwordless login flow (showing a disclaimer about the SMS delivery in demo apps).
+ - Defines three main routes:
+ - `/`: Public landing page - accessible regardless of auth state
+ - `/auth`: Renders SuperTokens' pre-built auth UI customized for multi-tenancy - accessible regardless of auth state
+ - `/dashboard`: Protected route requiring authentication
+
+3. **Home Component (`/` route, `/Home/index.tsx` component)**
+
+ - Public landing page accessible to all users
+ - Provides navigation to authentication and dashboard
+ - Displays basic application information and links
+
+4. **Auth Component (`/auth` route, `/Auth/index.tsx` component)**
+
+ - Public page accessible by all users
+ - Has customization to allow for choosing tenants
+ - Different login methods are shown depending on tenant configuration inside of core
+
+5. **Dashboard Component (`/dashboard` route, `/Dashboard/index.tsx` component)**
+ - Protected route only accessible to authenticated users
+ - Protected by `SessionAuth` component
+ - Displays user information and session details
+ - Provides functionality to:
+ - View user ID
+ - Call test API endpoints
+ - Access documentation
+ - Sign out
+
+When a user visits the application, they start at the home page (`/`). They can choose to authenticate through the `/auth` route, and once authenticated, they gain access to the protected dashboard. The session state is managed throughout the application using SuperTokens' session management.
+
+## Customizations
+
+If you want to customize the default auth UI, you have two options:
+
+1. Refer to the [docs](https://supertokens.com/docs/thirdpartyemailpassword/advanced-customizations/react-component-override/usage) on how to customize the pre-built UI.
+2. Roll your own UI by choosing "Custom UI" in the right sidebar in the [docs](https://supertokens.com/docs/thirdpartyemailpassword/quickstart/frontend-setup).
+
+## Additional resources
+
+- Custom UI Example: https://github.com/supertokens/supertokens-web-js/tree/master/examples/react/with-thirdpartyemailpassword
+- Custom UI Blog post: https://supertokens.medium.com/adding-social-login-to-your-website-with-supertokens-custom-ui-only-5fa4d7ab6402
+- Awesome SuperTokens: https://github.com/kohasummons/awesome-supertokens
+
+## Contributing
+
+Please refer to the [CONTRIBUTING.md](https://github.com/supertokens/create-supertokens-app/blob/master/CONTRIBUTING.md) file in the root of the [`create-supertokens-app`](https://github.com/supertokens/create-supertokens-app) repo.
+
+## Contact us
+
+For any questions, or support requests, please email us at team@supertokens.io, or join our [Discord](https://supertokens.io/discord) server.
+
+## Authors
+
+Created with :heart: by the folks at SuperTokens.io.
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/config/multitenancy.tsx b/boilerplate/frontend/react-multitenancy/config/multitenancy.tsx
similarity index 84%
rename from boilerplate/frontend/supertokens-react-multitenancy/config/multitenancy.tsx
rename to boilerplate/frontend/react-multitenancy/config/multitenancy.tsx
index 3e832cb3..2593cf81 100644
--- a/boilerplate/frontend/supertokens-react-multitenancy/config/multitenancy.tsx
+++ b/boilerplate/frontend/react-multitenancy/config/multitenancy.tsx
@@ -8,14 +8,14 @@ import Session from "supertokens-auth-react/recipe/session";
import Multitenancy from "supertokens-auth-react/recipe/multitenancy";
export function getApiDomain() {
- const apiPort = process.env.REACT_APP_API_PORT || 3001;
- const apiUrl = process.env.REACT_APP_API_URL || `http://localhost:${apiPort}`;
+ const apiPort = import.meta.env.VITE_APP_API_PORT || 3001;
+ const apiUrl = import.meta.env.VITE_APP_API_URL || `http://localhost:${apiPort}`;
return apiUrl;
}
export function getWebsiteDomain() {
- const websitePort = process.env.REACT_APP_WEBSITE_PORT || 3000;
- const websiteUrl = process.env.REACT_APP_WEBSITE_URL || `http://localhost:${websitePort}`;
+ const websitePort = import.meta.env.VITE_APP_WEBSITE_PORT || 3000;
+ const websiteUrl = import.meta.env.VITE_APP_WEBSITE_URL || `http://localhost:${websitePort}`;
return websiteUrl;
}
@@ -32,15 +32,13 @@ export const SuperTokensConfig = {
websiteDomain: getWebsiteDomain(),
},
usesDynamicLoginMethods: true,
+ style: styleOverride,
// recipeList contains all the modules that you want to
// use from SuperTokens. See the full list here: https://supertokens.com/docs/guides
- style: styleOverride,
recipeList: [
EmailPassword.init(),
ThirdParty.init(),
- Passwordless.init({
- contactMethod: "EMAIL",
- }),
+ Passwordless.init({ contactMethod: "EMAIL" }),
Session.init(),
Multitenancy.init({
override: {
diff --git a/boilerplate/frontend/react-multitenancy/eslint.config.js b/boilerplate/frontend/react-multitenancy/eslint.config.js
new file mode 100644
index 00000000..e1770e4a
--- /dev/null
+++ b/boilerplate/frontend/react-multitenancy/eslint.config.js
@@ -0,0 +1,25 @@
+import js from "@eslint/js";
+import globals from "globals";
+import reactHooks from "eslint-plugin-react-hooks";
+import reactRefresh from "eslint-plugin-react-refresh";
+import tseslint from "typescript-eslint";
+
+export default tseslint.config(
+ { ignores: ["dist"] },
+ {
+ extends: [js.configs.recommended, ...tseslint.configs.recommended],
+ files: ["**/*.{ts,tsx}"],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ },
+ plugins: {
+ "react-hooks": reactHooks,
+ "react-refresh": reactRefresh,
+ },
+ rules: {
+ ...reactHooks.configs.recommended.rules,
+ "react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
+ },
+ }
+);
diff --git a/boilerplate/frontend/react-multitenancy/index.html b/boilerplate/frontend/react-multitenancy/index.html
new file mode 100644
index 00000000..32e95580
--- /dev/null
+++ b/boilerplate/frontend/react-multitenancy/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+ } />
+
+ {/* This shows the login UI on "/auth" route */}
+ } />
+ {getSuperTokensRoutesForReactRouterDom(ReactRouter, PreBuiltUIList)}
+
+ {/* This protects the "/" route so that it shows
+ only if the user is logged in.
+ Else it redirects the user to "/auth" */}
+
+
+
+ }
+ />
+
+
+ );
+}
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/src/Home/CallAPIView.tsx b/boilerplate/frontend/react-multitenancy/src/Home/CallAPIView.tsx
similarity index 100%
rename from boilerplate/frontend/supertokens-react-multitenancy/src/Home/CallAPIView.tsx
rename to boilerplate/frontend/react-multitenancy/src/Home/CallAPIView.tsx
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/src/Home/Home.css b/boilerplate/frontend/react-multitenancy/src/Home/Home.css
similarity index 100%
rename from boilerplate/frontend/supertokens-react-multitenancy/src/Home/Home.css
rename to boilerplate/frontend/react-multitenancy/src/Home/Home.css
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/src/Home/SuccessView.tsx b/boilerplate/frontend/react-multitenancy/src/Home/SuccessView.tsx
similarity index 100%
rename from boilerplate/frontend/supertokens-react-multitenancy/src/Home/SuccessView.tsx
rename to boilerplate/frontend/react-multitenancy/src/Home/SuccessView.tsx
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/src/Home/index.tsx b/boilerplate/frontend/react-multitenancy/src/Home/index.tsx
similarity index 100%
rename from boilerplate/frontend/supertokens-react-multitenancy/src/Home/index.tsx
rename to boilerplate/frontend/react-multitenancy/src/Home/index.tsx
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/src/assets/fonts/MenloRegular.ttf b/boilerplate/frontend/react-multitenancy/src/assets/fonts/MenloRegular.ttf
similarity index 100%
rename from boilerplate/frontend/supertokens-react-multitenancy/src/assets/fonts/MenloRegular.ttf
rename to boilerplate/frontend/react-multitenancy/src/assets/fonts/MenloRegular.ttf
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/src/assets/images/arrow-right-icon.svg b/boilerplate/frontend/react-multitenancy/src/assets/images/arrow-right-icon.svg
similarity index 100%
rename from boilerplate/frontend/supertokens-react-multitenancy/src/assets/images/arrow-right-icon.svg
rename to boilerplate/frontend/react-multitenancy/src/assets/images/arrow-right-icon.svg
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/src/assets/images/background.png b/boilerplate/frontend/react-multitenancy/src/assets/images/background.png
similarity index 100%
rename from boilerplate/frontend/supertokens-react-multitenancy/src/assets/images/background.png
rename to boilerplate/frontend/react-multitenancy/src/assets/images/background.png
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/src/assets/images/blogs-icon.svg b/boilerplate/frontend/react-multitenancy/src/assets/images/blogs-icon.svg
similarity index 100%
rename from boilerplate/frontend/supertokens-react-multitenancy/src/assets/images/blogs-icon.svg
rename to boilerplate/frontend/react-multitenancy/src/assets/images/blogs-icon.svg
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/src/assets/images/celebrate-icon.svg b/boilerplate/frontend/react-multitenancy/src/assets/images/celebrate-icon.svg
similarity index 100%
rename from boilerplate/frontend/supertokens-react-multitenancy/src/assets/images/celebrate-icon.svg
rename to boilerplate/frontend/react-multitenancy/src/assets/images/celebrate-icon.svg
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/src/assets/images/guide-icon.svg b/boilerplate/frontend/react-multitenancy/src/assets/images/guide-icon.svg
similarity index 100%
rename from boilerplate/frontend/supertokens-react-multitenancy/src/assets/images/guide-icon.svg
rename to boilerplate/frontend/react-multitenancy/src/assets/images/guide-icon.svg
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/src/assets/images/index.ts b/boilerplate/frontend/react-multitenancy/src/assets/images/index.ts
similarity index 100%
rename from boilerplate/frontend/supertokens-react-multitenancy/src/assets/images/index.ts
rename to boilerplate/frontend/react-multitenancy/src/assets/images/index.ts
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/src/assets/images/separator-line.svg b/boilerplate/frontend/react-multitenancy/src/assets/images/separator-line.svg
similarity index 100%
rename from boilerplate/frontend/supertokens-react-multitenancy/src/assets/images/separator-line.svg
rename to boilerplate/frontend/react-multitenancy/src/assets/images/separator-line.svg
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/src/assets/images/sign-out-icon.svg b/boilerplate/frontend/react-multitenancy/src/assets/images/sign-out-icon.svg
similarity index 100%
rename from boilerplate/frontend/supertokens-react-multitenancy/src/assets/images/sign-out-icon.svg
rename to boilerplate/frontend/react-multitenancy/src/assets/images/sign-out-icon.svg
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/src/config.tsx b/boilerplate/frontend/react-multitenancy/src/config.tsx
similarity index 100%
rename from boilerplate/frontend/supertokens-react-multitenancy/src/config.tsx
rename to boilerplate/frontend/react-multitenancy/src/config.tsx
diff --git a/boilerplate/frontend/react-multitenancy/src/main.tsx b/boilerplate/frontend/react-multitenancy/src/main.tsx
new file mode 100644
index 00000000..cd384efe
--- /dev/null
+++ b/boilerplate/frontend/react-multitenancy/src/main.tsx
@@ -0,0 +1,10 @@
+import { StrictMode } from "react";
+import { createRoot } from "react-dom/client";
+import "./App.css";
+import App from "./App.tsx";
+
+createRoot(document.getElementById("root")!).render(
+
+
+
+);
diff --git a/boilerplate/frontend/react-multitenancy/src/vite-env.d.ts b/boilerplate/frontend/react-multitenancy/src/vite-env.d.ts
new file mode 100644
index 00000000..11f02fe2
--- /dev/null
+++ b/boilerplate/frontend/react-multitenancy/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/boilerplate/frontend/react-multitenancy/tsconfig.app.json b/boilerplate/frontend/react-multitenancy/tsconfig.app.json
new file mode 100644
index 00000000..dfc691d4
--- /dev/null
+++ b/boilerplate/frontend/react-multitenancy/tsconfig.app.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["src"]
+}
diff --git a/boilerplate/frontend/react-multitenancy/tsconfig.json b/boilerplate/frontend/react-multitenancy/tsconfig.json
new file mode 100644
index 00000000..eb69b0d0
--- /dev/null
+++ b/boilerplate/frontend/react-multitenancy/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ "files": [],
+ "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }]
+}
diff --git a/boilerplate/frontend/react-multitenancy/tsconfig.node.json b/boilerplate/frontend/react-multitenancy/tsconfig.node.json
new file mode 100644
index 00000000..ff0dc7df
--- /dev/null
+++ b/boilerplate/frontend/react-multitenancy/tsconfig.node.json
@@ -0,0 +1,24 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "target": "ES2022",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/boilerplate/frontend/react-multitenancy/vite.config.ts b/boilerplate/frontend/react-multitenancy/vite.config.ts
new file mode 100644
index 00000000..21420ded
--- /dev/null
+++ b/boilerplate/frontend/react-multitenancy/vite.config.ts
@@ -0,0 +1,10 @@
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react";
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [react()],
+ server: {
+ port: 3000,
+ },
+});
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/package.json b/boilerplate/frontend/supertokens-react-multitenancy/package.json
deleted file mode 100644
index 68535516..00000000
--- a/boilerplate/frontend/supertokens-react-multitenancy/package.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": "supertokens-react",
- "version": "0.1.0",
- "private": true,
- "dependencies": {
- "@testing-library/jest-dom": "^5.16.5",
- "@testing-library/react": "^13.4.0",
- "@testing-library/user-event": "^13.5.0",
- "@types/jest": "^27.5.2",
- "@types/node": "^16.11.56",
- "@types/react": "^18.0.18",
- "@types/react-dom": "^18.0.6",
- "axios": "^0.21.0",
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
- "react-router-dom": "^6.2.1",
- "react-scripts": "5.0.1",
- "supertokens-auth-react": "latest",
- "typescript": "^4.8.2",
- "web-vitals": "^2.1.4"
- },
- "scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test",
- "eject": "react-scripts eject"
- },
- "eslintConfig": {
- "extends": [
- "react-app",
- "react-app/jest"
- ]
- },
- "browserslist": {
- "production": [
- ">0.2%",
- "not dead",
- "not op_mini all"
- ],
- "development": [
- "last 1 chrome version",
- "last 1 firefox version",
- "last 1 safari version"
- ]
- }
-}
diff --git a/boilerplate/frontend/supertokens-react-multitenancy/src/App.tsx b/boilerplate/frontend/supertokens-react-multitenancy/src/App.tsx
deleted file mode 100644
index 3ad3a1af..00000000
--- a/boilerplate/frontend/supertokens-react-multitenancy/src/App.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import "./App.css";
-import SuperTokens, { SuperTokensWrapper } from "supertokens-auth-react";
-import { SessionAuth } from "supertokens-auth-react/recipe/session";
-import { Routes, BrowserRouter as Router, Route } from "react-router-dom";
-import Home from "./Home";
-import { SuperTokensConfig, PreBuiltUIList } from "./config";
-import { Auth } from "./Auth";
-import { getSuperTokensRoutesForReactRouterDom } from "supertokens-auth-react/ui";
-import * as reactRouterDom from "react-router-dom";
-
-SuperTokens.init(SuperTokensConfig);
-
-function App() {
- /*
- * We override the pre built UI to show the ChangeTenantsButton along with the rest of the
- * login form. This component allows users to go back and select another tenant without logging in
- */
- return (
-
-
-
-
- {/*
- * The Auth component handles showing the tenant dropdown
- * to users who are not logged in. It also handles showing
- * the pre built UI provided by SuperTokens after users have
- * selected a tenant
- */}
- } />
-
- {getSuperTokensRoutesForReactRouterDom(reactRouterDom, PreBuiltUIList)}
-
- only if the user is logged in.
- Else it redirects the user to "/auth" */
-
-
-
- }
- />
-
-
-