├── .gitattributes ├── .gitignore ├── README.md ├── app ├── .eslintrc.js ├── .gitignore ├── .prettierrc.js ├── LICENSE ├── README.md ├── jest.config.js ├── jovo.debugger.js ├── jovo.project.js ├── models │ └── en.json ├── package.json ├── src │ ├── app.dev.ts │ ├── app.ts │ ├── components │ │ └── GlobalComponent.ts │ └── server.express.ts ├── test │ └── sample.test.ts └── tsconfig.json ├── client ├── .browserslistrc ├── .eslintrc.js ├── .gitignore ├── .prettierrc.js ├── README.md ├── babel.config.js ├── package.json ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── App.vue │ ├── assets │ │ └── css │ │ │ └── theme.pcss │ ├── components │ │ └── RecordButton.vue │ ├── main.ts │ ├── shims-tsx.d.ts │ └── shims-vue.d.ts ├── tailwind.config.js ├── tsconfig.json └── vue.config.js ├── img ├── jovo-web-client-to-app.png └── starter-web-standalone.gif └── package.json /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto eol=lf 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | dist 4 | 5 | 6 | # local env files 7 | .env 8 | .env.local 9 | .env.*.local 10 | 11 | # Log files 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | pnpm-debug.log* 16 | 17 | # Editor directories and files 18 | .idea 19 | .vscode 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jovo Web Starter: Standalone Voice Experience 2 | 3 | Fully customizable open source voice experience that can be hosted on any website. 4 | 5 | Built with the [Jovo Framework](https://github.com/jovotech/jovo-framework), [Vue.js 2](https://github.com/vuejs/vue), and [Tailwind CSS](https://github.com/tailwindlabs/tailwindcss). 6 | 7 | ![Jovo Standalone Voice Experience](./img/starter-web-standalone.gif) 8 | 9 | > Support Jovo by starring [our main repo](https://github.com/jovotech/jovo-framework) or joining [our Open Collective](https://opencollective.com/jovo-framework). 10 | 11 | - [Getting Started](#getting-started) 12 | - [How it works](#how-it-works) 13 | - [Customization](#customization) 14 | - [Client](#client) 15 | - [App](#app) 16 | - [Deployment](#deployment) 17 | - [About Jovo](#about-jovo) 18 | 19 | ## Getting Started 20 | 21 | 1. **Download starter** 22 | 23 | Clone this repository and install the dependencies: 24 | 25 | ```sh 26 | git clone https://github.com/jovotech/jovo-starter-web-standalone.git 27 | 28 | cd jovo-starter-web-standalone 29 | 30 | npm install 31 | ``` 32 | 33 | 2. **Start client (Vue.js)** 34 | 35 | ```sh 36 | $ cd client 37 | 38 | # Start Vue frontend 39 | $ npm run serve 40 | ``` 41 | 42 | 3. **Start app (Jovo)** 43 | In a new tab: 44 | 45 | ```sh 46 | $ cd app 47 | 48 | # Start Jovo development server 49 | $ npm run start:dev 50 | ``` 51 | 52 | 4. **Open the starter in your browser at `http://localhost:8080`.** 53 | 54 | > Note: For demo purposes and the ease of getting started quickly, the template uses the [Web Speech API](https://wicg.github.io/speech-api/) as an ASR, which only works in Google Chrome. 55 | 56 | ## How it works 57 | 58 | ![Jovo Web Client to App](img/jovo-web-client-to-app.png) 59 | 60 | This repository contains: 61 | 62 | - `app`: Backend logic built with the [Jovo Framework](https://github.com/jovotech/jovo-framework) using its [Web Platform integration](https://github.com/jovotech/jovo-framework/tree/v4/latest/platforms/platform-web). 63 | - `client`: Frontend built with [Vue.js 2](https://vuejs.org/) and [Tailwind CSS](https://tailwindcss.com/), communicating with the backend using the [Jovo Web Client for Vue.js 2](https://github.com/jovotech/jovo-framework/tree/v4/latest/clients/client-web-vue2). 64 | 65 | ## Customization 66 | 67 | The starter was built for you to have a working example as well as an entry point to get started with the Jovo Web integration. 68 | 69 | The following documentation will help you understand how the starter is structured and which components take care of which tasks. 70 | 71 | ### Client 72 | 73 | The client is a Vue.js project that consists of a single component "RecordButton" which is styled in Tailwind CSS. 74 | 75 | If you are new to Vue.js and want to develop your website starting with this project, you can take a look at the Vue.js guide [here](https://vuejs.org/v2/guide/). This will give you a quick start to how Vue.js works, so you can start creating right away. 76 | 77 | ### App 78 | 79 | The Jovo app uses the [Jovo Web Platform integration](http://jovo.tech/marketplace/platform-web) as well as [NLP.js](https://www.jovo.tech/marketplace/nlu-nlpjs) as its NLU. 80 | 81 | #### Language Model 82 | 83 | The language model consists of a single intent, `SwitchThemeIntent`, used to change the theme of the website to either dark or light mode. 84 | 85 | ## Deployment 86 | 87 | ### Client 88 | 89 | > Take a look at the Vue deployment docs [here](https://cli.vuejs.org/guide/deployment). 90 | 91 | To integrate Jovo Web Standalone into your existing project, you can use the npm script `build` inside of the `client/` directory. This will produce a bundle in a dedicated `dist/` directory, containing the whole Vue.js client with minified HTML, CSS and JavaScript, ready for dynamic integration into any website. 92 | 93 | ### App 94 | 95 | You can host your Jovo app on almost any platform, whether you choose a hosting provider or to build your own Node.js-based HTTP server. Here are a few examples: 96 | 97 | - [AWS Lambda](https://www.jovo.tech/marketplace/server-lambda) 98 | - [Express](https://www.jovo.tech/marketplace/server-express) 99 | 100 | ## About Jovo 101 | 102 | Jovo is the most popular development framework for voice, including platforms like Alexa, Google Assistant, and the web. 103 | 104 | - [Jovo Website](https://jovo.tech/) 105 | - [Documentation](https://jovo.tech/docs/) 106 | - [Marketplace](https://www.jovo.tech/marketplace/) 107 | - [Twitter](https://twitter.com/jovotech/) 108 | - [Forum](https://community.jovo.tech/) 109 | -------------------------------------------------------------------------------- /app/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', // Specifies the ESLint parser 4 | parserOptions: { 5 | ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features 6 | sourceType: 'module', // Allows for the use of imports 7 | }, 8 | extends: [ 9 | 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin 10 | 'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier 11 | 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. 12 | ], 13 | rules: { 14 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 15 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | db/ 3 | bundle/ 4 | bundle.zip 5 | .env 6 | dist/ 7 | build/ 8 | package-lock.json -------------------------------------------------------------------------------- /app/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 100, 3 | tabWidth: 2, 4 | useTabs: false, 5 | semi: true, 6 | singleQuote: true, 7 | quoteProps: 'consistent', 8 | trailingComma: 'all', 9 | bracketSpacing: true, 10 | arrowParens: 'always', 11 | }; 12 | -------------------------------------------------------------------------------- /app/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /app/README.md: -------------------------------------------------------------------------------- 1 | # Jovo v4 Template 2 | 3 | A sample voice app for the Jovo `v4` alpha version. Please note that this release is still very experimental. [You can find the documentation here](https://github.com/jovotech/jovo-framework/tree/v4dev/docs). 4 | 5 | This is the default template for the `jovov4 new` command. 6 | 7 | ## Quick Start 8 | 9 | You can install the new Jovo CLI like this: 10 | 11 | ```sh 12 | # Install globally 13 | $ npm install -g @jovotech/cli 14 | 15 | # Test the installation 16 | $ jovov4 -v 17 | ``` 18 | 19 | This will install the new CLI. For the beta phase, you can use it with `jovov4`. This way, you'll still be able to use Jovo CLI v3 (`jovo-cli` package) with `jovo`. 20 | 21 | After successfully installing the Jovo CLI, you can install the template using this command: 22 | 23 | ```sh 24 | $ jovov4 new 25 | ``` 26 | 27 | Change your working directory into your newly created project directory and run your voice app: 28 | 29 | ```sh 30 | # Change working directory to your previously specified directory 31 | $ cd 32 | 33 | # Run local development server 34 | $ jovov4 run 35 | ``` 36 | 37 | You can now open the Jovo Debugger with the `.` key. Note: The v4 Debugger can be reached using `webhookv4.jovo.cloud` instead of `webhook.jovo.cloud`. 38 | -------------------------------------------------------------------------------- /app/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | }; 5 | -------------------------------------------------------------------------------- /app/jovo.debugger.js: -------------------------------------------------------------------------------- 1 | const { DebuggerConfig } = require('@jovotech/plugin-debugger'); 2 | 3 | const debuggerConfig = new DebuggerConfig({ 4 | locales: ['en'], 5 | buttons: [ 6 | { 7 | label: 'LAUNCH', 8 | input: { 9 | type: 'LAUNCH', 10 | }, 11 | }, 12 | { 13 | label: 'Light Theme', 14 | input: { 15 | intent: 'SwitchThemeIntent', 16 | entities: { 17 | theme: { 18 | resolved: 'light', 19 | id: 'light', 20 | value: 'light', 21 | }, 22 | }, 23 | }, 24 | }, 25 | { 26 | label: 'Dark Theme', 27 | input: { 28 | intent: 'SwitchThemeIntent', 29 | entities: { 30 | theme: { 31 | resolved: 'dark', 32 | id: 'dark', 33 | value: 'dark', 34 | }, 35 | }, 36 | }, 37 | }, 38 | // ... 39 | ], 40 | }); 41 | 42 | module.exports = debuggerConfig; 43 | -------------------------------------------------------------------------------- /app/jovo.project.js: -------------------------------------------------------------------------------- 1 | const { ProjectConfig } = require('@jovotech/cli-core'); 2 | 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | JOVO PROJECT CONFIGURATION 6 | |-------------------------------------------------------------------------- 7 | | 8 | | Information used by the Jovo CLI to build and deploy projects 9 | | Learn more here: v4.jovo.tech/docs/project-config 10 | | 11 | */ 12 | const project = new ProjectConfig({ 13 | endpoint: '${JOVO_WEBHOOK_URL}', 14 | plugins: [ 15 | // Add Jovo CLI plugins here 16 | ], 17 | }); 18 | 19 | module.exports = project; 20 | -------------------------------------------------------------------------------- /app/models/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "invocation": "my test app", 3 | "version": "4.0", 4 | "intents": { 5 | "SwitchThemeIntent": { 6 | "phrases": [ 7 | "{theme}", 8 | "switch to {theme} mode", 9 | "{theme} mode", 10 | "enable {theme} mode", 11 | "{theme} theme", 12 | "switch to the {theme} theme", 13 | "i want the {theme} theme" 14 | ], 15 | "entities": { 16 | "theme": { 17 | "type": "ThemeType" 18 | } 19 | } 20 | } 21 | }, 22 | "entityTypes": { 23 | "ThemeType": { 24 | "values": [ 25 | { 26 | "value": "light" 27 | }, 28 | { "value": "dark" } 29 | ] 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jovo-starter-web-standalone-app", 3 | "private": true, 4 | "version": "4.0.0", 5 | "description": "Get started with Jovo Framework v4 using this sample TypeScript app.", 6 | "main": "./dist/index.js", 7 | "types": "./dist/index.d.ts", 8 | "scripts": { 9 | "test": "jest", 10 | "tsc": "tsc", 11 | "start:dev": "tsc-watch --onSuccess \"node ./dist/app.dev.js --jovo-webhook\" --noClear", 12 | "bundle": "esbuild --bundle --outfile=bundle/index.js --sourcemap --minify --keep-names --platform=node --target=node14 --format=cjs --external:aws-sdk --external:@oclif/* --external:@jovotech/cli*", 13 | "prebundle": "rimraf bundle", 14 | "postbundle": "cd bundle && bestzip ../bundle.zip * && cd ..", 15 | "bundle:dev": "npm run bundle -- src/app.dev.ts", 16 | "eslint": "eslint src test --fix --ext .ts" 17 | }, 18 | "dependencies": { 19 | "@jovotech/db-filedb": "^4.0.0", 20 | "@jovotech/framework": "^4.0.0", 21 | "@jovotech/nlu-nlpjs": "^4.0.0", 22 | "@jovotech/platform-web": "^4.0.0", 23 | "@jovotech/plugin-debugger": "^4.0.0", 24 | "@jovotech/server-express": "^4.0.0", 25 | "@nlpjs/lang-en": "^4.22.0", 26 | "cors": "^2.8.5", 27 | "source-map-support": "^0.5.19" 28 | }, 29 | "devDependencies": { 30 | "@jovotech/cli-core": "^4.0.0", 31 | "@types/cors": "^2.8.12", 32 | "@types/express": "^4.17.11", 33 | "@types/jest": "^27.0.2", 34 | "@types/socket.io-client": "^1.4.36", 35 | "@typescript-eslint/eslint-plugin": "^4.12.0", 36 | "@typescript-eslint/parser": "^4.12.0", 37 | "bestzip": "^2.1.7", 38 | "esbuild": "^0.12.5", 39 | "eslint": "^7.17.0", 40 | "eslint-config-prettier": "^7.1.0", 41 | "eslint-plugin-prettier": "^3.3.1", 42 | "jest": "^27.3.1", 43 | "prettier": "^2.2.1", 44 | "ts-jest": "^27.0.7", 45 | "tsc-watch": "^4.2.9", 46 | "typescript": "^4.2.3", 47 | "@jovotech/cli-command-build": "^4.0.0", 48 | "@jovotech/cli-command-get": "^4.0.0", 49 | "@jovotech/cli-command-run": "^4.0.0", 50 | "@jovotech/cli-command-new": "^4.0.0-", 51 | "@jovotech/cli-command-deploy": "^4.0.0", 52 | "@jovotech/filebuilder": "^0.0.1" 53 | }, 54 | "repository": { 55 | "type": "git", 56 | "url": "git+https://github.com/jovotech/jovo-starter-web-standalone.git" 57 | }, 58 | "author": "jovotech", 59 | "license": "Apache-2.0", 60 | "bugs": { 61 | "url": "https://github.com/jovotech/jovo-starter-web-standalone/issues" 62 | }, 63 | "homepage": "https://github.com/jovotech/jovo-starter-web-standalone#readme" 64 | } 65 | -------------------------------------------------------------------------------- /app/src/app.dev.ts: -------------------------------------------------------------------------------- 1 | import { FileDb } from '@jovotech/db-filedb'; 2 | import { JovoDebugger } from '@jovotech/plugin-debugger'; 3 | import { app } from './app'; 4 | 5 | /* 6 | |-------------------------------------------------------------------------- 7 | | STAGE CONFIGURATION 8 | |-------------------------------------------------------------------------- 9 | | 10 | | This configuration gets merged into the default app config 11 | | Learn more here: v4.jovo.tech/docs/staging 12 | | 13 | */ 14 | app.configure({ 15 | plugins: [ 16 | new FileDb({ 17 | skipTests: true, 18 | pathToFile: '../db/db.json', 19 | }), 20 | new JovoDebugger(), 21 | ], 22 | }); 23 | 24 | export * from './server.express'; 25 | -------------------------------------------------------------------------------- /app/src/app.ts: -------------------------------------------------------------------------------- 1 | import { App } from '@jovotech/framework'; 2 | import { NlpjsNlu } from '@jovotech/nlu-nlpjs'; 3 | import { WebPlatform } from '@jovotech/platform-web'; 4 | import { LangEn } from '@nlpjs/lang-en'; 5 | import { GlobalComponent } from './components/GlobalComponent'; 6 | /* 7 | |-------------------------------------------------------------------------- 8 | | APP CONFIGURATION 9 | |-------------------------------------------------------------------------- 10 | | 11 | | All relevant components, plugins, and configurations for your Jovo app 12 | | Learn more here: v4.jovo.tech/docs/app-config 13 | | 14 | */ 15 | 16 | const app = new App({ 17 | /* 18 | |-------------------------------------------------------------------------- 19 | | Components 20 | |-------------------------------------------------------------------------- 21 | | 22 | | Components contain the Jovo app logic 23 | | Learn more here: v4.jovo.tech/docs/components 24 | | 25 | */ 26 | 27 | components: [GlobalComponent], 28 | 29 | /* 30 | |-------------------------------------------------------------------------- 31 | | Plugins 32 | |-------------------------------------------------------------------------- 33 | | 34 | | Includes platforms, database integrations, third-party plugins, and more 35 | | Learn more here: v4.jovo.tech/marketplace 36 | | 37 | */ 38 | 39 | plugins: [ 40 | // Add Jovo plugins here 41 | new WebPlatform({ 42 | plugins: [ 43 | new NlpjsNlu({ 44 | languageMap: { 45 | en: LangEn, 46 | }, 47 | }), 48 | ], 49 | }), 50 | ], 51 | 52 | /* 53 | |-------------------------------------------------------------------------- 54 | | Other options 55 | |-------------------------------------------------------------------------- 56 | | 57 | | Includes all other configuration options like logging 58 | | Learn more here: v4.jovo.tech/docs/app-config 59 | | 60 | */ 61 | 62 | logging: true, 63 | 64 | routing: { 65 | intentMap: { 66 | 'AMAZON.StopIntent': 'END', 67 | }, 68 | }, 69 | }); 70 | 71 | export { app }; 72 | -------------------------------------------------------------------------------- /app/src/components/GlobalComponent.ts: -------------------------------------------------------------------------------- 1 | import { ArrayElement, BaseComponent, Component, Global, Intents } from '@jovotech/framework'; 2 | 3 | const SUPPORTED_THEMES = ['light', 'dark']; 4 | 5 | @Global() 6 | @Component() 7 | export class GlobalComponent extends BaseComponent { 8 | LAUNCH() { 9 | return this.$send({ 10 | message: 'You can say "switch to dark mode" or "light mode."', 11 | listen: false, 12 | }); 13 | } 14 | 15 | UNHANDLED() { 16 | return this.LAUNCH(); 17 | } 18 | 19 | @Intents(['SwitchThemeIntent']) 20 | switchTheme() { 21 | const theme = this.$entities.theme?.resolved; 22 | // if no theme was found or the theme is invalid 23 | if (!theme || !SUPPORTED_THEMES.includes(theme)) { 24 | return this.LAUNCH(); 25 | } 26 | 27 | return this.$send({ 28 | message: `Ok, ${theme} mode.`, 29 | listen: false, 30 | platforms: { 31 | web: { 32 | // custom property for this example 33 | theme, 34 | }, 35 | }, 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/server.express.ts: -------------------------------------------------------------------------------- 1 | import { ExpressJs, Request, Response, Webhook } from '@jovotech/server-express'; 2 | import cors from 'cors'; 3 | import { app } from './app'; 4 | 5 | /* 6 | |-------------------------------------------------------------------------- 7 | | EXPRESS SERVER CONFIGURATION 8 | |-------------------------------------------------------------------------- 9 | | 10 | | Creates a new express app instance, default for local development 11 | | Learn more here: www.jovo.tech/docs/server/express 12 | | 13 | */ 14 | const port = process.env.JOVO_PORT || 3000; 15 | (async () => { 16 | if (process.env.NODE_ENV === 'test' || process.env.JEST_WORKER_ID) { 17 | return; 18 | } 19 | 20 | Webhook.use(cors()); 21 | 22 | await app.initialize(); 23 | Webhook.listen(port, () => { 24 | console.info(`Local server listening on port ${port}.`); 25 | }); 26 | Webhook.get('/webhook', async (req: Request, res: Response) => { 27 | const response = await app.handle(new ExpressJs(req, res)); 28 | res.json(response); 29 | }); 30 | Webhook.post('/webhook', async (req: Request, res: Response) => { 31 | await app.handle(new ExpressJs(req, res)); 32 | }); 33 | })(); 34 | -------------------------------------------------------------------------------- /app/test/sample.test.ts: -------------------------------------------------------------------------------- 1 | import { TestSuite, InputType } from '@jovotech/framework'; 2 | 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | UNIT TESTING 6 | |-------------------------------------------------------------------------- 7 | | 8 | | Run `npm test` to execute this sample test. 9 | | Learn more here: v4.jovo.tech/docs/unit-testing 10 | | 11 | */ 12 | 13 | const testSuite = new TestSuite(); 14 | 15 | test('should ask the user if they like pizza', async () => { 16 | 17 | const { output } = await testSuite.run({ 18 | type: InputType.Launch, // or 'LAUNCH' 19 | }); 20 | 21 | expect(output).toEqual([ 22 | { 23 | message: 'Do you like pizza?', 24 | quickReplies: ['yes', 'no'], 25 | listen: true, 26 | }, 27 | ]); 28 | 29 | }); 30 | -------------------------------------------------------------------------------- /app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": [ 4 | "es2017" 5 | ], 6 | "allowJs": true, 7 | "module": "commonjs", 8 | "noImplicitAny": true, 9 | "esModuleInterop": true, 10 | "removeComments": false, 11 | "allowUnreachableCode": true, 12 | "resolveJsonModule": true, 13 | "noImplicitReturns": true, 14 | "preserveConstEnums": true, 15 | "declaration": true, 16 | "strict": true, 17 | "outDir": "dist", 18 | "target": "es2017", 19 | "sourceMap": true, 20 | "experimentalDecorators": true, 21 | "emitDecoratorMetadata": true, 22 | "skipLibCheck": true 23 | }, 24 | "include": [ 25 | "src" 26 | ], 27 | "exclude": [ 28 | "dist", 29 | "node_modules" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /client/.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /client/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true, 5 | }, 6 | extends: [ 7 | 'plugin:vue/essential', 8 | 'eslint:recommended', 9 | '@vue/typescript/recommended', 10 | '@vue/prettier', 11 | '@vue/prettier/@typescript-eslint', 12 | ], 13 | parserOptions: { 14 | ecmaVersion: 2020, 15 | }, 16 | rules: { 17 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 18 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 19 | }, 20 | }; 21 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /client/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 100, 3 | tabWidth: 2, 4 | useTabs: false, 5 | semi: true, 6 | singleQuote: true, 7 | quoteProps: 'consistent', 8 | trailingComma: 'all', 9 | bracketSpacing: true, 10 | arrowParens: 'always', 11 | }; 12 | -------------------------------------------------------------------------------- /client/README.md: -------------------------------------------------------------------------------- 1 | # client 2 | 3 | ## Project setup 4 | ``` 5 | npm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | npm run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | npm run build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | npm run lint 21 | ``` 22 | 23 | ### Customize configuration 24 | See [Configuration Reference](https://cli.vuejs.org/config/). 25 | -------------------------------------------------------------------------------- /client/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['@vue/cli-plugin-babel/preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jovo-starter-web-standalone-client", 3 | "version": "4.0.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "@jovotech/client-web-vue2": "^4.0.0", 12 | "core-js": "^3.6.5", 13 | "vue": "^2.6.14", 14 | "vue-class-component": "^7.2.3", 15 | "vue-property-decorator": "^8.4.2" 16 | }, 17 | "devDependencies": { 18 | "@types/web": "0.0.1", 19 | "@typescript-eslint/eslint-plugin": "^2.33.0", 20 | "@typescript-eslint/parser": "^2.33.0", 21 | "@vue/cli-plugin-babel": "~4.5.0", 22 | "@vue/cli-plugin-eslint": "~4.5.0", 23 | "@vue/cli-plugin-typescript": "~4.5.0", 24 | "@vue/cli-service": "~4.5.0", 25 | "@vue/eslint-config-prettier": "^6.0.0", 26 | "@vue/eslint-config-typescript": "^5.0.2", 27 | "autoprefixer": "^9.8.8", 28 | "eslint": "^6.7.2", 29 | "eslint-plugin-prettier": "^3.1.3", 30 | "eslint-plugin-vue": "^6.2.2", 31 | "postcss": "^7.0.39", 32 | "postcss-custom-properties": "^9.1.1", 33 | "postcss-import": "^12.0.1", 34 | "postcss-nested": "^4.2.3", 35 | "prettier": "^2.4.1", 36 | "tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.17", 37 | "typescript": "^4.4.4", 38 | "vue-template-compiler": "^2.6.14" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovotech/jovo-starter-web-standalone/e1e138bb827cf117db47b3fc9157d5eddc747aaf/client/public/favicon.ico -------------------------------------------------------------------------------- /client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /client/src/App.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 106 | 107 | 116 | -------------------------------------------------------------------------------- /client/src/assets/css/theme.pcss: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap'); 2 | @import 'tailwindcss/base'; 3 | @import 'tailwindcss/components'; 4 | @import 'tailwindcss/utilities'; 5 | -------------------------------------------------------------------------------- /client/src/components/RecordButton.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 109 | -------------------------------------------------------------------------------- /client/src/main.ts: -------------------------------------------------------------------------------- 1 | import JovoWebClientVue, { JovoWebClientVueConfig } from '@jovotech/client-web-vue2'; 2 | import Vue from 'vue'; 3 | import App from './App.vue'; 4 | 5 | Vue.config.productionTip = false; 6 | 7 | Vue.use(JovoWebClientVue, { 8 | endpointUrl: process.env.VUE_APP_CLIENT_ENDPOINT_URL || 'http://localhost:3000/webhook', 9 | config: { 10 | input: { 11 | audioRecorder: { 12 | startDetection: { 13 | enabled: false, 14 | }, 15 | silenceDetection: { 16 | enabled: false, 17 | }, 18 | }, 19 | speechRecognizer: { 20 | lang: 'en', 21 | startDetection: { 22 | enabled: false, 23 | }, 24 | silenceDetection: { 25 | enabled: false, 26 | }, 27 | }, 28 | }, 29 | output: { 30 | reprompts: { 31 | enabled: false, 32 | }, 33 | }, 34 | store: { 35 | shouldPersistSession: false, 36 | }, 37 | }, 38 | }); 39 | 40 | new Vue({ 41 | render: (h) => h(App), 42 | }).$mount('#app'); 43 | -------------------------------------------------------------------------------- /client/src/shims-tsx.d.ts: -------------------------------------------------------------------------------- 1 | import Vue, { VNode } from 'vue'; 2 | 3 | declare global { 4 | namespace JSX { 5 | // tslint:disable no-empty-interface 6 | interface Element extends VNode {} 7 | // tslint:disable no-empty-interface 8 | interface ElementClass extends Vue {} 9 | interface IntrinsicElements { 10 | [elem: string]: any; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /client/src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import Vue from 'vue'; 3 | export default Vue; 4 | } 5 | -------------------------------------------------------------------------------- /client/tailwind.config.js: -------------------------------------------------------------------------------- 1 | const plugin = require('tailwindcss/plugin'); 2 | const selectorParser = require('postcss-selector-parser'); 3 | 4 | module.exports = { 5 | future: { 6 | removeDeprecatedGapUtilities: true, 7 | purgeLayersByDefault: true, 8 | }, 9 | purge: ['./src/**/*.html', './src/**/*.vue', './src/**/*.tsx', './src/**/*.ts'], 10 | theme: { 11 | fontFamily: { 12 | sans: ['Roboto', 'sans-serif'], 13 | }, 14 | extend: { 15 | height: { 16 | '2/6': '33.333333%', 17 | }, 18 | animation: { 19 | 'ripple': 'rippleanimation 0.5s linear infinite', 20 | 'ripple-dark': 'rippleanimation-dark 0.5s linear infinite', 21 | }, 22 | keyframes: { 23 | 'rippleanimation': { 24 | '100%': { 25 | 'box-shadow': 26 | '0 0 0 0.6em rgba(67, 74, 101, 0.3), 0 0 0 0.35em rgba(67, 74, 101, 0.3), 0 0 0 0.125em rgba(67, 74, 101, 0.3), 0 0 0 0 rgba(67, 74, 101, 0.3);', 27 | }, 28 | '0%': { 29 | 'box-shadow': 30 | '0 0 0 1em rgba(67, 74, 101, 0),0 0 0 0.65em rgba(67, 74, 101, 0.3),0 0 0 0.35em rgba(67, 74, 101, 0.3),0 0 0 0.125em rgba(67, 74, 101, 0.3);', 31 | }, 32 | }, 33 | 'rippleanimation-dark': { 34 | '100%': { 35 | 'box-shadow': 36 | '0 0 0 0.6em rgba(255, 255, 255, 0.3), 0 0 0 0.35em rgba(255, 255, 255, 0.3), 0 0 0 0.125em rgba(255, 255, 255, 0.3), 0 0 0 0 rgba(255, 255, 255, 0.3);', 37 | }, 38 | '0%': { 39 | 'box-shadow': 40 | '0 0 0 1em rgba(255, 255, 255, 0),0 0 0 0.65em rgba(255, 255, 255, 0.3),0 0 0 0.35em rgba(255, 255, 255, 0.3),0 0 0 0.125em rgba(255, 255, 255, 0.3);', 41 | }, 42 | }, 43 | }, 44 | }, 45 | boxShadow: { 46 | '2xl': '0 10px 50px -12px rgba(0, 0, 0, 0.25)', 47 | }, 48 | }, 49 | variants: { 50 | backgroundColor: ({ before }) => before(['dark']), 51 | textColor: ({ before }) => before(['dark']), 52 | animation: ({ before }) => before(['dark']), 53 | }, 54 | plugins: [ 55 | plugin(function ({ addVariant, theme, e, prefix }) { 56 | const darkSelector = theme('darkSelector', '.mode-dark'); 57 | 58 | addVariant('dark', ({ modifySelectors, separator }) => { 59 | modifySelectors(({ selector }) => { 60 | return selectorParser((selectors) => { 61 | selectors.walkClasses((sel) => { 62 | sel.value = `dark${separator}${sel.value}`; 63 | sel.parent.insertBefore(sel, selectorParser().astSync(prefix(`${darkSelector} `))); 64 | }); 65 | }).processSync(selector); 66 | }); 67 | }); 68 | }), 69 | ], 70 | }; 71 | -------------------------------------------------------------------------------- /client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "experimentalDecorators": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "sourceMap": true, 14 | "baseUrl": ".", 15 | "types": [ 16 | "webpack-env" 17 | ], 18 | "paths": { 19 | "@/*": [ 20 | "src/*" 21 | ] 22 | }, 23 | "lib": [ 24 | "esnext", 25 | "scripthost" 26 | ] 27 | }, 28 | "include": [ 29 | "src/**/*.ts", 30 | "src/**/*.tsx", 31 | "src/**/*.vue", 32 | "tests/**/*.ts", 33 | "tests/**/*.tsx" 34 | ], 35 | "exclude": [ 36 | "node_modules" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /client/vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parallel: false, 3 | chainWebpack: (config) => { 4 | config.resolve.symlinks(false); 5 | }, 6 | transpileDependencies: ['@jovotech/client-web-vue2', '@jovotech/client-web'], 7 | publicPath: process.env.PUBLICPATH || '', 8 | css: { 9 | loaderOptions: { 10 | postcss: { 11 | // eslint-disable-next-line @typescript-eslint/no-var-requires 12 | plugins: [ 13 | require('postcss-import'), 14 | require('tailwindcss'), 15 | require('postcss-nested'), 16 | require('postcss-custom-properties'), 17 | require('autoprefixer'), 18 | ], 19 | }, 20 | }, 21 | }, 22 | }; 23 | -------------------------------------------------------------------------------- /img/jovo-web-client-to-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovotech/jovo-starter-web-standalone/e1e138bb827cf117db47b3fc9157d5eddc747aaf/img/jovo-web-client-to-app.png -------------------------------------------------------------------------------- /img/starter-web-standalone.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovotech/jovo-starter-web-standalone/e1e138bb827cf117db47b3fc9157d5eddc747aaf/img/starter-web-standalone.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jovo-starter-web-standalone", 3 | "version": "4.0.0", 4 | "private": true, 5 | "scripts": { 6 | "install": "npm run setup", 7 | "setup": "npm run setup:app & npm run setup:client", 8 | "setup:app": "cd app && npm i && cd ..", 9 | "setup:client": "cd client && npm i && cd .." 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/jovotech/jovo-starter-web-standalone.git" 14 | }, 15 | "author": "jovotech", 16 | "license": "Apache-2.0", 17 | "bugs": { 18 | "url": "https://github.com/jovotech/jovo-starter-web-standalone/issues" 19 | }, 20 | "homepage": "https://github.com/jovotech/jovo-starter-web-standalone#readme" 21 | } 22 | --------------------------------------------------------------------------------