├── src ├── stytch.js ├── main.js ├── App.vue ├── views │ ├── ProfileView.vue │ ├── AuthenticateView.vue │ └── LoginView.vue └── router │ └── index.js ├── .prettierrc.json ├── .eslintrc.cjs ├── vite.config.js ├── .gitignore ├── package.json ├── public ├── github.svg ├── favicon.svg ├── stytch.css └── logo.svg ├── index.html └── README.md /src/stytch.js: -------------------------------------------------------------------------------- 1 | import { StytchUIClient } from '@stytch/vanilla-js' 2 | 3 | export default new StytchUIClient(import.meta.env.VITE_STYTCH_PUBLIC_TOKEN) 4 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/prettierrc", 3 | "semi": false, 4 | "tabWidth": 2, 5 | "singleQuote": true, 6 | "printWidth": 100, 7 | "trailingComma": "none" 8 | } -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | 5 | const app = createApp(App) 6 | 7 | app.use(router) 8 | 9 | app.mount('#app') 10 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | require('@rushstack/eslint-patch/modern-module-resolution') 3 | 4 | module.exports = { 5 | root: true, 6 | 'extends': [ 7 | 'plugin:vue/vue3-essential', 8 | 'eslint:recommended', 9 | '@vue/eslint-config-prettier/skip-formatting' 10 | ], 11 | parserOptions: { 12 | ecmaVersion: 'latest' 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | import vueJsx from '@vitejs/plugin-vue-jsx' 6 | 7 | // https://vitejs.dev/config/ 8 | export default defineConfig({ 9 | plugins: [vue(), vueJsx()], 10 | resolve: { 11 | alias: { 12 | '@': fileURLToPath(new URL('./src', import.meta.url)) 13 | } 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | 5 | /node_modules 6 | /.pnp 7 | .pnp.js 8 | 9 | # testing 10 | 11 | /coverage 12 | 13 | # production 14 | 15 | /build 16 | 17 | # misc 18 | 19 | .DS_Store 20 | .env.local 21 | .env.development.local 22 | .env.test.local 23 | .env.production.local 24 | 25 | npm-debug.log* 26 | yarn-debug.log* 27 | yarn-error.log\* 28 | 29 | # Environment variables 30 | 31 | .env 32 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stytch-vue-example", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite --host localhost --port 3000", 7 | "build": "vite build", 8 | "preview": "vite preview", 9 | "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore", 10 | "format": "prettier --write src/" 11 | }, 12 | "dependencies": { 13 | "@stytch/vanilla-js": "^0.10.2", 14 | "vue": "^3.2.47", 15 | "vue-router": "^4.1.6" 16 | }, 17 | "devDependencies": { 18 | "@rushstack/eslint-patch": "^1.2.0", 19 | "@vitejs/plugin-vue": "^4.0.0", 20 | "@vitejs/plugin-vue-jsx": "^3.0.0", 21 | "@vue/eslint-config-prettier": "^7.1.0", 22 | "eslint": "^8.34.0", 23 | "eslint-plugin-vue": "^9.9.0", 24 | "prettier": "^2.8.4", 25 | "vite": "^4.1.4" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/views/ProfileView.vue: -------------------------------------------------------------------------------- 1 | 10 | 29 | -------------------------------------------------------------------------------- /public/github.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/AuthenticateView.vue: -------------------------------------------------------------------------------- 1 | 26 | 29 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | Stytch Vue Example 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 28 |
29 |
30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from 'vue-router' 2 | import AuthenticateView from '../views/AuthenticateView.vue' 3 | import LoginView from '../views/LoginView.vue' 4 | import ProfileView from '../views/ProfileView.vue' 5 | import stytch from '../stytch' 6 | 7 | export const ROUTES = { 8 | LOGIN: 'login', 9 | AUTHENTICATE: 'authenticate', 10 | PROFILE: 'profile' 11 | } 12 | 13 | const router = createRouter({ 14 | history: createWebHistory(import.meta.env.BASE_URL), 15 | routes: [ 16 | { 17 | path: '/', 18 | name: ROUTES.LOGIN, 19 | component: LoginView, 20 | meta: { requiresAuth: false } 21 | }, 22 | { 23 | path: '/authenticate', 24 | name: ROUTES.AUTHENTICATE, 25 | component: AuthenticateView, 26 | meta: { requiresAuth: false } 27 | }, 28 | { 29 | path: '/profile', 30 | name: ROUTES.PROFILE, 31 | component: ProfileView, 32 | meta: { requiresAuth: true } 33 | } 34 | ] 35 | }) 36 | 37 | // When navigating to authenticated routes check for a session 38 | router.beforeEach((to) => { 39 | if (to.meta.requiresAuth && !stytch.session.getSync()) { 40 | return { 41 | name: ROUTES.LOGIN 42 | } 43 | } 44 | }) 45 | 46 | export default router 47 | -------------------------------------------------------------------------------- /src/views/LoginView.vue: -------------------------------------------------------------------------------- 1 | 51 | 56 | -------------------------------------------------------------------------------- /public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/stytch.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | font-family: Arial, Helvetica, sans-serif; 5 | color: rgb(25, 48, 61); 6 | box-sizing: border-box; 7 | } 8 | 9 | h1 { 10 | font-size: 24px; 11 | font-weight: 600; 12 | margin-bottom: 16px; 13 | } 14 | 15 | h2 { 16 | font-size: 20px; 17 | font-weight: 500; 18 | line-height: '30px'; 19 | margin-bottom: 4px; 20 | } 21 | 22 | p { 23 | font-size: 18px; 24 | font-weight: 400; 25 | margin-bottom: 16px; 26 | } 27 | 28 | main { 29 | display: flex; 30 | min-height: calc(100vh - 70px); 31 | justify-content: center; 32 | align-items: center; 33 | flex-direction: column; 34 | padding: 36px 0px; 35 | } 36 | 37 | .container { 38 | max-width: 650px; 39 | width: 100%; 40 | padding: 0 16px; 41 | } 42 | 43 | .card { 44 | width: 100%; 45 | padding: 24px 32px; 46 | border: 1px solid rgb(173, 188, 197); 47 | border-radius: 8px; 48 | display: flex; 49 | flex-direction: column; 50 | align-items: center; 51 | } 52 | 53 | button.primary { 54 | width: 100%; 55 | height: 45px; 56 | cursor: pointer; 57 | font-size: 18px; 58 | color: white; 59 | background-color: #4a37be; 60 | border: none; 61 | border-radius: 4px; 62 | } 63 | 64 | pre.code-block { 65 | max-height: 200px; 66 | width: 100%; 67 | overflow: scroll; 68 | background-color: #10232e; 69 | border: none; 70 | border-radius: 4px; 71 | padding: 16px 8px; 72 | margin-bottom: 16px; 73 | color: white; 74 | font-family: monospace; 75 | } 76 | 77 | span.code { 78 | font-family: monospace; 79 | font-weight: 400; 80 | line-height: 28px; 81 | padding-left: 4px; 82 | border-radius: 4px; 83 | padding-right: 4px; 84 | background-color: #ecfaff; 85 | } 86 | 87 | header { 88 | width: 100%; 89 | height: 70px; 90 | background-color: #eeecff; 91 | display: flex; 92 | align-items: center; 93 | justify-content: space-between; 94 | padding: 0 16px; 95 | gap: 16px; 96 | } 97 | 98 | header > img { 99 | max-width: 250px; 100 | height: 100%; 101 | overflow: hidden; 102 | } 103 | 104 | a.header { 105 | font-size: 16px; 106 | font-weight: 600; 107 | text-decoration: none; 108 | display: flex; 109 | align-items: center; 110 | padding: 8px; 111 | border-radius: 4px; 112 | } 113 | 114 | a.header:hover { 115 | background-color: #d4ceff; 116 | } 117 | 118 | header > .link-container { 119 | display: flex; 120 | gap: 16px; 121 | } 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stytch Vue example application 2 | 3 |

