{"id":17532775,"url":"https://github.com/helixsoftco/vuelix","last_synced_at":"2025-03-06T12:31:16.291Z","repository":{"id":45881128,"uuid":"431285431","full_name":"helixsoftco/vuelix","owner":"helixsoftco","description":"Vue 3 + Vite template/framework: Auth System + OpenAPI Client Generator + Routes Transitions + i18n + File System Routing + Layouts System + Universal Icons Framework + More!","archived":false,"fork":false,"pushed_at":"2023-04-21T08:29:33.000Z","size":145,"stargazers_count":94,"open_issues_count":4,"forks_count":13,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-21T23:37:28.874Z","etag":null,"topics":["auth","file-system-routing","i18n","layouts","openapi","routing","typescript","universal-icons","vite","vue","vue3"],"latest_commit_sha":null,"homepage":"","language":"Vue","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/helixsoftco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-11-23T23:30:35.000Z","updated_at":"2024-10-17T10:11:23.000Z","dependencies_parsed_at":"2023-01-20T00:03:36.251Z","dependency_job_id":null,"html_url":"https://github.com/helixsoftco/vuelix","commit_stats":null,"previous_names":[],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helixsoftco%2Fvuelix","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helixsoftco%2Fvuelix/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helixsoftco%2Fvuelix/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helixsoftco%2Fvuelix/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/helixsoftco","download_url":"https://codeload.github.com/helixsoftco/vuelix/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242211228,"owners_count":20090231,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auth","file-system-routing","i18n","layouts","openapi","routing","typescript","universal-icons","vite","vue","vue3"],"created_at":"2024-10-20T18:01:42.860Z","updated_at":"2025-03-06T12:31:15.901Z","avatar_url":"https://github.com/helixsoftco.png","language":"Vue","funding_links":[],"categories":["Vue"],"sub_categories":[],"readme":"# Vuelix\n\nVuelix is a Vue 3 + Vite starter template to scaffold new projects really fast and with a great developer experience.\n\n## Table of contents\n\n- [Setup](#setup)\n- [Build](#build)\n- [Features](#features)\n  - [🚀 Vue 3 + Vite 2](#-vue-3--vite-2)\n  - [🦾 TypeScript and SCSS](#-typescript-and-scss)\n  - [🗂 File system routing](#-file-system-routing)\n  - [📑 Layouts system](#-layouts-system)\n  - [🔗 Path Aliasing](#-path-aliasing)\n  - [😃 Universal Icons Framework](#-universal-icons-framework)\n  - [✨ Routes Transitions](#-routes-transitions)\n  - [🪄 Eslint + Prettier](#-eslint--prettier)\n  - [🔧 OpenAPI Client Generator](#-openapi-client-generator)\n  - [👤 Authentication System](#-authentication-system)\n    - [The Auth Plugin](#the-auth-plugin)\n    - [The Navigation Guards](#the-navigation-guards)\n    - [The Axios Interceptors](#the-axios-interceptors)\n  - [🌐 Internationalization: vue-i18n and vue-i18n-extract](#-internationalization-vue-i18n-and-vue-i18n-extract)\n- [Recommended IDE Setup](#recommended-ide-setup)\n- [Deployment](#deployment)\n  - [Heroku](#heroku)\n\n## Setup\n\nInstall Dependencies\n\n```\nnpm install\n```\n\nGenerate API client\n\n```\nnpm run gen-api\n```\n\n\u003e **NOTE:** This command requires a java `jvm` to be installed, if you want to avoid asking all developers to install it\n\u003e check [OpenAPI Client Generator](#-openapi-client-generator) for more info.\n\nStart the development server\n\n```\nnpm run dev\n```\n\n## Build\n\nTo build the app, run\n\n```\nnpm run build\n```\n\nAnd to preview it, after building the app run\n\n```\nnpm run serve\n```\n\n## Features\n\n### 🚀 Vue 3 + Vite 2\n\nThe version 3 of Vue with its powerful **Composition API** is available in this project.\n\nThe new `\u003cscript setup\u003e` SFCs syntax is also available and recommended.\n\nVite is the lightning Fast Next Generation Frontend Tooling that highly improves the development experience along with\nall the community-created plugins.\n\n\u003e **NOTE:** The initial state of this project was generated using Vite oficial scaffolding: `npm init vite@latest`\n\nSee:\n\n- [Vue 3 Docs](https://v3.vuejs.org)\n- [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup)\n- [Vite Docs](https://vitejs.dev/guide/features.html)\n\n### 🦾 TypeScript and SCSS\n\nTypeScript and SCSS languages are supported and strongly recommended.\n\nSee:\n\n- [TypeScript](https://www.typescriptlang.org/)\n- [SCSS](https://sass-lang.com/)\n\n### 🗂 File system routing\n\nRoutes for `vue-router` will be auto-generated from Vue files in the `src/pages` using the file structure.\n\nSee:\n\n- [vite-plugin-pages](https://github.com/hannoeru/vite-plugin-pages)\n\n### 📑 Layouts system\n\nVue components in the `src/layouts` dir are used as layouts.\nBy default, `default.vue` will be used unless an alternative is specified in the route meta.\n\nYou can specify the layout in the page's SFCs like this:\n\n```vue\n\u003croute lang=\"yaml\"\u003e\nmeta:\n  layout: home\n\u003c/route\u003e\n```\n\nSee:\n\n- [vite-plugin-vue-layouts](https://github.com/JohnCampionJr/vite-plugin-vue-layouts)\n- [vite-plugin-pages](https://github.com/hannoeru/vite-plugin-pages)\n\n### 🔗 Path Aliasing\n\n`@/` is aliased to the `./src/` folder.\n\nFor example, instead of having\n\n```ts\nimport HelloWorld from '../../../components/HelloWorld.vue'\n```\n\nyou can use\n\n```ts\nimport HelloWorld from '@/components/HelloWorld.vue'\n```\n\n### 😃 Universal Icons Framework\n\nUse icons from any icon set, one syntax for all icons: Material Design Icons, Bootstrap Icons, Font Awesome, etc.\nAll icons libraries are available powered by [iconify](https://iconify.design/) and [unplugin-icons](https://github.com/antfu/unplugin-icons). And don't worry, **only** the icons you use would be included in the final bundle,\nkeeping the production build lightweight.\n\nThe usage is simple, if you want for instance a Material Design Icon (mdi) with name \"thumb-up\",\nthen just place this inside your template:\n\n```html\n\u003ci-mdi-thumb-up /\u003e\n```\n\nJust by placing it, the `unplugin-icons/resolver` would look for the corresponding icon and in case the related\niconify icon set is not installed, it would automatically install it using `npm`, e.g. `@iconify-json/mdi`.\n\nThe convention to use icons is as follows:\n\n```\n{prefix}-{collection}-{icon}\n```\n\nWhere the `prefix` is \"i\", the `collection` is the collection ID from https://icon-sets.iconify.design/,\nand finally the `icon` is the icon name.\n\nSee:\n\n- [unplugin-icons](https://github.com/antfu/unplugin-icons)\n- [iconify](https://iconify.design/)\n- [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components)\n- [Icônes - to search for icons available in iconify](https://icones.js.org/)\n\n### ✨ Routes Transitions\n\nRoute changes are animated. By default, the `fade` transition will be used unless an alternative is specified in the route meta.\n\nThe `fade` and `slide-fade` transitions are available.\nYou can specify the transition in the page's SFCs like this:\n\n```vue\n\u003croute lang=\"yaml\"\u003e\nmeta:\n  transition: slide-fade\n\u003c/route\u003e\n```\n\n\u003e _NOTE:_ Transitions are not triggered between routes of the same type, therefore changing the parameters of the active route won't cause a route transition. This could be changed by using the `route.fullPath` instead of `route.name` as the key in [RouterViewTransition.vue](./src/components/RouterViewTransition.vue). More info: https://stackoverflow.com/a/70042452/4873750.\n\n\u003e Route transitions can be deactivated by changing the provided `enable-route-transitions` value in [main.ts](./src/main.ts).\n\nSee:\n\n- [RouterViewTransition.vue](./src/components/RouterViewTransition.vue)\n\n### 🪄 Eslint + Prettier\n\nThis project comes with the recommended Eslint configuration for Vue 3 plus integration with Prettier.\nPrettier helps formatting code while Eslint helps catching bugs in development.\n\nWhen opening the project in VSCode, it will ask the developers to install Eslint and Prettier, because that way\nthe VSCode [settings.json](.vscode/settings.json) will work and therefore both Prettier and Eslint fix will be\nexecuted when saving a file.\n\nAditionally, commands to lint, check and autoformat code are available in the scripts of [package.json](./package.json)\n\nSee:\n\n- [Eslint](https://eslint.org/)\n- [Prettier](https://prettier.io/docs/en/comparison.html)\n- [eslint-plugin-vue](https://eslint.vuejs.org/)\n- [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier)\n- [vue-eslint-parser](https://github.com/vuejs/vue-eslint-parser)\n\n### 🔧 OpenAPI Client Generator\n\nManually creating an API client is hard to maintain and time demanding,\nbut thanks to OpenAPI and its generators we can now generate the entire API client from an `OpenAPI Spec`.\n\nTo do so just place your spec in `spec/schema.yml`, then run:\n\n```\nnpm run gen-api\n```\n\nWhich would generate the API client in Typescript and place the generated code in `src/api-client`.\n\n\u003e **NOTE:** This command requires `java` to be installed, because the OpenAPI generator is built with it, if you\n\u003e want to avoid asking all developers to install a `jvm` and run this command by themselves, just run it once you change\n\u003e the OpenAPI spec, and commit the generated code, for that you need to remove the `/src/api-client` line from the `.gitignore`.\n\u003e The reason we exclude the generated client by default if because it can always be generated from the spec (`spec/schema.yml`), and because\n\u003e the spec file is actually versioned, then the code reviewing is improved by checking only spec changes and not the generated code that nobody wrotes.\n\n\u003e **INFO:** If you have a Mac with an M1 Chip, this page have the correct `OpenJDK` installers for you: https://www.azul.com/downloads/?os=macos\u0026architecture=arm-64-bit\n\nTo use the generated APIs just initialize them and make it available for the rest of the application.\nThe following is an example using Swagger Demo PetStore API:\n\n```ts\n// \"api/index.ts\"\nimport { PetApi } from '@/api-client'\nexport const petApi = new PetApi()\n```\n\nYou can also configure the APIs parameters like `basePath` and provide your own `axios` instance with interceptors configured like this:\n\n```ts\n// \"api/index.ts\"\nimport { PetApi } from '@/api-client'\nimport { Configuration } from '@/api-client/configuration'\nimport axiosInstance from './axios'\n\n// See Vite env vars: https://vitejs.dev/guide/env-and-mode.html\nconst config = new Configuration({ basePath: import.meta.env.BASE_URL })\nexport const petApi = new PetApi(config, undefined, axiosInstance)\n```\n\nThen in your Vue Components:\n\n```html\n\u003c!-- \"pages/home.vue\" --\u003e\n\u003cscript setup lang=\"ts\"\u003e\n  import { petApi } from '@/api'\n  import { Pet, PetStatusEnum } from '@/api-client'\n  import { ref } from 'vue'\n\n  const pets = ref\u003cPet[]\u003e()\n  const loading = ref(false)\n\n  async function testOpenAPI() {\n    loading.value = true\n    const { data } = await petApi.findPetsByStatus({ status: [PetStatusEnum.Available] })\n    pets.value = data.slice(0, 10)\n    loading.value = false\n  }\n\u003c/script\u003e\n```\n\nSee:\n\n- [OpenAPI Specification](https://swagger.io/docs/specification/about/)\n- [OpenAPI Generator](https://openapi-generator.tech/)\n- [OpenAPI Generator CLI](https://github.com/openapitools/openapi-generator-cli)\n- [OpenAPI typescript-axios generator](https://openapi-generator.tech/docs/generators/typescript-axios)\n\n### 👤 Authentication System\n\nThe auth system consist on three main parts:\n\n- The Plugin\n- The Navigation Guards\n- The Axios Interceptors\n\n#### The Auth Plugin\n\nThe plugin is installed in Vue's `globalProperties` with the name `$auth`, it includes an `isAuthenticated` property,\nan `user` object, an `accessToken` plus the `login` and `logout` functions. It can be used in templates like this:\n\n```html\n\u003cspan v-if=\"$auth.isAuthenticated\"\u003e\n  Authenticated as \u003cb\u003e{{ $auth.user.email }}\u003c/b\u003e\n  \u003cbutton @click=\"$auth.logout\"\u003eLogout\u003c/button\u003e\n\u003c/span\u003e\n\u003cspan v-else\u003eNot Authenticated\u003c/span\u003e\n```\n\nThe `auth` instance is created using the composition API, therefore we can alternatively retrieve it outside of\ncomponents with the `useAuth` function:\n\n```ts\nimport { useAuth } from './useAuth'\n\nconst auth = useAuth()\nif (auth.isAuthenticated) {\n  console.log(auth.userFullName)\n}\n```\n\n```html\n\u003cscript setup lang=\"ts\"\u003e\n  import { useAuth } from './useAuth'\n  import { watchEffect } from 'vue'\n\n  const auth = useAuth()\n  watchEffect(() =\u003e {\n    console.log(auth.isAuthenticated)\n  })\n\u003c/script\u003e\n```\n\nAditionally, the auth plugin can be inspected in the **Vue's Devtools panel** when having the extension in the browser.\nThe plugin's values are displayed when inspecting any component.\n\n#### The Navigation Guards\n\nThe navigation guards protects pages from non-authenticated users and redirect them to the login page,\nby default **all** pages but the `login` page are protected.\n\nIn order to make a page available for non-authenticated users, a route meta boolean called `public` needs to be\nconfigured in the page. E.g:\n\n```vue\n\u003c!-- pages/index.html --\u003e\n\u003croute lang=\"yaml\"\u003e\nmeta:\n  public: true\n\u003c/route\u003e\n```\n\nThe navigation guards can be disabled by changing the `autoConfigureNavigationGuards` when configuring the auth system:\n\n```ts\n// main.ts\nimport { createApp } from 'vue'\nimport { createAuth } from './auth'\nimport App from './App.vue'\nimport router from './router'\n\nconst auth = createAuth({\n  router,\n  loginRouteName: 'login',\n  autoConfigureNavigationGuards: false,\n})\n\nconst app = createApp(App)\napp.use(router)\napp.use(auth)\n```\n\n#### The Axios Interceptors\n\nThe axios interceptors helps appending auth information to requests and responses of APIs.\n\nThe main interceptor adds the `Authorization` header with a value of `Bearer the-token-value` to all authenticated requests.\n\nThis can be configured and disabled in the `createAuth` options:\n\n```ts\n// api/axios.ts\nimport axios from 'axios'\n\nconst axiosInstance = axios.create()\nexport default axiosInstance\n```\n\n```ts\n// main.ts\nimport { createApp } from 'vue'\nimport { createAuth } from './auth'\nimport App from './App.vue'\nimport router from './router'\nimport axiosInstance from './api/axios'\n\nconst auth = createAuth({\n  router,\n  axios: {\n    instance: axiosInstance,\n    autoAddAuthorizationHeader: true, // default: false\n    authorizationHeaderPrefix: 'Token', // default: 'Bearer'\n  },\n})\n\nconst app = createApp(App)\napp.use(router)\napp.use(auth)\n```\n\nSee:\n\n- [Auth System](./src/auth)\n- [Vue Router - Navigation Guards](https://next.router.vuejs.org/guide/advanced/navigation-guards.html)\n- [Axios - Interceptors](https://github.com/axios/axios#interceptors)\n- [Vue Devtools - Plugin Registration](https://devtools.vuejs.org/plugin/plugins-guide.html#registering-your-plugin)\n\n### 🌐 Internationalization: vue-i18n and vue-i18n-extract\n\nThe `vue-i18n` package is used as the internationalization system.\n\nAll translation files located in the `locales` dir are loaded automatically with the corresponding language code obtained from the file name, e.g. `locales/es.json` -\u003e lang code: `es`.\n\n**How to use it?**\n\nPut the texts in the original language inside the function of vue-i18n, for example:\n\n```html\n\u003c!-- Single or double quote, and template literals --\u003e\n\u003cp\u003e{{ $t('Hello World') }} {{ $t(\"Hello, how are you?\") }} {{ $t(`Hey. I'm watching you!`) }}\u003c/p\u003e\n\n\u003c!-- *Note: to be able to use it in tags or when we send text to a component, we must use the single quote format\nand bind it to the attribute. --\u003e\n\n\u003cMyComponent :text=\"$t('example text')\" /\u003e\n\n\u003cb-form-input v-model=\"name\" type=\"text\" :placeholder=\"$t('Name')\"\u003e\u003c/b-form-input\u003e\n\n// In TS:\n\u003cscript setup lang=\"ts\"\u003e\n  import { useI18n } from 'vue-i18n'\n\n  const { t } = useI18n()\n  t('This is an example')\n\u003c/script\u003e\n```\n\nYou may have noticed that we don't use translations keys like: `greetings.hello`, the reason is that defining keys is a troublesome task, and keys doesn't always show what we want to display, take this translation file for example:\n\n```js\n// es.json\n\n{\n  \"greetings\": {\n    \"hello\": \"Hola, ¿cómo estás?.\"\n  }\n}\n```\n\nAnd the corresponding translation usage:\n\n```js\n// Component.vue\n\nt('greetings.hello')\n```\n\nBy just looking at the translation key, we won't know what the original text was, now look a this example:\n\n```js\n// es.json\n\n{\n  \"Hello, how are you?\": \"Hola, ¿cómo estás?.\"\n}\n```\n\n```js\n// Component.vue\n\n$t('Hello, how are you?')\n```\n\nBetter right?, we can directly see the original text, and it's much simpler to translate, we also won't need to define keys because **the original text is the key!**.\n\n**Browser language detection**\n\nThe default language would match the language of the browser,\nin case the language is not supported by the application, the fallback language `en` would be activated.\n\n**Vue i18n extract**\n\nManually extracting the texts from vue or js,ts files is a complex task, we are often lazy to do so or we forget to add them, therefore we lose the sync between the translations files and the source code, that's why we use `vue-i18n-extract`, a handy tool that runs static analysis of the source code files and extracts the translation texts from the source code and add them to the translations files like `es.json`, `en.json`, `de.json`, etc. It no only adds the missing keys but also with a command we can remove the no longer used translations.\n\nTo extract the keys/original text into the translations files, run:\n\n```\nnpm run vue-i18n-extract\n```\n\nThis executes the command located in `package.json`, which will search for the keys in the vue files given, compare it with the files inside the lang folder and if it finds new words, it will add them.\n\nThis script uses the [vue-i18n-extract.config.js](./vue-i18n-extract.config.js) file for its configuration. This file is located in the root of the project.\n\n**Adding a new language:**\n\nTo add a new language, for instance the German language, just create its file inside the `locales` folder using its language code, example: `./locales/de.json`. Then run `npm run vue-i18n-extract` to populate the translation keys into that file.\n\n\u003e _IMPORTANT_: When creating the file, make it a valid JSON file, then at least it must has `{}`, otherwise the extraction would fail.\n\nExample:\n\n```js\n// locales/es.json\n\n{\n}\n```\n\nThe file would be loaded automatically by `vite`, a vite restart may be needed.\n\n**Removing unused translations**\n\nIn case you want to remove the keys that are in the translation files but are not being used in the vue files, you can run:\n\n```\nnpm run vue-i18n-extract-remove\n```\n\nSee:\n\n- [Vue i18n](https://vue-i18n.intlify.dev/)\n- [Vue i18n extract](https://github.com/pixari/vue-i18n-extract)\n- [i18n plugin](./src/plugins/i18n.ts)\n\n## Recommended IDE Setup\n\n- [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar) + [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) + [Eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)\n\n## Deployment\n\n### Heroku\n\nIn Heroku create the app, then configure the following buildpacks in the same order:\n\n- heroku/jvm\n- heroku/nodejs\n- heroku-community/static\n\nConfig the Heroku remote:\n\n```\nheroku login\nheroku git:remote -a \u003capp_name\u003e\n```\n\nFinally, push the changes:\n\n```\ngit push heroku main\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhelixsoftco%2Fvuelix","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhelixsoftco%2Fvuelix","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhelixsoftco%2Fvuelix/lists"}