4 | 5 |

6 | 7 | ## Overview 8 | 9 | This example application demonstrates how one may use Stytch within a Vue application. This project was bootstrapped with [create-vue](https://github.com/vuejs/create-vue). 10 | 11 | This project uses Stytch's [JavaScript SDK](https://stytch.com/docs/sdks/javascript-sdk) which provides pre-built UI components and headless methods to securely interact with Stytch. 12 | 13 | This application features Email Magic Links for authentication, as well as our Sessions Management product to manage user sessions. You can use this application's source code as a learning resource, or use it as a jumping off point for your own project. We are excited to see what you build with Stytch! 14 | 15 | ## Set up 16 | 17 | Follow the steps below to get this application fully functional and running using your own Stytch credentials. 18 | 19 | ### In the Stytch Dashboard 20 | 21 | 1. Create a [Stytch](https://stytch.com/) account. Once your account is set up a Project called "My first project" will be automatically created for you. 22 | 23 | 2. Within your new Project, navigate to [SDK configuration](https://stytch.com/dashboard/sdk-configuration), and make the following changes: 24 | 25 | - Click **Enable SDK**. 26 | - Under **Authorized environments** add the domain `http://localhost:3000`. 27 | Authorized environments 28 | 29 | - Within the **Email Magic Links** drawer, toggle on **Enable the LoginOrCreate Flow**. 30 | SDK Email Magic Links 31 | 32 | 3. Navigate to [Redirect URLs](https://stytch.com/dashboard/redirect-urls), and add `http://localhost:3000` as the types **Login** and **Sign-up**. 33 | Redirect URLs 34 | 35 | 4. Finally, navigate to [API Keys](https://stytch.com/dashboard/api-keys), and copy your `public_token`. You will need this value later on. 36 | 37 | ### On your machine 38 | 39 | In your terminal clone the project and install dependencies: 40 | 41 | ```bash 42 | git clone https://github.com/stytchauth/stytch-vue-example.git 43 | cd stytch-vue-example 44 | npm i 45 | ``` 46 | 47 | Next, create `.env.local` file by running the command below and your `public_token`. Learn more about Vue's support for [custom environment variables here](https://cli.vuejs.org/guide/mode-and-env.html#environment-variables). 48 | 49 | ```bash 50 | echo "VITE_STYTCH_PUBLIC_TOKEN=YOUR_TOKEN_HERE" > .env.local 51 | # For example, echo "VITE_STYTCH_PUBLIC_TOKEN=public-token-test-123abcd-1234-1234-abcd-123123abcabc" > .env.local 52 | ``` 53 | 54 | ## Running locally 55 | 56 | After completing all the set up steps above the application can be run with the command: 57 | 58 | ```bash 59 | npm run dev 60 | ``` 61 | 62 | The application will be available at [`http://localhost:3000`](http://localhost:3000). 63 | 64 | You'll be able to login with Email Magic Links and see your Stytch User object, Stytch Session, and see how logging out works. 65 | 66 | ## Next steps 67 | 68 | This example app showcases a small portion of what you can accomplish with Stytch. Here are a few ideas to explore: 69 | 70 | 1. Add additional login methods like [Passwords](https://stytch.com/docs/passwords#guides_getting-started-sdk). 71 | 2. Replace the prebuilt UI with your own using by using the SDK's [headless methods](https://stytch.com/docs/sdks/javascript-sdk). 72 | 3. Add a Google OAuth button with the high converting [Google One Tap UI](https://stytch.com/docs/oauth#guides_google-sdk). 73 | 4. Secure your app further by building MFA authentication using methods like [WebAuthn](https://stytch.com/docs/sdks/javascript-sdk#webauthn). 74 | 5. Use [Stytch Sessions](https://stytch.com/docs/sessions) to secure your backend. 75 | 76 | ## Get help and join the community 77 | 78 | #### :speech_balloon: Stytch community Slack 79 | 80 | Join the discussion, ask questions, and suggest new features in our ​[Slack community](https://stytch.com/docs/resources/support/overview)! 81 | 82 | #### :question: Need support? 83 | 84 | Check out the [Stytch Forum](https://forum.stytch.com/) or email us at [support@stytch.com](mailto:support@stytch.com). 85 | -------------------------------------------------------------------------------- /public/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | --------------------------------------------------------------------------------