quasarframework/quasar Tags: legacy: 1.22.10, latest: 2.19.3 References: Docs API Changes This section documents version-specific API changes — prioritize recent major/minor releases. - BREAKING: - uses + instead of + in Vue 3 source - BREAKING: / / / - use and attributes instead of / props source - BREAKING: - completely redesigned, removed and props; renamed to source - BREAKING: - methods returns ; and require parameter source - BREAKING: - renamed prop to to avoid TS naming conflicts source - BREAKING: - all boolean properties now explicitly instead of since v2.17.0 source - BREAKING: uti…

\n )\n\n+/**\n+ * \u003c\u003c| lang [attrs] [title] |>>\n+ * ...content...\n+ */\n const tabsLineRE = new RegExp(\n '^\u003c\u003c\\\\|\\\\s+' + // starts with \"\u003c\u003c|\" + at least one space char\n `(?\u003clang>${ langMatch })` + // then a language name\n@@ -72,29 +84,65 @@ function extractTabs (content) {\n const props = tabMap[ tabName ]\n return (\n `\u003cq-tab-panel class=\"q-pa-none\" name=\"${ tabName }\">` +\n- `\u003cpre v-pre class=\"doc-code\">${ highlight(props.content.join('\\n'), props.attrs) }\u003c/pre>` +\n- '\u003ccopy-button />' +\n+ highlight(props.content.join('\\n'), props.attrs) +\n '\u003c/q-tab-panel>'\n )\n }).join('\\n')\n }\n }\n\n-function highlight (content, attrs) {\n- const { lang, numbered } = attrs\n- const highlightedText = prism.highlight(content, prism.languages[ lang ], lang)\n+const magicCommentRE = / *\\/\\/\\[! (?\u003cklass>[\\w-]+)\\] */\n+const magicCommentGlobalRE = new RegExp(magicCommentRE, 'g')\n\n- if (numbered === true) {\n- const lines = highlightedText.split('\\n')\n- const lineCount = ('' + highlightedText.length).length\n+function getLineClasses (content, highlightedLines) {\n+ const lines = content.split('\\n')\n```\n\n```tabs\n\u003c\u003c| js [numbered] Config file |>>\nexport default function (ctx) { // can be async too\n console.log(ctx)\n\n // Example output on console:\n {\n dev: true,\n prod: false\n }\n\n const { FOO } = process.env // ❌ It doesn't allow destructuring or similar\n process.env.FOO // ✅ It can only replace direct usage like this\n\n // context gets generated based on the parameters\n // with which you run \"quasar dev\" or \"quasar build\"\n}\n\u003c\u003c| js Other file |>>\nconst x = {\n dev: true,\n prod: false\n}\n```\n\n```tabs quasar.config file\n\u003c\u003c| js One |>>\nexport default function (ctx) { // can be async too\n console.log(ctx)\n\n // Example output on console:\n {\n dev: true,\n prod: false\n }\n\n const { FOO } = process.env // ❌ It doesn't allow destructuring or similar\n process.env.FOO // ✅ It can only replace direct usage like this\n\n // context gets generated based on the parameters\n // with which you run \"quasar dev\" or \"quasar build\"\n}\n\u003c\u003c| js [numbered] Two (numbered) |>>\nconst x = {\n dev: true,\n prod: false\n}\n\u003c\u003c| diff Three (with diff) |>>\n{\n min: 0\n- super: false\n+ super: true\n max: 100\n}\n```\n\n## Tree\n\n\u003cDocTree :def=\"scope.tree\" />\n\n## Table\n\n| Prop name | Description |\n| ------------ | ----------------------------------------------------------------------------------------------------------------- |\n| `app` | Vue app instance |\n| `router` | Instance of Vue Router from 'src/router/index.js' |\n| `store` | Instance of Pinia - **store only will be passed if your project uses Pinia (you have src/stores)** |\n| `ssrContext` | Available only on server-side, if building for SSR. [More info](/quasar-cli-vite/developing-ssr/ssr-context) |\n| `urlPath` | The pathname (path + search) part of the URL. It also contains the hash on client-side. |\n| `publicPath` | The configured public path. |\n| `redirect` | Function to call to redirect to another URL. Accepts String (full URL) or a Vue Router location String or Object. |\n\n## List\n\nLorem ipsum dolor sit amet, **consectetur adipiscing** elit, sed do _eiusmod_ tempor incididunt ut labore et dolore magna aliqua.\n\n1. Quasar is initialized (components, directives, plugins, Quasar i18n, Quasar icon sets)\n2. Quasar Extras get imported (Roboto font -- if used, icons, animations, ...)\n3. Quasar CSS & your app's global CSS are imported\n4. App.vue is loaded (not yet being used)\n5. Store is imported (if using Pinia in src/stores)\n6. Pinia (if using) is injected into the Vue app instance\n7. Router is imported (in src/router)\n\nLorem ipsum dolor sit amet, **consectetur adipiscing** elit, sed do _eiusmod_ tempor incididunt ut labore et dolore magna aliqua.\n\n- It is important that you specify all sections of a QLayout, even if you don't use them. For example, even if you don't use footer or right side drawer, still specify them within your QLayout's `view` prop.\n- When QDrawer is set into overlay mode, **it will force it to go into fixed position**, regardless if QLayout's \"view\" prop is configured with \"l/r\" or \"L/R\". Also, **if on iOS platform and QLayout is containerized**, the fixed position will also be forced upon QDrawer due to platform limitations that cannot be overcome.\n\nLorem ipsum dolor sit amet, **consectetur adipiscing** elit, sed do _eiusmod_ tempor incididunt ut labore et dolore magna aliqua.\n\n\u003cDocInstallation plugins=\"AppFullscreen\" />\n\n\u003cDocApi file=\"QSelect\" />\n\n\u003cDocApi file=\"TouchSwipe\" />\n\n\u003cDocApi file=\"Loading\" />\n\n\u003cDocExample title=\"Title for example card\" file=\"StandardSizes\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":17952,"content_sha256":"820a49df60f577ecc0ae9a481a2fcb6c1c4a2c43c82b693b2dd44809c8bf9a0b"},{"filename":"references/docs/_INDEX.md","content":"---\ntotal: 387\n---\n\n# Docs Index\n\n- [Design Elements](./__elements.md): Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam...\n- [Documentation](./docs.md)\n- [Why Donate?](./why-donate.md): Quasar Framework is an MIT-licensed open-source project maintained by Razvan Stoenescu along with his Team and a community of open source contribut...\n\n## api-explorer (1)\n\n- [Quasar API Explorer](./api-explorer/api-explorer.md): Here you can explore the API for all the Quasar UI Vue components, Vue directives & Quasar UI plugins.\n\n## app-extensions/development-guide (5)\n\n- [App Extension Index API](./app-extensions/development-guide/index-api.md): This page refers to src/index.js file, which is executed on quasar dev and quasar build. This is the main process where you can modify the build to...\n- [App Extension Install API](./app-extensions/development-guide/install-api.md): This page refers to src/install.js file which is executed on the installation of the App Extension only. Not all App Extensions will need an instal...\n- [App Extension Development](./app-extensions/development-guide/introduction.md): This section of the docs deals with creating your own App Extensions.\n- [App Extension Prompts API](./app-extensions/development-guide/prompts-api.md): This page refers to src/prompts.js file which handles the prompts when installing the App Extension. Not all App Extensions will need prompts -- th...\n- [App Extension Uninstall API](./app-extensions/development-guide/uninstall-api.md): This page refers to src/uninstall.js file which is executed when the App Extension is uninstalled. Not all App Extensions will need an uninstall --...\n\n## app-extensions (2)\n\n- [Discover App Extensions](./app-extensions/discover.md): Review submitted Community App Extensions.\n- [App Extensions](./app-extensions/introduction.md): App Extensions are a way to painlessly inject complicated (or simple) libraries with a variety of dependencies, boot files, templates and custom lo...\n\n## app-extensions/tips-and-tricks (7)\n\n- [Chain Webpack](./app-extensions/tips-and-tricks/chain-webpack.md): This guide is for when you want to ensure that a Webpack Loader is chained into the hosting app, because you depend on it for your own App Extensio...\n- [Injecting Quasar Plugin](./app-extensions/tips-and-tricks/inject-quasar-plugin.md): This guide is for when you want to ensure that a Quasar Plugin will be injected into the hosting app, because you depend on it for your own App Ext...\n- [App Extension tips & tricks introduction](./app-extensions/tips-and-tricks/introduction.md): These documentation pages will help you with information or formulae on how to do some of the things with a Quasar App Extension. Make sure you als...\n- [Quasar JSON API Schema](./app-extensions/tips-and-tricks/json-api.md): This page describes the JSON API Schema used for component App Extensions.\n- [Providing a directive](./app-extensions/tips-and-tricks/provide-a-directive.md): This guide is for when you want to create a new directive and provide it through an App Extension, which will inject it into the hosting app.\n- [Provide a UI component](./app-extensions/tips-and-tricks/provide-a-ui-component.md): This guide is for when you want to create a new UI component and provide it through an App Extension, which will inject it into the hosting app.\n- [Starter kit equivalent](./app-extensions/tips-and-tricks/starter-kit-equivalent.md): This guide is for when you want to create what essentially is a \"starter kit\" that adds stuff (/quasar.config file configuration, folders, files, C...\n\n## components (1)\n\n- [Quasar Components](./components/components.md)\n\n## how-to-contribute (5)\n\n- [Commit Conventions](./how-to-contribute/commit-conventions.md): ::: warning\nThis rule applies to ALL Quasar repositories.\n:::\n- [Contribution Guide](./how-to-contribute/contribution-guide.md): This guide covers ways in which you can become a part of the ongoing development of Quasar.\n- [How-to Start a New Project](./how-to-contribute/new-project.md): You have a great new idea which is in line with the Quasar vision. Great, here is how to make it happen!\n- [The Role of the Project Maintainer](./how-to-contribute/project-maintainer.md): More info - Best Practices for Maintainers\n- [Active Project, Goals and Maintainers](./how-to-contribute/running-projects.md): | Project | Responsibility | Maintainer | Repo, Links ...\n\n## icongenie (5)\n\n- [App Icons List](./icongenie/app-icons-list.md): Each Quasar CLI mode requires its own list of icons and splash screens.\nThese are taken care of by Icon Genie through its generate command.\n- [Icon Genie CLI Command List](./icongenie/command-list.md): Familiarize yourself with the list of available Icon Genie CLI commands inside a Quasar project folder:\n- [Icon Genie CLI Installation](./icongenie/installation.md): Make sure that you have Node.js >=16 installed on your machine.\n- [Icon Genie CLI](./icongenie/introduction.md): You love the default Quasar logo, probably as much as the team does, but you just spent what feels like a lifetime making your own pixel-perfect re...\n- [Icon Genie Profile Files](./icongenie/profile-files.md): If you need to automate the creation of all your app's icons and splash screens, Icon Genie offers configuration files which can be run in batch.\n\n## integrations (1)\n\n- [Quasar Integrations](./integrations/integrations.md)\n\n## introduction-to-quasar (1)\n\n- [Why Quasar?](./introduction-to-quasar/introduction-to-quasar.md): Because it saves development costs drastically. Only Quasar can do:\n\n## layout (6)\n\n- [Layout Drawer](./layout/drawer.md): QLayout allows you to configure your views as a 3x3 matrix, containing optional left-side and/or right-side Drawers. If you haven’t already, please...\n- [Layout Header and Footer](./layout/header-and-footer.md): QLayout allows you to configure your views as a 3x3 matrix, containing an optional Header and/or Footer (mostly used for navbar, but can be anythin...\n- [Layout QPageScroller](./layout/page-scroller.md): The QPageScroller component helps in placing DOM elements / components wrapped by it into a static position within the content area of your QPage, ...\n- [Layout QPageSticky](./layout/page-sticky.md): The QPageSticky component helps in placing DOM elements / components wrapped by it into a static position within the content area of your QPage, no...\n- [Layout Page](./layout/page.md): We will be talking about encapsulating pages within a QLayout. If you haven’t already, please read QLayout documentation page first.\n- [Routing with Layouts and Pages](./layout/routing-with-layouts-and-pages.md): You can benefit from Vue Router's capabilities while structuring your routes with a Quasar Layout. The information below is just a recommendation a...\n\n## layout/gallery (1)\n\n- [Layout Gallery](./layout/gallery/gallery.md): As a way to help you get started quicker, we've written a few ready Quasar Layouts for you. Please also take time to learn each Quasar component, o...\n\n## layout/grid (5)\n\n- [Grid Column](./layout/grid/column.md): In the hope that you've previously read the Introduction to Flexbox theory, let's get deeper into Columns.\n- [Flexbox Patterns](./layout/grid/flexbox-patterns.md): Here are some common patterns for using Flexbox. Some more info can be found at Tobias Ahlin Blog.\n- [Grid Gutter](./layout/grid/gutter.md): In the hope that you've previously read the Introduction to Flexbox theory, let's get deeper into Gutters.\n- [Introduction to Flexbox](./layout/grid/introduction-to-flexbox.md): Quasar provides lots of CSS classes to help you build your UI easily with the help of Flexbox. Think of it like operating with rows and columns wit...\n- [Grid Row](./layout/grid/row.md): In the hope that you've previously read the Introduction to Flexbox theory, let's get deeper into Rows.\n\n## layout/grid/flex-playground (1)\n\n- [Flex Grid Playground](./layout/grid/flex-playground/flex-playground.md): To help you understand the Flexbox better, we have written an interactive playground for you. Create your grid and then copy the values to your pro...\n\n## layout/layout (1)\n\n- [Layout](./layout/layout/layout.md): The QLayout is a component designed to manage the entire window and wrap page content with elements such as a navigational bar or a drawer. Multipl...\n\n## meet-the-team (1)\n\n- [Meet the Team](./meet-the-team/meet-the-team.md): Hailing from all around the planet, the Quasar Team is not only international but full of people with a vast range of fields of expertise. From rea...\n\n## options (12)\n\n- [Animations](./options/animations.md): CSS Transitions can be handled by the Vue Transition Component. The transitions are used for entering (appearing) or leaving (disappearing) animati...\n- [App Icons](./options/app-icons.md): If you were to target all platforms that Quasar currently supports, you will need to make 100+ different files of 4 different media types (png, ico...\n- [App Internationalization (i18n)](./options/app-internationalization.md): Internationalization is a design process that ensures a product (a website or application) can be adapted to various languages and regions without ...\n- [Global node generation](./options/global-node.md): You can define custom className for this global node elements.\n- [Installing Icon Libraries](./options/installing-icon-libraries.md): ::: tip\nThis page refers to using webfont icons only. Svg icons do not need any installation step.\n:::\n- [Platform Detection](./options/platform-detection.md): Helpers are built into Quasar to detect the Platform (and its capabilities) within the context of which the code is running.\n- [Quasar Icon Sets](./options/quasar-icon-sets.md): Quasar components have their own icons. Rather than forcing you into using one icon library in particular (so that they can display correctly), Qua...\n- [Quasar Language Packs](./options/quasar-language-packs.md): A Quasar Language Pack refers to the internationalization of Quasar's own components, some of which have labels.\n- [RTL Support](./options/rtl-support.md): RTL is referring to \"right to left\" UI for languages that need it.\n- [Screen Plugin](./options/screen-plugin.md): The Quasar Screen plugin allows you to have a dynamic and responsive UI when dealing with your Javascript code. When possible, it is recommended to...\n- [SEO with Quasar](./options/seo.md): The term SEO refers to Search Engine Optimization. And Quasar covers this aspect too through the Quasar Meta Plugin.\n- [The $q object](./options/the-q-object.md): Quasar supplies a $q object that you can use for various purposes. You will notice it throughout the docs.\n\n## options/transitions (1)\n\n- [Quasar Components Transitions](./options/transitions/transitions.md): There are a few Quasar components that implement transitions through transition-show / transition-hide or transition-prev / transition-next or simp...\n\n## quasar-cli-vite (22)\n\n- [Ajax Requests](./quasar-cli-vite/ajax-requests.md): If you haven't selected Axios during the project initialization then you should create a new boot file axios.js that looks like this:\n(Here you can...\n- [API Proxying for Dev](./quasar-cli-vite/api-proxying.md): When integrating a project folder (created by Quasar CLI) with an existing backend, a common need is to access the backend API when using the dev s...\n- [Boot files](./quasar-cli-vite/boot-files.md): A common use case for Quasar applications is to run code before the root Vue app instance is instantiated, like injecting and initializing your own...\n- [Browser compatibility](./quasar-cli-vite/browser-compatibility.md): In order to configure the browser compatibility for your app, you will need to edit the /quasar.config file:\n- [Commands List](./quasar-cli-vite/commands-list.md): Familiarize yourself with the list of available commands inside a Quasar project:\n- [Convert project to Quasar CLI with Vite](./quasar-cli-vite/convert-to-quasar-cli-with-vite.md): This page will guide you on how to convert a Quasar CLI with Webpack (@quasar/app-webpack v4) project into a Quasar CLI with Vite one (@quasar/app-...\n- [CSS Preprocessors](./quasar-cli-vite/css-preprocessors.md): Sass or SCSS (recommending any of the two flavours) are the out of the box supported css preprocessors through Quasar CLI, should you want to use t...\n- [Developing Mobile Apps](./quasar-cli-vite/developing-mobile-apps.md): Quasar offers two solutions for creating mobile apps:\n- [Directory Structure](./quasar-cli-vite/directory-structure.md): This is the structure of a project with all modes installed. There's no reason to be intimidated though!\n- [App Handling Assets](./quasar-cli-vite/handling-assets.md): You will notice in the project structure we have two directories for assets: /public/ and /src/assets/. What is the difference between them? Some a...\n- [Handling process.env](./quasar-cli-vite/handling-process-env.md): Using process.env can help you in many ways:\n- [Handling Vite](./quasar-cli-vite/handling-vite.md): The build system uses Vite to create the UI of your website/app (/src folder). Don't worry if you aren't acquainted with Vite. Out of the box, you ...\n- [Lazy Loading / Code Splitting](./quasar-cli-vite/lazy-loading.md): When your website/app is small, you can load all layouts/pages/components into the initial bundle and serve everything at startup. But when your co...\n- [Linter](./quasar-cli-vite/linter.md): Having a code linter (like ESLint v9+) in place is highly recommended and ensures your code looks legible. It also helps you capture some errors be...\n- [Opening Your Dev Server to the Public](./quasar-cli-vite/opening-dev-server-to-public.md): At some point you may want to show someone else the project you've been working on. Fortunately, there are a couple of good tools to accomplish thi...\n- [PreFetch Feature](./quasar-cli-vite/prefetch-feature.md): The PreFetch is a feature (only available when using Quasar CLI) which allows the components picked up by Vue Router (defined in /src/router/routes...\n- [Configuring quasar.config file](./quasar-cli-vite/quasar-config-file.md): Notice that your scaffolded project folder contains a /quasar.config file. So what can you configure through it? Basically anything that Quasar CLI...\n- [App Routing](./quasar-cli-vite/routing.md): You'll notice that your Quasar project contains a /src/router folder. This holds the routing configuration of your website/app:\n- [State management with Pinia](./quasar-cli-vite/state-management-with-pinia.md): In large applications, state management often becomes complex due to multiple pieces of state scattered across many components and the interactions...\n- [Supporting TypeScript](./quasar-cli-vite/supporting-ts.md): If you didn't select TypeScript support when creating your project, you can still add it later. This guide will show you how to add TypeScript supp...\n- [Testing & Auditing](./quasar-cli-vite/testing-and-auditing.md): Your Quasar projects have the ability to add unit and e2e testing harnesses. This introduction will not go into details about how to write and use ...\n- [Upgrade Guide for Quasar CLI with Vite](./quasar-cli-vite/upgrade-guide.md): You might want to release new versions of your Quasar App Extensions with support for the new @quasar/app-vite. If you are not touching the quasar....\n\n## quasar-cli-vite/developing-browser-extensions (9)\n\n- [App Icons for (BEX)](./quasar-cli-vite/developing-browser-extensions/app-icons-browser-extension.md): This build target includes the icons required for browser extensions. You need all of them - and if you discover one that is new or missing, please...\n- [Background Script](./quasar-cli-vite/developing-browser-extensions/background-script.md): The background script runs in the context of the BEX itself and can listen to all available browser extension events.\n- [BEX Bridge Communication](./quasar-cli-vite/developing-browser-extensions/bex-bridge.md): Allowing a Quasar App to communicate with the various parts of the BEX is essential. Quasar closes this gap using a bridge.\n- [BEX Build Commands](./quasar-cli-vite/developing-browser-extensions/build-commands.md): Start developing a Browser Extension with just one command.\n- [Configuring BEX](./quasar-cli-vite/developing-browser-extensions/configuring-bex.md): Before we can configure anything, we need to understand how the BEX is structured. A BEX can be one (or more) of the following:\n- [Content Scripts](./quasar-cli-vite/developing-browser-extensions/content-scripts.md): The content script(s) run in the context of the web page. There will be a new content script instance per tab running the extension.\n- [What is a Browser Extension](./quasar-cli-vite/developing-browser-extensions/introduction.md): A Browser Extension (BEX) is an application that runs in the browsers context and is used to customize the web browser in some way.\n- [Preparation for BEX](./quasar-cli-vite/developing-browser-extensions/preparation.md): The difference between building a SPA, Mobile App, Electron App, BEX or SSR is simply determined by the \"mode\" parameter in \"quasar dev\" and \"quasa...\n- [Types of BEX](./quasar-cli-vite/developing-browser-extensions/types-of-bex.md): As already discussed, Quasar can handle the various places where a browser extension can live, namely New Tab, Web Page, Dev Tools Options or Popup...\n\n## quasar-cli-vite/developing-capacitor-apps (11)\n\n- [App Icons for Capacitor](./quasar-cli-vite/developing-capacitor-apps/app-icons-capacitor.md): Capacitor is one of the most complicated of all of the build targets as far as icons go, because not only do you need to place the icons in specifi...\n- [Capacitor Build Commands](./quasar-cli-vite/developing-capacitor-apps/build-commands.md): It will open the IDE (Android Studio / Xcode) and from there you can manually select the emulator (or multiple ones simultaneously!) and install th...\n- [Capacitor APIs](./quasar-cli-vite/developing-capacitor-apps/capacitor-api.md): You can hook into the native device APIs by using Capacitor APIs.\n- [Capacitor versions](./quasar-cli-vite/developing-capacitor-apps/capacitor-version-support.md): The officially supported versions of Capacitor are v1 through v6.\n- [Configuring Capacitor](./quasar-cli-vite/developing-capacitor-apps/configuring-capacitor.md): We'll be using Quasar CLI to develop and build a Mobile App. The difference between building a SPA, PWA, Electron App or a Mobile App is simply det...\n- [What is Capacitor](./quasar-cli-vite/developing-capacitor-apps/introduction.md): Capacitor is a cross-platform native runtime for deploying web applications to mobile. It is maintained by Ionic and designed as a modern successor...\n- [Live Updates](./quasar-cli-vite/developing-capacitor-apps/live-updates.md): Live Updates, also known as Over-the-Air (OTA) or hot code updates, are a way to push updates to your app without going through the app store revie...\n- [Managing Google Analytics](./quasar-cli-vite/developing-capacitor-apps/managing-google-analytics.md): Getting to know your users and measuring user behavior is an important step in App Development. Unfortunately, it takes a bit of non-standard work ...\n- [Preparation for Capacitor App](./quasar-cli-vite/developing-capacitor-apps/preparation.md): Before we dive in to the actual development, we need to do some preparation work.\n- [Publishing to Store](./quasar-cli-vite/developing-capacitor-apps/publishing-to-store.md): So, you've finished working on your Mobile App. Now it's time to deploy it. Let's learn how.\n- [Capacitor Troubleshooting and Tips](./quasar-cli-vite/developing-capacitor-apps/troubleshooting-and-tips.md): While you are developing a Mobile App with Capacitor Mode, you can access $q.capacitor in your Vue files. This is an alias to the global Capacitor ...\n\n## quasar-cli-vite/developing-cordova-apps (9)\n\n- [App Icons for Cordova](./quasar-cli-vite/developing-cordova-apps/app-icons-cordova.md): Cordova is one of the most complicated of all of the build targets as far as icons go, because not only do you need to place the icons in specific ...\n- [Mobile App Build Commands](./quasar-cli-vite/developing-cordova-apps/build-commands.md): Before we dive in, make sure you got the Cordova CLI installed.\n- [Configuring Cordova](./quasar-cli-vite/developing-cordova-apps/configuring-cordova.md): We'll be using Quasar CLI (and Cordova CLI) to develop and build a Mobile App. The difference between building a SPA, PWA, Electron App or a Mobile...\n- [Cordova Plugins](./quasar-cli-vite/developing-cordova-apps/cordova-plugins.md): You can hook into the native device APIs by using Cordova Plugins.\n- [What is Cordova](./quasar-cli-vite/developing-cordova-apps/introduction.md): Apache Cordova is a mobile application development framework originally created by Nitobi. Adobe Systems purchased Nitobi in 2011, rebranded it as ...\n- [Managing Google Analytics](./quasar-cli-vite/developing-cordova-apps/managing-google-analytics.md): Getting to know your users and measuring user behavior is an important step in App Development. Unfortunately, it takes a bit of non-standard work ...\n- [Preparation for Cordova App](./quasar-cli-vite/developing-cordova-apps/preparation.md): Before we dive into the actual development, we need to do some preparation work.\n- [Publishing to Store](./quasar-cli-vite/developing-cordova-apps/publishing-to-store.md): So, you've finished working on your Mobile App. Now it's time to deploy it. Let's learn how.\n- [Cordova Troubleshooting and Tips](./quasar-cli-vite/developing-cordova-apps/troubleshooting-and-tips.md): While you are developing a Mobile App with Cordova Mode, you can access $q.cordova in your Vue files. This is an alias to the global cordova Object.\n\n## quasar-cli-vite/developing-electron-apps (13)\n\n- [App Icons for Electron](./quasar-cli-vite/developing-electron-apps/app-icons-electron.md): These images are used to display the icon of the application in the desktop operating system in the tray, on the desktop, in the file-browser and i...\n- [Electron Build Commands](./quasar-cli-vite/developing-electron-apps/build-commands.md): It opens up an Electron window with dev-tools included. You have HMR for the renderer process and changes to main process are also picked up (but t...\n- [Configuring Electron](./quasar-cli-vite/developing-electron-apps/configuring-electron.md): We'll be using Quasar CLI to develop and build an Electron App. The difference between building a SPA, PWA, Mobile App or an Electron App is simply...\n- [Electron Accessing Files](./quasar-cli-vite/developing-electron-apps/electron-accessing-files.md): Since the main process is bundled using Esbuild, the use of dirname and filename will not provide an expected value in production. Referring to the...\n- [Electron Packages](./quasar-cli-vite/developing-electron-apps/electron-packages.md): You can yarn/npm/pnpm/bun install and use Electron specific packages in your main thread and preload script. Take a look at the link and choose wis...\n- [Electron Preload Script](./quasar-cli-vite/developing-electron-apps/electron-preload-script.md): For security reasons, the renderer thread (your UI code from /src) does not have access to the Node.js stuff. However, you can run Node.js code and...\n- [Electron Security Concerns](./quasar-cli-vite/developing-electron-apps/electron-security-concerns.md): If you are not vigilant when building Electron apps, you will probably be placing the users of your app in tangible digital danger. Things like XSS...\n- [Upgrade guide on Electron](./quasar-cli-vite/developing-electron-apps/electron-upgrade-guide.md): When you add the Electron mode in a Quasar project for the first time you will get the latest version of the Electron package. At some point in tim...\n- [Electron with Typescript](./quasar-cli-vite/developing-electron-apps/electron-with-typescript.md): In order to support Electron with Typescript, you will need to rename the extension for your files in /src-electron from .js to .ts and make the ne...\n- [Frameless Electron Window](./quasar-cli-vite/developing-electron-apps/frameless-electron-window.md): A nice combo is to use frameless Electron window along with QBar component. Here's why.\n- [What is Electron](./quasar-cli-vite/developing-electron-apps/introduction.md): Electron (formerly known as Atom Shell) is an open-source framework created by Cheng Zhao, and now developed by GitHub. It allows for the developme...\n- [Preparation for Electron](./quasar-cli-vite/developing-electron-apps/preparation.md): Before we dive in to the actual development, we need to do some preparation work.\n- [Troubleshooting and Tips](./quasar-cli-vite/developing-electron-apps/troubleshooting-and-tips.md): You probably want your app to only give access to the browser devtools on dev mode only. On the production version (without debugging enabled) you'...\n\n## quasar-cli-vite/developing-pwa (8)\n\n- [App Icons for PWA](./quasar-cli-vite/developing-pwa/app-icons-pwa.md): This build target includes a variety of special icons for individual browsers and operating systems. You need all of them - and if you discover one...\n- [PWA Build Commands](./quasar-cli-vite/developing-pwa/build-commands.md): ::: warning\nThe development server uses a bare minimum Service Worker precaching only the public folder. Working offline will not be available.\n:::\n- [Configuring PWA](./quasar-cli-vite/developing-pwa/configuring-pwa.md): Adding PWA mode to a Quasar project means a new folder will be created: /src-pwa, which contains PWA specific files:\n- [Handling Service Worker](./quasar-cli-vite/developing-pwa/handling-service-worker.md): Here you'll learn how to interact with the Service Worker from within your website/app space. Remember, service workers MUST be served over HTTPS.\n- [Hot Module Reload for PWA](./quasar-cli-vite/developing-pwa/hmr-for-dev.md): When in develop mode (not production), having a Service Worker installed and running will mess with the HMR (Hot Module Reload). However, the brows...\n- [What is a PWA](./quasar-cli-vite/developing-pwa/introduction.md): A Progressive Web App (PWA) is a web app that uses modern web capabilities to deliver an app-like experience to users. These apps meet certain requ...\n- [Preparation for PWA](./quasar-cli-vite/developing-pwa/preparation.md): We'll be using Quasar CLI to develop and build a PWA. The difference between building a SPA, Mobile App, Electron App, PWA or SSR is simply determi...\n- [PWA with Typescript](./quasar-cli-vite/developing-pwa/pwa-with-typescript.md): In order to support PWA with Typescript, you will need to rename the extension for your files in /src-pwa from .js to .ts and make the necessary TS...\n\n## quasar-cli-vite/developing-spa (4)\n\n- [App Icons for SPA](./quasar-cli-vite/developing-spa/app-icons-spa.md): This build target includes a variety of special icons for individual browsers and operating systems. You need all of them - and if you discover one...\n- [SPA Build Commands](./quasar-cli-vite/developing-spa/build-commands.md): Developing:\n- [Deploying a SPA](./quasar-cli-vite/developing-spa/deploying.md): There exist many services that allow deploying applications with ease.\nTo list all of them would not be possible so we will focus on the general de...\n- [What is SPA](./quasar-cli-vite/developing-spa/introduction.md): A Single-Page Application (SPA) is a web application or web site that interacts with the user by dynamically rewriting the current page rather than...\n\n## quasar-cli-vite/developing-ssr (17)\n\n- [App Icons for SSR](./quasar-cli-vite/developing-ssr/app-icons-ssr.md): This build target includes a variety of special icons for individual browsers and operating systems. You need all of them - and if you discover one...\n- [SSR Build Commands](./quasar-cli-vite/developing-ssr/build-commands.md): If you want a production build with debugging enabled:\n- [Client Side Hydration](./quasar-cli-vite/developing-ssr/client-side-hydration.md): Hydration refers to the client-side process during which Vue takes over the static HTML sent by the server and turns it into dynamic DOM that can r...\n- [Configuring SSR](./quasar-cli-vite/developing-ssr/configuring-ssr.md): This is the place where you can configure some SSR options. Like if you want the client side to takeover as a SPA (Single Page Application -- the d...\n- [Deploying SSR](./quasar-cli-vite/developing-ssr/deploying.md): When deploying as a SPA or PWA, the distributables folder that gets generated by Quasar CLI can be served by a static webserver. However, this not ...\n- [SSR Handling of 404 and 500 Errors](./quasar-cli-vite/developing-ssr/handling-404-and-500-errors.md): The handling of the 404 & 500 errors on SSR is a bit different than on the other modes (like SPA). If you check out /src-ssr/middlewares/render.js,...\n- [What is SSR](./quasar-cli-vite/developing-ssr/introduction.md): Quasar and Vue.js are frameworks for building client-side applications. By default, Quasar Vue components produce and manipulate DOM in the browser...\n- [Preparation for SSR](./quasar-cli-vite/developing-ssr/preparation.md): We’ll be using Quasar CLI to develop and build a SSR website. The difference between building a SPA, Mobile App, Electron App, PWA or SSR is simply...\n- [SEO for SSR](./quasar-cli-vite/developing-ssr/seo-for-ssr.md): The term SEO refers to Search Engine Optimization. And Quasar covers this aspect too through the Quasar Meta Plugin.\n- [The ssrContext Object](./quasar-cli-vite/developing-ssr/ssr-context.md): The ssrContext Object is the SSR context with which all the app's Vue components are rendered with.\n- [SSR FAQ](./quasar-cli-vite/developing-ssr/ssr-frequently-asked-questions.md): Take a look at our Client Side Hydration page. When you get hydration errors, it means the HTML rendered on the server does not match the equivalen...\n- [SSR Middleware](./quasar-cli-vite/developing-ssr/ssr-middleware.md): The SSR middleware files fulfill one special purpose: they prepare the Nodejs server that runs your SSR app with additional functionality (Express ...\n- [SSR Webserver](./quasar-cli-vite/developing-ssr/ssr-webserver.md): Notice that your generated /src-ssr contains a file named server.js. This file defines how your SSR webserver is created, managed and served. You c...\n- [SSR with PWA Client Takeover](./quasar-cli-vite/developing-ssr/ssr-with-pwa.md): With Quasar CLI you can build your app with the killer combo of SSR + PWA. In order to enable PWA for SSR builds, you need to edit your /quasar.con...\n- [SSR with Typescript](./quasar-cli-vite/developing-ssr/ssr-with-typescript.md): In order to support SSR with Typescript, you will need to rename all your files in /src-ssr from .js to .ts and make the necessary TS code changes.\n- [Vue SSR Directives](./quasar-cli-vite/developing-ssr/vue-ssr-directives.md): ::: warning\nThis guide refers to usage with Quasar v2.6+\n:::\n- [Writing Universal Code](./quasar-cli-vite/developing-ssr/writing-universal-code.md): Writing universal code (also called isomorphic) means writing code that runs on both the server and the client. Due to use-case and platform API di...\n\n## quasar-cli-webpack (22)\n\n- [Ajax Requests](./quasar-cli-webpack/ajax-requests.md): If you haven't selected Axios during the project initialization then you should create a new boot file axios.js that looks like this:\n(Here you can...\n- [API Proxying for Dev](./quasar-cli-webpack/api-proxying.md): When integrating a project folder (created by Quasar CLI) with an existing backend, a common need is to access the backend API when using the dev s...\n- [Boot files](./quasar-cli-webpack/boot-files.md): A common use case for Quasar applications is to run code before the root Vue app instance is instantiated, like injecting and initializing your own...\n- [Browser compatibility](./quasar-cli-webpack/browser-compatibility.md): Your /package.json file should contain a browserslist field. This will tell Quasar App the range of browsers that the project is targeting. Babel a...\n- [Commands List](./quasar-cli-webpack/commands-list.md): Familiarize yourself with the list of available commands inside a Quasar project:\n- [Convert project to Quasar CLI with Webpack](./quasar-cli-webpack/convert-to-quasar-cli-with-webpack.md): This page will guide you on how to convert a Quasar CLI with Vite (@quasar/app-vite v2) project into a Quasar CLI with Webpack one (@quasar/app-web...\n- [CSS Preprocessors](./quasar-cli-webpack/css-preprocessors.md): Sass or SCSS (recommending any of the two flavours) are the out of the box supported css preprocessors through Quasar CLI, should you want to use t...\n- [Developing Mobile Apps](./quasar-cli-webpack/developing-mobile-apps.md): Quasar offers two solutions for creating mobile apps:\n- [Directory Structure](./quasar-cli-webpack/directory-structure.md): This is the structure of a project with all modes installed. There's no reason to be intimidated though!\n- [App Handling Assets](./quasar-cli-webpack/handling-assets.md): You will notice in the project structure we have two directories for assets: /public/ and /src/assets/. What is the difference between them? Some a...\n- [Handling process.env](./quasar-cli-webpack/handling-process-env.md): Accessing process.env can help you in many ways:\n- [Handling Webpack](./quasar-cli-webpack/handling-webpack.md): The build system uses Webpack to create your website/app. Don't worry if you aren't acquainted with Webpack. Out of the box, you won't need to conf...\n- [Lazy Loading / Code Splitting](./quasar-cli-webpack/lazy-loading.md): When your website/app is small, you can load all layouts/pages/components into the initial bundle and serve everything at startup. But when your co...\n- [Linter](./quasar-cli-webpack/linter.md): Having a code linter (like ESLint v9+) in place is highly recommended and ensures your code looks legible. It also helps you capture some errors be...\n- [Opening Your Dev Server to the Public](./quasar-cli-webpack/opening-dev-server-to-public.md): At some point you may want to show someone else the project you've been working on. Fortunately, there are a couple of good tools to accomplish thi...\n- [PreFetch Feature](./quasar-cli-webpack/prefetch-feature.md): The PreFetch is a feature (only available when using Quasar CLI) which allows the components picked up by Vue Router (defined in /src/router/routes...\n- [Configuring quasar.config file](./quasar-cli-webpack/quasar-config-file.md): Quasar makes use of some awesome development tools under its hood, like Webpack. One of the great things about Quasar is its handling of most of th...\n- [App Routing](./quasar-cli-webpack/routing.md): You'll notice that your Quasar project contains a /src/router folder. This holds the routing configuration of your website/app:\n- [State management with Pinia](./quasar-cli-webpack/state-management-with-pinia.md): In large applications, state management often becomes complex due to multiple pieces of state scattered across many components and the interactions...\n- [Supporting TypeScript](./quasar-cli-webpack/supporting-ts.md): If you didn't select TypeScript support when creating your project, you can still add it later. This guide will show you how to add TypeScript supp...\n- [Testing & Auditing](./quasar-cli-webpack/testing-and-auditing.md): Your Quasar projects have the ability to add unit and e2e testing harnesses. This introduction will not go into details about how to write and use ...\n- [Upgrade Guide for Quasar CLI with Webpack](./quasar-cli-webpack/upgrade-guide.md): You might want to release new versions of your Quasar App Extensions with support for the new @quasar/app-webpack. If you are not touching the quas...\n\n## quasar-cli-webpack/developing-browser-extensions (9)\n\n- [App Icons for (BEX)](./quasar-cli-webpack/developing-browser-extensions/app-icons-browser-extension.md): This build target includes the icons required for browser extensions. You need all of them - and if you discover one that is new or missing, please...\n- [Background Script](./quasar-cli-webpack/developing-browser-extensions/background-script.md): The background script runs in the context of the BEX itself and can listen to all available browser extension events.\n- [BEX Bridge Communication](./quasar-cli-webpack/developing-browser-extensions/bex-bridge.md): Allowing a Quasar App to communicate with the various parts of the BEX is essential. Quasar closes this gap using a bridge.\n- [BEX Build Commands](./quasar-cli-webpack/developing-browser-extensions/build-commands.md): Start developing a Browser Extension with just one command.\n- [Configuring BEX](./quasar-cli-webpack/developing-browser-extensions/configuring-bex.md): Before we can configure anything, we need to understand how the BEX is structured. A BEX can be one (or more) of the following:\n- [Content Scripts](./quasar-cli-webpack/developing-browser-extensions/content-scripts.md): The content script(s) run in the context of the web page. There will be a new content script instance per tab running the extension.\n- [What is a Browser Extension](./quasar-cli-webpack/developing-browser-extensions/introduction.md): A Browser Extension (BEX) is an application that runs in the browsers context and is used to customize the web browser in some way.\n- [Preparation for BEX](./quasar-cli-webpack/developing-browser-extensions/preparation.md): The difference between building a SPA, Mobile App, Electron App, BEX or SSR is simply determined by the \"mode\" parameter in \"quasar dev\" and \"quasa...\n- [Types of BEX](./quasar-cli-webpack/developing-browser-extensions/types-of-bex.md): As already discussed, Quasar can handle the various places where a browser extension can live, namely New Tab, Web Page, Dev Tools Options or Popup...\n\n## quasar-cli-webpack/developing-capacitor-apps (11)\n\n- [App Icons for Capacitor](./quasar-cli-webpack/developing-capacitor-apps/app-icons-capacitor.md): Capacitor is one of the most complicated of all of the build targets as far as icons go, because not only do you need to place the icons in specifi...\n- [Capacitor Build Commands](./quasar-cli-webpack/developing-capacitor-apps/build-commands.md): It will open the IDE (Android Studio / Xcode) and from there you can manually select the emulator (or multiple ones simultaneously!) and install th...\n- [Capacitor APIs](./quasar-cli-webpack/developing-capacitor-apps/capacitor-api.md): You can hook into the native device APIs by using Capacitor APIs.\n- [Capacitor versions](./quasar-cli-webpack/developing-capacitor-apps/capacitor-version-support.md): The officially supported versions of Capacitor are v1 through v6.\n- [Configuring Capacitor](./quasar-cli-webpack/developing-capacitor-apps/configuring-capacitor.md): We'll be using Quasar CLI to develop and build a Mobile App. The difference between building a SPA, PWA, Electron App or a Mobile App is simply det...\n- [What is Capacitor](./quasar-cli-webpack/developing-capacitor-apps/introduction.md): Capacitor is a cross-platform native runtime for deploying web applications to mobile. It is maintained by Ionic and designed as a modern successor...\n- [Live Updates](./quasar-cli-webpack/developing-capacitor-apps/live-updates.md): Live Updates, also known as Over-the-Air (OTA) or hot code updates, are a way to push updates to your app without going through the app store revie...\n- [Managing Google Analytics](./quasar-cli-webpack/developing-capacitor-apps/managing-google-analytics.md): Getting to know your users and measuring user behavior is an important step in App Development. Unfortunately, it takes a bit of non-standard work ...\n- [Preparation for Capacitor App](./quasar-cli-webpack/developing-capacitor-apps/preparation.md): Before we dive in to the actual development, we need to do some preparation work.\n- [Publishing to Store](./quasar-cli-webpack/developing-capacitor-apps/publishing-to-store.md): So, you've finished working on your Mobile App. Now it's time to deploy it. Let's learn how.\n- [Capacitor Troubleshooting and Tips](./quasar-cli-webpack/developing-capacitor-apps/troubleshooting-and-tips.md): While you are developing a Mobile App with Capacitor Mode, you can access $q.capacitor in your Vue files. This is an alias to the global Capacitor ...\n\n## quasar-cli-webpack/developing-cordova-apps (9)\n\n- [App Icons for Cordova](./quasar-cli-webpack/developing-cordova-apps/app-icons-cordova.md): Cordova is one of the most complicated of all of the build targets as far as icons go, because not only do you need to place the icons in specific ...\n- [Mobile App Build Commands](./quasar-cli-webpack/developing-cordova-apps/build-commands.md): Before we dive in, make sure you got the Cordova CLI installed.\n- [Configuring Cordova](./quasar-cli-webpack/developing-cordova-apps/configuring-cordova.md): We'll be using Quasar CLI (and Cordova CLI) to develop and build a Mobile App. The difference between building a SPA, PWA, Electron App or a Mobile...\n- [Cordova Plugins](./quasar-cli-webpack/developing-cordova-apps/cordova-plugins.md): You can hook into the native device APIs by using Cordova Plugins.\n- [What is Cordova](./quasar-cli-webpack/developing-cordova-apps/introduction.md): Apache Cordova is a mobile application development framework originally created by Nitobi. Adobe Systems purchased Nitobi in 2011, rebranded it as ...\n- [Managing Google Analytics](./quasar-cli-webpack/developing-cordova-apps/managing-google-analytics.md): Getting to know your users and measuring user behavior is an important step in App Development. Unfortunately, it takes a bit of non-standard work ...\n- [Preparation for Cordova App](./quasar-cli-webpack/developing-cordova-apps/preparation.md): Before we dive into the actual development, we need to do some preparation work.\n- [Publishing to Store](./quasar-cli-webpack/developing-cordova-apps/publishing-to-store.md): So, you've finished working on your Mobile App. Now it's time to deploy it. Let's learn how.\n- [Cordova Troubleshooting and Tips](./quasar-cli-webpack/developing-cordova-apps/troubleshooting-and-tips.md): While you are developing a Mobile App with Cordova Mode, you can access $q.cordova in your Vue files. This is an alias to the global cordova Object.\n\n## quasar-cli-webpack/developing-electron-apps (13)\n\n- [App Icons for Electron](./quasar-cli-webpack/developing-electron-apps/app-icons-electron.md): These images are used to display the icon of the application in the desktop operating system in the tray, on the desktop, in the file-browser and i...\n- [Electron Build Commands](./quasar-cli-webpack/developing-electron-apps/build-commands.md): It opens up an Electron window with dev-tools included. You have HMR for the renderer process and changes to main process are also picked up (but t...\n- [Configuring Electron](./quasar-cli-webpack/developing-electron-apps/configuring-electron.md): We'll be using Quasar CLI to develop and build an Electron App. The difference between building a SPA, PWA, Mobile App or an Electron App is simply...\n- [Electron Accessing Files](./quasar-cli-webpack/developing-electron-apps/electron-accessing-files.md): Since the main process is bundled using Esbuild, the use of dirname and filename will not provide an expected value in production. Referring to the...\n- [Electron Packages](./quasar-cli-webpack/developing-electron-apps/electron-packages.md): You can yarn/npm/pnpm/bun install and use Electron specific packages in your main thread and preload script. Take a look at the link and choose wis...\n- [Electron Preload Script](./quasar-cli-webpack/developing-electron-apps/electron-preload-script.md): For security reasons, the renderer thread (your UI code from /src) does not have access to the Node.js stuff. However, you can run Node.js code and...\n- [Electron Security Concerns](./quasar-cli-webpack/developing-electron-apps/electron-security-concerns.md): If you are not vigilant when building Electron apps, you will probably be placing the users of your app in tangible digital danger. Things like XSS...\n- [Upgrade guide on Electron](./quasar-cli-webpack/developing-electron-apps/electron-upgrade-guide.md): When you add the Electron mode in a Quasar project for the first time you will get the latest version of the Electron package. At some point in tim...\n- [Electron with Typescript](./quasar-cli-webpack/developing-electron-apps/electron-with-typescript.md): In order to support Electron with Typescript, you will need to rename the extension for your files in /src-electron from .js to .ts and make the ne...\n- [Frameless Electron Window](./quasar-cli-webpack/developing-electron-apps/frameless-electron-window.md): A nice combo is to use frameless Electron window along with QBar component. Here's why.\n- [What is Electron](./quasar-cli-webpack/developing-electron-apps/introduction.md): Electron (formerly known as Atom Shell) is an open-source framework created by Cheng Zhao, and now developed by GitHub. It allows for the developme...\n- [Preparation for Electron](./quasar-cli-webpack/developing-electron-apps/preparation.md): Before we dive in to the actual development, we need to do some preparation work.\n- [Troubleshooting and Tips](./quasar-cli-webpack/developing-electron-apps/troubleshooting-and-tips.md): You probably want your app to only give access to the browser devtools on dev mode only. On the production version (without debugging enabled) you'...\n\n## quasar-cli-webpack/developing-pwa (8)\n\n- [App Icons for PWA](./quasar-cli-webpack/developing-pwa/app-icons-pwa.md): This build target includes a variety of special icons for individual browsers and operating systems. You need all of them - and if you discover one...\n- [PWA Build Commands](./quasar-cli-webpack/developing-pwa/build-commands.md): ::: warning\nThe development server uses a bare minimum Service Worker precaching only the public folder. Working offline will not be available.\n:::\n- [Configuring PWA](./quasar-cli-webpack/developing-pwa/configuring-pwa.md): Adding PWA mode to a Quasar project means a new folder will be created: /src-pwa, which contains PWA specific files:\n- [Handling Service Worker](./quasar-cli-webpack/developing-pwa/handling-service-worker.md): Here you'll learn how to interact with the Service Worker from within your website/app space. Remember, service workers MUST be served over HTTPS.\n- [Hot Module Reload for PWA](./quasar-cli-webpack/developing-pwa/hmr-for-dev.md): When in develop mode (not production), having a Service Worker installed and running will mess with the HMR (Hot Module Reload). However, the brows...\n- [What is a PWA](./quasar-cli-webpack/developing-pwa/introduction.md): A Progressive Web App (PWA) is a web app that uses modern web capabilities to deliver an app-like experience to users. These apps meet certain requ...\n- [Preparation for PWA](./quasar-cli-webpack/developing-pwa/preparation.md): We'll be using Quasar CLI to develop and build a PWA. The difference between building a SPA, Mobile App, Electron App, PWA or SSR is simply determi...\n- [PWA with Typescript](./quasar-cli-webpack/developing-pwa/pwa-with-typescript.md): In order to support PWA with Typescript, you will need to rename the extension for your files in /src-pwa from .js to .ts and make the necessary TS...\n\n## quasar-cli-webpack/developing-spa (4)\n\n- [App Icons for SPA](./quasar-cli-webpack/developing-spa/app-icons-spa.md): This build target includes a variety of special icons for individual browsers and operating systems. You need all of them - and if you discover one...\n- [SPA Build Commands](./quasar-cli-webpack/developing-spa/build-commands.md): Developing:\n- [Deploying a SPA](./quasar-cli-webpack/developing-spa/deploying.md): There exist many services that allow deploying applications with ease.\nTo list all of them would not be possible so we will focus on the general de...\n- [What is SPA](./quasar-cli-webpack/developing-spa/introduction.md): A Single-Page Application (SPA) is a web application or web site that interacts with the user by dynamically rewriting the current page rather than...\n\n## quasar-cli-webpack/developing-ssr (17)\n\n- [App Icons for SSR](./quasar-cli-webpack/developing-ssr/app-icons-ssr.md): This build target includes a variety of special icons for individual browsers and operating systems. You need all of them - and if you discover one...\n- [SSR Build Commands](./quasar-cli-webpack/developing-ssr/build-commands.md): Quasar CLI makes it incredibly simple to develop or build the final distributables from your source code.\n- [Client Side Hydration](./quasar-cli-webpack/developing-ssr/client-side-hydration.md): Hydration refers to the client-side process during which Vue takes over the static HTML sent by the server and turns it into dynamic DOM that can r...\n- [Configuring SSR](./quasar-cli-webpack/developing-ssr/configuring-ssr.md): This is the place where you can configure some SSR options. Like if you want the client side to takeover as a SPA (Single Page Application -- the d...\n- [Deploying SSR](./quasar-cli-webpack/developing-ssr/deploying.md): When deploying as a SPA or PWA, the distributables folder that gets generated by Quasar CLI can be served by a static webserver. However, this is n...\n- [SSR Handling of 404 and 500 Errors](./quasar-cli-webpack/developing-ssr/handling-404-and-500-errors.md): The handling of the 404 & 500 errors on SSR is a bit different than on the other modes (like SPA). If you check out /src-ssr/middlewares/render.js,...\n- [What is SSR](./quasar-cli-webpack/developing-ssr/introduction.md): Quasar and Vue.js are frameworks for building client-side applications. By default, Quasar Vue components produce and manipulate DOM in the browser...\n- [Preparation for SSR](./quasar-cli-webpack/developing-ssr/preparation.md): We’ll be using Quasar CLI to develop and build a SSR website. The difference between building a SPA, Mobile App, Electron App, PWA or SSR is simply...\n- [SEO for SSR](./quasar-cli-webpack/developing-ssr/seo-for-ssr.md): The term SEO refers to Search Engine Optimization. And Quasar covers this aspect too through the Quasar Meta Plugin.\n- [The ssrContext Object](./quasar-cli-webpack/developing-ssr/ssr-context.md): The ssrContext Object is the SSR context with which all the app's Vue components are rendered with.\n- [SSR FAQ](./quasar-cli-webpack/developing-ssr/ssr-frequently-asked-questions.md): Take a look at our Client Side Hydration page. When you get hydration errors, it means the HTML rendered on the server does not match the equivalen...\n- [SSR Middleware](./quasar-cli-webpack/developing-ssr/ssr-middleware.md): The SSR middleware files fulfill one special purpose: they prepare the Nodejs server that runs your SSR app with additional functionality (Express ...\n- [SSR Webserver](./quasar-cli-webpack/developing-ssr/ssr-webserver.md): Notice that your generated /src-ssr contains a file named server.js. This file defines how your SSR webserver is created, managed and served. You c...\n- [SSR with PWA Client Takeover](./quasar-cli-webpack/developing-ssr/ssr-with-pwa.md): With Quasar CLI you can build your app with the killer combo of SSR + PWA. In order to enable PWA for SSR builds, you need to edit your /quasar.con...\n- [SSR with Typescript](./quasar-cli-webpack/developing-ssr/ssr-with-typescript.md): In order to support SSR with Typescript, you will need to rename all your files in /src-ssr from .js to .ts and make the necessary TS code changes.\n- [Vue SSR Directives](./quasar-cli-webpack/developing-ssr/vue-ssr-directives.md): ::: warning\nThis guide refers to usage with Quasar v2.6+\n:::\n- [Writing Universal Code](./quasar-cli-webpack/developing-ssr/writing-universal-code.md): Writing universal code (also called isomorphic) means writing code that runs on both the server and the client. Due to use-case and platform API di...\n\n## quasar-plugins (12)\n\n- [AddressbarColor Plugin](./quasar-plugins/addressbar-color.md): Newer mobile browsers have the ability to specify a color for the addressbar, like in the image below.\n- [Fullscreen Plugin](./quasar-plugins/app-fullscreen.md): There are times when you want your website or App to run in fullscreen.\nQuasar makes it easy by wrapping the Web Fullscreen API.\n- [App Visibility](./quasar-plugins/app-visibility.md): Quasar makes use of the Web Page Visibility API which lets you know when a website/app is visible or in focus.\n- [Bottom Sheet Plugin](./quasar-plugins/bottom-sheet.md): Bottom Sheets slide up from the bottom edge of the device screen, and display a set of options with the ability to confirm or cancel an action. Bot...\n- [Cookies](./quasar-plugins/cookies.md): This is a wrapper over the standardized document.cookie.\n- [Dark Plugin](./quasar-plugins/dark.md): ::: tip\nFor a better understanding of this Quasar plugin, please head to the Style & Identity Dark Mode page.\n:::\n- [Dialog Plugin](./quasar-plugins/dialog.md): Quasar Dialogs are a great way to offer the user the ability to choose a specific action or list of actions. They also can provide the user with im...\n- [LoadingBar](./quasar-plugins/loading-bar.md): The Quasar LoadingBar plugin offers an easy way to set up your app with a QAjaxBar in case you don't want to handle a QAjaxBar component yourself.\n- [Loading Plugin](./quasar-plugins/loading.md): Loading is a feature that you can use to display an overlay with a spinner on top of your App's content to inform the user that a background operat...\n- [Quasar Meta Plugin](./quasar-plugins/meta.md): Better SEO for your website! The Meta plugin can dynamically change page title, manage tags, manage \u003chtml> and \u003cbody> DOM element attributes...\n- [Notify](./quasar-plugins/notify.md): Notify is a Quasar plugin that can display animated messages (floating above everything in your pages) to users in the form of a notification. They...\n- [Local/Session Storage Plugins](./quasar-plugins/web-storage.md): Quasar provides a wrapper over Web Storage API.\n\n## quasar-utils (9)\n\n- [Color Utils](./quasar-utils/color-utils.md): Quasar provides a set of useful functions to manipulate colors easily in most use cases, without the high additional cost of integrating dedicated ...\n- [Date Utils](./quasar-utils/date-utils.md): Quasar provides a set of useful functions to manipulate JS Date easily in most use cases, without the high additional cost of integrating dedicated...\n- [DOM Utils](./quasar-utils/dom-utils.md): You will notice all examples import different parts of Quasar. However, if you need only one specific util method, then you can use ES6 destructuri...\n- [EventBus Util](./quasar-utils/event-bus-util.md): Quasar supplies a global EventBus, especially useful when upgrading from Quasar v1 where the native Vue 2 interface has been dropped.\n- [Formatter Utils](./quasar-utils/formatter-utils.md): You will notice all examples import format Object from Quasar. However, if you need only one formatter method from it, then you can use ES6 destruc...\n- [Morph Utils](./quasar-utils/morph-utils.md): You can morph one DOM element into another (with animation) or between two states of the same element using Quasar's morph util described below.\n- [Other Utils](./quasar-utils/other-utils.md): ::: tip\nFor usage with the UMD build see here.\n:::\n- [Scrolling Utils](./quasar-utils/scrolling-utils.md): ::: tip\nFor usage with the UMD build see here.\n:::\n- [Type Checking Utils (\u003cis>)](./quasar-utils/type-checking-utils.md): ::: tip\nFor usage with the UMD build see here.\n:::\n\n## security (2)\n\n- [Security DO's and DON'Ts](./security/dos-and-donts.md): DO periodically review the security of your application, because any lapse may be putting yourself, your team, your users and even your server at r...\n- [Report a vulnerability](./security/report-a-vulnerability.md): If you have found a potential security threat, vulnerability or exploit in Quasar or one of its upstream dependencies, please:\n\n## sponsors-and-backers (1)\n\n- [Sponsors and Backers](./sponsors-and-backers/sponsors-and-backers.md): ::: tip Author of Quasar Framework\nQuasar was born because I felt that a full featured framework to build responsive websites, PWAs (Progressive We...\n\n## start (7)\n\n- [How To Use Vue](./start/how-to-use-vue.md): Before you begin with Quasar, it is a good idea to have a fairly good knowledge about how Vue 3 works. For devs experienced with reactive UIs, the ...\n- [Pick a Quasar Flavour](./start/pick-quasar-flavour.md): There are four ways of using Quasar. Pick the one that suits you best:\n- [Quasar Playground](./start/playground.md): You can fork and use these links for reporting issues on GitHub too. These links (obviously) use the Quasar UMD version.\n- [Quasar CLI](./start/quasar-cli.md): Quasar CLI is the pride of Quasar Framework. You can seamlessly build:\n- [Quick Start](./start/quick-start.md): It takes two easy steps and in a couple of minutes, you are off and running with a full-fledged Vue app, built with state-of-the-art best practices...\n- [Configure VS Code](./start/vs-code-configuration.md): ::: tip\nThis guide assumes you have already installed VS Code(Visual Studio Code).\n:::\n- [Vue CLI Quasar Plugin](./start/vue-cli-plugin.md): ::: danger\nThe Vue CLI is in maintenance mode. You should probably start your work with Quasar CLI instead.\n:::\n\n## start/release-notes (1)\n\n- [Release Notes](./start/release-notes/release-notes.md): Release notes (with changelog) for Quasar core packages are available on GitHub Releases.\n\n## start/umd (1)\n\n- [Quasar UMD - CDN install](./start/umd/umd.md): If you want to embed Quasar into your existing website project, integrating it in a progressive manner, then go for the UMD/Standalone (Unified Mod...\n\n## start/upgrade-guide (1)\n\n- [UI Upgrade Guide](./start/upgrade-guide/upgrade-guide.md): ::: tip Quasar CLI with Vite or Webpack\nYou now have the option to choose between Quasar CLI with Vite and Quasar CLI with Webpack.\n:::\n\n## start/vite-plugin (1)\n\n- [Vite plugin for Quasar](./start/vite-plugin/vite-plugin.md): If you want to embed Quasar into your existing Vite project then follow this guide to install and use the @quasar/vite-plugin.\nWhat our Vite plugin...\n\n## style (8)\n\n- [Body classes](./style/body-classes.md): Quasar attaches some very useful helper CSS classes to document.body which you can take advantage of:\n- [Breakpoints](./style/breakpoints.md): Quasar uses the following CSS breakpoints:\n- [Dark Mode](./style/dark-mode.md): Dark Mode is a supplemental mode that can be used to display mostly dark surfaces on the UI. The design reduces the light emitted by device screens...\n- [Other CSS Helper Classes](./style/other-helper-classes.md): There are a lot of CSS classes that you can use while writing your Vue templates. Very handy to ease the complexity of your VueModels and templates.\n- [CSS Positioning Classes](./style/positioning.md): There are CSS classes supplied by Quasar to help you position a DOM element easily:\n- [CSS Shadows (Elevation)](./style/shadows.md): Simple yet effective way to add shadows to create a depth/elevation effect.\nThe shadows are in accordance to Material Design specifications (24 lev...\n- [CSS Spacing Classes](./style/spacing.md): There are CSS classes supplied by Quasar to help you with spacing for DOM elements or components. All options are\nprefixed with q- and then broken ...\n- [CSS Visibility](./style/visibility.md): There are some CSS classes that you can use out of the box for common functionality.\n\n## style/color-palette (1)\n\n- [Color Palette](./style/color-palette/color-palette.md): Quasar Framework offers a wide selection of colors out of the box. You can use them both as Sass/SCSS variables in your CSS code or directly as CSS...\n\n## style/sass-scss-variables (1)\n\n- [Sass/SCSS Variables](./style/sass-scss-variables/sass-scss-variables.md): There are Sass/SCSS variables built into Quasar that you can change and/or use within devland should you wish to.\n\n## style/theme-builder (1)\n\n- [Theme Builder](./style/theme-builder/theme-builder.md): One of the most important parts of a website/app is to build a brand for it. First step is to choose the brand colors that you are going to use and...\n\n## style/typography (1)\n\n- [Typography](./style/typography/typography.md): We'll handle the typography supplied by Quasar in the sections below.\n\n## video-tutorials (1)\n\n- [Video Tutorials](./video-tutorials/video-tutorials.md): ::: tip\nThe video tutorials below have been created by the community.\n:::\n\n## vue-components (70)\n\n- [Ajax Bar](./vue-components/ajax-bar.md): In most mobile apps and even some desktop apps, you will most likely have some API communication to a server via an Ajax call. Since these calls ca...\n- [Avatar](./vue-components/avatar.md): The QAvatar component creates a scalable, color-able element that can have text, icon or image within its shape. By default it is circular, but it ...\n- [Badge](./vue-components/badge.md): The QBadge component allows you to create a small badge for adding information like contextual data that needs to stand out and get noticed. It is ...\n- [Banner](./vue-components/banner.md): The QBanner component creates a banner element to display a prominent message and related optional actions.\n- [Bar](./vue-components/bar.md): The QBar is a small component for creating the top bar on different types of mobile or desktop websites/apps. For instance, in desktop apps QBar wi...\n- [Breadcrumbs](./vue-components/breadcrumbs.md): The QBreadcrumbs component is used as a navigational aid in UI. It allows users to keep track of their location within programs, documents, or webs...\n- [Dropdown Button](./vue-components/button-dropdown.md): QBtnDropdown is a very convenient dropdown button. Goes very well with QList as dropdown content, but it's by no means limited to it.\n- [Button Group](./vue-components/button-group.md): You can conveniently group QBtn and QBtnDropdown using QBtnGroup. Be sure to check those component's respective pages to see their props and methods.\n- [Button Toggle](./vue-components/button-toggle.md): The QBtnToggle component is another basic element for user input, similar to QRadio but with buttons. You can use this to supply a way for the user...\n- [Button](./vue-components/button.md): Quasar has a component called QBtn which is a button with a few extra useful features. For instance, it comes in two shapes: rectangle (default) an...\n- [Card](./vue-components/card.md): The QCard component is a great way to display important pieces of grouped content. This pattern is quickly emerging as a core design pattern for Ap...\n- [Carousel](./vue-components/carousel.md): The QCarousel component allows you to display more information with less real estate, using slides. Useful for creating Wizards or an image gallery...\n- [Chat Message](./vue-components/chat.md): Quasar supplies a chat component called QChatMessage which is really a chat entry that renders the data given by the props.\n- [Checkbox](./vue-components/checkbox.md): The QCheckbox component is another basic element for user input. You can use this to supply a way for the user to toggle an option.\n- [Chip](./vue-components/chip.md): The QChip component is basically a simple UI block entity, representing for example more advanced underlying data, such as a contact, in a compact ...\n- [Circular Progress](./vue-components/circular-progress.md): The QCircularProgress component displays a colored circular progress. The bar can either have a determinate progress, or an indeterminate animation...\n- [Color Picker](./vue-components/color-picker.md): The QColor component provides a method to input colors.\n- [QDate](./vue-components/date.md): The QDate component provides a method to input date. Currently it supports Gregorian (default) and Persian calendars.\n- [Dialog](./vue-components/dialog.md): The QDialog component is a great way to offer the user the ability to choose a specific action or list of actions. They also can provide the user w...\n- [Editor (WYSIWYG)](./vue-components/editor.md): The QEditor component is a WYSIWYG (“what you see is what you get”) editor component that enables the user to write and even paste HTML. It uses th...\n- [Expansion Item](./vue-components/expansion-item.md): The QExpansionItem component allows the hiding of content that is not immediately relevant to the user. Think of them as accordion elements that ex...\n- [Field](./vue-components/field.md): The QField component is used to provide common functionality and aspect to form components. It uses :model-value (or v-model if you want to use cle...\n- [File Picker](./vue-components/file.md): QFile is a component which handles the user interaction for picking file(s).\n- [Floating Action Button](./vue-components/floating-action-button.md): A Floating Action Button (FAB) represents the primary action in a Page. But, it's not limited to only a single action. It can contain any number of...\n- [Form](./vue-components/form.md): The QForm component renders a DOM element and allows you to easily validate child form components (like QInput, QSelect or your QField wrapp...\n- [Icon](./vue-components/icon.md): The QIcon component allows you to easily insert icons within other components or any other area of your pages.\nQuasar supports out of the box: Mate...\n- [QImg](./vue-components/img.md): The QImg component makes working with images (any picture format) easy and also adds a nice loading effect to it along with many other features (ex...\n- [Infinite Scroll](./vue-components/infinite-scroll.md): The QInfiniteScroll component allows you to load new content as the user scrolls the page.\n- [Inner Loading](./vue-components/inner-loading.md): The QInnerLoading component allows you to add a progress animation within a component. Much like the Loading Plugin, its purpose is to offer visual...\n- [Input](./vue-components/input.md): The QInput component is used to capture text input from the user. It uses v-model, similar to a regular input. It has support for errors and valida...\n- [Intersection](./vue-components/intersection.md): The QIntersection component is essentially a wrapper over the Intersection directive with the added benefit that it handles the state by itself (do...\n- [Knob](./vue-components/knob.md): The QKnob component is used to take a number input from the user through mouse/touch panning. It is based on QCircularProgress and inherits all its...\n- [Linear Progress](./vue-components/linear-progress.md): The QLinearProgress component displays a colored loading bar. The bar can either have a determinate progress or an indeterminate animation. It shou...\n- [List and List Items](./vue-components/list-and-list-items.md): The QList and QItem are a group of components which can work together to present multiple line items vertically as a single continuous element. The...\n- [Markup Table](./vue-components/markup-table.md): The QMarkupTable is a way for you to simply wrap a native \u003ctable> in order to make it look like a Material Design table.\n- [No SSR](./vue-components/no-ssr.md): The QNoSsr component makes sense only if you are creating a SSR website/app.\n- [Option Group](./vue-components/option-group.md): The QOptionGroup component is a helper component that allows you better control for grouping binary (on or off, true or false, 1 or 0) form input c...\n- [Pagination](./vue-components/pagination.md): The QPagination component is available for whenever a pagination system is required. It offers the user a simple UI for moving between items or pages.\n- [Parallax](./vue-components/parallax.md): Parallax scrolling is a technique in computer graphics and web design, where background images move by the camera slower than foreground images, cr...\n- [Popup Edit](./vue-components/popup-edit.md): The QPopupEdit component can be used to edit a value “in place”, like for example a cell in QTable. By default, a cell is displayed as a String, th...\n- [Popup Proxy](./vue-components/popup-proxy.md): QPopupProxy should be used when you need either a QMenu (on bigger screens) or a QDialog (on smaller screens) to be displayed. It acts as a proxy w...\n- [Pull to refresh](./vue-components/pull-to-refresh.md): The QPullToRefresh is a component that allows the user to pull down in order to refresh page content (or retrieve the newest content).\n- [Radio](./vue-components/radio.md): The QRadio component is another basic element for user input. You can use this to supply a way for the user to pick an option from multiple choices.\n- [Range](./vue-components/range.md): The QRange component is a great way to offer the user the selection of a sub-range of values between a minimum and maximum value, with optional ste...\n- [Rating](./vue-components/rating.md): Quasar Rating is a Component which allows users to rate items, usually known as “Star Rating”.\n- [Resize Observer (for Element)](./vue-components/resize-observer.md): QResizeObserver is a Quasar component that emits a resize event whenever the wrapping DOM element / component (defined as direct parent of QResizeO...\n- [Responsive](./vue-components/responsive.md): QResponsive is a component which forces the content to maintain an aspect ratio based on its width.\n- [Scroll Area](./vue-components/scroll-area.md): The QScrollArea component offers a neat way of customizing the scrollbars by encapsulating your content. Think of it as a DOM element which has ove...\n- [Scroll Observer](./vue-components/scroll-observer.md): QScrollObserver is a Quasar component that emits a scroll event whenever the user scrolls the page or overflowed container with .scroll CSS class a...\n- [Select](./vue-components/select.md): The QSelect component has two types of selection: single or multiple. This component opens up a menu for the selection list and action. A filter ca...\n- [Separator](./vue-components/separator.md): The QSeparator component is used to separate sections of text, other components, etc... It creates a colored line across the width of the parent. I...\n- [Skeleton](./vue-components/skeleton.md): The QSkeleton is a component for displaying a placeholder preview of your content before you load the actual page data. It's a nice way of informin...\n- [Slide Item](./vue-components/slide-item.md): The QSlideItem component is essentially a QItem with two additional slots (left and right) which allows user to drag the item (through mouse or wit...\n- [Slide Transition](./vue-components/slide-transition.md): QSlideTransition slides the DOM element (or component) up or down, based on its visibility: works alongside v-show and v-if on a single element, si...\n- [Slider](./vue-components/slider.md): The QSlider is a great way for the user to specify a number value between a minimum and maximum value, with optional steps between valid values. Th...\n- [QSpace](./vue-components/space.md): The purpose of QSpace (has no props) is to simply fill all available space inside of a flexbox DOM element.\n- [Spinners](./vue-components/spinners.md): A Spinner is used to show the user a timely process is currently taking place. It is an important UX feature, which gives the user the feeling the ...\n- [QSplitter](./vue-components/splitter.md): The QSplitter component allow containers to be split vertically and/or horizontally through a draggable separator bar.\n- [Stepper](./vue-components/stepper.md): Steppers display progress through a sequence of logical and numbered steps. They may also be used for navigation.\nThey're usually useful when the u...\n- [Tab Panels](./vue-components/tab-panels.md): Tab panels are a way of displaying more information using less window real estate.\n- [Table](./vue-components/table.md): QTable is a component that allows you to display data in a tabular manner. It's generally called a datatable. It packs the following main features:\n- [Tabs](./vue-components/tabs.md): Tabs are a way of displaying more information using less window real estate. This page describes the tab selection part through QTabs, QTab and QRo...\n- [QTime](./vue-components/time.md): The QTime component provides a method to input time.\n- [Timeline](./vue-components/timeline.md): The QTimeline component displays a list of events in chronological order. It is typically a graphic design showing a long bar labelled with dates a...\n- [Toggle](./vue-components/toggle.md): The QToggle component is another basic element for user input. You can use this for turning settings, features or true/false inputs on and off.\n- [Toolbar](./vue-components/toolbar.md): QToolbar is a component usually part of Layout Header and Footer, but it can be used anywhere on the page.\n- [Tree](./vue-components/tree.md): Quasar Tree represents a highly configurable component that displays hierarchical data, such as a table of contents in a tree structure.\n- [Uploader](./vue-components/uploader.md): Quasar supplies a way for you to upload files through the QUploader component.\n- [Video](./vue-components/video.md): Using the QVideo component makes embedding a video like Youtube easy. It also resizes to fit the container by default.\n- [Virtual Scroll](./vue-components/virtual-scroll.md): The QVirtualScroll component allows you to display only a part of a long list of items and update the visible items as the user scrolls in the cont...\n\n## vue-components/menu (1)\n\n- [QMenu](./vue-components/menu/menu.md): The QMenu component is a convenient way to show menus. Goes very well with QList as dropdown content, but it's by no means limited to it.\n\n## vue-components/tooltip (1)\n\n- [Tooltip](./vue-components/tooltip/tooltip.md): The QTooltip component is to be used when you want to offer the user more information about a certain area in your App. When hovering the mouse ove...\n\n## vue-composables (11)\n\n- [useDialogPluginComponent composable](./vue-composables/use-dialog-plugin-component.md): ::: tip\nThe useDialogPluginComponent composable is part of Quasar Dialog Plugin (Invoking custom component). If you haven't dug into it by now, ple...\n- [useFormChild composable](./vue-composables/use-form-child.md): This composable refers to QForm wrapping your own custom component which you want to communicate with.\n- [useHydration composable](./vue-composables/use-hydration.md): The useHydration composable is useful when you build for SSR (but can be used for non SSR builds as well). It is a lower level util of the QNoSsr c...\n- [useId composable](./vue-composables/use-id.md): The useId() composable returns a Vue Ref holding a string that can be used as a unique identifier to apply to a DOM node attribute.\n- [useInterval composable](./vue-composables/use-interval.md): The useInterval() composable is similar in scope with the native setInterval(), with some key differences. The composable takes care of \"cancelling...\n- [useMeta composable](./vue-composables/use-meta.md): The useMeta composable is part of Quasar Meta Plugin. If you haven't dug into it by now, please have a first read there.\n- [useQuasar composable](./vue-composables/use-quasar.md): The useQuasar composable is used in order to get access to the $q Object.\n- [useRenderCache composable](./vue-composables/use-render-cache.md): The useRenderCache() composable is useful especially when you are dealing with Vue render functions (though not restricted to it). When you are bui...\n- [useSplitAttrs composable](./vue-composables/use-split-attrs.md): Vue's attrs in a component can contain both listeners and real HTML attributes. The useSplitAttrs() composable breaks down this Vue attr object int...\n- [useTick composable](./vue-composables/use-tick.md): The useTick() composable is similar in scope with the nextTick() from Vue, with some key differences. Once you trigger a nextTick() it will get exe...\n- [useTimeout composable](./vue-composables/use-timeout.md): The useTimeout() composable is similar in scope with the native setTimeout(), with some key differences. Once you trigger a setTimeout(fn, delay) i...\n\n## vue-directives (11)\n\n- [Close Popup Directive](./vue-directives/close-popup.md): This directive is a helper when dealing with QDialog and QMenu components. When attached to a DOM element or component then that component will clo...\n- [Intersection Directive](./vue-directives/intersection.md): \"Intersection\" is a Quasar directive that enables a method to be called when the user scrolls and the DOM element (or component) that it is applied...\n- [Material Ripples](./vue-directives/material-ripples.md): Material Ripple effect can easily be added to any DOM element (or component) through the v-ripple Quasar directive.\n- [Morph Directive](./vue-directives/morph.md): \"Morph\" is a Quasar directive that provides the ability to morph DOM elements between two states.\n- [Mutation Directive](./vue-directives/mutation.md): \"Mutation\" is a Quasar directive that provides the ability to watch for changes being made to the DOM tree and call a method when these are triggered.\n- [Scroll Fire Directive](./vue-directives/scroll-fire.md): \"Scroll Fire\" is a directive that enables a method to be called (once and only once) when the user scrolls current page and the DOM element (or com...\n- [Directive v-scroll](./vue-directives/scroll.md): This is a Vue directive which takes one parameter (a Function) and fires when user scrolls the page containing that DOM node.\n- [Touch Hold Directive](./vue-directives/touch-hold.md): Quasar offers full-featured Vue directives that can totally replace libraries like Hammerjs: v-touch-pan, v-touch-swipe, v-touch-hold and even v-to...\n- [Touch Pan Directive](./vue-directives/touch-pan.md): Quasar offers full-featured Vue directives that can totally replace libraries like Hammerjs: v-touch-pan, v-touch-swipe, v-touch-hold and even v-to...\n- [Touch Repeat Directive](./vue-directives/touch-repeat.md): Quasar offers full-featured Vue directives that can totally replace libraries like Hammerjs: v-touch-pan, v-touch-swipe, v-touch-hold and v-touch-r...\n- [Touch Swipe Directive](./vue-directives/touch-swipe.md): Quasar offers full-featured Vue directives that can totally replace libraries like Hammerjs: v-touch-pan, v-touch-swipe, v-touch-hold and even v-to...\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":78308,"content_sha256":"f498d06966ba75def5e1d23714b6eaa73946fe203309224939ac86a1510806d0"},{"filename":"references/docs/api-explorer/api-explorer.md","content":"---\ntitle: Quasar API Explorer\ndesc: Explore all the Quasar components, directives and plugins API in one place.\nkeys: API Explorer\n---\n\nHere you can explore the API for all the Quasar UI Vue components, Vue directives & Quasar UI plugins.\n\n\n\n\u003cDocApiExplorer />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":262,"content_sha256":"99dd0bd4ab12f4c62119d00b70fad64ea61563ee1c381bbd462be5d891871ff8"},{"filename":"references/docs/app-extensions/development-guide/index-api.md","content":"---\ntitle: App Extension Index API\ndesc: The API for the index script of a Quasar App Extension. Provides access to Quasar context, registers new CLI commands, extends Webpack config and more.\n---\n\nThis page refers to `src/index.js` file, which is executed on `quasar dev` and `quasar build`. This is the main process where you can modify the build to suit the needs of your App Extension. For instance, registering a boot file, modifying the webpack process, registering CSS, registering a UI component, registering a Quasar CLI command, etc.\n\nExample of basic structure of the file:\n\n```js\n// can be async\nexport default function (api) {\n // props & methods for \"api\" Object described below\n}\n```\n\n### api.ctx\n\nSame as the `ctx` from the `/quasar.config` file. Helps you make decisions based on the context in which `quasar dev` or `quasar build` runs.\n\nExample: You might want to use one of the api methods if running for electron mode only.\n\n```js\nif (api.ctx.dev === true && api.ctx.mode.electron === true) {\n api.beforeDev(api => {\n // do something when running quasar dev and\n // with Electron mode\n })\n}\n```\n\n### api.engine\n\nContains the Quasar CLI engine (as String) being used. Examples: `@quasar/app-vite` or `@quasar/app-webpack`.\n\n### api.hasVite\n\nBoolean - is running on `@quasar/app-vite` or not.\n\n### api.hasWebpack\n\nBoolean - is running on `@quasar/app-webpack` or not.\n\n### api.extId\n\nContains the `ext-id` (String) of this App Extension.\n\n### api.prompts\n\nIs an Object which has the answers to the prompts when this App Extension got installed. For more info on prompts, check out [Prompts API](/app-extensions/development-guide/prompts-api).\n\n### api.resolve\n\nResolves paths within the app on which this App Extension is running. Eliminates the need to import `path` and resolve the paths yourself.\n\n```js\n// resolves to root of app\napi.resolve.app('src/my-file.js')\n\n// resolves to root/src of app\napi.resolve.src('my-file.js')\n\n// resolves to root/public of app\n// (@quasar/app-webpack v3.4+ or @quasar/app-vite v1+)\napi.resolve.public('my-image.png')\n\n// resolves to root/src-pwa of app\napi.resolve.pwa('some-file.js')\n\n// resolves to root/src-ssr of app\napi.resolve.ssr('some-file.js')\n\n// resolves to root/src-cordova of app\napi.resolve.cordova('config.xml')\n\n// resolves to root/src-electron of app\napi.resolve.electron('some-file.js')\n\n// resolves to root/src-electron of app\napi.resolve.electron('some-file.js')\n\n// resolves to root/src-bex of app\napi.resolve.bex('some-file.js')\n```\n\n### api.appDir\n\nContains the full path (String) to the root of the app on which this App Extension is running.\n\n### api.hasTypescript \u003cq-badge label=\"@quasar/app-vite 1.6+\" /> \u003cq-badge label=\"@quasar/app-webpack 3.11+\" />\n\n```js\n/**\n * @return {Promise\u003cboolean>} host project has Typescript active or not\n */\nawait api.hasTypescript()\n```\n\n### api.hasLint \u003cq-badge label=\"@quasar/app-vite 1.6+\" /> \u003cq-badge label=\"@quasar/app-webpack 3.11+\" />\n\n```js\n/**\n * @return {Promise\u003cboolean>} host project has ESLint or not\n */\nawait api.hasLint()\n```\n\n### api.getStorePackageName \u003cq-badge label=\"@quasar/app-vite 1.6+\" /> \u003cq-badge label=\"@quasar/app-webpack 3.11+\" />\n\n```js\n/**\n * @return {Promise\u003cstring|undefined>} 'pinia' | 'vuex' | undefined\n */\nawait api.getStorePackageName()\n```\n\n### api.getNodePackagerName \u003cq-badge label=\"@quasar/app-vite 1.6+\" /> \u003cq-badge label=\"@quasar/app-webpack 3.11+\" />\n\n```js\n/**\n * @return {Promise\u003c'npm' | 'yarn' | 'pnpm' | 'bun'>}\n */\nawait api.getNodePackagerName()\n```\n\n### api.compatibleWith\n\nEnsure the App Extension is compatible with a package installed in the host app through a semver condition.\n\nIf the semver condition is not met, then @quasar/app errors out and halts execution.\n\nExample of semver condition: `'1.x || >=2.5.0 || 5.0.0 - 7.2.3'`.\n\n```js\n/**\n * @param {string} packageName\n * @param {string} semverCondition\n */\napi.compatibleWith('@quasar/app', '1.x')\n```\n\n```js A more complex example\nif (api.hasVite === true) {\n api.compatibleWith('@quasar/app-vite', '^2.0.0')\n} else {\n api.compatbileWith('@quasar/app-webpack', '^4.0.0')\n}\n```\n\n### api.hasPackage\n\nDetermine if some package is installed in the host app through a semver condition.\n\nExample of semver condition: `'1.x || >=2.5.0 || 5.0.0 - 7.2.3'`.\n\n```js\n/**\n * @param {string} packageName\n * @param {string} (optional) semverCondition\n * @return {boolean} package is installed and meets optional semver condition\n */\nif (api.hasPackage('vuelidate')) {\n // hey, this app has it (any version of it)\n}\nif (api.hasPackage('quasar', '^2.0.0')) {\n // hey, this app has Quasar UI v2 installed\n}\n```\n\n### api.hasExtension\n\nCheck if another app extension is npm installed and Quasar CLI has invoked it.\n\n```js\n/**\n * Check if another app extension is installed\n *\n * @param {string} extId\n * @return {boolean} has the extension installed & invoked\n */\nif (api.hasExtension(extId)) {\n // hey, we have it\n}\n```\n\n### api.getPackageVersion\n\nGet the version of a host app package.\n\n```js\n/**\n * @param {string} packageName\n * @return {string|undefined} version of app's package\n */\nconsole.log(api.getPackageVersion(packageName))\n// output examples:\n// 1.1.3\n// undefined (when package not found)\n```\n\n### api.extendQuasarConf\n\nExtends quasar.config file\n\n```js\n/**\n * @param {function} fn\n * (cfg: Object, ctx: Object) => undefined\n */\napi.extendQuasarConf((conf, api) => {\n // do something with quasar.config file:\n // add, change anything\n})\n```\n\n```js A more complex example:\napi.extendQuasarConf((conf, api) => {\n if (api.hasVite === true) {\n // do something with quasar.config file that is specific\n // to @quasar/app-vite\n } else {\n // api.hasWebpack === true\n // do something with quasar.config file that is specific\n // to @quasar/app-webpack\n }\n})\n```\n\n#### Registering boot and css files\n\n```js\nexport default function (api, ctx) {\n api.extendQuasarConf((conf, api) => {\n // make sure my-ext boot file is registered\n conf.boot.push('~quasar-app-extension-my-ext/src/boot/my-ext-bootfile.js')\n\n if (api.hasVite !== true) {\n // make sure boot file transpiles\n conf.build.webpackTranspileDependencies.push(\n /quasar-app-extension-my-ext[\\\\/]src[\\\\/]boot/\n )\n // if boot file imports anything, make sure that\n // the regex above matches those files too!\n }\n\n // make sure my-ext css goes through webpack\n conf.css.push('~quasar-app-extension-my-ext/src/component/my-ext.sass')\n })\n}\n```\n\n::: tip\nNotice the tidle (`~`) in front of the paths. This tells Quasar CLI that the path is a dependency from node_modules instead of a relative path to App Extension index script file.\n:::\n\n### api.registerCommand\n\nRegister a command that will become available as `quasar run \u003cext-id> \u003ccmd> [args]` (or the short form: `quasar \u003cext-id> \u003ccmd> [args]`).\n\n```js\n/**\n * @param {string} commandName\n * @param {function} fn\n * ({ args: [ string, ... ], params: {object} }) => ?Promise\n */\napi.registerCommand('start', ({ args, params }) => {\n // do something here\n // this registers the \"start\" command\n // and this handler is executed when running\n // $ quasar run \u003cext-id> start\n})\n```\n\n### api.registerDescribeApi\n\nRegister an API file for `$ quasar describe` command.\n\n```js\n/**\n * @param {string} name\n * @param {string} relativePath\n * (relative path starting from the file where you have this call)\n */\napi.registerDescribeApi(\n 'MyComponent',\n './relative/path/to/my/component/file.json'\n)\n```\n\nThe above will then respond to `$ quasar describe MyComponent`.\n\nFor syntax of such a JSON file, look into `/node_modules/quasar/dist/api` (in your project folder). Be aware that your JSON must contain a `type` property (\"component\", \"directive\", \"plugin\"). For instance:\n\n```json\n{\n \"type\": \"component\",\n \"props\": {\n },\n ...\n}\n```\n\n::: tip\nAlways test with the `quasar describe` command to ensure you got the syntax right and there are no errors.\n:::\n\n### api.getPersistentConf\n\nGet the internal persistent config of this extension. Returns empty object if it has none.\n\n```js\n/**\n * @return {object} cfg\n */\napi.getPersistentConf()\n```\n\n### api.setPersistentConf\n\nSet the internal persistent config of this extension. If it already exists, it is overwritten.\n\n```js\n/**\n * @param {object} cfg\n */\napi.setPersistentConf({\n // ....\n})\n```\n\n### api.mergePersistentConf\n\nDeep merge into the internal persistent config of this extension. If extension does not have any config already set, this is essentially equivalent to setting it for the first time.\n\n```js\n/**\n * @param {object} cfg\n */\napi.mergePersistentConf({\n // ....\n})\n```\n\n### api.beforeDev\n\nPrepare external services before `$ quasar dev` command runs, like starting some backend or any other service that the app relies on.\n\nCan use async/await or directly return a Promise.\n\n```js\n/**\n * @param {function} fn\n * (api, { quasarConf }) => ?Promise\n */\napi.beforeDev((api, { quasarConf }) => {\n // do something\n})\n```\n\n### api.afterDev\n\nRun hook after Quasar dev server is started (`$ quasar build`). At this point, the dev server has been started and is available should you wish to do something with it.\n\nCan use async/await or directly return a Promise.\n\n```js\n/**\n * @param {function} fn\n * (api, { quasarConf }) => ?Promise\n */\napi.afterDev((api, { quasarConf }) => {\n // do something\n})\n```\n\n### api.beforeBuild\n\nRun hook before Quasar builds app for production (`$ quasar build`). At this point, the distributables folder hasn't been created yet.\n\nCan use async/await or directly return a Promise.\n\n```js\n/**\n * @param {function} fn\n * (api, { quasarConf }) => ?Promise\n */\napi.beforeBuild((api, { quasarConf }) => {\n // do something\n})\n```\n\n### api.afterBuild\n\nRun hook after Quasar built app for production (`$ quasar build`). At this point, the distributables folder has been created and is available should you wish to do something with it.\n\nCan use async/await or directly return a Promise.\n\n```js\n/**\n * @param {function} fn\n * (api, { quasarConf }) => ?Promise\n */\napi.afterBuild((api, { quasarConf }) => {\n // do something\n})\n```\n\n### api.onPublish\n\nRun hook if publishing was requested (`$ quasar build -P`), after Quasar built app for production and the afterBuild hook (if specified) was executed.\n\nCan use async/await or directly return a Promise.\n\n```js\n/**\n * @param {function} fn\n * () => ?Promise\n * @param {object} opts\n * * arg - argument supplied to \"--publish\"/\"-P\" parameter\n * * distDir - folder where distributables were built\n */\napi.onPublish((api, opts) => {\n // do something\n})\n```\n\n## @quasar/app-vite only\n\n### api.extendViteConf\n\n```js\n/**\n * @param {function} fn\n * (viteConf: Object, invoke: Object {isClient, isServer}, api) => undefined\n */\nif (api.hasVite === true) {\n api.extendViteConf((viteConf, { isClient, isServer }, api) => {\n // add/remove/change Quasar CLI generated Vite config object\n })\n}\n```\n\n### api.extendSSRWebserverConf\n\n```js\n/**\n * @param {function} fn\n * (esbuildConf: Object, api) => undefined\n */\nif (api.hasVite === true) {\n api.extendSSRWebserverConf((esbuildConf, api) => {\n // add/remove/change Quasar CLI generated esbuild config object\n // that is used for the SSR webserver (includes SSR middlewares)\n })\n}\n```\n\n### api.extendElectronMainConf\n\n```js\n/**\n * @param {function} fn\n * (esbuildConf: Object, api) => undefined\n */\nif (api.hasVite === true) {\n api.extendElectronMainConf((esbuildConf, api) => {\n // add/remove/change Quasar CLI generated esbuild config object\n // that is used for the SSR webserver (includes SSR middlewares)\n })\n}\n```\n\n### api.extendElectronPreloadConf\n\n```js\n/**\n * @param {function} fn\n * (esbuildConf: Object, api) => undefined\n */\nif (api.hasVite === true) {\n api.extendElectronPreloadConf((esbuildConf, api) => {\n // add/remove/change Quasar CLI generated esbuild config object\n // that is used for the SSR webserver (includes SSR middlewares)\n })\n}\n```\n\n### api.extendPWACustomSWConf\n\n```js\n/**\n * @param {function} fn\n * (esbuildConf: Object, api) => undefined\n */\nif (api.hasVite === true) {\n api.extendPWACustomSWConf((esbuildConf, api) => {\n // add/remove/change Quasar CLI generated esbuild config object\n // that is used for the SSR webserver (includes SSR middlewares)\n })\n}\n```\n\n### api.extendBexScriptsConf\n\n```js\n/**\n * @param {function} fn\n * (esbuildConf: Object, api) => undefined\n */\nif (api.hasVite === true) {\n api.extendBexScriptsConf((esbuildConf, api) => {\n // add/remove/change Quasar CLI generated esbuild config object\n // that is used for the SSR webserver (includes SSR middlewares)\n })\n}\n```\n\n## @quasar/app-webpack only\n\n### api.chainWebpack\n\nChain webpack config\n\n```js\n/**\n * @param {function} fn\n * (chain: ChainObject, invoke: Object {isClient, isServer}, api) => undefined\n */\nif (api.hasWebpack === true) {\n api.chainWebpack((chain, { isClient, isServer }, api) => {\n // add/remove/change chain (Webpack chain Object)\n })\n}\n```\n\nThe configuration is a Webpack chain Object. The API for it is described on webpack-chain docs.\n\n### api.extendWebpack\n\nExtend webpack config\n\n```js\n/**\n * @param {function} fn\n * (cfg: Object, invoke: Object {isClient, isServer}, api) => undefined\n */\nif (api.hasWebpack === true) {\n api.extendWebpack((cfg, { isClient, isServer }, api) => {\n // add/remove/change cfg (Webpack configuration Object)\n })\n}\n```\n\n### api.chainWebpackMainElectronProcess\n\nChain webpack config of the main electron process\n\n```js\n/**\n * @param {function} fn\n * (chain: ChainObject) => undefined\n */\nif (api.hasWebpack === true) {\n api.chainWebpackMainElectronProcess((chain, { isClient, isServer }, api) => {\n // add/remove/change chain (Webpack chain Object)\n })\n}\n```\n\n### api.extendWebpackMainElectronProcess\n\nExtend webpack config Object of the main electron process\n\n```js\n/**\n * @param {function} fn\n * (cfg: Object) => undefined\n */\nif (api.hasWebpack === true) {\n api.extendWebpackMainElectronProcess((cfg, { isClient, isServer }, api) => {\n // add/remove/change cfg (Webpack configuration Object)\n })\n}\n```\n\n### api.chainWebpackPreloadElectronProcess\n\nChain webpack config of the preload electron process\n\n```js\n/**\n * @param {function} fn\n * (chain: ChainObject) => undefined\n */\nif (api.hasWebpack === true) {\n api.chainWebpackPreloadElectronProcess(\n (chain, { isClient, isServer }, api) => {\n // add/remove/change chain (Webpack chain Object)\n }\n )\n}\n```\n\n### api.extendWebpackPreloadElectronProcess\n\nExtend webpack config Object of the preload electron process\n\n```js\n/**\n * @param {function} fn\n * (cfg: Object) => undefined\n */\nif (api.hasWebpack === true) {\n api.extendWebpackPreloadElectronProcess(\n (cfg, { isClient, isServer }, api) => {\n // add/remove/change cfg (Webpack configuration Object)\n }\n )\n}\n```\n\n### api.chainWebpackWebserver\n\nChain webpack config of SSR webserver (includes the SSR middlewares from /src-ssr/middlewares)\n\n```js\n/**\n * @param {function} fn\n * (chain: ChainObject) => undefined\n */\nif (api.hasWebpack === true) {\n api.chainWebpackWebserver((chain, { isClient, isServer }, api) => {\n // add/remove/change chain (Webpack chain Object)\n // isClient is always \"false\" and isServer is always \"true\"\n })\n}\n```\n\n### api.extendWebpackWebserver\n\nExtend webpack config Object of SSR webserver (includes the SSR middlewares from /src-ssr/middlewares)\n\n```js\n/**\n * @param {function} fn\n * (cfg: Object) => undefined\n */\nif (api.hasWebpack === true) {\n api.extendWebpackWebserver((cfg, { isClient, isServer }, api) => {\n // add/remove/change cfg (Webpack configuration Object)\n // isClient is always \"false\" and isServer is always \"true\"\n })\n}\n```\n\n### api.chainWebpackCustomSW\n\nChain webpack config for the custom service worker when using InjectManifest (content of /src-pwa/custom-service-worker.js):\n\n```js\n/**\n * @param {function} fn\n * (cfg: ChainObject) => undefined\n */\nif (api.hasWebpack === true) {\n api.chainWebpackCustomSW((cfg, { isClient, isServer }, api) => {\n // add/remove/change cfg (Webpack chain Object)\n })\n}\n```\n\n### api.extendWebpackCustomSW\n\nExtend webpack config Object for the custom service worker when using InjectManifest (content of /src-pwa/custom-service-worker.js):\n\n```js\n/**\n * @param {function} fn\n * (chain: Object) => undefined\n */\nif (api.hasWebpack === true) {\n api.extendWebpackCustomSW((chain, { isClient, isServer }, api) => {\n // add/remove/change chain (Webpack configuration Object)\n })\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":16562,"content_sha256":"f0ffa3cf233b48e55c24caf2458930cf84234446d2a82f9347acab13b95d96f0"},{"filename":"references/docs/app-extensions/development-guide/install-api.md","content":"---\ntitle: App Extension Install API\ndesc: The API for the install script of a Quasar App Extension. Initializes the app space by rendering or changing files and more.\n---\n\nThis page refers to `src/install.js` file which is executed on the installation of the App Extension only. Not all App Extensions will need an install -- this is an optional step.\n\nExample of basic structure of the file:\n\n```js\n// can be async\nexport default function (api) {\n // props and methods for \"api\" Object\n // are described below\n}\n```\n\n### api.engine\n\nContains the Quasar CLI engine (as String) being used. Examples: `@quasar/app-vite` or `@quasar/app-webpack`.\n\n### api.hasVite\n\nBoolean - is running on `@quasar/app-vite` or not.\n\n### api.hasWebpack\n\nBoolean - is running on `@quasar/app-webpack` or not.\n\n### api.extId\n\nContains the `ext-id` (String) of this App Extension.\n\n### api.prompts\n\nIs an Object which has the answers to the prompts when this App Extension gets installed. For more info on prompts, check out [Prompts API](/app-extensions/development-guide/prompts-api).\n\n### api.resolve\n\nResolves paths within the app on which this App Extension is running. Eliminates the need to import `path` and resolve the paths yourself.\n\n```js\n// resolves to root of app\napi.resolve.app('src/my-file.js')\n\n// resolves to root/src of app\napi.resolve.src('my-file.js')\n\n// resolves to root/public of app\n// (@quasar/app-webpack v3.4+ or @quasar/app-vite v1+)\napi.resolve.public('my-image.png')\n\n// resolves to root/src-pwa of app\napi.resolve.pwa('some-file.js')\n\n// resolves to root/src-ssr of app\napi.resolve.ssr('some-file.js')\n\n// resolves to root/src-cordova of app\napi.resolve.cordova('config.xml')\n\n// resolves to root/src-electron of app\napi.resolve.electron('some-file.js')\n\n// resolves to root/src-bex of app\napi.resolve.bex('some-file.js')\n```\n\n### api.appDir\n\nContains the full path (String) to the root of the app on which this App Extension is running.\n\n### api.hasTypescript \u003cq-badge label=\"@quasar/app-vite 1.6+\" /> \u003cq-badge label=\"@quasar/app-webpack 3.11+\" />\n\n```js\n/**\n * @return {Promise\u003cboolean>} host project has Typescript active or not\n */\nawait api.hasTypescript()\n```\n\n### api.hasLint \u003cq-badge label=\"@quasar/app-vite 1.6+\" /> \u003cq-badge label=\"@quasar/app-webpack 3.11+\" />\n\n```js\n/**\n * @return {Promise\u003cboolean>} host project has ESLint or not\n */\nawait api.hasLint()\n```\n\n### api.getStorePackageName \u003cq-badge label=\"@quasar/app-vite 1.6+\" /> \u003cq-badge label=\"@quasar/app-webpack 3.11+\" />\n\n```js\n/**\n * @return {Promise\u003cstring|undefined>} 'pinia' | 'vuex' | undefined\n */\nawait api.getStorePackageName()\n```\n\n### api.getNodePackagerName \u003cq-badge label=\"@quasar/app-vite 1.6+\" /> \u003cq-badge label=\"@quasar/app-webpack 3.11+\" />\n\n```js\n/**\n * @return {Promise\u003c'npm' | 'yarn' | 'pnpm' | 'bun'>}\n */\nawait api.getNodePackagerName()\n```\n\n### api.compatibleWith\n\nEnsure the App Extension is compatible with a package installed in the host app through a semver condition.\n\nIf the semver condition is not met, then Quasar CLI errors out and halts execution.\n\nExample of semver condition: `'1.x || >=2.5.0 || 5.0.0 - 7.2.3'`.\n\n```js\n/**\n * @param {string} packageName\n * @param {string} semverCondition\n */\napi.compatibleWith(packageName, '1.x')\n```\n\n```js A more complex example:\nif (api.hasVite === true) {\n api.compatibleWith('@quasar/app-vite', '^2.0.0')\n} else {\n api.compatbileWith('@quasar/app-webpack', '^4.0.0')\n}\n```\n\n### api.hasPackage\n\nDetermine if some package is installed in the host app through a semver condition.\n\nExample of semver condition: `'1.x || >=2.5.0 || 5.0.0 - 7.2.3'`.\n\n```js\n/**\n * @param {string} packageName\n * @param {string} (optional) semverCondition\n * @return {boolean} package is installed and meets optional semver condition\n */\nif (api.hasPackage('vuelidate')) {\n // hey, this app has it (any version of it)\n}\nif (api.hasPackage('quasar', '^2.0.0')) {\n // hey, this app has Quasar UI v2 installed\n}\n```\n\n### api.hasExtension\n\nCheck if another app extension is npm installed and Quasar CLI has invoked it.\n\n```js\n/**\n * Check if another app extension is installed\n *\n * @param {string} extId\n * @return {boolean} has the extension installed & invoked\n */\nif (api.hasExtension(extId)) {\n // hey, we have it\n}\n```\n\n### api.getPackageVersion\n\nGet the version of a host app package.\n\n```js\n/**\n * @param {string} packageName\n * @return {string|undefined} version of app's package\n */\nconsole.log(api.getPackageVersion(packageName))\n// output examples:\n// 1.1.3\n// undefined (when package not found)\n```\n\n### api.extendPackageJson\n\nHelper method to extend package.json with new props. If specifying existing props, **it will override** them.\n\n```js\n/**\n * @param {object|string} extPkg - Object to extend with or relative path to a JSON file\n */\napi.extendPackageJson({\n scripts: {\n electron: 'quasar dev -m electron'\n }\n})\n```\n\nThe above example adds an npm script to the app's package.json, so you can then execute `yarn electron` (or the equivalent `npm run electron`).\n\n### api.extendJsonFile\n\nExtend a JSON file with new props (deep merge). If specifying existing props, it will override them.\n\n```js\n/**\n * @param {string} file (relative path to app root folder)\n * @param {object} newData (Object to merge in)\n */\napi.extendJsonFile('src/some.json', {\n newProp: 'some-value'\n})\n```\n\n### api.render\n\nRenders (copies) a folder from your App Extension templates (any folder you specify) into root of the app. Maintains the same folder structure that the template folder has.\n\nIf some of the files already exist in the app then it will ask the user if they should be overwritten or not.\n\nNeeds a relative path to the folder of the file calling render().\n\n```js\n/**\n * Render a folder from extension templates into devland\n * Needs a path (to a folder) relative to the path of the file where render() is called\n *\n * @param {string} templatePath (relative path to folder to render in app)\n * @param {object} scope (optional; rendering scope variables)\n */\napi.render('./path/to/a/template/folder')\n```\n\n#### Filename edge cases\n\nIf you want to render a template file that either begins with a dot (i.e. .env) you will have to follow a specific naming convention, since dotfiles are ignored when publishing your plugin to npm:\n\n```bash\n# templates containing dotfiles must use an\n# underscore instead of the dot in their names:\n\nsome-folder/_env\n\n# When calling api.render('./some-folder'), this will be\n# rendered in the project folder as:\n\n/.env\n```\n\nIf you want to render a file whose name actually begins with an underscore, then the filename must begin with `__` (two underscore characters instead of only one):\n\n```bash\nsome-folder/__my.css\n\n# When calling api.render('./template'), this will be\n# rendered in the project folder as:\n\n/_my.css\n```\n\n#### Using scope\n\nYou can also inject some decision-making code into the files to be rendered by interpolating with lodash/template syntax.\n\nExample:\n\n```js src/install.js\n// (my-folder is located in same folder as\n// the file in which following call takes place)\napi.render('./my-folder', {\n prompts: api.prompts\n})\n```\n\nLet's imagine we use a [Prompts API](/app-extensions/development-guide/prompts-api) file too. It asks the user if he/she wants \"Feature X\" and stores the answer in a variable called \"featureX\".\n\nWe can take some decisions on what the files that we render look like, during rendering them. This removes the need of creating two folders and deciding which to render, based on some decision.\n\n```js src/my-folder/some-file.js\n\u003c% if (prompts.featureX) { %>\nconst message = 'This is content when \"Feature X\" exists'\n\u003c% } else { %>\nconst message = 'This is content when we don\\'t have \"Feature X\"'\n\u003c% } %>\n```\n\nPossibilities are limited only by your imagination.\n\n### api.renderFile\n\nSimilar with api.render() with the difference that this method renders a single file.\n\n```js\n/**\n * Render a file from extension template into devland\n * Needs a path (to a file) relative to the path of the file where renderFile() is called\n *\n * @param {string} relativeSourcePath (file path relative to the folder from which the install script is called)\n * @param {string} relativeTargetPath (file path relative to the root of the app -- including filename!)\n * @param {object} scope (optional; rendering scope variables)\n */\napi.renderFile(\n './path/to/a/template/filename',\n 'path/relative/to/app/root/filename',\n {\n prompts: api.prompts\n }\n)\n\napi.renderFile('./my-file.json', 'src/my-file.json')\n```\n\n### api.getPersistentConf\n\nGet the internal persistent config of this extension. Returns empty object if it has none.\n\n```js\n/**\n * @return {object} cfg\n */\napi.getPersistentConf()\n```\n\n### api.setPersistentConf\n\nSet the internal persistent config of this extension. If it already exists, it is overwritten.\n\n```js\n/**\n * @param {object} cfg\n */\napi.setPersistentConf({\n // ....\n})\n```\n\n### api.mergePersistentConf\n\nDeep merge into the internal persistent config of this extension. If extension does not have any config already set, this is essentially equivalent to setting it for the first time.\n\n```js\n/**\n * @param {object} cfg\n */\napi.mergePersistentConf({\n // ....\n})\n```\n\n### api.onExitLog\n\nAdds a message to be printed after App CLI finishes up installing the App Extension and is about to exit. Can be called multiple times to register multiple exit logs.\n\n```js\n/**\n * @param {string} msg\n */\napi.onExitLog('Thanks for installing my awesome extension')\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9489,"content_sha256":"b5174a556776a882b533363aea0f080bebb991c67b4d7275bf917c18d468970e"},{"filename":"references/docs/app-extensions/development-guide/introduction.md","content":"---\ntitle: App Extension Development\ndesc: How to setup your machine for a Quasar App Extension development and getting started quickly.\nscope:\n appExtensionTree:\n l: '.'\n c:\n - l: package.json\n - l: src\n c:\n - l: index.js\n e: Described in Index API\n - l: install.js\n e: Described in Install API\n - l: prompts.js\n e: Described in Prompts API\n - l: uninstall.js\n e: Described in Uninstall API\n uiKitTree:\n l: '.'\n c:\n - l: app-extension\n c:\n - l: package.json\n - l: src\n c:\n - l: index.js\n e: Described in Index API\n - l: install.js\n e: Described in Install API\n - l: prompts.js\n e: Described in Prompts API\n - l: uninstall.js\n e: Described in Uninstall API\n - l: ui\n c:\n - l: package.json\n - l: build\n e: build scripts\n - l: dev\n e: Quasar app for testing component/directive\n - l: src\n c:\n - l: components\n e: '(optional) Folder for your component(s)'\n c:\n - l: Component.js\n e: '(optional) Code for your component(s)'\n - l: Component.sass\n e: '(optional) Sass for your component(s)'\n - l: directives\n e: '(optional) Folder for your directive(s)'\n c:\n - l: Directive.js\n e: '(optional) Code for your directive(s)'\n - l: Directive.sass\n e: '(optional) Sass for your directive(s)'\n - l: index.common.js\n e: CommonJS entry point\n - l: index.esm.js\n e: ESM entry point\n - l: index.umd.js\n e: UMD entry point\n - l: vue-plugin.js\n e: Exports the associated Vue plugin\n - l: index.sass\n e: Exports the associated SASS files\n---\n\nThis section of the docs deals with creating your own App Extensions.\n\nIt is assumed you have already installed one of the official App Extensions. Having this experience at your disposal is going to be very valuable when you start building your own App Extensions. If you run into problems, please visit our Discord server's channel `#app-extensions`.\n\n## Getting started\n\nAn App Extension is an npm package. There are two official kits for creating App Extensions:\n\n1. App Extension (AE) kit\n2. UI kit\n\n### App Extension (AE) kit\n\nIf your app extension does _not_ involve UI (i.e. does _not_ have components or directives) then use the AE kit. An example of this would be an extension that creates a boot file only.\n\n### UI kit\n\nIf your app extension does involve UI (i.e. does have components or directives) then use the UI kit. An example of this would be an extension that provides a UI element for use in your app. This has a `ui` folder for creating your component/directive, a `ui/dev` Quasar application for testing your component/directive in isolation, and an `app-extension` folder for creating the App Extension that will be used for injecting your component/directive via the Quasar CLI into a Quasar app. The UI kit can also be used such that your component/directive can also be used with the Quasar Vite plugin or UMD.\n\n### 3rd party integration\n\nIf your objective is to install a 3rd-party library into Vue, then it depends upon the library...\n\n- If you also aim to provide some UI components or such that uses that Vue plugin, you should use the _UI Kit_. This would be a good choice for including something like a Calendar extension.\n- If the only objective is to load it through a simple `app.use(SomeVuePlugin)` in a boot file, and maybe some config updates and such, the _AE Kit_ may be a better choice. This is a good choice for example for something like including Axios.\n\n### Creating the App Extension\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn create quasar\n# then pick the AppExtension option\n\u003c\u003c| bash NPM |>>\n$ npm init quasar@latest\n# then pick the AppExtension option\n\u003c\u003c| bash PNPM |>>\n$ pnpm create quasar@latest\n# then pick the AppExtension option\n\u003c\u003c| bash Bun |>>\n$ bun create quasar@latest\n# then pick the AppExtension option\n```\n\n\n\nIt will prompt you about your specific needs. Do you need an install script, an uninstall script, will you be prompting the user with some questions? Pick only what you will be using. You can manually add these later if you decide otherwise.\n\nFor the sake of this documentation page, let's assume we answered with `my-ext` to the App Extension `ext-id` question (regarding the prompts above). Remember that the folder name for the App Extension source folder can be different from the actual `ext-id`. At the end, we will publish our new npm package (`quasar-app-extension-my-ext`).\n\nBased on your response, Quasar CLI will create a folder for your App Extension’s source code that will have the following structure:\n\nThe app-extension kit:\n\n\u003cDocTree :def=\"scope.appExtensionTree\" />\n\nThe ui kit:\n\n\u003cDocTree :def=\"scope.uiKitTree\" />\n\nExcept for `src/index.js` (from the `app-extension` kit) or `app-extension/src/index.js` (from the `ui` kit) , all the other files are optional. You can manually add or remove them at any point in time.\n\nWhen using the `UI` kit, you will have two npm packages; one for the App Extension and one for the UI module. For testing with the `dev` app, from the `ui` folder type `yarn dev`. Create pages in the `dev` folder for testing and they will automatically be injected into the test app. Also, check out the `scripts` section in the `package.json` to see what you have available. When you `yarn build`, a `dist` folder will be created and populated with various types of packages (common, esm, and umd).\n\n## App Extension Scripts description\n\n| Name | Description |\n| ------------------ | --------------------------------------------------------- |\n| `src/prompts.js` | Handles the prompts when installing the App Extension |\n| `src/install.js` | Extends the installation procedure of the App Extension |\n| `src/index.js` | Is executed on `quasar dev` and `quasar build` |\n| `src/uninstall.js` | Extends the uninstallation procedure of the App Extension |\n\n## Handling package dependencies\n\nIf your App Extension has its own dependencies over some packages in order for it to be able to run (except for packages supplied by Quasar CLI, like \"quasar\", \"@quasar/extras\", \"@quasar/app\" -- you should use \"api.compatibleWith()\" for those in your /install.js and /index.js scripts -- check [Install API](/app-extensions/development-guide/install-api) and [Index API](/app-extensions/development-guide/index-api)), then yarn/npm installing them into your App Extension folder will supply them into the hosting app.\n\nExample: You are creating a UI component that depends on \"my-table\" npm package (name is bogus, just for making a point here), then you should yarn/npm install \"my-table\" in your App Extension folder.\n\n::: warning\nNever yarn/npm install packages that are supplied by the Quasar CLI, because App Extensions should not be so intrusive and force the user to use a certain Quasar version. Instead, make use of \"api.compatibleWith()\" for those, which is equivalent to softly saying \"Sorry, you need to install this version of Quasar if you want to take advantage of my App Extension\".\n:::\n\n## Manually testing\n\nWe need to create a Quasar project folder to be able to test it while we develop the extension:\n\n```bash\n$ yarn create quasar\n# or\n$ npm init quasar@latest\n\n# pick \"App with Quasar CLI\"\n```\n\n### Install and prompts scripts\n\n::: tip\nLearn more about what you can do with the [Prompts API](/app-extensions/development-guide/prompts-api) and the [Install API](/app-extensions/development-guide/install-api).\n:::\n\nInside the testing Quasar project folder, we manually add our App Extension. Notice that we are not specifying the npm package name (it's not published yet!) but a path to our App Extension folder where we develop it, since we want to test unpublished work:\n\n```bash\n$ yarn add --dev file://path/to/our/app/ext/app-extension\n# or\n$ yarn add --dev link://path/to/our/app/ext/app-extension\n# or\n$ npm add --save-dev file://path/to/our/app/ext/app-extension\n```\n\nYou will need to figure out which command works best for your environment.\n\n::: warning\nThere have been many reports of problems linking via `file:` and `link:`. This is outside of Quasar's reach, but is likely to do with your development environment, aka your mileage with Windows will vary.\n:::\n\nWe then invoke it. The invoking procedure assumes that the App Extension's package is already yarn/npm installed (which we did earlier) and skips that step:\n\n```bash\n# we said our \u003cext-id> will be \"my-ext\", so:\n$ quasar ext invoke my-ext\n```\n\nThis will trigger the installation of our new App Extension. You need to redo these two steps each time you make changes and you want to test them.\n\nAdditionally, if you would like to have HMR (hot module reload) capabilities in your test app while developing your App Extension, then your `quasar.config file > devServer > watchFiles` would look like this:\n\n```js\n// quasar.config file for\n// Quasar CLI with Webpack (@quasar/app-webpack)\n\ndevServer: {\n // be sure to change \u003cmyextid> below to\n // your App Extension name:\n watchFiles: ['/node_modules/quasar-app-extension-\u003cmyextid>/*']\n}\n```\n\n#### @quasar/app-webpack\n\nYou might want to extend the Webpack config. Assuming you are using the [`chainWebpack`](/quasar-cli-webpack/handling-webpack#usage-with-quasar-conf-js) method, your `quasar.config file > build > chainWebpack` should look like this:\n\n```js\nchainWebpack (chain) {\n chain.merge({\n snapshot: {\n managedPaths: []\n }\n })\n},\n```\n\n#### @quasar/app-vite\n\nYou might want to extend the Vite config. Assuming you are using the [`extendViteConf`](/quasar-cli-vite/handling-vite#updating-vite-config) method, your `quasar.config file > build > extendViteConf` should look like this:\n\n```js\nextendViteConf (viteConf, { isClient, isServer }) {\n // do stuff in-place with viteConf\n},\n```\n\n### Uninstall script\n\n::: tip\nLearn more about what you can do with the [Uninstall API](/app-extensions/development-guide/uninstall-api).\n:::\n\nAssuming you've installed your App Extension following the section above, we can now test the uninstall script (if you have any):\n\n```bash\n$ quasar ext uninvoke my-ext\n```\n\nThe command above similarly does not modify or remove the npm package from package.json and node_modules. It simply calls the uninstall script and removes it from the registered/installed App Extensions list in your testing Quasar app project folder. Your end-user will however call `$ quasar ext remove my-ext` to uninstall it, which also uninstalls the npm package.\n\nYou need to redo these install steps and issue the uninvoke command each time you make changes to the uninstall script and you want to test them.\n\n### Index script\n\nIn the sections above we described how to test the prompts, install and uninstall scripts. Now it's time for the index script, which is the heart of your App Extension.\n\nThis is where you can tamper with all `quasar.config` file options, extend the Webpack configuration, register Quasar CLI commands, start up external services required for developing your app and many more.\n\nAs a result, the index script is run each time `$ quasar dev` and `$ quasar build` are executed.\n\nIn order to test the index script, you can repeat the uninstall and install procedures described above each time you change something in the App Extension script code. But it becomes very tedious. If you are developing on a Unix OS (MacOS, Linux), you can take advantage of the `yarn link` command which creates a symbolic link from the Quasar testing app's node_modules folder to the folder of your extension:\n\n```bash\n$ cd /path/to/app/extension/folder\n\n# we register the extension through yarn\n$ yarn link\n\n$ cd /path/to/quasar/testing/app/folder\n\n$ yarn link quasar-app-extension-\u003cext-id>\n# in our demo case, it's this:\n# $ yarn link quasar-app-extension-my-ext\n```\n\nRemember that if you need to `yarn/npm install` any dependencies into **your** App Extension, then you must also uninstall your App Extension and re-install it in your test app:\n\n```bash\n$ cd /path/to/app/extension/folder\n\n# run yarn/npm command (install/uninstall, etc)\n\n# then\n\n$ cd /path/to/quasar/testing/app/folder\n\n# Uninstall the app ext\n$ quasar ext uninvoke my-ext\n\n# Re-install the app ext\n$ quasar ext invoke my-ext\n```\n\nYou really only need to `quasar ext invoke my-ext` (install) the App Extension to re-install it. The above information is for completeness.\n\n::: warning\nThere have been many reports of problems with `yarn link` on Windows. This is outside of Quasar's reach, but is likely to do with your development environment, aka your mileage with Windows will vary.\n:::\n\n::: tip\nLearn more about what you can do with the [Index API](/app-extensions/development-guide/index-api).\n:::\n\n## Publishing\n\nWhen you finalized your App Extension and you're ready to deploy it, all you need to do is to publish it to the npm repository.\n\nInside of your App Extension folder, run yarn publish or npm publish. Both do the same thing.\n\n::: warning\nIt's important to remember to NOT strip out the `quasar-app-extension-` prefix from the `name` property of your extension's `package.json`, otherwise Quasar CLI will not recognize it.\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":13697,"content_sha256":"a9d598337a377b7e1aac798a65d7d9c80c9d1fcb011db96a86a6f48410ca2c1e"},{"filename":"references/docs/app-extensions/development-guide/prompts-api.md","content":"---\ntitle: App Extension Prompts API\ndesc: Syntax of the questions that the user is going to be asked in order to configure the Quasar App Extension.\n---\n\nThis page refers to `src/prompts.js` file which handles the prompts when installing the App Extension. Not all App Extensions will need prompts -- this is an optional step.\n\nThe user's answers are stored into `/quasar.extensions.json` (root of project folder), which should not be tampered with unless you really know what you are doing.\n\nExample of basic structure of the file:\n\n```js\n// For @quasar/app-vite 1.6+ and @quasar/app-webpack v3.11+\n// 1. It can be async\n// 2. It receives the \"api\" param\nexport default function (api) {\n return [\n // questions\n ]\n}\n```\n\nYou will have access to `api.prompts` (which holds your App Extension's answers) in [Install](/app-extensions/development-guide/install-api), [Index](/app-extensions/development-guide/index-api) and [Uninstall](/app-extensions/development-guide/uninstall-api).\n\nLet's now focus on the structure of the returned Array which defines the questions. The sections below offer examples for the most used types of questions.\n\n## Questions format\n\n::: warning\nThe following is not an exhaustive list of possible types of questions and by no means it describes the full API available. Check out Inquirer.js for that (which is used by Quasar CLI under the hood).\n:::\n\n### String\n\n```js\n{\n // \"description\" will be the variable\n // storing the answer\n name: 'description'\n type: 'input',\n required: false, // optional\n message: 'Project description',\n default: 'A Quasar Framework app', // optional\n}\n```\n\n```js\n{\n name: 'source_build',\n type: 'input',\n required: true, // optional\n message:\n 'If you want a separate file to be the source image during production, please specify it here: ',\n validate: (input) => {\n // ...do something ...\n },\n default: (answers) => {\n return answers.source_dev || defaultImg\n }\n}\n```\n\n### Confirm\n\n```js\n{\n // \"featureX\" will be the variable\n // storing the answer\n name: 'featureX',\n type: 'confirm',\n message: 'Use Feature X?',\n default: true // optional\n}\n```\n\n### List of choices\n\n```js\n{\n // \"iconSet\" will be the variable\n // storing the answer\n name: 'iconSet',\n type: 'list',\n message: 'Choose Icon Set',\n choices: [\n {\n name: 'Material Icons (recommended)',\n value: 'material-icons', // value of the answer variable\n short: 'Material Icons' // Short name displayed after user picks this\n },\n {\n name: 'Fontawesome v6',\n value: 'fontawesome-v6', // value of the answer variable\n short: 'Fontawesome v6' // Short name displayed after user picks this\n }\n // ... all other choices\n ]\n}\n```\n\n## The API param \u003cq-badge label=\"@quasar/app-vite 1.6+\" /> \u003cq-badge label=\"@quasar/app-webpack 3.11+\" />\n\n::: warning COMPATIBILITY WARNING\nThe `api` param has been introduced in @quasar/app-vite v1.6+ and @quasar/app-webpack v3.11+.\n\nOlder versions of these CLIs will not supply any param.\n:::\n\n### api.engine\n\nContains the Quasar CLI engine (as String) being used. Examples: `@quasar/app-vite` or `@quasar/app-webpack`.\n\n### api.hasVite\n\nBoolean - is running on `@quasar/app-vite` or not.\n\n### api.hasWebpack\n\nBoolean - is running on `@quasar/app-webpack` or not.\n\n### api.extId\n\nContains the `ext-id` (String) of this App Extension.\n\n### api.resolve\n\nResolves paths within the app on which this App Extension is running. Eliminates the need to import `path` and resolve the paths yourself.\n\n```js\n// resolves to root of app\napi.resolve.app('src/my-file.js')\n\n// resolves to root/src of app\napi.resolve.src('my-file.js')\n\n// resolves to root/public of app\n// (@quasar/app-webpack v3.4+ or @quasar/app-vite v1+)\napi.resolve.public('my-image.png')\n\n// resolves to root/src-pwa of app\napi.resolve.pwa('some-file.js')\n\n// resolves to root/src-ssr of app\napi.resolve.ssr('some-file.js')\n\n// resolves to root/src-cordova of app\napi.resolve.cordova('config.xml')\n\n// resolves to root/src-electron of app\napi.resolve.electron('some-file.js')\n\n// resolves to root/src-bex of app\napi.resolve.bex('some-file.js')\n```\n\n### api.appDir\n\nContains the full path (String) to the root of the app on which this App Extension is running.\n\n### api.hasTypescript\n\n```js\n/**\n * @return {Promise\u003cboolean>} host project has Typescript active or not\n */\nawait api.hasTypescript()\n```\n\n### api.hasLint\n\n```js\n/**\n * @return {Promise\u003cboolean>} host project has ESLint or not\n */\nawait api.hasLint()\n```\n\n### api.getStorePackageName\n\n```js\n/**\n * @return {Promise\u003cstring|undefined>} 'pinia' | 'vuex' | undefined\n */\nawait api.getStorePackageName()\n```\n\n### api.getNodePackagerName\n\n```js\n/**\n * @return {Promise\u003c'npm' | 'yarn' | 'pnpm' | 'bun'>}\n */\nawait api.getNodePackagerName()\n```\n\n### api.compatibleWith\n\nEnsure the App Extension is compatible with a package installed in the host app through a semver condition.\n\nIf the semver condition is not met, then Quasar CLI errors out and halts execution.\n\nExample of semver condition: `'1.x || >=2.5.0 || 5.0.0 - 7.2.3'`.\n\n```js\n/**\n * @param {string} packageName\n * @param {string} semverCondition\n */\napi.compatibleWith(packageName, '1.x')\n```\n\n```js A more complex example:\nif (api.hasVite === true) {\n api.compatibleWith('@quasar/app-vite', '^2.0.0')\n} else {\n api.compatbileWith('@quasar/app-webpack', '^4.0.0')\n}\n```\n\n### api.hasPackage\n\nDetermine if some package is installed in the host app through a semver condition.\n\nExample of semver condition: `'1.x || >=2.5.0 || 5.0.0 - 7.2.3'`.\n\n```js\n/**\n * @param {string} packageName\n * @param {string} (optional) semverCondition\n * @return {boolean} package is installed and meets optional semver condition\n */\nif (api.hasPackage('vuelidate')) {\n // hey, this app has it (any version of it)\n}\nif (api.hasPackage('quasar', '^2.0.0')) {\n // hey, this app has Quasar UI v2 installed\n}\n```\n\n### api.hasExtension\n\nCheck if another app extension is npm installed and Quasar CLI has invoked it.\n\n```js\n/**\n * Check if another app extension is installed\n *\n * @param {string} extId\n * @return {boolean} has the extension installed & invoked\n */\nif (api.hasExtension(extId)) {\n // hey, we have it\n}\n```\n\n### api.getPackageVersion\n\nGet the version of a host app package.\n\n```js\n/**\n * @param {string} packageName\n * @return {string|undefined} version of app's package\n */\nconsole.log(api.getPackageVersion(packageName))\n// output examples:\n// 1.1.3\n// undefined (when package not found)\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":6498,"content_sha256":"834773742ecb35bfaaf710c91996dd214060d0049220d823b4b5ea9530650cf8"},{"filename":"references/docs/app-extensions/development-guide/uninstall-api.md","content":"---\ntitle: App Extension Uninstall API\ndesc: The API for the uninstall script of a Quasar App Extension.\n---\n\nThis page refers to `src/uninstall.js` file which is executed when the App Extension is uninstalled. Not all App Extensions will need an uninstall -- this is an optional step.\n\nExample of basic structure of the file:\n\n```js\n// can be async\nexport default function (api) {\n // props and methods for \"api\" Object\n // are described below\n}\n```\n\n### api.engine\n\nContains the Quasar CLI engine (as String) being used. Examples: `@quasar/app-vite` or `@quasar/app-webpack`.\n\n### api.hasVite\n\nBoolean - is running on `@quasar/app-vite` or not.\n\n### api.hasWebpack\n\nBoolean - is running on `@quasar/app-webpack` or not.\n\n### api.extId\n\nContains the `ext-id` (String) of this App Extension.\n\n### api.prompts\n\nIs an Object which has the answers to the prompts when this App Extension gets installed. For more info on prompts, check out [Prompts API](/app-extensions/development-guide/prompts-api).\n\n### api.resolve\n\nResolves paths within the app on which this App Extension is running. Eliminates the need to import `path` and resolve the paths yourself.\n\n```js\n// resolves to root of app\napi.resolve.app('src/my-file.js')\n\n// resolves to root/src of app\napi.resolve.src('my-file.js')\n\n// resolves to root/public of app\n// (@quasar/app-webpack v3.4+ or @quasar/app-vite v1+)\napi.resolve.public('my-image.png')\n\n// resolves to root/src-pwa of app\napi.resolve.pwa('some-file.js')\n\n// resolves to root/src-ssr of app\napi.resolve.ssr('some-file.js')\n\n// resolves to root/src-cordova of app\napi.resolve.cordova('config.xml')\n\n// resolves to root/src-electron of app\napi.resolve.electron('some-file.js')\n\n// resolves to root/src-bex of app\napi.resolve.bex('some-file.js')\n```\n\n### api.appDir\n\nContains the full path (String) to the root of the app on which this App Extension is running.\n\n### api.hasTypescript \u003cq-badge label=\"@quasar/app-vite 1.6+\" /> \u003cq-badge label=\"@quasar/app-webpack 3.11+\" />\n\n```js\n/**\n * @return {Promise\u003cboolean>} host project has Typescript active or not\n */\nawait api.hasTypescript()\n```\n\n### api.hasLint \u003cq-badge label=\"@quasar/app-vite 1.6+\" /> \u003cq-badge label=\"@quasar/app-webpack 3.11+\" />\n\n```js\n/**\n * @return {Promise\u003cboolean>} host project has ESLint or not\n */\nawait api.hasLint()\n```\n\n### api.getStorePackageName \u003cq-badge label=\"@quasar/app-vite 1.6+\" /> \u003cq-badge label=\"@quasar/app-webpack 3.11+\" />\n\n```js\n/**\n * @return {Promise\u003cstring|undefined>} 'pinia' | 'vuex' | undefined\n */\nawait api.getStorePackageName()\n```\n\n### api.getNodePackagerName \u003cq-badge label=\"@quasar/app-vite 1.6+\" /> \u003cq-badge label=\"@quasar/app-webpack 3.11+\" />\n\n```js\n/**\n * @return {Promise\u003c'npm' | 'yarn' | 'pnpm' | 'bun'>}\n */\nawait api.getNodePackagerName()\n```\n\n### api.hasPackage\n\nDetermine if some package is installed in the host app through a semver condition.\n\nExample of semver condition: `'1.x || >=2.5.0 || 5.0.0 - 7.2.3'`.\n\n```js\n/**\n * @param {string} packageName\n * @param {string} (optional) semverCondition\n * @return {boolean} package is installed and meets optional semver condition\n */\nif (api.hasPackage('vuelidate')) {\n // hey, this app has it (any version of it)\n}\nif (api.hasPackage('quasar', '^2.0.0')) {\n // hey, this app has Quasar UI v2 installed\n}\n```\n\n### api.hasExtension\n\nCheck if another app extension is installed.\n\n```js\n/**\n * Check if another app extension is installed\n *\n * @param {string} extId\n * @return {boolean} has the extension installed.\n */\nif (api.hasExtension(extId)) {\n // hey, we have it\n}\n```\n\n### api.getPackageVersion\n\nGet the version of a host app package.\n\n```js\n/**\n * @param {string} packageName\n * @return {string|undefined} version of app's package\n */\nconsole.log(api.getPackageVersion(packageName))\n// output examples:\n// 1.1.3\n// undefined (when package not found)\n```\n\n### api.removePath\n\nRemoves a file or folder from the app project folder (which the App Extension has installed and is no longer needed).\n\nBe mindful about it and do not delete the files that would break developer's app.\n\nThe path to file or folder needs to be relative to project's root folder.\n\n```js\n/**\n * @param {string} __path\n */\napi.removePath('my-folder')\n```\n\nThe above example deletes \"my-folder\" from the root of the app.\n\n### api.getPersistentConf\n\nGet the internal persistent config of this extension. Returns empty object if it has none.\n\n```js\n/**\n * @return {object} cfg\n */\napi.getPersistentConf()\n```\n\n### api.onExitLog\n\nAdds a message to be printed after App CLI finishes up uninstalling the App Extension and is about to exit. Can be called multiple times to register multiple exit logs.\n\n```js\n/**\n * @param {string} msg\n */\napi.onExitLog('Thanks for having used my extension')\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4755,"content_sha256":"e31cf9f468019f2dd0adc7a4fe02d4ca52cd792166fc5d95d8c2e30a4796a8ce"},{"filename":"references/docs/app-extensions/discover.md","content":"---\ntitle: Discover App Extensions\ndesc: Look up official and community Quasar App Extensions.\n---\n\n\u003cq-btn icon-right=\"search\" label=\"Look up extensions\" href=\"https://www.npmjs.com/search?q=quasar-app-extension\" target=\"_blank\" rel=\"noopener noreferrer\" />\n\n## Community App Extensions\n\nReview submitted Community App Extensions.\n\n> And please don't forget to submit your own! Learn what Quasar [App Extensions](/app-extensions/introduction) are and how to [create one](/app-extensions/development-guide/introduction).\n\n## Official App Extensions\n\nBelow is a list of official app-extensions created by members of the Quasar team.\n\n### Tooling\n\n| Alias | Description |\n| --------------------------------------------------------------------------------- | -------------------------------------------------------------------- |\n| @quasar/testing AEs | Includes pre-configured sub-extensions for all of your testing needs |\n| @quasar/apollo | Includes pre-configured Apollo integration |\n\n### Components\n\n| Alias | Description |\n| ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |\n| @quasar/qmediaplayer | HTML5 video and audio player |\n| @quasar/qflashcard | Show some information and reveal more with CSS Transition Mashups |\n| @quasar/qoverlay | Overlays simplified. Add any component on top of the overlay |\n| @quasar/qactivity | Create activity timelines |\n| @quasar/qmarkdown | Markdown for your pages |\n| @quasar/qpdfviewer | View PDF documents in your Quasar app |\n| @quasar/qcalendar | Calendar for Quasar |\n| @quasar/qscroller | Many scrolling components, including QScroller, QTimeScroller, QDateScroller, QDateTimeScroller and scrolling time ranges |\n| @quasar/qwindow | Floating, movable, resizable interactive windows for Quasar |\n| @quasar/qiconpicker | Icon Picker for your Quasar apps |\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3178,"content_sha256":"872adce850713f8962859563b2fc519af7505cd5e7f06d4b1d5710cebd7e90fa"},{"filename":"references/docs/app-extensions/introduction.md","content":"---\ntitle: App Extensions\ndesc: What Quasar App Extensions are and how they can help both you and the community.\n---\n\nApp Extensions are a way to painlessly inject complicated (or simple) libraries with a variety of dependencies, boot files, templates and custom logic. They can extend webpack, the `quasar.config` file, tightly couple external UI components to core, and even register new commands with the Quasar CLI. They can be run with `quasar dev` and have complete access to the current live `ctx` (context).\n\nThe patterns for development literally open the floodgates to making Quasar one of the most extensible and powerful frameworks out there - now limited only by your imagination and innovation. This page will introduce you to the usage of App Extensions.\n\n::: warning\nApp Extensions are designed specifically **for Quasar CLI only**. This means that you will not be able to install them or run them with the Quasar Vite plugin or in UMD environments.\n:::\n\n## What can an App Extension do?\n\n1. Enhance CLI behavior with new commands\n2. Make a Quasar UI plug-in\n3. Install an accompanying application\n4. Create and share a custom component\n5. Create and share added features to the framework or other applications\n6. Build, launch and control an API server\n7. Hook, combine and extend Quasar core components\n8. Modify code based on dynamically changing values that sit outside of the Quasar environment\n9. Create and manage abstractions of platform specific interfaces\n10. ... and a whole lot more\n\nApp Extensions **replace the need to create custom starter kits**. Anything you add on top of the official starter kit can come in the form of an App Extension. This also eliminates maintenance overhead of keeping unofficial starter kits up to date with the official one and so we can ensure that every developer will always get the latest and greatest Quasar specs out of the box.\n\n## App Extension ext-id\n\nAll App Extensions must prefix their name with `quasar-app-extension-`. Everything that follows after this prefix is considered to be the short alias of it. We call this the `ext-id` throughout the documentation.\n\nExample:\n\n- ext-id for `quasar-app-extension-awesomeness` is `awesomeness`\n- ext-id for `@some-npm-org/quasar-app-extension-awesomeness` is `@some-npm-org/awesomeness`\n\nOne of the benefits of this naming scheme is that it makes Quasar App Extensions discoverability easy while searching for their npm packages: [App Extension - Discover](/app-extensions/discover).\n\n## Anatomy of App Extensions\n\nApp Extensions can be installed, executed and also uninstalled. The following guide discusses this in an abstract way. For details about individual extensions and how to work with them, please consult their respective repositories.\n\n### Installing an App Extension\n\n```bash\n$ quasar ext add \u003cext-id>\n```\n\nThis command will find and install the extension's module. After installation is complete, there may be one or more prompts asking you to make choices or add information needed by the extension. When the installation is concluded, you will be returned to the command line.\n\n### List Installed App Extensions\n\nThere are several ways to \"discover\" what App Extensions have been installed:\n\n```bash\n$ quasar ext\n$ quasar info\n$ cat quasar.extensions.json\n```\n\n### \"Running\" App Extensions\n\nThere is no one way to run app extensions, because some of them might not even have any code to run (i.e. are merely template files copied to specific folders within your project), whereas others may merely be installation helpers and others might choose to add a new command to the Quasar CLI.\n\nNevertheless, each and every App Extension will be initialized during `quasar dev` and `quasar build`.\n\n### Updating an App Extension\n\nYou may need to update your extension, and this is done with the same command as used for installation:\n\n```bash\n$ quasar ext add \u003cext-id>\n```\n\n::: warning\nReinstalling the extension MIGHT overwrite files that you have changed. You will be presented with the option to overwrite the files detected.\n:::\n\n### Removing an App Extension\n\nYou can remove an App Extension from being hooked from the Quasar CLI by running this command. Depending upon the author and the extension itself, you may have to manually clean up files though.\n\n```bash\n$ quasar ext remove \u003cext-id>\n```\n\n## List of official app-extensions\n\nCheck out [Discover App Extensions](/app-extensions/discover) page.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4430,"content_sha256":"347471a8296d7ec8e3b4f5c077e73ce202b4eda5f44901354bee3cd0f16b2d90"},{"filename":"references/docs/app-extensions/tips-and-tricks/chain-webpack.md","content":"---\ntitle: Chain Webpack\ndesc: Tips and tricks on how to use a Quasar App Extension to configure the host app to use a Webpack loader.\nscope:\n tree:\n l: '.'\n c:\n - l: package.json\n - l: src\n c:\n - l: index.js\n e: Described in Index API\n---\n\nThis guide is for when you want to ensure that a Webpack Loader is chained into the hosting app, because you depend on it for your own App Extension to work.\nWe are assuming we will release this App Extension for `@quasar/app-webpack`, as it does not makes sense for `@quasar/app-vite` (which does not uses Webpack at all).\n\n::: tip\nIn order for creating an App Extension project folder, please first read the [Development Guide > Introduction](/app-extensions/development-guide/introduction).\n:::\n\n::: tip Full Example\nTo see an example of what we will build, head over to full example, which is a GitHub repo with this App Extension.\n:::\n\nWe will only need the /index.js script for this, because we can use the [Index API](/app-extensions/development-guide/index-api) to configure the quasar.config file from the host app to include our Webpack chaining.\n\n\u003cDocTree :def=\"scope.tree\" />\n\nAnd /index.js would look like this:\n\n```js File: /index.js\nexport default function (api) {\n // (Optional!)\n // Quasar compatibility check; you may need\n // hard dependencies, as in a minimum version of the \"quasar\"\n // package or a minimum version of Quasar App CLI\n api.compatibleWith('quasar', '^2.0.0')\n api.compatibleWith('@quasar/app-webpack', '^4.0.0')\n\n // chain webpack\n api.chainWebpack(chain => chainWebpack(api.ctx, chain))\n}\n```\n\nOur \"chainWebpack\" method, in the same file as above:\n\n```js File: /index.js\nimport MarkdownIt from 'markdown-it'\n\nconst md = new MarkdownIt()\n\nconst chainWebpack = (ctx, chain) => {\n const rule = chain.module.rule('md').test(/\\.md$/).pre()\n\n rule\n .use('v-loader')\n .loader('vue-loader')\n .options({\n productionMode: ctx.prod,\n transformAssetUrls: {\n video: 'src',\n source: 'src',\n img: 'src',\n image: 'xlink:href'\n }\n })\n\n rule\n .use('ware-loader')\n .loader('ware-loader')\n .options({\n raw: true,\n middleware: function (source) {\n // use markdown-it to render the markdown file to html, then\n // surround the output of that that with Vue template syntax\n // so it can be processed by the 'vue-loader'\n return `\u003ctemplate>\u003cdiv>${md.render(source)}\u003c/div>\u003c/template>`\n }\n })\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2516,"content_sha256":"051f087ced86021e8d198134261471dd4570c4723b4ae2bf29a49589a3a66e68"},{"filename":"references/docs/app-extensions/tips-and-tricks/inject-quasar-plugin.md","content":"---\ntitle: Injecting Quasar Plugin\ndesc: Tips and tricks on how to use a Quasar App Extension to configure the host app to use a Quasar Plugin.\nscope:\n tree:\n l: '.'\n c:\n - l: package.json\n - l: src\n c:\n - l: index.js\n e: Described in Index API\n---\n\nThis guide is for when you want to ensure that a [Quasar Plugin](/quasar-plugins) will be injected into the hosting app, because you depend on it for your own App Extension to work.\n\n::: tip\nIn order for creating an App Extension project folder, please first read the [Development Guide > Introduction](/app-extensions/development-guide/introduction).\n:::\n\n::: tip Full Example\nTo see an example of what we will build, head over to full example, which is a GitHub repo with this App Extension.\n:::\n\nWe will only need the /index.js script for this, because we can use the [Index API](/app-extensions/development-guide/index-api) to configure quasar.config file from the host app to include our required Quasar Plugin.\n\n\u003cDocTree :def=\"scope.tree\" />\n\nAnd /index.js would look like this:\n\n```js File: /index.js\nexport default function (api) {\n // (Optional!)\n // Quasar compatibility check; you may need\n // hard dependencies, as in a minimum version of the \"quasar\"\n // package or a minimum version of Quasar App CLI\n api.compatibleWith('quasar', '^2.0.0')\n\n if (api.hasVite === true) {\n api.compatibleWith('@quasar/app-vite', '^2.0.0')\n } else {\n // api.hasWebpack === true\n api.compatibleWith('@quasar/app-webpack', '^4.0.0')\n }\n\n // Here we extend /quasar.config file, so we can add\n // a boot file which registers our new Vue directive;\n // \"extendConf\" will be defined below (keep reading the tutorial)\n api.extendQuasarConf(extendConf)\n}\n```\n\nOur \"extendConf\" method, in the same file as above:\n\n```js File: /index.js\nfunction extendConf(conf) {\n // we push to /quasar.config file > framework > plugins:\n conf.framework.plugins.push('AppVisibility')\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1977,"content_sha256":"ec0631a0afcedea4b18664e1b516609e2a1f4f4d5364670f48c6aadff2f67006"},{"filename":"references/docs/app-extensions/tips-and-tricks/introduction.md","content":"---\ntitle: App Extension tips & tricks introduction\ndesc: Introduction to the list of Quasar App Extension tips & tricks documentation.\n---\n\nThese documentation pages will help you with information or formulae on how to do some of the things with a Quasar App Extension. Make sure you also study the introduction and the APIs of App Extension pages first.\n\nEnjoy!\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":364,"content_sha256":"70c953866fca9baf334bf729fa313d6adcfa8519432a67cce526f54eb2b3bc4a"},{"filename":"references/docs/app-extensions/tips-and-tricks/json-api.md","content":"---\ntitle: Quasar JSON API Schema\ndesc: The JSON API used to describe Component App Extensions.\n---\n\nThis page describes the JSON API Schema used for component App Extensions.\n\n## Benefits of using JSON API\n\n1. Describes your existing data format(s)\n2. Provides clear human- and machine- readable documentation\n3. Validates data which is useful for:\n - Automated testing\n - Ensuring quality of submitted data\n\n## JSON Data Structures\n\nAt its heart, JSON is built on the following data structures:\n\nobject:\n\n```json\n{ \"key1\": \"value1\", \"key2\": \"value2\" }\n```\n\narray:\n\n```json\n[\"first\", \"second\", \"third\"]\n```\n\nnumber:\n\n```json\n42\n3.1415926\n```\n\nstring:\n\n```json\n\"This is a string\"\n```\n\nboolean:\n\n```json\ntrue\nfalse\n```\n\nnull:\n\n```json\nnull\n```\n\n## Quasar JSON API\n\nThe unfilled schema typically looks like this:\n\n```json\n{\n \"props\": {},\n \"events\": {},\n \"slots\": {},\n \"methods\": {}\n}\n```\n\n### General\n\nThe first part of a definition is the actual item name itself.\n\n::: tip\nIf in the `props` section, this should be the forward facing name. Meaning, if your item being described is in camelCase, then the forward facing item name is in kebab-case. ex: `myProp` becomes `my-prop`.\n:::\n\nThe rest of the definitions can be one of the following:\n\n| Name | Description |\n| :--------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| type | Optional for everything but `props`. This can be a single item or array of items. Values are: `[\"Array\", \"Boolean\", \"Function\", \"Number\", \"Object\", \"String\", \"Null\", \"Any\"]` |\n| desc | Any string that describes the item being described |\n| required | [true,false] |\n| values | an array of constrained values. Ex: `[0, 0.5, 1.0, 1.5, 2.0]` |\n| definition | Describes an object definition. This is an object that pretty much conforms to the base object. It can contain `\"type\"`, `\"desc\"`, `\"required\"`, `\"examples\"`, `\"values\"` and `\"definition\"` (recursive) |\n| params | Typically is used to describe parameters to a function. This needs one or more parameters as the key to an object that pretty much conforms to the base object. It can contain `\"type\"`, `\"desc\"`, `\"required\"`, `\"examples\"`, `\"values\"` and `\"definition\"` (recursive) |\n| returns | The returned value (for methods or functions) |\n| category | Used for grouping |\n\nAll items are optional, but in the very least you should provide a description.\n\n### Props example\n\n```json\n \"props\": {\n \"value\": {\n \"type\": \"Boolean\",\n \"desc\": \"Model of the component defining if it is shown or hidden to the user; Either use this property (along with a listener for 'input' event) OR use v-model directive\",\n \"default\": true,\n \"examples\": [\n \"v-model=\\\"footerState\\\"\"\n ],\n \"category\": \"model\"\n },\n \"locale\": {\n \"type\": \"Object\",\n \"desc\": \"Locale formatting options\",\n \"examples\": [ \":locale=\\\"{ monthsShort: ['Ian', 'Feb', 'Mar', '...'] }\\\"\" ],\n \"definition\": {\n \"days\": {\n \"type\": \"Array\",\n \"desc\": \"List of full day names (DDDD), starting with Sunday\",\n \"examples\": [ \"['Duminica', 'Luni', 'Marti', '...']\" ]\n },\n \"daysShort\": {\n \"type\": \"Array\",\n \"desc\": \"List of short day names (DDD), starting with Sunday\",\n \"examples\": [ \"['Dum', 'Lun', 'Mar', '...']\" ]\n },\n \"months\": {\n \"type\": \"Array\",\n \"desc\": \"List of full month names (MMMM), starting with January\",\n \"examples\": [ \"['Ianuarie', 'Februarie', 'Martie', '...']\" ]\n },\n \"monthsShort\": {\n \"type\": \"Array\",\n \"desc\": \"List of short month names (MMM), starting with January\",\n \"examples\": [ \"['Ian', 'Feb', 'Mar', '...']\" ]\n }\n },\n \"category\": \"model\"\n },\n \"options\": {\n \"type\": \"Function\",\n \"desc\": \"Optionally configure what time is the user allowed to set; Overridden by 'hour-options', 'minute-options' and 'second-options' if those are set\",\n \"params\": {\n \"hr\": {\n \"type\": \"Number\",\n \"desc\": \"Hour\",\n \"examples\": [ 15 ]\n },\n \"min\": {\n \"type\": \"Number\",\n \"desc\": \"Minutes\",\n \"examples\": [ 38 ]\n },\n \"sec\": {\n \"type\": \"Number\",\n \"desc\": \"Seconds\",\n \"examples\": [ 12 ]\n }\n },\n \"returns\": null,\n \"examples\": [\n \":options=\\\"(hr, min, sec) => hr \u003c= 6\\\"\"\n ],\n \"category\": \"behavior\"\n },\n \"events\": {\n \"type\": [ \"Array\", \"Function\" ],\n \"desc\": \"A list of events to highlight on the calendar; If using a function, it receives the date as a String and must return a Boolean (matches or not)\",\n \"examples\": [\n \":events=\\\"['2018/11/05', '2018/11/06', '2018/11/09', '2018/11/23']\\\"\",\n \":events=\\\"date => date[9] % 3 === 0\\\"\"\n ],\n \"category\": \"model\"\n }\n }\n```\n\n### Events example\n\n```json\n \"events\": {\n \"show\": {\n \"desc\": \"Emitted after component has triggered show()\",\n \"params\": {\n \"evt\": {\n \"type\": \"Object\",\n \"desc\": \"JS event object\",\n \"required\": true\n }\n }\n },\n \"input\": {\n \"params\": {\n \"value\": {\n \"type\": \"String\"\n },\n \"reason\": {\n \"type\": \"String\",\n \"desc\": \"Reason of the user interaction (what was picked)\",\n \"values\": [ \"year\", \"month\", \"day\", \"today\", \"locale\", \"mask\" ]\n },\n \"details\": {\n \"type\": \"Object\",\n \"desc\": \"Object of properties on the new model\",\n \"definition\": {\n \"year\": {\n \"type\": \"Number\"\n },\n \"month\": {\n \"type\": \"Number\"\n },\n \"day\": {\n \"type\": \"Number\"\n }\n }\n }\n }\n }\n }\n```\n\n### Slots example\n\n```json\n \"slots\": {\n \"default\": {\n \"desc\": \"This is where Banner content goes\"\n },\n\n \"avatar\": {\n \"desc\": \"Slot for displaying an avatar (suggestions: QIcon, QAvatar)\"\n },\n\n \"selected-item\": {\n \"desc\": \"Override default selection slot; Suggestion: QChip\",\n \"scope\": {\n \"index\": {\n \"type\": \"Number\",\n \"desc\": \"Selection index\",\n \"examples\": [ 0 ]\n },\n \"opt\": {\n \"type\": \"Any\",\n \"desc\": \"Selected option -- its value is taken from model\"\n },\n \"selected\": {\n \"type\": \"Boolean\",\n \"desc\": \"Always true -- passed down as prop to QItem (when using QItem)\"\n },\n \"removeAtIndex\": {\n \"type\": \"Function\",\n \"desc\": \"Remove selected option located at specific index\",\n \"params\": {\n \"index\": {\n \"type\": \"Number\",\n \"required\": true,\n \"desc\": \"Index at which to remove selection\",\n \"examples\": [ 0 ]\n }\n },\n \"returns\": null\n },\n \"toggleOption\": {\n \"type\": \"Function\",\n \"desc\": \"Add/remove option from model\",\n \"params\": {\n \"opt\": {\n \"type\": \"Any\",\n \"required\": true,\n \"desc\": \"Option to add to model\",\n \"__exemption\": [ \"examples\" ]\n }\n },\n \"returns\": null\n },\n \"tabindex\": {\n \"type\": \"Number\",\n \"desc\": \"Tabindex HTML attribute value associated with respective option\",\n \"values\": [ 0, -1 ]\n }\n }\n }\n },\n```\n\n### Methods example\n\n```json\n \"methods\": {\n \"focus\": {\n \"desc\": \"Focus on first focusable element/component in the form\"\n },\n\n \"validate\": {\n \"desc\": \"Triggers a validation on all applicable inner Quasar components\",\n \"params\": {\n \"shouldFocus\": {\n \"type\": \"Boolean\",\n \"desc\": \"Tell if it should focus or not on component with error on submitting form; Overrides 'no-focus-error' prop if specified\"\n }\n },\n \"returns\": {\n \"type\": \"Promise\u003cboolean>\",\n \"desc\": \"Promise is always fulfilled and receives the outcome (true -> validation was a success, false -> invalid models detected)\",\n \"examples\": [\n \"validate().then(outcome => { ... })\"\n ]\n }\n }\n }\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":10044,"content_sha256":"64a5eacf78b10374044b744755f05b857ec44225de72a14693b376d34ece8a05"},{"filename":"references/docs/app-extensions/tips-and-tricks/provide-a-directive.md","content":"---\ntitle: Providing a directive\ndesc: Tips and tricks on how to provide a Vue directive to the host app of a Quasar App Extension.\nscope:\n tree:\n l: '.'\n c:\n - l: package.json\n - l: src\n c:\n - l: boot\n e: folder to contain boot code\n c:\n - l: register-my-directive.js\n e: boot file for directive\n - l: directive\n e: folder to contain directive\n c:\n - l: MyDirective.js\n e: directive file\n - l: index.js\n e: Described in Index API\n---\n\nThis guide is for when you want to create a new directive and provide it through an App Extension, which will inject it into the hosting app.\n\n::: tip\nTo create an App Extension project folder, please first read the [Development Guide > Introduction](/app-extensions/development-guide/introduction).\n:::\n\n::: tip Full Example\nTo see an example of what we will build, head over to MyDirective full example, which is a GitHub repo with this App Extension.\n:::\n\nCreate a folder structure to keep your code modularized and organized. For instance, for a directive, create a structure that looks like this:\n\n\u003cDocTree :def=\"scope.tree\" />\n\nNow, you need to handle registering your Vue directive. You do this with the `/index.js` file (described in the [Index API](/app-extensions/development-guide/index-api)) that was created when you set up your new App Extension.\n\nLet's break it down.\n\n```js File: /index.js\nexport default function (api) {\n // (Optional!)\n // Quasar compatibility check; you may need\n // hard dependencies, as in a minimum version of the \"quasar\"\n // package or a minimum version of Quasar App CLI\n api.compatibleWith('quasar', '^2.0.0')\n\n if (api.hasVite === true) {\n api.compatibleWith('@quasar/app-vite', '^2.0.0')\n } else {\n // api.hasWebpack === true\n api.compatibleWith('@quasar/app-webpack', '^4.0.0')\n }\n\n // Here we extend the /quasar.config file, so we can add\n // a boot file which registers our new Vue directive;\n // \"extendConf\" will be defined below (keep reading the tutorial)\n api.extendQuasarConf(extendConf)\n}\n```\n\nThe first group does a compatibility check with Quasar (which is optional, but recommended). If your component is using features of Quasar that were available after a certain version, you can make sure that the version of Quasar installed is the correct one.\n\n::: tip\nNot only can you do a `api.compatibleWith()` to check against Quasar packages, but with any other available packages (that you do not supply yourself through your App Extension) as well. Please read [Handling package dependencies](/app-extensions/development-guide/introduction#handling-package-dependencies) section from the App Extension Development Guide > Introduction page for more information.\n:::\n\nThe second group tells Quasar to call our custom function when the `extendQuasarConf` CLI life-cycle hook is called. It would look something like this:\n\n```js File: /index.js\nfunction extendConf(conf, api) {\n // make sure my-directive boot file is registered\n conf.boot.push(\n '~quasar-app-extension-my-directive/src/boot/register-my-directive.js'\n )\n\n // @quasar/app-vite does not need this\n if (api.hasVite !== true) {\n // make sure boot & other files get transpiled\n conf.build.webpackTranspileDependencies.push(\n /quasar-app-extension-my-directive[\\\\/]src/\n )\n }\n}\n```\n\nFinally, let's see how the boot file would look like. Make sure that you read the [@quasar/app-vite Boot files](/quasar-cli-vite/boot-files) / [@quasar/app-webpack Boot files](/quasar-cli-webpack/boot-files) documentation and understand what a Boot file is first.\n\n```js File: /src/boot/my-directive.js\nimport MyDirective from '../directive/MyDirective.js'\n\n// We globally register our directive with Vue;\n// Remember that all directives in Vue will start with 'v-'\n// but that should not be part of your directive name\n// https://vuejs.org/guide/custom-directive.html#custom-directives\n// 'my-directive' will be used as 'v-my-directive'\nexport default ({ app }) => {\n app.directive('my-directive', MyDirective)\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4157,"content_sha256":"e2256043cc8854cd8c978bd61821cef8d81a68d05efd7c61add01b6ffd431d29"},{"filename":"references/docs/app-extensions/tips-and-tricks/provide-a-ui-component.md","content":"---\ntitle: Provide a UI component\ndesc: Tips and tricks on how to provide a Vue component to the host app of a Quasar App Extension.\nscope:\n tree:\n l: '.'\n c:\n - l: package.json\n - l: src\n c:\n - l: boot\n e: folder to contain boot code\n c:\n - l: register-my-component.js\n e: boot file for component\n - l: component\n e: folder to contain component\n c:\n - l: MyComponent.vue\n e: component file (can be .vue or even .js)\n - l: MyComponent.sass\n e: sass file for component (or .scss/.css, or whatever you need)\n - l: index.js\n e: Described in Index API\n---\n\nThis guide is for when you want to create a new UI component and provide it through an App Extension, which will inject it into the hosting app.\n\n::: tip\nIn order for creating an App Extension project folder, please first read the [Development Guide > Introduction](/app-extensions/development-guide/introduction).\n:::\n\n::: tip Full Example\nTo see an example of what we will build, head over to MyComponent full example, which is a GitHub repo with this App Extension.\n:::\n\nCreate a folder structure to keep your code modularized and organized. For instance, for a UI component, create a structure that looks like this:\n\n\u003cDocTree :def=\"scope.tree\" />\n\nNow, you need to handle registering your component. You do this with the `/index.js` file (described in the [Index API](/app-extensions/development-guide/index-api)) that was created when you set up your new App Extension.\n\nLet's break it down.\n\n```js File: /index.js\nexport default function (api) {\n // (Optional!)\n // Quasar compatibility check; you may need\n // hard dependencies, as in a minimum version of the \"quasar\"\n // package or a minimum version of Quasar App CLI\n api.compatibleWith('quasar', '^2.0.0')\n\n if (api.hasVite === true) {\n api.compatibleWith('@quasar/app-vite', '^2.0.0')\n } else {\n // api.hasWebpack === true\n api.compatibleWith('@quasar/app-webpack', '^4.0.0')\n }\n\n // Here we extend the /quasar.config file, so we can add\n // a boot file which registers our new UI component;\n // \"extendConf\" will be defined below (keep reading the tutorial)\n api.extendQuasarConf(extendConf)\n}\n```\n\nThe first group does a compatibility check with Quasar (which is optional, but recommended). If your component is using features of Quasar that were available after a certain version, you can make sure that the version of Quasar installed is the correct one.\n\n::: tip\nNot only can you do a `api.compatibleWith()` to check against Quasar packages, but with any other available packages (that you do not supply yourself through your App Extension) as well. Please read [Handling package dependencies](/app-extensions/development-guide/introduction#handling-package-dependencies) section from the App Extension Development Guide > Introduction page for more information.\n:::\n\nThe second group tells Quasar to call our custom function when the `extendQuasarConf` CLI life-cycle hook is called. It would look something like this:\n\n```js File: /index.js\nfunction extendConf(conf, api) {\n // make sure my-component boot file is registered\n conf.boot.push(\n '~quasar-app-extension-my-component/src/boot/register-my-component.js'\n )\n\n // @quasar/app-vite does not need this\n if (api.hasVite !== true) {\n // make sure boot & component files get transpiled\n conf.build.transpileDependencies.push(\n /quasar-app-extension-my-component[\\\\/]src/\n )\n }\n\n // make sure my-component css goes through webpack to avoid ssr issues\n conf.css.push(\n '~quasar-app-extension-my-component/src/component/MyComponent.sass'\n )\n}\n```\n\nFinally, let's see how the boot file would look like. Make sure that you read the [@quasar/app-vite Boot files](/quasar-cli-vite/boot-files) / [@quasar/app-webpack Boot files](/quasar-cli-webpack/boot-files) documentation and understand what a Boot file is first.\n\n```js File: /src/boot/register-my-component.js\nimport MyComponent from '../component/MyComponent.vue'\n\n// we globally register our component with Vue\nexport default ({ app }) => {\n app.component('my-component', MyComponent)\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4256,"content_sha256":"749b2628af50db3c53c350018813215a9f0bfe419e0d9e63a81d5293681eda09"},{"filename":"references/docs/app-extensions/tips-and-tricks/starter-kit-equivalent.md","content":"---\ntitle: Starter kit equivalent\ndesc: Tips and tricks on how to use a Quasar App Extension to create the equivalent of a starter kit.\nscope:\n tree:\n l: '.'\n c:\n - l: README.md\n - l: package.json\n - l: src\n c:\n - l: boot\n c:\n - l: my-starter-kit-boot.js\n - l: templates\n c:\n - l: common-files\n c:\n - l: README.md\n - l: some-folder\n c:\n - l: tasks.md\n - l: serviceA\n c:\n - l: src\n c:\n - l: services\n c:\n - l: serviceA.js\n - l: serviceB\n c:\n - l: src\n c:\n - l: services\n c:\n - l: serviceB.js\n - l: index.js\n e: Described in Index API\n - l: install.js\n e: Described in Install API\n - l: prompts.js\n e: Described in Prompts API\n - l: uninstall.js\n e: Described in Uninstall API\n---\n\nThis guide is for when you want to create what essentially is a \"starter kit\" that adds stuff (/quasar.config file configuration, folders, files, CLI hooks) on top of the official starter kit. This allows you to have multiple projects sharing a common structure/logic (and only one package to manage them rather than having to change all projects individually to match your common pattern), and also allows you to share all this with the community.\n\n::: tip\nIn order for creating an App Extension project folder, please first read the [Development Guide > Introduction](/app-extensions/development-guide/introduction).\n:::\n\n::: tip Full Example\nTo see an example of what we will build, head over to MyStarterKit full example, which is a github repo with this App Extension.\n:::\n\nWe'll be creating an example App Extension which does the following:\n\n- it prompts the user what features it wants this App Extension to install\n- renders (copies) files into the hosting folder, according to the answers he gave\n- it extends the /quasar.config file\n- it extends the Webpack configuration\n- it uses an App Extension hook (onPublish)\n- it removes the added files when the App Extension gets uninstalled\n- it uses the prompts to define what the App Extension does\n\n## The structure\n\nFor the intents of this example, we'll be creating the following folder structure:\n\n\u003cDocTree :def=\"scope.tree\" />\n\n## The install script\n\nThe install script below is only rendering files into the hosted app. Notice the `src/templates` folder above, where we decided to keep these templates.\n\n```js src/install.js\nexport default function (api) {\n // (Optional!)\n // Quasar compatibility check; you may need\n // hard dependencies, as in a minimum version of the \"quasar\"\n // package or a minimum version of Quasar App CLI\n api.compatibleWith('quasar', '^2.0.0')\n\n if (api.hasVite === true) {\n api.compatibleWith('@quasar/app-vite', '^2.0.0')\n } else {\n // api.hasWebpack === true\n api.compatibleWith('@quasar/app-webpack', '^4.0.0')\n }\n\n // We render some files into the hosting project\n\n if (api.prompts.serviceA) {\n api.render('./templates/serviceA')\n }\n\n if (api.prompts.serviceB) {\n // we supply interpolation variables\n // to the template\n api.render('./templates/serviceB', {\n productName: api.prompts.productName\n })\n }\n\n // we always render the following template:\n api.render('./templates/common-files')\n}\n```\n\nNotice that we use the prompts to decide what to render into the hosting project. Furthermore, if the user has selected \"service B\", then we'll also have a \"productName\" that we can use when we render the service B's file.\n\n## The index script\n\nWe do a few things in the index script, like extending the /quasar.config file, hooking into one of the many Index API hooks (onPublish in this case), and chaining the Webpack configuration:\n\n```js src/index.js\nexport default function (api) {\n // (Optional!)\n // Quasar compatibility check; you may need\n // hard dependencies, as in a minimum version of the \"quasar\"\n // package or a minimum version of Quasar App CLI\n api.compatibleWith('quasar', '^2.0.0')\n\n if (api.hasVite === true) {\n api.compatibleWith('@quasar/app-vite', '^2.0.0')\n } else {\n // api.hasWebpack === true\n api.compatibleWith('@quasar/app-webpack', '^4.0.0')\n }\n\n // Here we extend the /quasar.config file;\n // (extendQuasarConf() will be defined later in this tutorial, continue reading)\n api.extendQuasarConf(extendQuasarConf)\n\n // Here we register the onPublish hook,\n // only if user answered that he wants the publishing service\n if (api.prompts.publishService) {\n // onPublish() will be defined later in this tutorial, continue reading\n api.onPublish(onPublish)\n }\n\n if (api.hasVite === true) {\n api.extendViteConf(extendVite)\n } else {\n // api.hasWebpack === true\n // we add/change/remove something in the Webpack configuration\n // (chainWebpack() will be defined later in this tutorial, continue reading)\n api.chainWebpack(chainWebpack)\n }\n\n // there's lots more hooks that you can use...\n}\n```\n\nHere's an example of `extendQuasarConf` definition:\n\n```js\nfunction extendQuasarConf(conf, api) {\n conf.extras.push('ionicons-v4')\n conf.framework.iconSet = 'ionicons-v4'\n\n //\n // We register a boot file. User does not need to tamper with it,\n // so we keep it into the App Extension code:\n //\n\n // make sure my-ext boot file is registered\n conf.boot.push(\n '~quasar-app-extension-my-starter-kit/src/boot/my-starter-kit-boot.js'\n )\n\n // @quasar/app-vite does not need this\n if (api.hasVite !== true) {\n // make sure boot file get transpiled\n conf.build.webpackTranspileDependencies.push(\n /quasar-app-extension-my-starter-kit[\\\\/]src/\n )\n }\n}\n```\n\nThe `onPublish` function:\n\n```js\nfunction onPublish(api, { arg, distDir }) {\n // this hook is called when \"quasar build --publish\" is called\n\n // your publish logic here...\n console.log('We should publish now. But maybe later? :)')\n\n // are we trying to publish a Cordova app?\n if (api.ctx.modeName === 'cordova') {\n // do something\n }\n}\n```\n\nThe `extendVite` function:\n\n```js\nfunction extendVite(viteConf, { isClient, isServer }, api) {\n // viteConf is a Vite config object generated by Quasar CLI\n}\n```\n\nThe `chainWebpack` function:\n\n```js\nfunction chainWebpack(cfg, { isClient, isServer }, api) {\n // cfg is a Webpack chain Object;\n // docs on how to use it: webpack-chain docs (https://github.com/neutrinojs/webpack-chain)\n}\n```\n\n## The uninstall script\n\nWhen the App Extension gets uninstall, we need to do some cleanup. But beware what you delete from the app-space! Some files might still be needed. Proceed with extreme care, if you decide to have an uninstall script.\n\n```js\n// we yarn added it to our App Extension,\n// so we can import the following:\nimport rimraf from 'rimraf'\n\nexport default function (api) {\n // Careful when you remove folders!\n // You don't want to delete files that are still needed by the Project,\n // or files that are not owned by this app extension.\n\n // Here, we could also remove the /src/services folder altogether,\n // but what if the user has added other files into this folder?\n\n if (api.prompts.serviceA) {\n // we added it on install, so we remove it\n rimraf.sync(api.resolve.src('services/serviceA.js'))\n }\n\n if (api.prompts.serviceB) {\n // we added it on install, so we remove it\n rimraf.sync(api.resolve.src('services/serviceB.js'))\n }\n\n // we added it on install, so we remove it\n rimraf.sync(api.resolve.app('some-folder'))\n // warning... we've added this folder, but what if the\n // developer added more files into this folder???\n}\n```\n\nNotice that we are requesting `rimraf` npm package. This means that we yarn/npm added it into our App Extension project.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":8037,"content_sha256":"7dfb9a6944174719f00a94cbe850d06654fff83a06e4e1b256b3cbfdd6c59f64"},{"filename":"references/docs/components/components.md","content":"---\ntitle: Quasar Components\ndesc: The list of most important Quasar components, directives, plugins and utils\nheading: false\neditLink: false\n---\n\n\n\n\u003cComponentsListing />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":171,"content_sha256":"b06015e2f24e5de64a5c807c402cd06f7d2c1e5acb1ef2f1841c30bcc9ee1e01"},{"filename":"references/docs/docs.md","content":"---\ntitle: Documentation\ndesc: Welcome to Quasar documentation website!\nheading: false\neditLink: false\nkeys: Welcome,Quasar\n---\n\n\n\n\u003cDocsHomepage />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":148,"content_sha256":"2d911e0476ccab366c3313b0927880a61a88e6d7c3fcdfeb866d19f67a7cd8f7"},{"filename":"references/docs/how-to-contribute/commit-conventions.md","content":"---\ntitle: Commit Conventions\ndesc: Quasar commit conventions\n---\n\n## Goals\n\n- Allow ignoring commits by git bisect (not important commits like formatting)\n- Provide better information when browsing the history\n\n::: warning\nThis rule applies to ALL Quasar repositories.\n:::\n\nWell-cared log is a beautiful and useful thing. `git blame`, `revert`, `rebase`, `log`, `shortlog` and other subcommands come to life. Reviewing others’ commits and pull requests becomes something worth doing, and suddenly can be done independently. Understanding why something happened months or years ago becomes not only possible but efficient.\n\n## The Rules of a Great Git Commit Message\n\n1. Separate subject from body with a blank line\n2. Limit the subject line to 70 characters\n3. Capitalize the subject line\n4. Do not end the subject line with a period\n5. Use the imperative mood in the subject line\n6. Wrap the body at 80 characters\n7. Use the body to explain what and why vs. how\n\n## Format of a Commit Message\n\n```\ntype(\u003cscope>): \u003cSubject> #\u003cgithub-ref-id>\n\n\u003cbody>\n\n\u003cfooter>\n```\n\n### Example of a Commit Message\n\n```\nfix(ui): Ensure Range headers adhere more closely to RFC 2616 #2310\n\nTo add new dependency use `range-parser`to compute the range.\nIt is more well-tested in the wild.\n\nBREAKING CHANGE:\nport-runner command line option has changed to runner-port.\nTo migrate your project, change all the commands,\nwhere you use --port-runner to --runner-port.\n```\n\n## Message Subject (First Line)\n\nThe first line cannot be longer than 70 characters, the second line is always blank. The type and scope should always be lowercase as shown below.\n\n**Allowed `\u003ctype>` values:**\n\n- **feat** - new feature for the user, not a new feature for build script\n- **fix** - bug fix for the user, not a fix to a build script\n- **docs** - documentation only changes\n- **style** - changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc.)\n- **refactor** - refactoring production code, a code change that neither fixes a bug nor adds a feature\n- **chore** - other changes that don't modify src or test files (_no production code change_) and dependency updates\n- **perf** - change that improves performance\n- **revert** - reverts a previous commit\n- **test** - adding missing tests, refactoring tests; no production code change\n- **build** - changes that affect the build system or external dependencies (e.g. `ui/build/*`)\n- **ci** - changes to our Continuous Integrations configuration files and scripts (e.g. GitHub Actions)\n\n**Example `\u003cscope>` values:**\n\n- Directory/package related: ui, cli, app-webpack, app-vite, etc.\n- Feature related: api, TouchSwipe, QTime, etc.\n\n::: tip\nThe `\u003cscope>` can contain more values separated by ampersand(`&`). Example: `feat(app-vite&app-webpack): Add Capacitor mode`.\n\nThe `\u003cscope>` can be empty (e.g. if the change is global), in which case the parentheses are omitted. Example: `style: Use semicolons`\n:::\n\n## Message Body\n\n- uses the imperative, present tense: “change” not “changed” nor “changes”\n- includes motivation for the change and contrasts with previous behavior\n\n## Message Footer\n\n### Breaking Changes\n\nAll breaking changes have to be mentioned as a breaking change block in the footer, which should start with the word BREAKING CHANGE: with a space or two newlines. The rest of the commit message is then the description of the change, justification and migration notes.\n\n```\nBREAKING CHANGE: isolate scope bindings definition has changed and\n the inject option for the directive controller injection was removed.\n\n To migrate the code follow the example below:\n\n Before:\n\n scope: {\n myAttr: 'attribute',\n myBind: 'bind',\n myExpression: 'expression',\n myEval: 'evaluate',\n myAccessor: 'accessor'\n }\n\n After:\n\n scope: {\n myAttr: '@',\n myBind: '@',\n myExpression: '&',\n // myEval - usually not useful, but in cases where the expression is assignable, you can use '='\n myAccessor: '=' // in directive's template change myAccessor() to myAccessor\n }\n```\n\n### Referencing Issues\n\nClosed issues should be listed on a separate line in the footer prefixed with \"Closes\" keyword like this:\n\n`Closes #234`\n\nor in the case of multiple issues:\n\n`Closes #123, #245, #992`\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4316,"content_sha256":"674f9ef0a91b0b953fecbea14c78c67b78d417b3f0c3880fe702752590850dc4"},{"filename":"references/docs/how-to-contribute/contribution-guide.md","content":"---\ntitle: Contribution Guide\ndesc: How to contribute to Quasar Framework.\n---\n\nThis guide covers ways in which you can become a part of the ongoing development of Quasar.\n\nBut, before we begin, a first important note. Everyone interacting in Quasar is expected to follow the Quasar Code of Conduct.\n\nNow that we've got that covered, let's go!\n\nAfter reading this guide, you will know:\n\n- How to use GitHub to report issues.\n- How to clone the repo and run the test suite.\n- How to help resolve existing issues.\n- How to contribute to the Quasar documentation.\n- How to create a Quasar App Extension.\n- How to contribute to the Quasar source code.\n\nQuasar is not \"someone else's framework\". Many people have contributed to Quasar ranging from a single character to massive architectural changes or significant documentation - all with the goal of making Quasar better for everyone. Even if you don't feel up to writing code or documentation yet, there are a variety of other ways that you can contribute, from reporting issues to testing patches.\n\n## Help with Support\n\nOne of the easiest ways to contribute is to answer questions in the different Q&A systems we have. Be a supportive and positive member of the Quasar community by answering questions you know answers to, or even by adding your best guess. Being a part of such discussions can also be a good learning experience. It's a win-win!\n\nHere are our discussion/Q&A venues:\n\n- GitHub Discussions: A place to ask questions and get answers about Quasar and its ecosystem. It’s also a great place to share your knowledge and experience with others. You can also use it to share your ideas and feature requests.\n- Discord Server: A place for Quasar devs to meet and chat in real time. You can ask questions, share your knowledge, and help others. It's also possible to post job offers or look for a job there.\n\n## Share (and Build) Your Experience\n\nApart from answering questions and sharing resources in the forum and chat, there are a few other less obvious ways to share and expand what you know:\n\n- **Develop learning materials**. It’s often said that the best way to learn is to teach. If there’s something interesting you’re doing with Quasar, strengthen your expertise by writing a blog post, developing a workshop, or even publishing a gist that you share on social media.\n- **Share your tech stack**. Show others which technologies are well tested and can be integrated with Quasar. Promote your project and fill out your favorite Quasar-based stack. Make sure to mention @Quasarframework and all other relevant technologies.\n- **Watch a repo you care about**. This will send you notifications whenever there’s activity in that repository, giving you insider knowledge about ongoing discussions and upcoming features. It’s a fantastic way to build expertise so that you’re eventually able to help address issues and pull requests.\n\n## Reporting an Issue\n\n- GitHub: If you want to create a bug report or a docs report, that’s what the GitHub issues are for. Make sure that you select the correct template and follow the given instructions while creating an issue.\n\n::: danger Reporting a vulnerability\nPlease do not report security vulnerabilities with public GitHub issue reports. Follow the [Report a vulnerability](/security/report-a-vulnerability) steps for security issues.\n:::\n\nIf you've found a problem in Quasar which is not a security risk, do a search on GitHub under Issues to check if it is already answered or even fixed in the development branch (`dev`).\n\n- The issue list of the main repo is **exclusively** for bug reports and docs reports. Non-conforming issues will be closed immediately.\n - For simple beginner questions, you can get quick answers from the Quasar Discord chat.\n\n - For more complicated questions, you can use the Discussions section. Make sure to provide enough information when asking your questions - this makes it easier for others to help you!\n\n - For feature requests, you can start a new feature discussion.\n\n- Try to search for your issue, it may have already been answered or even fixed in the development branch (`dev`).\n\n- Check if the issue is reproducible with the latest stable version of Quasar. Please always indicate the specific version you are using.\n\n- It is **required** that you clearly describe the steps necessary to reproduce the issue you are running into. Although we would love to help our users as much as possible, diagnosing issues without clear reproduction steps is extremely time-consuming and simply not sustainable.\n\n- Use only the minimum amount of code necessary to reproduce the unexpected behavior. A good bug report should isolate specific methods that exhibit unexpected behavior and precisely define how expectations were violated. What did you expect the method or methods to do, and how did the observed behavior differ? The more precisely you isolate the issue, the faster we can investigate.\n\n- Issues with no clear reproduction steps will not be triaged. If an issue labeled \"bug/0-needs-info\" receives no further input from the issue author for a significant period of time, it will be closed.\n\n- If your issue is resolved but still open, don’t hesitate to close it. In case you found a solution by yourself, it could be helpful to explain how you fixed it.\n\n- Most importantly, we beg your patience: the team must balance your request against many other responsibilities — fixing other bugs, answering other questions, new features, new documentation, etc. The issue list is not paid support and we cannot make guarantees about how fast your issue can be resolved, although we do our very best.\n\n## Helping to Resolve Existing Issues\n\nAs a next step beyond reporting issues, you can help the Quasar Team resolve existing ones by providing feedback about them. If you are new to Quasar development, that might be a great way to walk your first steps, you'll get familiar with the code base and the processes.\n\nIf you check the issues list in GitHub Issues, you'll find lots of issues already requiring attention. What can you do for these? Quite a bit, actually:\n\n#### Verifying Bug Reports\n\nFor starters, it helps just to verify bug reports. Can you reproduce the reported issue on your own computer? If so, you can add a comment to the issue saying that you're seeing the same thing.\n\nIf an issue is very vague, can you help narrow it down to something more specific? Maybe you can provide additional information to help reproduce a bug, or help by eliminating needless steps that aren't required to demonstrate the problem.\n\nAnything you can do to make bug reports more succinct or easier to reproduce helps folks trying to write code to fix those bugs - whether you end up writing the code yourself or not.\n\n#### Testing Patches\n\nYou can also help out by examining pull requests that have been submitted to Quasar via GitHub. In order to apply someone's changes, you need to first create a dedicated branch:\n\n```bash\n$ git checkout -b testing_branch\n```\n\nThen, you can use their remote branch to update your codebase. For example, let's say the GitHub user JohnSmith has forked and pushed to a topic branch \"orange\" located at https://github.com/JohnSmith/quasar.\n\n```bash\n$ git remote add JohnSmith https://github.com/JohnSmith/quasar.git\n$ git pull JohnSmith orange\n```\n\nAfter applying their branch, test it out! Here are some things to think about:\n\n- Does the change actually work?\n- Does it have the proper documentation coverage? Should documentation elsewhere be updated?\n- Do you like the implementation? Can you think of a nicer or faster way to implement a part of their change?\n\nOnce you're happy that the pull request contains a good change, comment on the GitHub issue indicating your approval. Your comment should indicate that you like the change and what you like about it. Something like:\n\n::: tip Example pull request comment\nI like the way you've restructured the code in card.vue - much nicer. Documentation is updated too.\n:::\n\nIf your comment simply reads \"+1\", then odds are that other reviewers aren't going to take it too seriously. Show that you took the time to review the pull request.\n\n## Contributing to the Quasar Documentation\n\nYou can help improve the Quasar documentation by making it more coherent, consistent, or readable, adding missing information, correcting factual errors, fixing typos, or bringing them up to date with the latest edge Quasar.\n\n::: tip Typos or small changes can be fixed directly from the documentation\nUse a pencil icon in the top right corner of every documentation page. Edit the source file, preview the changes, add a description of your change and hit `Propose a file change` and on the next screen `Create pull request`.\n:::\n\nFor larger edits change the Quasar source files (located here on GitHub).\n\n### Documentation Best Practices\n\nOver time we consolidated a set of rules which we follow and following them will speed up the merge process:\n\n- Capitalize titles, see How to Use Capitalize My Title.\n- Use the present tense.\n- Be concise, avoid text / code duplication.\n- Link to the external sources which are used as master information sources and are usually updated more frequently, like Mozilla MDN, Vue.js API rather than compiled tutorials which tend to be outdated soon.\n- Do the proofreading before opening a PR\n- Do not repeat texts from other sources, but keep only things which are relevant and shows in a context Quasar specific features\n- Use official names. For example use `Firebase` instead of `firebase`\n- Exclude from PR all drafts and unfinished pages\n\n#### Fork\n\nNavigate to the Quasar GitHub repository and press \"Fork\" in the upper right-hand corner.\n\n::: warning Select dev branch\nMake sure you have `dev` branch selected and this is where all the work is done.\n:::\n\n#### Clone the forked repository\n\nTo be able to change the documentation, you need to clone forked repository:\n\n```bash\n$ git clone https://github.com/your-user-name/quasar.git\n$ cd quasar\n$ git checkout dev\n```\n\n#### Install dependencies\n\nInstall the required dependencies.\n\n```bash\n$ pnpm i\n```\n\n#### Running documentation against your local repository\n\n```bash\n$ cd docs\n$ pnpm dev\n```\n\nThe documentation runs against your local cloned repository.\n\n#### Edit and test your changes locally\n\n#### Commit your changes\n\nWhen you're happy with the change on your computer, you need to commit the changes to Git:\n\n```bash\n$ git commit -a\n```\n\nThis should fire up your editor to write a commit message. When you have finished, save and close to continue.\n\n#### Update your local repository\n\nIt's pretty likely that other changes to master have happened while you were working. Go get them.\n\n1. Add a remote Quasar repository as an upstream\n\n```bash\n$ git remote add upstream https://github.com/quasarframework/quasar.git\n```\n\n2. Fetch all remote branches\n\n```bash\n$ git fetch upstream\n```\n\n3. Check out your fork's local `dev` branch.\n\n```bash\n$ git checkout dev\n> Switched to branch 'dev'\n```\n\n4. Merge the changes from `upstream/dev` into your local `dev` branch. This brings your fork's `dev` branch into sync with the upstream repository, without losing your local changes.\n\n```bash\n$ git merge upstream/dev\n```\n\nNo conflicts? Tests still pass? Change still seems reasonable to you? Then move on and open a pull request to apply your changes to the dev branch in main Quasar repository.\n\n#### Issue a pull request\n\nNavigate to your repository you just pushed to (e.g. https://github.com/your-user-name/quasar) and click on \"New Pull Request\" seen in the left top panel.\n\nEnsure the change sets you introduced are included. Fill in some details about your potential patch including a meaningful title. When finished, press Click on \"Create pull request\". The Quasar core team will be notified about your submission.\n\n## Write your Story\n\nWe're always looking for great write-ups on how you are using Quasar or the great experiences you've had with Quasar. If you write an article, we will publish it on our Medium publication channel and we'll also make sure your article gets the attention it deserves with our social media presence. If you are interested, please contact blog(at)quasar.dev. We'd love to hear from you!\n\n## Create new Quasar App Extension\n\nAn easy way to start to contribute to Quasar is to generalize the code you have created on your project and publish it as a Quasar App Extension. Follow this guide on how to [create a new extension](/app-extensions/development-guide/introduction).\n\nWhen done, submit a PR on Quasar Awesome, share your achievement via Quasar Forum.\n\n## Contributing to the Quasar UI Source Code\n\nAs with any project, there are rules to contributing. Ours are written here, please read them carefully. After that, read the Quasar code of conduct and you’ll be ready to contribute to Quasar’s core repositories.\n\n\n\nAn article Look at the source code will help you to get familiar with a Quasar code base.\n\n#### Pull Request Guidelines\n\n- Checkout a topic branch from the relevant branch, e.g. `dev` (Qv2) or `v1` (Qv1), and merge back against that branch.\n\n- **DO NOT** check in `dist` in the commits.\n\n- It's OK to have multiple small commits as you work on the PR - we will let GitHub automatically squash it before merging.\n\n- If adding new feature:\n - Provide convincing reason to add this feature.\n - Ideally you should open a suggestion issue first and have it green-lighted before working on it. Otherwise, you risk spending a lot of time on something which might not get accepted at all or not in the form you expect.\n\n- If fixing a bug:\n - If you are resolving a specific issue, add `(fix: #xxxx[,#xxx])` (#xxxx is the issue id) in your PR title for a better release log, e.g. `fix: update entities encoding/decoding (fix #3899)`.\n - Provide detailed description of the bug in the PR. A live demo is preferred.\n\n#### Development Setup\n\nYou will need Node.js version **v22+** along pnpm. Read `package.json` and take notice of the scripts you can use.\n\nAfter cloning the repo, run:\n\n```bash\n$ pnpm i\n```\n\n#### Commonly used NPM scripts\n\n```bash\n# Start dev server with a demo app. This app has Quasar source code linked directly so any change will trigger HMR (Hot Module Reload) on the dev server.\n# There's a section for each feature where tests are made.\n$ pnpm dev\n\n# build all dist files, including npm packages\n$ pnpm build\n# build only js dist files\n$ pnpm build js\n# build only type related files\n$ pnpm build js types\n# build only css dist files\n$ pnpm build css\n\n# lint sources\n$ pnpm lint\n```\n\n#### Project Structure (/ui)\n\n\n\n- `build` - contains build-related configuration files. In most cases you don't need to touch them.\n\n- `src` - contains the source code. The codebase is written in ES2015.\n - `components` - JS, Sass and JSON (API) files for Quasar Vue components\n\n - `composables` - Quasar's composables for Vue 3 Composition API\n\n - `directives` - Vue directives supplied by Quasar\n\n - `plugins` - Quasar plugins\n\n - `css` - Sass definitions and core code for Quasar styles\n\n - `utils` - utilities used by the framework and exported to the public API\n\n- `lang` - Quasar language packs\n\n- `icon-set` - Quasar icon sets\n\n- `dist` - contains built files for distribution (only after a build).\n\n- `dev` - app with Quasar sources linked directly used for testing purposes. Each feature/component has its own `*.vue` file. Adding a new file automatically creates a route for it and adds it to the \"homepage\" list (based on the file name).\n\n#### Dev Server for Quasar (/ui)\n\nRunning `pnpm dev` starts up a dev server which uses HMR (Hot Module Reload) for Quasar source code. You can easily test your changes by making necessary changes to `/dev` `*.vue` files.\n\n\n\n## Financial Contribution\n\nQuasar Framework is an MIT-licensed open source project. Its ongoing development is made possible thanks to the support by these awesome backers.\n\n**Please read our manifest on [Why donations are important](/why-donate)**. If you'd like to become a donator, check out Quasar Framework's Donator campaign.\n\n## Quasar Contributors\n\nThank you to all the people who already contributed to Quasar!\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":16193,"content_sha256":"4eb79bdc9e41d6f4bbac5c9d08e10c184465201e8d2ebf5d058a4feaa7da0fd5"},{"filename":"references/docs/how-to-contribute/new-project.md","content":"---\ntitle: How-to Start a New Project\ndesc: How to start a new project for Quasar.\n---\n\nYou have a great new idea which is in line with the [Quasar vision](/introduction-to-quasar). Great, here is how to make it happen!\n\n1. Email to Razvan (`razvan.stoenescu [at] gmail [dot] com`) the following:\n\n a. **The need** you are fulfilling with the new Quasar Project\n\n b. **Name of the owner**/maintainer the project?\n\n c. **Vision** and a **technical high-level overview**\n\n d. **When do you plan the first public release**?\n\n e. **Milestones** with estimated dates\n\n f. How much **time you need from the Quasar team**\n\n g. Document the **changes** which are needed **in the Quasar core / extensions**\n\n h. Sustainability plan - any project creates more work and pressure on the existing Quasar team - what is **your long-term maintenance plan**\n\n2. Set up a meeting with Razvan to discuss it and invite all engaged in the project\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":943,"content_sha256":"716a1054f3cacd3db6961af3b59767eae810bea7d2d5d0127188441aa8c7a7be"},{"filename":"references/docs/how-to-contribute/project-maintainer.md","content":"---\ntitle: The Role of the Project Maintainer\ndesc: The role of a Quasar project manager\n---\n\n## Your Profile\n\n- You have a vision on something great that you want to build and own\n- You have enough time to put into it to succeed (although, yes, “You may have a job and the job is your priority, not this Quasar Project” --- this is perfectly fine)\n- You are not already involved in other projects that take a lot of your time and focus\n- You love open source\n- You want to help others\n- You can accept constructive criticism\n\n## Your Responsibilities\n\n- You are loosely aware of the entire Quasar ecosystem / inner-workings and in a detail of your Quasar feature / component / app extension / area.\n- You are recognized in the community (forum / chat) as the authority and lead over your Quasar feature / component / app extension / area and you actively supports it\n- You document, communicate and keep updated the vision of the Quasar feature / component / app extension / area that you are responsible for\n- You deliver the vision by implementing, fixing bugs, reviewing and merging PRs directly and via contributors\n- You focus on high usability for the end users - demos, documentation, community requests via forum and Discord\n- You provide inputs for Marketing and Media departments for articles on your Quasar Project\n - you don’t have to be the one writing the articles, although preferred, but at least find someone willing\n- You provide a code review for other Quasar maintainers and request a code review of your contributions\n- You keep track of the ongoing work and reported issues to make sure that it gets reviewed and merged in a timely manner.\n - You acknowledge every important contributor and give credit for their work (also in written form on the repo README, on every presentation material, on documentation).\n- You have also the final responsibility\n - If no reviewer can be found for an important contribution, you review.\n - If no developer can be found to fix an important bug, you develop.\n - If something goes wrong, it’s eventually your fault.\n- You keep the Quasar team updated at least on bi-weekly basis\n - You have regular calls with Razvan\n - You post a short project status into Discord #projects-status channel\n- You are brave to step down when you do not have time - it is perfectly fine to announce it.\n\nMore info - Best Practices for Maintainers\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2402,"content_sha256":"0bcabebf4ae333c598946d6628075b35111e74dfab507dcbd1b145847a76e341"},{"filename":"references/docs/how-to-contribute/running-projects.md","content":"---\ntitle: Active Project, Goals and Maintainers\ndesc: Quasar's active projects, goals and maintainers.\n---\n\n## List of Projects with Active Maintainer\n\n| Project | Responsibility | Maintainer | Repo, Links |\n| ----------------------- | ---------------------------------------------------------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Core UI, CLI, IconGenie | Ultimate responsibility of the Quasar, Quasar Core | Razvan | Main repo |\n| Media | Quasar is well known in JavaScript / Vue.js / backend / mobile and desktop dev community | Scott | Facebook, Medium, Twitter |\n| UI App Ext | Create and maintain UI extensions | Jeff | |\n| Quasar ESLint plugin | Plugin for ESLint with Quasar upgrade support warnings | Jeff | repo |\n| TypeScript support | Full TypeScript support for Quasar | Yusuf, Paolo | Main repo |\n| Quasar Testing AE | Maintenance and enhancements | Paolo | repo |\n| Apollo Client AE | Creator and maintainer | Scott | repo |\n\n## List of Projects Where New Maintainer is Needed\n\nThese projects are an inevitable part of the Quasar Framework, but to keep on our promise \"to raise the bar for web development as a whole\" we are looking for an active maintainer.\n\nIf you are interested, read [The Role of the Project Maintainer](/how-to-contribute/project-maintainer) and let Razvan know via Discord chat.\n\nWe can promise you that your Javascript and Vue.js skills will reach the stars!\n\n| Project | Required Skills | Links |\n| -------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| Cordova mode | Apache Cordova | app-vite, app-webpack |\n| Capacitor mode | Capacitor | app-vite, app-webpack |\n| Electron mode | Maintenance and enhancements | app-vite, app-webpack |\n| BEX | Browser Extension | app-vite, app-webpack |\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3487,"content_sha256":"e7c019db44b342a0fc4cf4286f6bebde1679124f505a12ea091732503c9b66e6"},{"filename":"references/docs/icongenie/app-icons-list.md","content":"---\ntitle: App Icons List\ndesc: List of the app icons and splash screens that are generated by the Icon Genie CLI based on the Quasar mode.\n---\n\nEach Quasar CLI mode requires its own list of icons and splash screens.\nThese are taken care of by Icon Genie through its [generate](/icongenie/command-list#generate) command.\n\nHere are the links to each mode's list:\n\n| Quasar Mode | @quasar/app-vite | @quasar/app-webpack |\n| ---------------------------- | -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |\n| App icons for SPA mode | [SPA mode](/quasar-cli-vite/developing-spa/app-icons-spa) | [SPA mode](/quasar-cli-webpack/developing-spa/app-icons-spa) |\n| App icons for PWA mode | [PWA mode](/quasar-cli-vite/developing-pwa/app-icons-pwa) | [PWA mode](/quasar-cli-webpack/developing-pwa/app-icons-pwa) |\n| App icons for SSR mode | [SSR mode](/quasar-cli-vite/developing-ssr/app-icons-ssr) | [SSR mode](/quasar-cli-webpack/developing-ssr/app-icons-ssr) |\n| App icons for Capacitor mode | [Capacitor mode](/quasar-cli-vite/developing-capacitor-apps/app-icons-capacitor) | [Capacitor mode](/quasar-cli-webpack/developing-capacitor-apps/app-icons-capacitor) |\n| App icons for Cordova mode | [Cordova mode](/quasar-cli-vite/developing-cordova-apps/app-icons-cordova) | [Cordova mode](/quasar-cli-webpack/developing-cordova-apps/app-icons-cordova) |\n| App icons for Electron mode | [Electron mode](/quasar-cli-vite/developing-electron-apps/app-icons-electron) | [Electron mode](/quasar-cli-webpack/developing-electron-apps/app-icons-electron) |\n| App icons for BEX mode | [BEX mode](/quasar-cli-vite/developing-browser-extensions/app-icons-browser-extension) | [BEX mode](/quasar-cli-webpack/developing-browser-extensions/app-icons-browser-extension) |\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2289,"content_sha256":"c0e4e4289ae43cfbdb54bf6ced1e9516deb4b517f80db4b29df68da6601e24fb"},{"filename":"references/docs/icongenie/command-list.md","content":"---\ntitle: Icon Genie CLI Command List\ndesc: Command list for Icon Genie CLI.\n---\n\nFamiliarize yourself with the list of available Icon Genie CLI commands inside a Quasar project folder:\n\n```bash\n$ icongenie\n\n Example usage\n $ icongenie \u003ccommand> \u003coptions>\n\n Help for a command\n $ icongenie \u003ccommand> --help\n $ icongenie \u003ccommand> -h\n\n Options\n --version, -v Print Quasar Icon Genie CLI version\n\n Commands\n generate, g Generate App icons & splash screens\n verify, v Verify your Quasar app's icons &\n splash screens\n profile, p Create Icon Genie profile files\n help, h Display this message\n```\n\nSee help for any command:\n\n```bash\n$ icongenie [command_name] --help\n```\n\n## Generate\n\nThe `generate` command is used for generating app icons and splash screens. It's at the heart of Icon Genie as it does the heavy lifting.\n\nTake a look below at usage and some examples. The most important parameter to note is `--icon` (or `-i`), which takes a transparent PNG as input for your app's icons and splash screens. Minimum size of the PNG is 64x64px, but it is highly recommended to go above 1024x1024px.\n\nFor splash screens, you may want to combine it with the `--background` (or `-b`) if you want your icon to be placed on top of a background.\n\nYou may also want to use the `--profile` (or `-p`) parameter, which can run one or more Icon Genie [profile files](/icongenie/profile-files).\n\n```bash\n$ icongenie generate -h\n\n Description\n Generate App icons & splash screens\n\n Usage\n $ icongenie generate [options]\n\n # generate icons for all installed Quasar modes\n $ icongenie generate -i /path/to/icon.png\n $ icongenie g -i /path/to/icon.png\n\n # generate for (as example) PWA mode only\n $ icongenie generate -m pwa --icon /path/to/icon.png\n\n # generate for (as example) Cordova & Capacitor mode only\n $ icongenie g -m cordova,capacitor -i\n /path/to/icon.png -b /path/to/background.png\n\n # generate by using a profile file\n $ icongenie generate -p ./icongenie-profile.json\n\n # generate by using batch of profile files\n $ icongenie generate -p ./folder-containing-profile-files\n\n Options\n --icon, -i Required;\n Path to source file for icon; must be:\n - a .png file\n - min resolution: 64x64 px (the higher the better!!)\n - with transparency\n Best results are with a square image (height = width)\n Image will be trimmed automatically\n (also see \"skip-trim\" and \"padding\" param)\n Path can be absolute, or relative to the root of the\n Quasar project folder\n Recommended min size: 1024x1024 px\n\n --background, -b Path to optional background source file (for splash screens);\n must be:\n - a .png file\n - min resolution: 128x128 px (the higher the better!!)\n - transparency is optional (but recommended if you\n combine with the splashscreen-color param)\n Path can be absolute, or relative to the root of the\n Quasar project folder\n Recommended min size: 1024x1024 px\n\n --mode, -m For which Quasar mode(s) to generate the assets;\n Default: all\n [all|spa|pwa|ssr|bex|cordova|capacitor|electron]\n Multiple can be specified, separated by \",\":\n spa,cordova\n\n --filter, -f Filter the available generators; when used, it can\n generate only one type of asset instead of all\n [png|ico|icns|splashscreen|svg]\n\n --quality Quality of the files [1 - 12] (default: 5)\n - higher quality --> bigger filesize & slower to create\n - lower quality --> smaller filesize & faster to create\n\n --skip-trim Do not trim the icon source file\n\n --padding Apply fixed padding to the icon after trimming it;\n Syntax: \u003choriz: number>,\u003cvert: number>\n Default: 0,0\n Example: \"--padding 10,5\" means apply 10px padding to top\n 10px to bottom, 5px to left side and 5px to rightside\n\n --theme-color Theme color to use for all generators requiring a color;\n It gets overridden if any generator color is also specified;\n The color must be in hex format (NOT hexa) without the leading\n '#' character. Transparency not allowed.\n Examples: 1976D2, eee\n\n --svg-color Color to use for the generated monochrome svgs\n Default (if no theme-color is specified): 1976D2\n The color must be in hex format (NOT hexa) without the leading\n '#' character. Transparency not allowed.\n Examples: 1976D2, eee\n\n --png-color Background color to use for the png generator, when\n \"background: true\" in the asset definition (like for\n the cordova/capacitor iOS icons);\n Default (if no theme-color is specified): fff\n The color must be in hex format (NOT hexa) without the leading\n '#' character. Transparency not allowed.\n Examples: 1976D2, eee\n\n --splashscreen-color Background color to use for the splashscreen generator;\n Default (if no theme-color is specified): fff\n The color must be in hex format (NOT hexa) without the leading\n '#' character. Transparency not allowed.\n Examples: 1976D2, eee\n\n --splashscreen-icon-ratio Ratio of icon size in respect to the width or height\n (whichever is smaller) of the resulting splashscreen;\n Represents percentages; Valid values: 0 - 100\n If 0 then it doesn't add the icon of top of background\n Default: 40\n\n --profile, -p Use JSON profile file(s):\n - path to folder (absolute or relative to current folder)\n that contains JSON profile files (icongenie-*.json)\n - path to a single *.json profile file (absolute or relative\n to current folder)\n Structure of a JSON profile file:\n {\n \"params\": {\n \"include\": [ ... ], /* optional */\n ...\n },\n \"assets\": [ /* list of custom assets */ ]\n }\n\n --help, -h Displays this message\n```\n\n## Verify\n\nThe `verify` command confirms that you have all required app icons and splash screens in the right place and that each file has the correct resolution in pixels.\n\n```bash\n$ icongenie -h\n\n Description\n Verifies your Quasar App's icons and splash screens\n for all installed modes.\n\n Usage\n $ icongenie verify [options]\n\n # verify all Quasar modes\n $ icongenie verify\n\n # verify specific mode\n $ icongenie verify -m spa\n\n # verify with specific filter\n $ icongenie verify -f ico\n\n # verify by using a profile file\n $ icongenie verify -p ./icongenie-profile.json\n\n # verify by using batch of profile files\n $ icongenie verify -p ./folder-containing-profile-files\n\n Options\n --mode, -m For which Quasar mode(s) to verify the assets;\n Default: all\n [all|spa|pwa|ssr|bex|cordova|capacitor|electron]\n Multiple can be specified, separated by \",\":\n spa,cordova,capacitor\n\n --filter, -f Filter the available generators; when used, it verifies\n only one type of asset instead of all\n [png|ico|icns|splashscreen|svg]\n\n --profile Use JSON profile file(s) to extract the asset list to verify:\n - path to folder (absolute or relative to current folder)\n that contains JSON profile files (icongenie-*.json)\n - path to a single *.json profile file (absolute or relative\n to current folder)\n Structure of a JSON profile file:\n {\n \"params\": {\n \"include\": [ ... ], /* optional */\n ...\n },\n \"assets\": [ /* list of custom assets */ ]\n }\n\n --help, -h Displays this message\n```\n\n## Profile\n\nIcon Genie also supports profile files. These files are in JSON format and tell Icon Genie which images to generate and how to generate them. The `profile` command is a helper to scaffold these profiles. They are very useful for automation, if needed.\n\nThe generic form of a JSON profile file is:\n\n```json\n{\n \"params\": {},\n \"assets\": []\n}\n```\n\nYou can also generate multiple profile files (with different params/settings). For more information please head on to the [Profile files](/icongenie/profile-files) page.\n\n```bash\n$ icongenie profile -h\n\n Description\n Helper command to easily bootstrap Icon Genie profile files.\n\n Usage\n $ icongenie profile -o \u003cfilename> [options]\n\n # supplying params list\n $ icongenie profile -o \u003cfilename> --include pwa,spa --quality 7\n\n # supplying assets based on Icon Genie's internal list\n $ icongenie profile -o \u003cfilename> --assets spa,bex\n\n Options\n --output, -o Name of the new Icon Genie profile file\n\n --assets, -a Prefill the assets Array with Icon Genie's\n internal list, based on the modes that you indicate;\n [all|spa|pwa|ssr|bex|cordova|capacitor|electron]\n Multiple can be specified, separated by \",\":\n spa,cordova\n\n --icon, -i Path to source file for icons; must be:\n - a .png file\n - min resolution: 64x64 px (the higher the better!!)\n - with transparency\n Best results are with a square image (height = width)\n Image will be trimmed automatically\n (also see \"skip-trim\" and \"padding\" param)\n Path can be absolute, or relative to the root of the\n Quasar project folder\n Recommended min size: 1024x1024 px\n\n --background, -b Path to optional background source file (for splash screens);\n must be:\n - a .png file\n - min resolution: 128x128 px (the higher the better!!)\n - transparency is optional (but recommended if you\n combine with the splashscreen-color param)\n Path can be absolute, or relative to the root of the\n Quasar project folder\n Recommended min size: 1024x1024 px\n\n --include Prefill the params.include property;\n [all|spa|pwa|ssr|bex|cordova|capacitor|electron]\n Multiple can be specified, separated by \",\":\n spa,cordova\n\n --filter, -f Prefill the params.filter property;\n [png|ico|icns|splashscreen|svg]\n\n --quality Prefill in the params.quality property;\n Quality of the files [1 - 12] (default: 5)\n - higher quality --> bigger filesize & slower to create\n - lower quality --> smaller filesize & faster to create\n\n --skip-trim Do not trim the icon source file\n\n --padding Apply fixed padding to the icon after trimming it;\n Syntax: \u003choriz: number>,\u003cvert: number>\n Default: 0,0\n Example: \"--padding 10,5\" means apply 10px padding to top\n 10px to bottom, 5px to left side and 5px to rightside\n\n --theme-color Prefill the params.themeColor property;\n Theme color to use for all generators requiring a color;\n It gets overridden if any generator color is also specified;\n The color must be in hex format (NOT hexa) without the leading\n '#' character. Transparency not allowed.\n Examples: 1976D2, eee\n\n --svg-color Prefill the params.svgColor property;\n Color to use for the generated monochrome svgs\n Default (if no theme-color is specified): 1976D2\n The color must be in hex format (NOT hexa) without the leading\n '#' character. Transparency not allowed.\n Examples: 1976D2, eee\n\n --png-color Prefill the params.pngColor property;\n Background color to use for the png generator, when\n \"background: true\" in the asset definition (like for\n the Cordova/Capacitor iOS icons);\n Default (if no theme-color is specified): fff\n The color must be in hex format (NOT hexa) without the leading\n '#' character. Transparency not allowed.\n Examples: 1976D2, eee\n\n --splashscreen-color Prefill the params.splashscreenColor property;\n Background color to use for the splashscreen generator;\n Default (if no theme-color is specified): fff\n The color must be in hex format (NOT hexa) without the leading\n '#' character. Transparency not allowed.\n Examples: 1976D2, eee\n\n --splashscreen-icon-ratio Prefill the params.splashscreenIconRatio property;\n Ratio of icon size in respect to the width or height\n (whichever is smaller) of the resulting splashscreen;\n Represents percentages; Valid values: 0 - 100\n If 0 then it doesn't add the icon of top of background\n Default: 40\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":15235,"content_sha256":"dbba4d3bd67ae40a9d3076521189e59eed0fd097bd5ead70c89a586aadb6ec34"},{"filename":"references/docs/icongenie/installation.md","content":"---\ntitle: Icon Genie CLI Installation\ndesc: How to install the Icon Genie CLI on your development machine.\n---\n\nMake sure that you have Node.js >=16 installed on your machine.\n\n::: warning\n**Do not use uneven versions of Node.js i.e. 19, 21, 23 etc.** These versions aren't tested with Quasar and often cause issues due to their experimental nature. We highly recommend always using the LTS version of Node.\n:::\n\nYou will be installing the Icon Genie CLI globally. You don't need to install it in your project folder.\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n# Node.js >=18 is required.\n$ yarn global add @quasar/icongenie\n\u003c\u003c| bash NPM |>>\n# Node.js >=18 is required.\n$ npm i -g @quasar/icongenie\n\u003c\u003c| bash PNPM |>>\n# Node.js >=18 is required.\n$ pnpm add -g @quasar/icongenie\n\u003c\u003c| bash Bun |>>\n# Node.js >=18 is required.\n$ bun install -g @quasar/icongenie\n```\n\nThis will install the `icongenie` command line tool.\n\n::: tip Attention developers on Windows\nIf you get an error like \"pngquant failed to build\" then you need to also globally install windows-build-tools (\"yarn global add windows-build-tools\" or \"npm install --global windows-build-tools\"). Then go to C:\\Users\\\\\u003cwindows_username>\\\\.windows-build-tools and run vs_BuildTools.exe. From there select npm/yarn and python to install. After this step it might require you to reboot your machine, otherwise you can now install @quasar/icongenie.\n:::\n\n## Installation tips\n\nIf you are using Yarn, make sure that the Yarn global install location is in your PATH:\n\n```bash\n# in ~/.bashrc or equivalent\nexport PATH=\"$(yarn global bin):$PATH\"\n```\n\nUnder Windows, modify user's PATH environment variable. If you are using yarn then add `%LOCALAPPDATA%\\yarn\\bin`, otherwise if you're using npm then add `%APPDATA%\\npm`.\n\n## Upgrading to Icon Genie v2\n\nThis section applies to those that have been using Icon Genie v1 and are now upgrading to Icon Genie v2.\n\n### NPM package name change\n\nVersion 1 was a Quasar [App Extension](/app-extensions/introduction) and so you installed it into your project folder. The new version (v2) does NOT need to be installed locally as it is installed globally. Your CI/CD will not need it as it is a one-time process and the output files (images) will be added directly to your project folder.\n\nAs a consequence, please uninstall Icon Genie v1 from your project folder:\n\n```bash\n# from your Quasar CLI project folder:\n$ quasar ext remove @quasar/icon-genie\n```\n\n### Input files\n\nWith version 1 you required to have an app-icon.png and an app-splashscreen.png (at a fixed width and height). This is no longer the case with version 2. You will now just need a png file (its name can be anything) with transparency and with minimum of 64x64 px (but the higher, the better! -- recommended min size: 1024x1024) for the icon, and then another optional png (any name) for the background of the splash screens (min 128x128 px, but recommended minimum is 1024x1024 px).\n\nThe splash screens work in a completely different manner too. They will get generated with the icon on top of the optional background. The size ratio of the icon to width or height (whichever is lower) can be adjusted with the CLI params (`--splashscreen-icon-ratio`). You can even tell Icon Genie that the ratio is 0 so it won't add the icon on top of the background.\n\n### Output files\n\nWe have refined the list of icons and splash screens that are generated to match the latest standards and to also avoid duplication. So you will notice that some of the older files don't get generated anymore and some are completely new. Icon Genie will now tell you what tags you need to add (if any) to your /index.html (**you can copy paste the tags and replace your old ones**) -- so be mindful about the list of tags.\n\nIt might be a good idea to delete all your current icon/splashscreen files and let Icon Genie do its job again. This way you will be sure that what you're left with is actually used in your Quasar App.\n\n## What's new in Icon Genie v2\n\nIcon Genie v2 is a complete rewrite from top to bottom.\n\n- Icon Genie is now a CLI on its own, not a Quasar App Extension any more.\n- The input files (for the icon and the background) can have any name, be placed anywhere, and they don't need to have a fixed width + height. Starting with v2.1, the icon input file does not needs to have same width and height. Also, the icon input file is now automatically trimmed.\n- You can now configure a padding for the icon input file. (v2.1+)\n- We have refined the list of icons and splash screens that get generated to match the latest standards and to also avoid duplication.\n- Splash screens are created in a better manner, with the icon on top of the background (with the icon having any size ratio that you want, including 0 which means: \"I only want the background image with no icon on top\")\n- New commands: [generate](/icongenie/command-list#generate), [verify](/icongenie/command-list#verify), and [profile](/icongenie/command-list#profile), each with its own purpose.\n- The `generate` command now also shows you what tags you need in your `/index.html` file.\n- The `verify` command can even check if every file is in the right place and it has the right width by height.\n- A lot of new parameters: quality, svg-color, png-color, splashscreen-color, splashscreen-icon-ratio, etc etc. Check the [command list](/icongenie/command-list) page.\n- You can now control each type of asset (ico, png, splashscreen, ...) for each Quasar mode individually, each with its own settings/parameters. Check the `--filter`, `--quality` and all the color parameters. One good use case is with the `.ico` files.\n- Automation is now possible through Icon Genie [profile files](/icongenie/profile-files).\n- You can now **generate your own custom image files** using the Icon Genie API through the [profile files](/icongenie/profile-files).\n\nFinally, we need to emphasize again on the `quality` parameter, which will dictate how good-looking and how big (KB) your images will be.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5985,"content_sha256":"e91658595f3ae0cec570f9c846be4ce647341d804be867613f1c3f7847812503"},{"filename":"references/docs/icongenie/introduction.md","content":"---\ntitle: Icon Genie CLI\ndesc: A Quasar tool for generating all your app's icons and splash screens in 100+ formats.\n---\n\nYou love the default Quasar logo, probably as much as the team does, but you just spent what feels like a lifetime making your own pixel-perfect representation of the soul of your application and now you want to replace that logo with your own!\n\nThere are many different situations where your icon might be seen: in the browser tab, on the desktop, on the home screen of a mobile phone and even in an app store. Then there are splash screens to create in all the various device sizes and orientations.\n\nThis means you need your logo in about 100+ different sizes with representative names, arcane formats, placed in the correct folders and probably some proper `\u003cxml>` declarations for Cordova too. Even if you know exactly what you're doing, this is a tedious and error-prone task. To make your life easy and care-free, we've built the Icon Genie CLI tool to make this exhausting process **dead simple**.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/iconfactory.png\" style=\"float:right;max-width:15%;min-width:240px;padding-top:40px\">\n\n## How it helps you\n\n::: tip\nWe highly recommend using the Icon Genie CLI **for your Quasar CLI-generated projects** because it consumes a source icon and automatically clones, scales, minifies and places the icons and splash screens in the appropriate directories for you. When needed, it also tells you what tags you'll need to add to your /index.html file.\n:::\n\n## Requirements\n\nThis tool was built by the Quasar Team especially **with the Quasar CLI project structure in mind**. If you build your project folder with another CLI, you should explore Icon Genie [profile files](/icongenie/profile-files).\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1760,"content_sha256":"400205d87c2357eeaef82a7f727ccb5d0dc937b0826345a223f46544b237532f"},{"filename":"references/docs/icongenie/profile-files.md","content":"---\ntitle: Icon Genie Profile Files\ndesc: How to use profile files with the Icon Genie CLI.\n---\n\nIf you need to automate the creation of all your app's icons and splash screens, Icon Genie offers configuration files which can be run in batch.\n\nThese configuration files are called \"profile files\". The files are in JSON format and tell Icon Genie which images to generate and how to generate them. They also spare you from having to remember the whole set of Icon Genie commands and parameters to generate your assets.\n\n## File structure\n\nThe generic form of a JSON profile file is:\n\n```json\n{\n \"params\": {},\n \"assets\": []\n}\n```\n\nWe will be discussing each in the next sections.\n\n### Params\n\nThe `params` object from a JSON profile file takes the same prop names as the [generate](/icongenie/command-list#generate) command parameters (but camelCased instead of the CLI's kebab-case). There is one key difference: instead of using `mode` (examples: \"spa,pwa\", \"all\") you will be writing `include` (examples: [ \"spa\", \"pwa\" ], [ \"all\" ]).\n\nFull list of props that you can write for the `params` object:\n\n| Prop name | Type | Description | Examples |\n| --------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |\n| include | Array | Include Icon Genie hardcoded sets of assets for specific Quasar modes | `[ \"spa\", \"pwa\" ]` / `[ \"all\" ]` |\n| icon | String | Path to source file for icon; can be absolute or relative to the root of the Quasar project folder | `my-icon.png` |\n| background | String | Path to optional background source file (for splash screens); can be absolute or relative to the root of the Quasar project folder | `my-bg.png` |\n| filter | String | Optionally filter the assets by generators; when used, it can generate only one type of asset instead of all | `ico` |\n| quality | Number [1-12] | Quality of the generated files; higher quality means bigger filesize, slower; lower quality means smaller filesize, faster | `12` |\n| padding | Array [Number] | (v2.1+) Apply fixed padding to the icon image after trimming it; Syntax: [ \u003choriz_px>, \u003cvert_px> ]; Default is: [0, 0] | `[10, 0]` / `[5,5]` |\n| skipTrim | Boolean | (v2.2+) Do not trim the icon source file | |\n| themeColor | String [hex] | Theme color to use for all generators requiring a color; it gets overridden if any generator color is also specified | `ccc` / `e2b399` |\n| pngColor | String [hex] | Background color to use for the png generator, when \"background: true\" in the asset definition (like for the cordova/capacitor iOS icons) | `ccc` / `e2b399` |\n| splashscreenColor | String [hex] | Background color to use for the splashscreen generator | `ccc` / `e2b399` |\n| svgColor | String [hex] | Color to use for the generated monochrome SVGs | `ccc` / `e2b399` |\n| splashscreenIconRatio | Number [0-100] | Ratio of icon size in respect to the width or height (whichever is smaller) of the resulting splashscreen; represents percentages; 0 means it won't add the icon of top of the background | `40` |\n\n### Assets\n\nThe `assets` array can contain custom definitions for **extra assets**, should you need them. This can be used when Icon Genie's default list for each mode is not sufficient for your use case. If you don't specify the `include` prop in `params` you can only generate your custom assets.\n\nIn 99% of the cases you won't need to specify the `assets` array, but Icon Genie is designed to be very flexible, so it includes this feature too.\n\nSome examples for `assets` from which you can extract the syntax for every type of possible asset that Icon Genie can generate:\n\n```json\n\"assets\": [\n {\n \"generator\": \"png\",\n \"name\": \"icon-{size}x{size}.png\",\n \"folder\": \"src-bex/icons\",\n \"sizes\": [ 16, 48, 128 ]\n },\n\n {\n \"generator\": \"svg\",\n \"name\": \"safari-pinned-tab.svg\",\n \"folder\": \"public/icons\"\n },\n\n {\n \"generator\": \"splashscreen\",\n \"name\": \"apple-launch-{size}.png\",\n \"folder\": \"public/icons\",\n \"sizes\": [\n [ 1668, 2388 ]\n ],\n \"tag\": \"\u003clink rel=\\\"apple-touch-startup-image\\\" media=\\\"(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2)\\\" href=\\\"icons/{name}\\\">\"\n },\n\n {\n \"generator\": \"icns\",\n \"name\": \"icon.icns\",\n \"folder\": \"src-electron/icons\"\n },\n\n {\n \"generator\": \"ico\",\n \"name\": \"icon.ico\",\n \"folder\": \"src-electron/icons\"\n },\n\n {\n \"generator\": \"splashscreen\",\n \"name\": \"Default-Landscape-2436h.png\",\n \"folder\": \"src-cordova/res/screen/ios\",\n \"sizes\": [\n [ 2436, 1125 ]\n ]\n },\n\n {\n \"generator\": \"png\",\n \"name\": \"[email protected]\",\n \"folder\": \"src-cordova/res/ios\",\n \"sizes\": [ 58 ],\n \"platform\": \"cordova-ios\",\n \"background\": true\n },\n\n {\n \"generator\": \"png\",\n \"name\": \"[email protected]\",\n \"folder\": \"src-cordova/res/ios\",\n \"sizes\": [ 58 ],\n \"platform\": \"cordova-ios\",\n \"background\": true\n },\n\n {\n \"generator\": \"png\",\n \"name\": \"xxxhdpi.png\",\n \"folder\": \"src-cordova/res/android\",\n \"sizes\": [ 192 ],\n \"platform\": \"cordova-android\",\n \"density\": \"xxxhdpi\"\n },\n\n {\n \"generator\": \"splashscreen\",\n \"name\": \"Default@2x~ipad~comany.png\",\n \"folder\": \"src-cordova/res/screen/ios\",\n \"sizes\": [\n [ 1278, 2732 ]\n ],\n \"platform\": \"cordova-ios\"\n },\n\n {\n \"generator\": \"splashscreen\",\n \"name\": \"splash-land-xxxhdpi.png\",\n \"folder\": \"src-cordova/res/screen/android\",\n \"sizes\": [\n [ 1920, 1280 ]\n ],\n \"platform\": \"cordova-android\",\n \"density\": \"land-xxxhdpi\"\n }\n]\n```\n\n## Bootstrap profiles\n\nIcon Genie also offers the [profile command](/icongenie/command-list#profile) which can bootstrap JSON profile files for you. It can help you create one or more such files that you can then run in batch through the [generate command](/icongenie/command-list#generate) with `--profile` param (or short `-p`).\n\nThe most handy use case is to generate multiple profile files into one specific folder, each with their own parameters, and then run all of them through `$ icongenie generate -p /path/to/folder`.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":7855,"content_sha256":"6d0d40915f8aefbfc5cf2ae7bbc49f3e173b5954be8dc45a787836d83e6f8acb"},{"filename":"references/docs/index.md","content":"---\ntitle: \"Quasar Framework\"\nmeta:\n \"og:description\": \"Developer-oriented, front-end framework with VueJS components for best-in-class high-performance, responsive websites, PWA, SSR, Mobile and Desktop apps, all from the same codebase. Sensible people choose Vue. Productive people choose Quasar. Be both.\"\n \"og:title\": \"Quasar Framework - Build high-performance VueJS user interfaces in record time\"\n \"twitter:description\": \"Developer-oriented, front-end framework with VueJS components for best-in-class high-performance, responsive websites, PWA, SSR, Mobile and Desktop apps, all from the same codebase. Sensible people choose Vue. Productive people choose Quasar. Be both.\"\n \"twitter:title\": \"Quasar Framework - Build high-performance VueJS user interfaces in record time\"\n description: \"Developer-oriented, front-end framework with VueJS components for best-in-class high-performance, responsive websites, PWA, SSR, Mobile and Desktop apps, all from the same codebase. Sensible people choose Vue. Productive people choose Quasar. Be both.\"\n---\n\n# The enterprise-ready cross-platform VueJs framework\n\nOur Platinum sponsors\n\n\n\n\n\n\n\n## Why should you choose Quasar?\n\n__\n\nTop Class Components\n\nA library of more than 70 high performance customizable Material Design web components for all your needs\n\nBrowse components\n\n__\n\nOne codebase many integrations\n\nKeep your favorite technology, we provide all the needed integrations out of the box.\n\nDiscover Integrations\n\n__\n\nGreat documentation\n\nAll the details you deserve to start working properly. Every star-pilot needs a good manual.\n\nGet Started\n\n__\n\n## What our community thinks of Quasar\n\n\"You've never heard of Quasar? It's the framework that made a mobile app, desktop app and browser extension altogether in less than 12 minutes.\"\n\nAlvaro Sabu\n\n@alvarosabu\n\n__\n\nI must say Im quite surprise how complete @quasarframework is, been working on a really complex select component and it works like charm. Very well documented.\n\n6:39 PM · Oct 16, 2020 from Terrassa, España\n\nRead on Twitter\n\nDale Zak\n\n@dalezak\n\n__\n\nOk, I’m really impressed with the @QuasarFramework, great documentation and powerful framework for building #iOS, #Android, #PWA and #SPA apps using #VueJS https://quasar.dev \n\n7:39 PM · May 7, 2020 from Saskatoon, Saskatchewan\n\nRead on Twitter\n\nGregory Luneau\n\n@LuneauGregory\n\n__\n\nQuasar is the best thing since sliced bread.\n\n6:51 PM · May 28, 2021\n\nRead on Twitter\n\nTony OHagan\n\n@tony_ohagan\n\n__\n\nQuasar listen .. I've submitted several suggestions which they acted on ( QSplitter, line-awesome icons and Icon genie!). Optimised rock solid components and best docs & examples in the business save me time and money every week. #QuasarLove #quasarframework\n\n12:59 PM · Jan 20, 2022\n\nRead on Twitter\n\nMarco Ruiz\n\n@estados\n\n__\n\nI love #quasarframework because I can make great web, mobile and desktop applications with a single code base. It's organized and clean, has an active community, and is at the forefront of innovation. #QuasarLove \n\n10:28 PM · Jan 19, 2022\n\nRead on Twitter\n\nNavicstein\n\n@NavicsteinR\n\n__\n\nVery very ahead, i wish there could be a world blaster to notify all Vue users that a framework like quasar exist!\n\n10:28 PM · Jan 19, 2022\n\nRead on Twitter\n\nprogrammerq.wallet\n\n@Qoyyuum\n\n__\n\nI love how #quasarframework is so versatile. Easy copy and paste components and UI elements (especially for a crappy designer like me) and quick x-platform deploy is amazingly easy! #QuasarLove\n\n11:49 AM · Jan 19, 2022\n\nRead on Twitter\n\nMauricio Etcheverry\n\n@maurietchev\n\n__\n\nI'm gonna marry @quasarframework. It was love at first sight \n\n4:25 PM · Dec 23, 2019\n\nRead on Twitter\n\nradioActive DROID\n\n@gpproton\n\n__\n\nQuasar really save you from toiling away with third party dependencies #QuasarLove #quasarframework\n\n2:06 PM · Jan 19, 2022\n\nRead on Twitter\n\nAli Ataf\n\n@AliAttaf1\n\n__\n\nThere is no situation I needed to make an !important override to the Quasar framework. It's just there, everything you will face will already be in their consideration. #QuasarLove #quasarframework\n\n9:19 PM · Jan 22, 2022\n\nRead on Twitter\n\nShawn Makinson\n\n@smakinson\n\n__\n\nI've used #quasarframework for websites, mobile & interactive touch via electron for museum & welcome center display. It's flexible, reliable, powerful and fast. Thank you Razvan & team as well as the community! #QuasarLove\n\n8:32 PM · Jan 20, 2022\n\nRead on Twitter\n\nSimon Swain\n\n@simon_swain\n\n__\n\nGotta throw some love out there for @quasarframework -- it really does make things stupidly easy and fast to build.\n\n9:23 AM · Sep 2, 2020\n\nRead on Twitter\n\nhyranity\n\n@hyranity\n\n__\n\nCode faster and smarter with the best Vue framework. Your brain will thank you. #quasarframework. #QuasarLove\n\n2:51 PM · Jan 19, 2022\n\nRead on Twitter\n\n__\n\n__\n\n## SPONSOR QUASAR, HELP THE PROJECT GROW!\n\nWorking for a company? Are you a freelancer? You can contribute, even a bit, and even get something back in return.\n\n\"So, um, we think we should discuss the bonus situation\" Consult tiers\n\n__\n\n## Our Sponsors\n\nEvery space odyssey has its patrons\n\n__\n\nDon't miss the news\n\nFollow our social pages to stay up to date\n\nDiscord Forum X (Twitter) Facebook\n\n---\n\nMIT License Privacy Policy\n\nCopyright 2015-present PULSARDEV SRL, Razvan Stoenescu\n\nThis website has been designed in collaboration with Dreamonkey Srl","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5342,"content_sha256":"365617c956740c9cf4a828d7fe3216bf737edbe15eefb69cbb399da8eb218b9d"},{"filename":"references/docs/integrations/integrations.md","content":"---\ntitle: Quasar Integrations\ndesc: Quasar Integrations\nheading: false\neditLink: false\n---\n\n\n\n\u003cQuasarIntegrations />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":118,"content_sha256":"385d0b0369ba49f29960468afd79080cc056883fe4215632e47284689f06b787"},{"filename":"references/docs/introduction-to-quasar/introduction-to-quasar.md","content":"---\ntitle: Why Quasar?\ndesc: What Quasar is and how it can considerably reduce your development time and costs.\n---\n\nBecause it saves development costs drastically. Only Quasar can do:\n\n\n\n\u003cIntroductionVideo />\n\nAlso because:\n\n- It's based on Vue.js\n- You get a state-of-the-art UI (that follows Material Guidelines) for your **websites** and **apps** out of the box\n- Best support for desktop and **mobile browsers** (including iOS Safari!) out of the box\n- Best-in-class support for each build mode (SPA, SSR, PWA, Mobile app, Desktop app & Browser Extension) and the best developer experience through a tight integration with our own CLI\n- It's easily customizable (CSS) and extendable (JS)\n- It's the most performance-focused framework\n- It's tree-shakable automatically\n- Incredible community on our Forum and Discord chat\n- Has a regular release cycle inclusive of new features\n- Gets quick fixes and listens to the community's requests\n- Handles the whole development experience (including even creating your app's icons and splash screens)\n\nWorried about bloat? You shouldn't be. If you only want to build a website, Quasar will only build the code required for a website, with nothing else. Same goes for the other build modes.\n\n## What is Quasar?\n\nQuasar (pronounced `/ˈkweɪ.zɑɹ/`) is an MIT licensed open-source Vue.js based framework, which allows you as a web developer to quickly create responsive++ websites/apps in many flavours:\n\n- SPAs (Single Page App)\n- SSR (Server-side Rendered App) (+ optional PWA client takeover)\n- PWAs (Progressive Web App)\n- BEX (Browser Extension)\n- Mobile Apps (Android, iOS, …) through Cordova or Capacitor\n- Multi-platform Desktop Apps (using Electron)\n\nQuasar's motto is: **write code once and simultaneously deploy it** as a website, a Mobile App and/or an Electron App. Yes, one codebase for all of them, helping you develop an app in record time by using a state-of-the-art CLI and backed by best-practice, blazing fast Quasar web components.\n\nWhen using Quasar, you won't need additional heavy libraries like Hammer.js, Moment.js or Bootstrap. It's got those needs covered internally, and all with a small footprint!\n\n## What else you got?\n\nBecause of the simplicity and power offered to you out of the box, Quasar, with its CLI, is packed full of features, all built to make your developer life easier.\n\n::: tip Food for thought\nQuasar is looking into the future and sets its own high and modern standards. And yes, in order to make progress in web development, we need to break the current establishment. Otherwise, we’d all continue to write websites in cgi-bin / perl today too, because many years ago that’s what developers were accustomed to. However, what most developers are accustomed to at one point in time doesn’t actually mean it’s the best solution or the “definite” solution, and Quasar will never bend into choosing what we believe is not the optimal path to high-quality work, not even over money.\n\u003cbr>\u003cbr>\n\n_What we want to achieve with Quasar is to raise the bar for web development as a whole. Make it go forward, evolve. Change minds. Point out when there’s a better alternative._\n:::\n\nBelow is a non-exhaustive list of Quasar's great aspects and features.\n\n#### All Platforms in One Go\n\nOne authoritative source of code for all platforms, simultaneously: responsive desktop/mobile websites (SPA, SSR + SPA client takeover, SSR + PWA client takeover), PWAs (Progressive Web Apps), mobile apps (that look native) and multi-platform desktop apps (through Electron).\n\n#### The largest set of top-class, fast and responsive web components\n\nThere’s a component for almost every web development need within Quasar. Each of Quasar's components is carefully crafted to offer you the best possible experience for your users. Quasar is **designed with performance & responsiveness in mind** – so the overhead of using Quasar is barely noticeable. This attention to performance and good design is something that gives us special pride.\n\n#### Best practices integrated by default\n\nQuasar was also built to encourage developers to follow web development best practices. To do this, Quasar is packed full of great features out of the box - **with no configuration needed**.\n\n#### App Extensions support\n\nQuasar App Extensions are a way to painlessly inject complicated (or simple) setups into your websites/apps. They're also a way for our big community to contribute and help you get up to speed even faster. **The patterns for development literally open the floodgates to making Quasar one of the most extensible and powerful frameworks out there** - limited only by your imagination and innovation.\n\n#### Full RTL Support\n\nRTL (right to left) support for both Quasar components & the developer’s own code. Developer-written website/app CSS code gets automatically converted to RTL if an RTL language pack is used.\n\n#### Progressively migrate your existing project\n\nQuasar offers a UMD (Unified Module Definition) version, which means developers can add a CSS and JS HTML tag into their existing project and they’re ready to use it. No build step is required.\n\n#### Focus on your features, not the boilerplating\n\nThe top-class project initialization with Quasar CLI makes getting started very easy for you as a developer. You can turn your idea into reality in record time. In other words, Quasar does the heavy lifting for you, so you are free to focus on your features and not on boilerplate.\n\n#### Automated testing & audit\n\nQuasar projects have the ability to add Unit and End-to-End testing harnesses out of the box, as well as an ever-growing suite of product quality and security auditing tools. All this to ensure that your websites/apps have the highest quality possible.\n\n#### Awesome ever-growing community\n\nWhen developers encounter a problem they can’t solve, they can visit the Quasar forum or our Discord chat server. The community is always there to help you. You can also get updates on new versions and features by following us on Twitter. You can also get special service as a backer/sponsor and help make sure Quasar stays relevant for you in the future too!\n\n#### A wide range of platform support\n\nGoogle Chrome, Firefox, Edge, Safari, Opera, iOS, Android, MacOS, Linux, Windows.\n\n#### Quasar Language Packs\n\nQuasar comes equipped with over 40 language packs out of the box. On top of that, if your language pack is missing, it takes just 5 minutes to add it.\n\n#### Great documentation\n\nAnd finally, it’s worth mentioning the significant amount of time taken to write great, bloat-free, focused and complete documentation so that developers can quickly pick up Quasar. We put special effort into our documentation to make sure there is no confusion.\n\n## Get started in under a minute\n\nHaving said this, let's [get started](/start)! You'll be running a website or app in under a minute.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":6900,"content_sha256":"1fecd68996d8213523da0c9c80489047b3a3f06ad2d9453c27b71836493c972f"},{"filename":"references/docs/layout/drawer.md","content":"---\ntitle: Layout Drawer\ndesc: How to use the QDrawer component. The sidebars of your Quasar app.\nkeys: QDrawer\nexamples: QDrawer\nrelated:\n - /layout/layout\n - /vue-components/list-and-list-items\n---\n\nQLayout allows you to configure your views as a 3x3 matrix, containing optional left-side and/or right-side Drawers. If you haven’t already, please read [QLayout](/layout/layout) documentation page first.\n\nQDrawer is the sidebar part of your QLayout.\n\n\u003cDocApi file=\"QDrawer\" />\n\n## Layout Builder\n\nScaffold your layout(s) by clicking on the button below.\n\n\u003cq-btn icon-right=\"launch\" label=\"Layout Builder\" href=\"/layout-builder\" target=\"_blank\" />\n\n## Usage\n\n::: tip\n\n- Since QDrawer needs a layout and QLayout by default manages the entire window, then for demoing purposes we are going to use containerized QLayouts. But remember that by no means you are required to use containerized QLayouts for QDrawer.\n- If the QDrawer content also has images and you want to use touch actions to close it, you might want to add `draggable=\"false\"` to them, otherwise the native browser behavior might interfere in a negative way.\n :::\n\n::: danger\nBy default, QDrawer has touch actions attached to it. If this interferes with your drawer content components, disable it by specifying the Boolean `no-swipe-close` property.\n:::\n\n::: warning\nWhen QDrawer is set into overlay mode, **it will force it to go into fixed position**, regardless if QLayout's \"view\" prop is configured with \"l/r\" or \"L/R\". Also, **if on iOS platform and QLayout is containerized**, the fixed position will also be forced upon QDrawer due to platform limitations that cannot be overcome.\n:::\n\n### Basic\n\n\u003cDocExample title=\"Basic\" file=\"Basic\" />\n\nConsider using QItems with routing props (like `to`) below. For demoing purposes these props have not been added as it would break the UMD version.\n\n\u003cDocExample title=\"With navigation menu\" file=\"Menu\" />\n\n\u003cDocExample title=\"Seamless menu\" file=\"MenuSeamless\" />\n\n\u003cDocExample title=\"Header Picture\" file=\"HeaderPicture\" />\n\n### Mini-mode\n\nDrawer can operate in two modes: 'normal' and 'mini', and you can switch between them by using the Boolean `mini` property on QLayoutDrawer.\n\n::: warning\nPlease note that **`mini` mode** does not apply when in **mobile** behavior.\n:::\n\nThere are some CSS classes that will help you customize the drawer when dealing with \"mini\" mode. These are very useful especially when using the \"click\" trigger:\n\n| CSS Class | Description |\n| -------------------- | ------------------------------------------------------- |\n| `q-mini-drawer-hide` | Hide when drawer is in \"mini\" mode or in \"mobile\" mode. |\n| `q-mini-drawer-only` | Show only when drawer is in \"mini\" mode. |\n\nYou can also write your own CSS classes based on the fact that QLayoutDrawer has `q-drawer--standard` CSS class when in \"normal\" mode and `q-drawer--mini` when in \"mini\" mode. Also, when drawer is in \"mobile\" behavior, it gets `q-drawer--mobile` CSS class.\n\n#### Mouseover/mouseout trigger\n\nConsider using QItems with routing props (like `to`) below. For demoing purposes these props have not been added as it would break the UMD version.\n\n\u003cDocExample title=\"Mini-mode with mouseover/mouseout trigger\" file=\"MiniMouseEvents\" />\n\n#### Mini to overlay\n\nThe `mini-to-overlay` Boolean property will always set your drawer with fixed position, regardless of your configuration from the `view` prop, but will occupy space on the layout only as wide as when in mini-mode.\n\n\u003cDocExample title=\"Mini to overlay\" file=\"MiniToOverlay\" />\n\n#### Click trigger\n\nIn the example below, when in \"mini\" mode, if the user clicks on Drawer then we switch to normal mode.\n\nConsider using QItems with routing props (like `to`) below. For demoing purposes these props have not been added as it would break the UMD version.\n\n\u003cDocExample title=\"Mini-mode with click trigger\" file=\"MiniClickEvent\" />\n\n#### Slots\n\nBy default, when in \"mini\" mode, Quasar CSS hides a few DOM elements to provide a neat narrow drawer. But there may certainly be use-cases where you need a deep tweak. You can use the \"mini\" Vue slot of QLayoutDrawer just for that. The content of this slot will replace your drawer's default content when in \"mini\" mode.\n\n\u003cDocExample title=\"Mini-mode with slot\" file=\"MiniSlot\" />\n\n### Overlay mode\n\nThe overlay mode prevents the drawer from occupying space on the layout and rather hover over the page instead. This will always set your drawer with fixed position, regardless of your configuration from the `view` prop.\n\nOn the example below, click the menu icon to see the drawer in action. It's best viewed on a desktop with a window of at least 500px width (this is the breakpoint that is set on this demo).\n\n\u003cDocExample title=\"Overlay mode\" file=\"OverlayMode\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4843,"content_sha256":"684451b6e04edf8e9ee687b85c2c816ab6c6143bba87514ee4f199084070e1c5"},{"filename":"references/docs/layout/gallery/gallery.md","content":"---\ntitle: Layout Gallery\ndesc: Gallery of a few layouts for your Quasar apps.\nrelated:\n - /layout/layout\n - /layout/header-and-footer\n - /layout/drawer\n - /layout/page\n---\n\nAs a way to help you get started quicker, we've written a few ready Quasar Layouts for you. Please also take time to learn each Quasar component, otherwise you'll be missing a lot of features.\n\n\n\n\u003cLayoutGallery class=\"q-mt-md\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":408,"content_sha256":"391deca814b4ae008ac105392906daa7adeb4c103e649e6b7c9944872ed3c17b"},{"filename":"references/docs/layout/grid/column.md","content":"---\ntitle: Grid Column\ndesc: How to use the Quasar grid for columns.\nexamples: grid\nrelated:\n - /layout/grid/introduction-to-flexbox\n - /layout/grid/row\n - /layout/grid/gutter\n - /layout/grid/flex-playground\n---\n\nIn the hope that you've previously read the [Introduction to Flexbox](/layout/grid/introduction-to-flexbox) theory, let's get deeper into Columns.\n\nUtilize breakpoint-specific row classes for equal-height rows. Add any number of unit-less classes for each breakpoint you need and every row will be the same height.\n\n## Equal-height\n\nFor example, here are two grid layouts that apply to every device and viewport, from xs to xl.\n\n\u003cDocExample title=\"Equal Height Example\" file=\"ColumnEqualWidth\" />\n\n## Setting one row height\n\nAuto-layout for flexbox grid rows also means you can set the height of one row and the others will automatically resize around it. You may use predefined grid classes (as shown below) or inline heights. Note that the other rows will resize no matter the height of the center row.\n\n\u003cDocExample title=\"Setting one row height\" file=\"ColumnRowWidth\" />\n\n## Variable height content\n\nUsing the `col-{breakpoint}-auto` classes, rows can size itself based on the natural height of its content. This is super handy with single line content like inputs, numbers, etc. This, in conjunction with horizontal alignment classes, is very useful for centering layouts with uneven row sizes as viewport height changes.\n\n\u003cDocExample title=\"Variable height content\" file=\"ColumnVariableWidth\" />\n\n## Responsive classes\n\nThe grid includes five tiers of predefined classes for building complex responsive layouts. Customize the size of your rows on extra small, small, medium, large, or extra large devices however you see fit.\n\n### All breakpoints\n\nFor grids that are the same from the smallest of devices to the largest, use the `.col` and `.col-*` classes. Specify a numbered class when you need a particularly sized row; otherwise, feel free to stick to .col.\n\n\u003cDocExample title=\"All breakpoints\" file=\"ColumnAllBreakpoints\" />\n\n### Mix and match\n\nDon’t want your rows to simply stack in some grid tiers? Use a combination of different classes for each tier as needed. See the example below for a better idea of how it all works.\n\n\u003cDocExample title=\"Mix and match\" file=\"ColumnMixAndMatch\" />\n\n### Alignment\n\nUse flexbox alignment utilities to vertically and horizontally align columns.\n\n\u003cDocExample title=\"Horizontal alignment\" file=\"ColumnHorizontalAlignment\" />\n\n\u003cDocExample title=\"Vertical alignment\" file=\"ColumnVerticalAlignment\" />\n\n::: tip\nThere is also the convenience `flex-center` CSS class which is equivalent to `items-center` + `justify-center`. Use it along with `flex`, `row` or `column`.\n:::\n\n### Wrapping\n\nIf more than 12 columns are placed within a single row, each group of extra columns will, as one unit, wrap onto a new line.\n\n\u003cDocExample title=\"Wrapping\" file=\"ColumnRowWrapping\" />\n\n### Reordering\n\n\u003cDocExample title=\"Reverse\" file=\"ColumnReverse\" />\n\n\u003cDocExample title=\"Flex order\" file=\"ColumnFlexOrder\" />\n\n### Nesting\n\nTo nest your content with the default grid, add a new `.row` and set of `.col-sm-*` columns within an existing `.col-sm-*` column. Nested rows should include a set of columns that add up to 12 or fewer (it is not required that you use all 12 available columns).\n\n\u003cDocExample title=\"Nesting\" file=\"ColumnNesting\" />\n\n## Flex Grid Playground\n\nTo see the Flex in action, you can use the Flex Playground to interactively learn more.\n\n\u003cq-btn icon-right=\"launch\" label=\"Flex Playground\" to=\"/layout/grid/flex-playground\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3592,"content_sha256":"8e45d44c17d9f377c7bf1ad8883bae1ebdb1e8ca93804b898e3603836a3a625e"},{"filename":"references/docs/layout/grid/flex-playground/flex-playground.md","content":"---\ntitle: Flex Grid Playground\ndesc: Interactively play with Quasar Flex Grid\nrelated:\n - /layout/grid/introduction-to-flexbox\n - /layout/grid/row\n - /layout/grid/column\n - /layout/grid/gutter\n---\n\nTo help you understand the Flexbox better, we have written an interactive playground for you. Create your grid and then copy the values to your projects.\n\n::: tip\nThe active child will have a blue index. Being active relates to the **Child Classes** and **Child Styles** listed below the results.\n:::\n\n\n\n\u003cFlexPlaygroundDemo class=\"q-mt-md scroll\" id=\"flex-playground\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":574,"content_sha256":"8f74f4b47fcb60b46ed5c23e414c90f4938e52767f96d8d355ddeaaad0e5a6d0"},{"filename":"references/docs/layout/grid/flexbox-patterns.md","content":"---\ntitle: Flexbox Patterns\ndesc: Common recipes for working with flexbox CSS is and how it can be used in a Quasar App.\nexamples: grid\nrelated:\n - /layout/grid/introduction-to-flexbox\n - /layout/grid/row\n - /layout/grid/column\n - /layout/grid/gutter\n - /layout/grid/flex-playground\n---\n\nHere are some common patterns for using Flexbox. Some more info can be found at Tobias Ahlin Blog.\n\n## Flex row / column break\n\nYou can define a CSS class that would force the element it is applied on to create a row / column break in a flex layout.\n\n```sass\n.flex-break\n flex: 1 0 100% !important\n.row\n .flex-break\n height: 0 !important\n.column\n .flex-break\n width: 0 !important\n```\n\nTake care not to use `no-wrap` when defining the flex container, and insert a `div` with class `flex-break` where you need.\n\n::: tip\nYou can use `q-py-##` on row breaking elements or `q-px-##` on column breaking elements to increase the space.\n:::\n\n```html\n\u003cdiv class=\"row\">\n \u003cdiv>Col 1 / Row 1\u003c/div>\n \u003cdiv>Col 2 / Row 1\u003c/div>\n \u003cdiv class=\"flex-break\">\u003c/div>\n \u003cdiv>Col 1 / Row 2\u003c/div>\n \u003cdiv class=\"flex-break q-py-md\">\u003c/div>\n \u003cdiv>Col 1 / Row 3\u003c/div>\n \u003cdiv>Col 2 / Row 3\u003c/div>\n \u003cdiv>Col 3 / Row 3\u003c/div>\n\u003c/div>\n```\n\n\u003cDocExample title=\"Row break\" file=\"BreakRow\" />\n\n::: warning\nWhen using `column` type flex you must define a height for the container. The height must be large enough to hold the longest column.\n:::\n\n\u003cDocExample title=\"Column break\" file=\"BreakColumn\" />\n\n## Masonry-like layout\n\nWhen using a `column` type flex with multiple columns the visual order of the elements will be in vertical columns. Sometimes you want the order to follow the rows in the layout, and in order to achieve this you can use a combination or custom order CSS styles and column break elements.\n\n::: warning\nYou must know how many columns you want use for the layout. Also for best visual aspect the elements in the layout should be close in height one to the others.\n:::\n\nThe general CSS formula for `$x` number of columns is:\n\n```scss\n$x: 3;\n\n@for $i from 1 through ($x - 1) {\n .item:nth-child(#{$x}n + #{$i}) {\n order: #{$i};\n }\n}\n\n.item:nth-child(#{$x}n) {\n order: #{$x};\n}\n```\n\nExample, supposing you want a 4 column layout:\n\n```sass\n.item:nth-child(4n+1)\n order: 1\n.item:nth-child(4n+2)\n order: 2\n.item:nth-child(4n+3)\n order: 3\n.item:nth-child(4n)\n order: 4\n```\n\nFor the HTML there are some requirements that should be followed:\n\n- the flex column container must have a height defined\n- the column breaking elements must be placed at the start\n- the column breaking elements must be as many as the columns\n- the first column breaking element must be hidden (class `hidden` or style `display: none`)\n\nExample, supposing you want a 4 column layout:\n\n```html\n\u003cdiv class=\"column\">\n \u003cdiv class=\"flex-break hidden\">\u003c/div>\n \u003cdiv class=\"flex-break\">\u003c/div>\n \u003cdiv class=\"flex-break\">\u003c/div>\n \u003cdiv class=\"flex-break\">\u003c/div>\n\n \u003cdiv>Cell 1\u003c/div>\n \u003cdiv>Cell 2\u003c/div>\n ...\n \u003cdiv>Cell last\u003c/div>\n\u003c/div>\n```\n\n\u003cDocExample title=\"Masonry\" file=\"Masonry\" />\n\n## Masonry with pseudo selectors to break rows / columns\n\nWhen it's not easy or not possible to insert the elements for row / column break and you need 2 or 3 rows / column you can use pseudo selectors.\n\n```sass\n.container-class\n &--2-rows\n :before\n flex: 1 0 100% !important\n height: 0 !important\n order: 1\n &--2-columns\n :before\n flex: 1 0 100% !important\n width: 0 !important\n order: 1\n &--3-rows\n :before,\n :after\n flex: 1 0 100% !important\n height: 0 !important\n order: 2\n &--3-columns\n :before,\n :after\n flex: 1 0 100% !important\n width: 0 !important\n order: 2\n```\n\n\u003cDocExample title=\"Masonry like table grid\" file=\"MasonryTableGrid\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3771,"content_sha256":"bbeb3340cbe6fb871541f079ee8368890cd4a787f6316a561e34d8a152cc0a1e"},{"filename":"references/docs/layout/grid/gutter.md","content":"---\ntitle: Grid Gutter\ndesc: How to use the Quasar grid for gutter spaces.\nexamples: grid\nrelated:\n - /layout/grid/introduction-to-flexbox\n - /layout/grid/row\n - /layout/grid/column\n - /layout/grid/flex-playground\n---\n\nIn the hope that you've previously read the [Introduction to Flexbox](/layout/grid/introduction-to-flexbox) theory, let's get deeper into Gutters.\n\nGutter Quasar CSS classes offer an easy way to space out elements (especially in a [Grid Row](/layout/grid/row)) one from each other at equal distance.\n\n## Types\n\nThere are two main types of gutters depending on your use-case: `q-gutter-{size}` and `q-col-gutter-{size}`. The first is to be used when the elements that you want to distance one from each other don't use `col-*` or `offset-*` classes that specify a width, and the latter is to be used when they do have `col-*` or `offset-*` classes specifying a width.\n\n::: tip\nSuffixes (`-none`, `-xs`, `-sm`, `-md`, `-lg`, `-xl`) do not refer to device screen size, but to the size of gutter between elements.\n:::\n\n## Classes \"q-gutter-{size}\"\n\n::: warning\nThe `q-gutter-*` classes apply a **negative top and left margins** to the parent and a **positive top and left margins** to the children. Take this into account when working with the other [Spacing classes](/style/spacing) so as to not to break the gutter's css.\n:::\n\nThese classes are to be used when the direct children don't have `col-*` or `offset-*` classes specifying a width.\n\n\u003cDocExample title=\"Sizes for q-gutter\" file=\"GutterSize\" />\n\nThere's also the `q-gutter-none` class (equivalent to: no gutter applied) which wasn't included in the example above.\n\n\u003cDocExample title=\"Horizontal only q-gutter\" file=\"GutterHorizontal\" />\n\n\u003cDocExample title=\"Vertical only q-gutter\" file=\"GutterVertical\" />\n\n\u003cDocExample title=\"Mixed horizontal and vertical q-gutter\" file=\"GutterMixed\" />\n\n## Classes \"q-col-gutter-{size}\"\n\n::: warning\nThe `q-col-gutter-*` classes apply a **negative top and left margins** to the parent and a **positive top and left paddings** to the children. Take this into account when working with the other [Spacing classes](/style/spacing) so as to not to break the gutter's css.\n:::\n\nThese classes are to be used when the direct children have `col-*` or `offset-*` classes that specify a width.\n\n\u003cDocExample title=\"Sizes for q-col-gutter\" file=\"ColGutterSize\" />\n\n\u003cDocExample title=\"Horizontal only q-col-gutter\" file=\"ColGutterHorizontal\" />\n\n\u003cDocExample title=\"Vertical only q-col-gutter\" file=\"ColGutterVertical\" />\n\n\u003cDocExample title=\"Mixed horizontal and vertical q-col-gutter\" file=\"ColGutterMixed\" />\n\n## Pros, cons and how to workaround problems - \"q-gutter-{size}\" vs. \"q-col-gutter-{size}\"\n\nBoth set of classes have pros and cons.\n\n::: warning\nBecause both `q-gutter-*` and `q-col-gutter-*` classes apply a **negative top and left margins** to the parent you should not apply styling targeting background, margin or border related properties on the parent.\n\nInstead you need to wrap them in a container, apply the styling on the container, and add `overflow-auto` or `row` class **on the container**\n:::\n\n\u003cDocExample title=\"Parent styling\" file=\"ParentStyling\" />\n\n::: tip\nThe `q-gutter-*` classes **do not change** the internal dimensions of the children, so you can use `background` or `border` directly on children.\n:::\n\n::: warning\nThe `q-col-gutter-*` classes **do change** the external dimensions of the children, so you cannot use `col-*` or `offset-*` classes specifying a width on children anymore.\n:::\n\n\u003cDocExample title=\"Children size compare\" file=\"ChildrenSizeCompare\" />\n\n::: warning\nBecause `q-col-gutter-*` classes apply a **negative top and left padding** to the children you should not apply styling targeting background, padding or border related properties on the children. Instead you need to put the styled element inside the child and apply the styling on that element.\n:::\n\n\u003cDocExample title=\"Children styling\" file=\"ChildrenStyling\" />\n\n## Flex Grid Playground\n\nTo see the Flex in action, you can use the Flex Playground to interactively learn more.\n\n\u003cq-btn icon-right=\"launch\" label=\"Flex Playground\" to=\"/layout/grid/flex-playground\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4177,"content_sha256":"25de617947ea0ecb3453452f5c4aceee0da19b27223767e331406a77c78754f9"},{"filename":"references/docs/layout/grid/introduction-to-flexbox.md","content":"---\ntitle: Introduction to Flexbox\ndesc: What the flexbox CSS is and how it can be used in a Quasar App.\nrelated:\n - /style/spacing\n - /style/visibility\n - /layout/grid/column\n - /layout/grid/gutter\n - /layout/grid/flex-playground\n---\n\nQuasar provides lots of CSS classes to help you build your UI easily with the help of Flexbox. Think of it like operating with rows and columns with many options at hand.\n\nFlexbox (upon which Quasar Flex CSS classes are based) module aims to provide a more efficient way to lay out, align and distribute space among items in a container, even when their size is unknown and/or dynamic (thus the word “flex”).\n\n::: tip\nThis page covers the basic theory of Quasar Flex CSS classes and prepares you for the in-depth pages on [Grid Row](/layout/grid/row), [Grid Column](/layout/grid/column) and [Grid Gutter](/layout/grid/gutter).\n:::\n\n## Key concept\n\nQuasar Flex CSS classes apply to either the Container (Parent) or the Container's items (Children).\n\n\n\n\n## Managing Parent\n\n### Setting Direction\n\nOne of the following CSS classes is mandatory for the parent in order for ones on the children (described in next sections) to have any effect.\n\n\n\n| Class Name | Description |\n| ---------------- | --------------------------------------------------------- |\n| `row` | Flex row |\n| `row inline` | Inline Flex row |\n| `column` | Flex column |\n| `column inline` | Inline Flex column |\n| `row reverse` | Flex row with `flex-direction` set to `row-reverse` |\n| `column reverse` | Flex column with `flex-direction` set to `column-reverse` |\n\nExample:\n\n```html\n\u003cdiv class=\"row\">\n \u003cdiv>First column\u003c/div>\n \u003cdiv>Second column\u003c/div>\n \u003cdiv>Third column\u003c/div>\n\u003c/div>\n```\n\n### Wrapping by default\n\nBy default, all rows and columns wrap their content.\n\n\n\nHowever if you explicitly do not want to wrap and by so doing you want to fit all content into one line, then add `no-wrap` CSS helper class.\n\nAlso, if you want to wrap in reverse order, then `reverse-wrap` is available.\n\n| Class Name | Description |\n| -------------- | ---------------------------------------------------------- |\n| `wrap` | Wrap if necessary (\"on\" by default, no need to specify it) |\n| `no-wrap` | Do NOT wrap even if necessary |\n| `reverse-wrap` | Wrap backwards if necessary |\n\n### Alignment\n\n**For alignment along the main axis**, use classes below. It helps distribute left over free space when either all the flex items on a line are inflexible, or are flexible but have reached their maximum size. It also exerts some control over the alignment of items when they overflow the line.\n\n\n\n**For alignment perpendicular to the main axis**, use classes below. This defines the default behavior for how flex items are laid out along the cross axis on the current line. Think of it as the horizontal-\\* version for the cross-axis (perpendicular to the main-axis).\n\n\n\n::: tip\nThere is also the convenience `flex-center` CSS class which is equivalent to `items-center` + `justify-center`. Use it along with `flex`, `row` or `column`.\n:::\n\nThe next classes **align a flex container's lines** within when there is extra space in the cross-axis, similar to how horizontal-\\* aligns individual items within the main-axis.\n\n\n\n## Managing Children\n\n### Distribution of Size\n\nQuasar uses a 12 point column system for distributing the size of row children. Here are some examples of the available CSS helper classes:\n\n```html\n\u003cdiv class=\"row\">\n \u003cdiv class=\"col-8\">two thirds\u003c/div>\n \u003cdiv class=\"col-2\">one sixth\u003c/div>\n \u003cdiv class=\"col-auto\">auto size based on content and available space\u003c/div>\n \u003cdiv class=\"col\">fills remaining available space\u003c/div>\n\u003c/div>\n```\n\nIn the example above, `col-8` fills two thirds (2/3) of the row width, because 8/12 = 2/3 = 66%, while `col-2` occupies one sixth (2/12 = 1/6 ~ 16.67%).\n\nCSS helper class `col-auto` makes the cell fill only the space it needs to be rendered. `col`, on the other hand, tries to fill all space available while also shrinking if needed.\n\nCSS helper class `col-grow` makes the cell fill at least the space it needs to be rendered, with the possibility to grow when more space is available.\n\nCSS helper class `col-shrink` makes the cell fill at most the space it needs to be rendered, with the possibility to shrink when not enough space is available.\n\nAnother example with a visual representation below it:\n\n```html\n\u003cdiv class=\"row\">\n \u003cdiv class=\"col\">1\u003c/div>\n \u003cdiv class=\"col\">1\u003c/div>\n \u003cdiv class=\"col\">1\u003c/div>\n \u003c!--\n we have 3 children, so equivalent\n to above would be to use `col-4`\n on each of the children\n -->\n\u003c/div>\n\n\u003cdiv class=\"row\">\n \u003cdiv class=\"col-3\">1\u003c/div>\n \u003cdiv class=\"col-6\">2\u003c/div>\n \u003cdiv class=\"col-3\">1\u003c/div>\n\u003c/div>\n```\n\n\n\nIt is also possible to offset a cell. For example: `offset-4` offsets a third of space (4/12 = 1/3 = 33%).\n\n### Wrapping\n\nWrapping is a key feature in understanding Flex CSS classes. You are not bound to use exactly 12 points per row. You can use less or even more.\n\nThis allows you, among other things, to dynamically stack rows vertically on smaller screens while displaying them on a single line on bigger screens. Read the \"Responsive Design\" section.\n\n```html\n\u003cdiv class=\"row\">\n \u003cdiv class=\"col-2\">...\u003c/div>\n\n \u003c!-- 2 + 6 \u003c 12, so next element is placed on same line -->\n \u003cdiv class=\"col-6\">...\u003c/div>\n\n \u003c!-- 2 + 6 + 10 > 12, so next element wraps to next line -->\n \u003cdiv class=\"col-10\">...\u003c/div>\n\n \u003c!--\n 10 + 3 > 12, so next element wraps to next line.\n Note that we take into consideration the current line only\n (with col-10 only, since it was wrapped to its own line).\n -->\n \u003cdiv class=\"col-3\">...\u003c/div>\n\u003c/div>\n```\n\n> Note that rows are wrappable by default. Should you wish to disable this, use the `no-wrap` CSS helper class.\n\n### Self Alignment\n\n**An item can override the aligned specified on parent**. This allows alignment to be overridden for individual flex items. Please see the \"Alignment\" explanation from \"Managing Parent\" to understand the available values (`self-start`, `self-center`, `self-baseline`, `self-end`, `self-stretch`).\n\n\n\n### Order\n\n**You can set the order** of child elements by using `order-first` and `order-last` CSS helper classes.\n\nBy default, flex items are laid out in source order. However, the order property controls the order in which they appear in the flex container. If you need more granularity, use `order` CSS property and assign the desired value.\n\nExample:\n\n```html\n\u003cdiv class=\"row\">\n \u003cdiv style=\"order: 2\">Second column\u003c/div>\n \u003cdiv class=\"order-last\">Third column\u003c/div>\n \u003cdiv class=\"order-first\">First column\u003c/div>\n\u003c/div>\n```\n\nHere is how the CSS `order` property works:\n\n\n\n## Responsive Design\n\nQuasar Flex CSS classes can be applied based on the width of the screen, to help you in making a responsive UI. The 12 points grid is inspired by Bootstrap's, so there are a lot of similarities.\n\nBreakpoint specifiers use a mobile-first approach, where the larger breakpoint definitions will override the smaller ones.\n\nWhat we've learned so far is that, for example, we can size the columns regardless of window width. If we are to create a responsive UI, we need to dynamically change the sizing while taking window width into account. First, let's learn about some tokens that you can inject in middle of `col-*`, `offset-*` and `col-auto` helper classes (look at table below for tokens).\n\n| Token | Min window width | Description / When it applies if not overridden by another larger breakpoint |\n| ----- | ---------------- | ---------------------------------------------------------------------------- |\n| `xs` | 0px | All window sizes (same as no breakpoint specifier) |\n| `sm` | 600px | Larger than extra small sized window |\n| `md` | 1024px | Larger than small window |\n| `lg` | 1440px | Larger than medium-sized sized window |\n| `xl` | 1920px | Larger than large sized window |\n\nExample: `col-md-7`, `offset-lg-3`, `col-xs-auto`.\n\nA full example: let's say we have a row with three children. In extra small windows, we need to stack the children vertically, In small windows we need to display them side by side (each having equal width), and starting with medium windows we should display them all on same line:\n\n```html\n\u003cdiv class=\"row\">\n \u003cdiv class=\"col-xs-12 col-sm-6 col-md-4\"> col \u003c/div>\n \u003cdiv class=\"col-xs-12 col-sm-6 col-md-4\"> col \u003c/div>\n \u003cdiv class=\"col-xs-12 col-sm-6 col-md-4\"> col \u003c/div>\n\u003c/div>\n```\n\nNotice in the above example that we used `col-xs-12` (12/12 = 100% of row, so each child will take full width of the container making all children stack vertically, since rows wrap content by default), `col-sm-6` (6/12 = 50% of row) and `col-md-4` (4/12 = 33% of row).\n\nLike previously mentioned, rows wrap content by default, so when 12 (or more) grid points are used for a row, content is wrapped to the next line. If we have two `\u003cdiv>`s and we use `col-8` on both, they will also stack, since 8 + 8 = 16 and we can only display 12 points on a single line.\n\n```html\n\u003cdiv class=\"row\">\n \u003c!--\n more than 12 grid points together,\n so second \u003cdiv> will wrap on next line\n -->\n \u003cdiv class=\"col-8\">col\u003c/div>\n \u003cdiv class=\"col-8\">col\u003c/div>\n\u003c/div>\n```\n\nAlso check [Visibility](/style/visibility#window-width-related) Style page to see thresholds on window width and these tokens (xs, sm, md, lg, xl) used on their own to hide or show DOM elements.\n\n## Flex Addons\n\nWhen enabled (through `quasar.config file > framework > cssAddon: true`) it provides breakpoint aware versions for all flex (and display) related CSS classes.\n\n::: warning\nNote that there will be a noticeable bump in CSS footprint when enabling it. So only do it if you really need it.\n:::\n\n```\n.flex-\u003cbp>-(block|inline)\n.(row|column|flex)-\u003cbp>(|-inline-\u003cbp>)\n.reverse-\u003cbp>\n.(wrap|no-wrap|reverse-wrap)-\u003cbp>\n.order-\u003cbp>-(first|last|none)\n.justify-\u003cbp>-(start|end|center|between|around|evenly)\n.items-\u003cbp>-(start|end|center|baseline|stretch)\n.content-\u003cbp>-(start|end|center|between|around)\n.self-\u003cbp>-(start|end|center|baseline|stretch)\n.flex-\u003cbp>-center\n.q-gutter-\u003cbp>(|-x|-y)-(xs|sm|md|lg|xl)\n.(col|offset)-\u003cbp>-(|0..12)\n```\n\nThere are also responsive classes for spacing, both for padding and for margin:\n\n```\n.q-(p|m)(t|r|b|l|a|x|y)-\u003cbp>-(none|auto|xs|sm|md|lg|xl)\n```\n\nExamples: `row-md`, `items-lg-end`, `q-pa-xs q-pa-sm-sm q-px-md-lg q-py-md-md`\n\n## Flex Playground\n\nTo see the Flex in action, you can use the Flex Playground to interactively learn more.\n\n\u003cq-btn icon-right=\"launch\" label=\"Flex Playground\" to=\"/layout/grid/flex-playground\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":11174,"content_sha256":"3d2dfd490d5a3f9728db0593773a7daa6cae29d051739cd9e716a766fba7e1d6"},{"filename":"references/docs/layout/grid/row.md","content":"---\ntitle: Grid Row\ndesc: How to use the Quasar grid for rows.\nexamples: grid\nrelated:\n - /layout/grid/introduction-to-flexbox\n - /layout/grid/column\n - /layout/grid/gutter\n - /layout/grid/flex-playground\n---\n\nIn the hope that you've previously read the [Introduction to Flexbox](/layout/grid/introduction-to-flexbox) theory, let's get deeper into Rows.\n\nUtilize breakpoint-specific column classes for equal-width columns. Add any number of unit-less classes for each breakpoint you need and every column will be the same width.\n\n## Equal-width\n\nFor example, here are two grid layouts that apply to every device and viewport, from xs to xl.\n\n\u003cDocExample title=\"Equal Width Example\" file=\"RowEqualWidth\" />\n\n## Setting one column width\n\nAuto-layout for flexbox grid columns also means you can set the width of one column and the others will automatically resize around it. You may use predefined grid classes (as shown below) or inline widths. Note that the other columns will resize no matter the width of the center column.\n\n\u003cDocExample title=\"Setting one column width\" file=\"RowColumnWidth\" />\n\n## Variable width content\n\nUsing the `col-{breakpoint}-auto` classes, columns can size itself based on the natural width of its content. This is super handy with single line content like inputs, numbers, etc (see last example on this page). This, in conjunction with horizontal alignment classes, is very useful for centering layouts with uneven column sizes as viewport width changes.\n\n\u003cDocExample title=\"Variable width content\" file=\"RowVariableWidth\" />\n\n## Responsive classes\n\nThe grid includes five tiers of predefined classes for building complex responsive layouts. Customize the size of your columns on extra small, small, medium, large, or extra large devices however you see fit.\n\n### All breakpoints\n\nFor grids that are the same from the smallest of devices to the largest, use the `.col` and `.col-*` classes. Specify a numbered class when you need a particularly sized column; otherwise, feel free to stick to .col.\n\n\u003cDocExample title=\"All breakpoints\" file=\"RowAllBreakpoints\" />\n\n### Stacked to horizontal\n\nUsing a combination of `.col-12` and `.col-md-*` classes, you can create a basic grid system that starts out stacked on small devices before becoming horizontal on desktop (medium) devices.\n\n\u003cDocExample title=\"Stacked to horizontal\" file=\"RowStackedToHorizontal\" />\n\n### Mix and match\n\nDon’t want your columns to simply stack in some grid tiers? Use a combination of different classes for each tier as needed. See the example below for a better idea of how it all works.\n\n\u003cDocExample title=\"Mix and match\" file=\"RowMixAndMatch\" />\n\n### Alignment\n\nUse flexbox alignment utilities to vertically and horizontally align columns.\n\n\u003cDocExample title=\"Vertical alignment\" file=\"RowVerticalAlignment\" />\n\n\u003cDocExample title=\"Horizontal alignment\" file=\"RowHorizontalAlignment\" />\n\n::: tip\nThere is also the convenience `flex-center` CSS class which is equivalent to `items-center` + `justify-center`. Use it along with `flex`, `row` or `column`.\n:::\n\n### Column wrapping\n\nIf more than 12 columns are placed within a single row, each group of extra columns will, as one unit, wrap onto a new line.\n\n\u003cDocExample title=\"Column wrapping\" file=\"RowColumnWrapping\" />\n\n### Reordering\n\n\u003cDocExample title=\"Reverse\" file=\"RowReverse\" />\n\n\u003cDocExample title=\"Flex order\" file=\"RowFlexOrder\" />\n\n### Offsetting columns\n\nMove columns to the right using `.offset-md-*` classes. These classes increase the left margin of a column by \\* columns. For example, `.offset-md-4` moves `.col-md-4` over four columns.\n\n\u003cDocExample title=\"Offsetting columns\" file=\"RowOffsettingColumns\" />\n\n### Nesting\n\nTo nest your content with the default grid, add a new .row and set of `.col-sm-*` columns within an existing `.col-sm-*` column. Nested rows should include a set of columns that add up to 12 or fewer (it is not required that you use all 12 available columns).\n\n\u003cDocExample title=\"Nesting\" file=\"RowNesting\" />\n\n## Flex Playground\n\nTo see the Flex in action, you can use the Flex Playground to interactively learn more.\n\n\u003cq-btn icon-right=\"launch\" label=\"Flex Playground\" to=\"/layout/grid/flex-playground\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4204,"content_sha256":"498a44c68210d42cc42fadb4d1caf06c381804a527443b8bedb1e5c7b611e331"},{"filename":"references/docs/layout/header-and-footer.md","content":"---\ntitle: Layout Header and Footer\ndesc: How to use the QHeader and QFooter components. The top and bottom bars of your Quasar app.\nkeys: QHeader,QFooter\nexamples: QHeader\nrelated:\n - /layout/layout\n - /layout/page\n - /vue-components/toolbar\n - /vue-components/breadcrumbs\n - /vue-components/tabs\n - /vue-components/bar\n---\n\nQLayout allows you to configure your views as a 3x3 matrix, containing an optional Header and/or Footer (mostly used for navbar, but can be anything). If you haven’t already, please read [QLayout](/layout/layout) documentation page first.\n\n\u003cDocApi file=\"QHeader\" />\n\n\u003cDocApi file=\"QFooter\" />\n\n## Layout Builder\n\nScaffold your layout(s) by clicking on the button below.\n\n\u003cq-btn icon-right=\"launch\" label=\"Layout Builder\" href=\"/layout-builder\" target=\"_blank\" />\n\n## Usage\n\n::: tip\nSince the header and footer needs a layout and QLayout by default manages the entire window, then for demoing purposes we are going to use containerized QLayouts. But remember that by no means you are required to use containerized QLayouts for QHeader or QFooter.\n:::\n\n\u003cDocExample title=\"Basic\" file=\"Basic\" />\n\nYou can use `glossy` class on toolbars in header and footer.\n\n\u003cDocExample title=\"Glossy\" file=\"Glossy\" />\n\n### Various content\n\n\u003cDocExample title=\"Playing with QToolbar\" file=\"Extended\" />\n\n\u003cDocExample title=\"Playing with QBreadcrumb\" file=\"Breadcrumbs\" />\n\n\u003cDocExample title=\"Playing with QTabs\" file=\"Tabs\" />\n\n### Reveal property\n\nIn the example below, scroll the page to see the QHeader and QFooter behavior.\n\n\u003cDocExample title=\"Reveal\" file=\"Reveal\" />\n\n### iOS look and feel\n\nIn the example below, you could use Ionicons icons (v4) with `ion-ios-` prefix for QTabs, which would perfectly match the iOS look and feel.\n\n\u003cDocExample title=\"iOS-like\" file=\"LookingIOS\" />\n\n### Desktop app look and feel\n\nThe example below is especially useful if you build an Electron app and you hide the default app frame.\n\n\u003cDocExample title=\"Desktop app-like\" file=\"AppLike\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1994,"content_sha256":"a7d92f08275b260a16f2f66bea0baef4fe9b9df52d914b71386bbf95fe9865a2"},{"filename":"references/docs/layout/layout/layout.md","content":"---\ntitle: Layout\ndesc: How to use the QLayout component. Manages the whole window of your Quasar app.\nkeys: QLayout\nexamples: QLayout\nrelated:\n - /layout/header-and-footer\n - /layout/drawer\n - /layout/page\n - /layout/page-sticky\n - /layout/page-scroller\n - /vue-components/floating-action-button\n---\n\nThe QLayout is a component designed to manage the entire window and wrap page content with elements such as a navigational bar or a drawer. Multiple pages can share the same QLayout, so the code is reusable, which is one of their key points.\n\n**QLayout is NOT mandatory**, but it does help you to better structure your website/app. It has a number of features which offer you major benefits in simplifying your website/app's layout design, right out of the box.\n\n\u003cDocApi file=\"QLayout\" />\n\n## Layout Builder\n\nScaffold your layout(s) by clicking on the button below.\n\n::: tip\nKeep an eye on your developer console for handy helpers on which components are being used but not declared in your quasar.config file.\n:::\n\n\u003cq-btn icon-right=\"launch\" label=\"Layout Builder\" href=\"/layout-builder\" target=\"_blank\" />\n\n## Usage\n\n::: warning Using margin CSS will break the layout\nQLayout depends on taking up the whole screen and so QPageContainer, QHeader, QFooter and QLayoutDrawer positions are managed by it (through the `view` prop). You **cannot** use _CSS margins_ as a style neither on QLayout itself nor on any of the QLayout components mentioned above. However you can safely use _CSS padding_.\n:::\n\n::: tip\nIf your layout uses Vue Router sub-routes (recommended), then it makes sense to use Vue's `\u003crouter-view />` component, which is just a placeholder where sub-routes are injected. For more information, please read [Routing with Layouts and Pages](/layout/routing-with-layouts-and-pages).\n:::\n\n### Understanding the \"view\" prop\n\nQuasar introduces a unique and excellent layout concept, which allows you to easily structure layouts to work in certain ways, by simply changing a short string notation.\n\nTo explain how this works, imagine your Layout is a 3x3 matrix of containers (depicted in blue below). The first row of containers would be the header and the last row would be the footer. The first column of containers would be the \"left\" and last column would be the \"right\". The center of the matrix, below the header and above the footer, would be the page or main content container.\n\nThis matrix of containers or \"QLayout View\" can be represented by a string that you should supply to the `view` property of QLayout. This string must contain exactly 11 characters:\n\n- 3 defining the header row\n- then a space\n- 3 defining the middle row\n- a space\n- then 3 defining the footer row\n\n\n\n\u003cViewProp />\n\nThe letters shown above are also case sensitive. For example, using at least one \"L\" (uppercase character instead of lowercase) will make your layout left side (drawer) be in a fixed position. Same applies for \"H\" (header), \"F\" (footer) and finally \"R\" (right side / drawer).\n\n\n\n\u003cViewPlay />\n\nFor example, if you want your layout's right side / drawer to be placed on the right of the header, page and footer, you'd use `hhr lpr ffr`. If you'd like to also make it fixed, just transform one `r` character to uppercase, like this: `hhr lpR ffr`, or `hhR lpr ffr` or `hhr lpr ffR`.\n\nThese settings are completely up to you to use as you'd like. You could even go wild with a setup like this: `lhh LpR ffr`. Try it out!\n\n\u003cq-btn icon-right=\"launch\" label=\"Layout Builder\" href=\"/layout-builder\" target=\"_blank\" />\n\n::: warning\n\n- It is important that you specify all sections of a QLayout, even if you don't use them. For example, even if you don't use footer or right side drawer, still specify them within your QLayout's `view` prop.\n- When QDrawer is set into overlay mode, **it will force it to go into fixed position**, regardless if QLayout's \"view\" prop is configured with \"l/r\" or \"L/R\". Also, **if on iOS platform and QLayout is containerized**, the fixed position will also be forced upon QDrawer due to platform limitations that cannot be overcome.\n :::\n\n### Containerized QLayout\n\nBy default, QLayout is managing the entire window. However, you can also use QLayout as a container (with specific height and width) to isolate it somewhere in your pages.\n\n::: warning\nPlease note that it **requires a CSS height (or min-height) being set explicitly**, otherwise it can't and it won't work.\n:::\n\nIn the example below, there is a containerized QLayout with drawers on each side (breakpoint of 700px on the left-side drawer and 500px on the right-side drawer). The breakpoint does not refer to the window width, but to the actual width of the QLayout container.\n\n\u003cDocExample title=\"Containerized QLayout\" file=\"Container\" />\n\n\u003cDocExample title=\"In a QDialog\" file=\"ContainerDialog\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4805,"content_sha256":"6485d2ae7d2ab4eb817f2930c300ea47d1c903dfedec15ecd656d5e9ca080046"},{"filename":"references/docs/layout/page-scroller.md","content":"---\ntitle: Layout QPageScroller\ndesc: How to use the QPageScroller component. Places components that will appear on screen after user scrolls the page.\nkeys: QPageScroller\nexamples: QPageScroller\nrelated:\n - /layout/layout\n - /layout/page\n---\n\nThe QPageScroller component helps in placing DOM elements / components wrapped by it into a static position within the content area of your QPage, no matter where the user scrolls.\n\nThe great advantage of this is that the elements wrapped by this component will never overlap the layout header, footer or drawer(s), even if those are not configured to be fixed. In the latter case, the position will be offset so that the overlap won't occur.\nTry it out with a non-fixed footer for example. When user reaches bottom of screen and footer comes into view, the component will shift up so it won't overlap with the footer.\n\nEssentially QPageScroller is very similar to QPageSticky. Whereas a QPageSticky component is always visible, a QPageScroller component only appears after a `scroll-offset` (property) is reached. Once visible, the user can click on it to quickly get back to the top of the page via `duration` property.\n\n\u003cDocApi file=\"QPageScroller\" />\n\n## Usage\n\n::: tip\nSince QPageScroller needs a layout and QLayout by default manages the entire window, then for demoing purposes we are going to use containerized QLayouts. But remember that by no means you are required to use containerized QLayouts for QPageScroller.\n:::\n\n::: warning\n\n- In order for QPageScroller to work, it must be placed within a QLayout component.\n- QPageScroller must be the last child element within its parent, so it can display on top of other content\n :::\n\n### Basic\n\n\u003cDocExample title=\"Basic\" file=\"Basic\" />\n\n### Expanded\n\n\u003cDocExample title=\"Expanded\" file=\"Expanded\" />\n\n### Reverse\n\n\u003cDocExample title=\"Reverse\" file=\"Reverse\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1864,"content_sha256":"2555ce4903f97ba83f7dc2c53b316d0847a177f40a4b18d91e62a834967da506"},{"filename":"references/docs/layout/page-sticky.md","content":"---\ntitle: Layout QPageSticky\ndesc: How to use the QPageSticky component. Statically place components on the layout without overlapping with header/footer/sidebars.\nkeys: QPageSticky\nexamples: QPageSticky\nrelated:\n - /layout/layout\n - /layout/page\n---\n\nThe QPageSticky component helps in placing DOM elements / components wrapped by it into a static position within the content area of your QPage, no matter where the user scrolls.\n\nThe great advantage of this is that the elements wrapped by this component will never overlap the layout header, footer or drawer(s), even if those are not configured to be fixed. In the latter case, the position will be offset so that the overlap won't occur.\nTry it out with a non-fixed footer for example. When user reaches bottom of screen and footer comes into view, the component will shift up so it won't overlap with the footer.\n\n\u003cDocApi file=\"QPageSticky\" />\n\n## Usage\n\n::: tip\nSince QPageSticky needs a layout and QLayout by default manages the entire window, then for demoing purposes we are going to use containerized QLayouts. But remember that by no means you are required to use containerized QLayouts for QPageSticky.\n:::\n\n::: warning\n\n- In order for QPageSticky to work, it must be placed within a QLayout component.\n- QPageSticky must be the last child element within its parent, so it can display on top of other content\n :::\n\n### Basic\n\nIn the example below, click on the menu buttons to show/hide Drawers, scroll the inner page, and resize the browser window so that the enclosing QLayout hits the Drawer's 700px and 500px breakpoints.\n\n\u003cDocExample title=\"Basic\" file=\"Basic\" />\n\n### Expanded\n\nIn the example below, click on the menu buttons to show/hide Drawers, scroll the inner page, and resize the browser window so that the enclosing QLayout hits the Drawer's 700px and 500px breakpoints.\n\nBy using expanded QPageSticky you can, for example, have a page-specific QToolbar as below.\n\n\u003cDocExample title=\"Expanded\" file=\"Expanded\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1993,"content_sha256":"90a10193643d7ff713e0306a7cb8584dbe08cf0e2c96883fd2753ab627c7522e"},{"filename":"references/docs/layout/page.md","content":"---\ntitle: Layout Page\ndesc: How to use QPageContainer and QPage components. They define the contents of your Quasar app pages.\nkeys: QPage\nexamples: QPage\nrelated:\n - /layout/layout\n---\n\nWe will be talking about encapsulating pages within a QLayout. If you haven’t already, please read [QLayout](/layout/layout) documentation page first.\n\n\u003cDocApi file=\"QPageContainer\" />\n\n\u003cDocApi file=\"QPage\" />\n\n## Layout Builder\n\nScaffold your layout(s) by clicking on the button below.\n\n\u003cq-btn icon-right=\"launch\" label=\"Layout Builder\" href=\"/layout-builder\" target=\"_blank\" />\n\n## Usage\n\nA QPage must be encapsulated by QPageContainer, which in turn must be a child of QLayout.\n\n```html\n\u003cq-layout>\n ...\n \u003cq-page-container>\n \u003cq-page>\n \u003c!-- page content -->\n \u003c/q-page>\n \u003c/q-page-container>\n ...\n\u003c/q-layout>\n```\n\nUsually, the QPageContainer is part of the Layout template (where it contains a `\u003crouter-view />` child only), and its content goes into separate vue files under `/src/pages`. If you haven't already, please read [Routing with Layouts and Pages](/layout/routing-with-layouts-and-pages).\n\n```html\n\u003c!-- vue file for Layout: -->\n\u003cq-layout>\n ...\n \u003cq-page-container>\n \u003crouter-view />\n \u003c/q-page-container>\n ...\n\u003c/q-layout>\n\n\u003c!-- vue file for a Page: -->\n\u003cq-page padding>\n \u003c!-- page content -->\n\u003c/q-page>\n```\n\n### Example\n\n::: tip\nSince QPageContainer and QPage need a layout and QLayout by default manages the entire window, then for demoing purposes we are going to use containerized QLayouts. But remember that by no means you are required to use containerized QLayouts for QPageContainer and QPage.\n:::\n\n\u003cDocExample title=\"Basic\" file=\"Basic\" />\n\n### Style-fn\n\nA QPage needs a QLayout because QLayout controls all the offsets of a page, keeping account of the space that header/footer/drawer use, according to its `view` property configuration. By default, your QPage component will have a `min-height` CSS property set on it to ensure that the content fills the screen at all times, even when the content is just a few lines.\n\nIf you wish to tweak, or even remove this property, you can do so by using the `style-fn` property:\n\n```html\n\u003ctemplate>\n \u003cq-page :style-fn=\"myTweak\">...\u003c/q-page>\n\u003c/template>\n\n\u003cscript>\n export default {\n // ...\n methods: {\n myTweak(offset) {\n // \"offset\" is a Number (pixels) that refers to the total\n // height of header + footer that occupies on screen,\n // based on the QLayout \"view\" prop configuration\n\n // this is actually what the default style-fn does in Quasar\n return { minHeight: offset ? `calc(100vh - ${offset}px)` : '100vh' }\n }\n }\n }\n\u003c/script>\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2670,"content_sha256":"21404171f1974378edff1969558a305ff4d0d1b2946e44bdbe83de040b39400c"},{"filename":"references/docs/layout/routing-with-layouts-and-pages.md","content":"---\ntitle: Routing with Layouts and Pages\ndesc: How to connect the Vue Router with your Quasar layouts and pages.\nscope:\n tree:\n l: src\n c:\n - l: layouts\n c:\n - l: User.vue\n e: our QLayout definition\n - l: pages\n c:\n - l: Posts.vue\n e: page for /user/feed route\n - l: Profile.vue\n e: page for /user/profile route\n---\n\nYou can benefit from Vue Router's capabilities while structuring your routes with a Quasar Layout. The information below is just a recommendation and not mandatory to follow. Quasar allows you full freedom. Take the lines below only as an example.\n\n[QLayout](/layout/layout) is the component used to encapsulate pages, so that multiple pages will share the same header, drawers and so on. However, you can also configure per page header/footer/drawers, but they all must be children of the QLayout component. In order to understand how this works, you need a little bit of reading on Vue Router nested routes.\n\nTo make it more clear, let's take an example. We have one layout ('user') and two pages ('user-feed' and 'user-profile'). We want to configure the website/app routes like this: `/user/feed` and `/user/profile`.\n\n## Creating Files\n\n**Quasar does not enforce a specific folder structure**. The following is just an example. You can put layouts and pages together in a folder, or put pages in your specific folder structure of choice, or create your own layout and page folders. It doesn't matter for Quasar. All that matters is that you reference them correctly in `/src/router/routes.js`.\n\nLet's create the layout and page files. You can use a helper command of Quasar CLI or simply create them yourself.\n\n```bash\n$ quasar new layout User\n app:new Generated layout: src/layouts/User.vue +0ms\n app:new Make sure to reference it in src/router/routes.js +2ms\n\n$ quasar new page Profile Posts\n app:new Generated page: src/pages/Profile.vue +0ms\n app:new Make sure to reference it in src/router/routes.js +2ms\n\n app:new Generated page: src/pages/Posts.vue +1ms\n app:new Make sure to reference it in src/router/routes.js +0ms\n```\n\nThe commands above create the following folder structure:\n\n\u003cDocTree :def=\"scope.tree\" />\n\n## Defining Routes\n\nYour Pages (`/src/pages`) and Layouts (`/src/layouts`) are injected into your website/app (and also managed) through Vue Router in `/src/router/routes.js`. Each Page and Layout needs to be referenced there.\n\nExample of `routes.js` using lazy-loading:\n\n```js\n// we define our routes in this file\n\nconst routes = [\n {\n path: '/',\n component: () => import('pages/Landing')\n }\n]\n\nexport default routes\n```\n\nExample of `routes.js` using eager loading:\n\n```js\n// we define our routes in this file\n\nimport LandingPage from 'pages/Landing'\n\nconst routes = [\n {\n path: '/',\n component: LandingPage\n }\n]\n\nexport default routes\n```\n\n::: tip\nMore in-depth analysis of Lazy loading / code-splitting with [@quasar/app-vite](/quasar-cli-vite/lazy-loading) or [@quasar/app-webpack](/quasar-cli-webpack/lazy-loading).\n:::\n\n::: tip\nConfiguring routes to use Layouts and Pages basically consists of correctly nesting routes, as we'll see in the next section.\n:::\n\n## Nested Routes\n\nReal app UIs are usually composed of components that are nested multiple levels deep. It is also very common that the segments of a URL corresponds to a certain structure of nested components, for example:\n\n```\n/user/profile /user/posts\n+------------------+ +-----------------+\n| User | | User |\n| +--------------+ | | +-------------+ |\n| | Profile | | +------> | | Posts | |\n| | | | | | | |\n| +--------------+ | | +-------------+ |\n+------------------+ +-----------------+\n```\n\nWith Vue Router, it is very simple to express this relationship using nested route configurations. We notice some things: both pages need to be wrapped by a User component. Hey, User component is then a Layout!\n\nSince User layout wraps inner pages, they need an injection point. This is supplied by the `\u003crouter-view>` component:\n\n```html /src/layouts/User.vue\n\u003ctemplate>\n \u003cq-layout>\n ...\n\n \u003c!-- this is where the Pages are injected -->\n \u003cq-page-container>\n \u003crouter-view>\u003c/router-view>\n \u003c/q-page-container>\n\n ...\n \u003c/q-layout>\n\u003c/template>\n```\n\n```html /src/pages/Profile.vue or Posts.vue\n\u003ctemplate>\n \u003cq-page> ...page content... \u003c/q-page>\n\u003c/template>\n```\n\nOur example has some routes specified (/user/profile and /user/posts). **So how can we put everything together now?** We edit the routes file. That's where we will configure routes, tell which components are Layouts and which are Pages and also reference/import them into our app:\n\n```js src/router/routes.js\nimport User from 'layouts/User'\nimport Profile from 'pages/Profile'\nimport Posts from 'pages/Posts'\n\nconst routes = [\n {\n path: '/user',\n\n // we use /src/layouts/User component which is imported above\n component: User,\n\n // hey, it has children routes and User has \u003crouter-view> in it;\n // It is really a Layout then!\n children: [\n // Profile page\n {\n path: 'profile', // here it is, route /user/profile\n component: Profile // we reference /src/pages/Profile.vue imported above\n },\n\n // Posts page\n {\n path: 'posts', // here it is, route /user/posts\n component: Posts // we reference /src/pages/Posts.vue imported above\n }\n ]\n }\n]\n\nexport default routes\n```\n\n::: warning\nNote that nested paths that start with `/` will be treated as a root path. This allows you to leverage component nesting without having to use a nested URL.\n:::\n\nOur routes configuration (`/src/router/routes.js`) should look like this:\n\n```js\nexport default [\n {\n path: '/user',\n\n // We point it to our component\n // where we defined our QLayout\n component: () => import('layouts/user'),\n\n // Now we define the sub-routes.\n // These are getting injected into\n // layout (from above) automatically\n // by using \u003crouter-view> placeholder\n // (need to specify it in layout)\n children: [\n {\n path: 'feed',\n component: () => import('pages/user-feed')\n },\n {\n path: 'profile',\n component: () => import('pages/user-profile')\n }\n ]\n }\n]\n```\n\nPlease notice a few things:\n\n- We are using lazy loading of layouts and pages (`() => import(\u003cpath>)`). If your website/app is small, then you can skip the lazy loading benefits as they could add more overhead than what it's worth:\n\n ```js\n import UserLayout from 'layouts/user'\n import UserFeed from 'pages/user-feed'\n import UserProfile from 'pages/user-profile'\n\n export default [\n path: '/user',\n component: UserLayout,\n children: [\n { path: 'feed', component: UserFeed },\n { path: 'profile', component: UserProfile }\n ]\n ]\n ```\n\n- Quasar provides some out of the box Webpack aliases ('layouts' which points to '/src/layouts' and 'pages' which points to '/src/pages'), which are used in the above examples.\n- Pages of a Layout are declared as children of it in the Vue Router configuration so that `\u003crouter-view/>` will know what page component to inject. Remember to always use this Vue component whenever your Layout has pages attached to it.\n\n ```html\n \u003cq-layout>\n ...\n \u003cq-page-container>\n \u003c!--\n This is where your pages will get\n injected into your Layout\n -->\n \u003crouter-view />\n \u003c/q-page-container>\n ...\n \u003c/q-layout>\n ```\n\n\u003cq-separator class=\"q-mt-xl\" />\n\n::: tip\nPlease check Vue Router documentation to fully understand the examples above and how to configure the router and its routes for your app.\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":7800,"content_sha256":"eba0f41327acf9b8322028c7db027855bdfcca6d15389572d1f92f9c8860dcc6"},{"filename":"references/docs/meet-the-team/meet-the-team.md","content":"---\ntitle: Meet the Team\ndesc: The list of people behind Quasar Framework.\nkeys: Team\nscope:\n core:\n - name: Razvan Stoenescu\n role: Creator, Lead Dev & Architect\n avatar: razvan_stoenescu.jpeg\n email: [email protected]\n twitter: rstoenescu1\n github: rstoenescu\n desc: Architecture and development of Quasar on all fronts\n - name: Dan Popescu\n role: Senior Core Developer\n avatar: dan_popescu.jpg\n email: [email protected]\n github: pdanpdan\n desc: Focuses on Quasar UI components, directives and plugins\n - name: Jeff Galbraith\n role: Senior Developer\n avatar: jeff_galbraith.jpg\n email: [email protected]\n twitter: jgalbraith64\n github: hawkeye64\n desc: UI components, App Extensions and community outreach\n - name: Scott Molinari\n role: Media Manager\n avatar: scott_molinari.jpg\n github: smolinari\n desc:\n Manages our Facebook page, blog and forum. Helps with docs, bug reports,\n external systems, writes and manages articles and offers community support.\n - name: Paolo Caleffi\n role: Senior Developer\n avatar: paolo_caleffi.jpg\n github: IlCallo\n desc: Typescript support\n - name: Yusuf Kandemir\n role: Senior Developer\n avatar: yusuf_kandemir.jpg\n github: yusufkandemir\n desc: Wizard developer on multiple areas of Quasar\n - name: Aldrin Marquez\n role: Community Staff\n avatar: aldrin_marquez.jpg\n github: metalsadman\n desc: Help desk\n - name: Luke Diebold\n role: Senior developer\n avatar: luke_diebold.png\n github: ldiebold\n desc: Creates video tutorials, podcasts and shows for Quasar Framework.\n others:\n - name: Allan Gaunt\n role: Senior Developer\n avatar: allan_gaunt.png\n github: webnoob\n desc: Wrote the initial BEX mode and much more\n - name: Tobias Mesquita\n role: Senior Developer\n avatar: tobias_mesquita.jpg\n github: TobyMosque\n desc: Help desk\n - name: Kerry Huguet\n role: Senior Developer\n avatar: kerry_huguet.jpeg\n github: outofmemoryagain\n desc: Typescript support\n - name: Noah Klayman\n role: Developer / Community Staff\n avatar: noah_klayman.jpeg\n github: nklayman\n desc: Wrote the initial Capacitor mode\n - name: Heitor Ribeiro\n role: Community Staff\n avatar: heitor_ribeiro.jpg\n github: bloodf\n desc: Writes articles and offers community support.\n - name: Jesús Villanueva\n role: Senior Developer\n avatar: jesus_villanueva.jpg\n github: jesusvilla\n desc: Help desk\n - name: Dmitrij Polianin\n role: Trainer / Community Staff\n avatar: dmitrij_polianin.jpg\n email: [email protected]\n github: DmitrijOkeanij\n desc: Russian Community maintainer and Quasar Trainer.\n---\n\nHailing from all around the planet, the Quasar Team is not only international but full of people with a vast range of fields of expertise. From real rocket engineers to Fortune 500 developers, the unifying factor among us is our dedication to quality and the love for our community of contributors and developers.\n\nWith hundreds of contributors to Quasar, **the list of people you can meet below is by no means exhaustive**. Just remember to thank everyone using Quasar and supporting us, because together we all help you push your products light-years ahead of your competition. A great way to do that is to donate.\n\n\n\n### Core Team\n\n\u003cdiv class=\"row items-stretch q-gutter-sm\">\n \u003cTeamMember\n v-for=\"m in scope.core\"\n :key=\"m.name\"\n :name=\"m.name\"\n :role=\"m.role\"\n :avatar=\"m.avatar\"\n :email=\"m.email\"\n :twitter=\"m.twitter\"\n :github=\"m.github\"\n :desc=\"m.desc\"\n />\n\u003c/div>\n\n### Honorable mentions\n\n\u003cdiv class=\"row items-stretch q-gutter-sm\">\n \u003cTeamMember\n v-for=\"m in scope.others\"\n :key=\"m.name\"\n :name=\"m.name\"\n :role=\"m.role\"\n :avatar=\"m.avatar\"\n :email=\"m.email\"\n :twitter=\"m.twitter\"\n :github=\"m.github\"\n :desc=\"m.desc\"\n />\n\u003c/div>\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4077,"content_sha256":"dc3b9c5f115b3be1c698a4a45e48041dd6eb0e9bc5def696781213b916fad767"},{"filename":"references/docs/options/animations.md","content":"---\ntitle: Animations\ndesc: Helper CSS animations supplied by Animate.css for a Quasar app.\n---\n\nCSS Transitions can be handled by the Vue Transition Component. The transitions are used for entering (appearing) or leaving (disappearing) animations.\n\nHowever, Quasar can supply a big list of ready to use CSS animations. The animation effects are borrowed from Animate.css. So there are 80+ animation types available for you to use out of the box. Check the list either on Animate.css website or on the demo available for this page.\n\n> Please refer to Vue documentation for learning on how to use the Vue supplied `\u003ctransition>` component.\n\n## Installation\n\nEdit the `/quasar.config` file:\n\n```js /quasar.config file\n// embedding all animations\nanimations: 'all'\n\n// or embedding only specific animations\nanimations: ['bounceInLeft', 'bounceOutRight']\n```\n\nIf you are building a website, you can also skip configuring the quasar.config file and use a CDN link which points to Animate.css like this (following is just an example, Google for latest link). Remember this will require an Internet connection for your user, as opposed to bundling from within the quasar.config file.\n\n```html /index.html\n\u003chead>\n ...\n\n \u003c!-- CDN example for Animate.css -->\n \u003clink\n rel=\"stylesheet\"\n href=\"https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css\"\n />\n\u003c/head>\n```\n\n::: warning\nIt should be noted that when you import Animate.css through the `\u003clink>` tag, all animation CSS classes must be prefixed with `animate__`. This is a breaking change in the migration of Animate.css from v3 to v4. If you want to avoid using prefixes, you can import the compat version.\n\u003cbr>\u003cbr>\nHowever, if you're using the **Quasar CLI**, no additional changes are needed.\n:::\n\n::: warning\n**Windows Developers**\nIf you're developing on Windows and the animations don't appear to be working, it's likely an OS level setting that's to blame.\nTry changing **Visual Effects** to **Adjust for Best Appearance**.\n\n1. Right click `My Computer` and select `Properties`\n2. Click `Advanced System Settings`\n3. Click the `Settings` button under `Performance`\n4. Under the `Visual Effects` tab, change the radio option to: `Adjust for Best Appearance`\n :::\n\n## Usage\n\n::: warning\nNotice the string `animated` in front of the actual animation class name.\n:::\n\n```html Example with wrapping only one DOM element / component\n\u003ctransition\n appear\n enter-active-class=\"animated fadeIn\"\n leave-active-class=\"animated fadeOut\"\n>\n \u003c!-- Wrapping only one DOM element, defined by QBtn -->\n \u003cq-btn color=\"secondary\" icon=\"mail\" label=\"Email\" />\n\u003c/transition>\n```\n\n### Built-in animation classes\n\nQuasar also provides some built-in classes to animate the active state between both enter and leave transitions. The animations provided are separated into three groups (click on them to expand):\n\n::: details General classes\n\n```\nbounce\nflash\nflip\nheadShake\nheartBeat\nhinge\njello\npulse\nrubberBand\nshake\nshakeX\nshakeY\nswing\ntada\nwobble\n```\n\n:::\n\n::: details \"In\" classes\n\n```\nbackInDown\nbackInLeft\nbackInRight\nbackInUp\nbounceIn\nbounceInDown\nbounceInLeft\nbounceInRight\nbounceInUp\nfadeIn\nfadeInBottomLeft\nfadeInBottomRight\nfadeInDown\nfadeInDownBig\nfadeInLeft\nfadeInLeftBig\nfadeInRight\nfadeInRightBig\nfadeInTopLeft\nfadeInTopRight\nfadeInUp\nfadeInUpBig\nflipInX\nflipInY\njackInTheBox\nlightSpeedInLeft\nlightSpeedInRight\nrollIn\nrotateIn\nrotateInDownLeft\nrotateInDownRight\nrotateInUpLeft\nrotateInUpRight\nslideInDown\nslideInLeft\nslideInRight\nslideInUp\nzoomIn\nzoomInDown\nzoomInLeft\nzoomInRight\nzoomInUp\n```\n\n:::\n\n::: details \"Out\" classes\n\n```\nbackOutDown\nbackOutLeft\nbackOutRight\nbackOutUp\nbounceOut\nbounceOutDown\nbounceOutLeft\nbounceOutRight\nbounceOutUp\nfadeOut\nfadeOutBottomLeft\nfadeOutBottomRight\nfadeOutDown\nfadeOutDownBig\nfadeOutLeft\nfadeOutLeftBig\nfadeOutRight\nfadeOutRightBig\nfadeOutTopLeft\nfadeOutTopRight\nfadeOutUp\nfadeOutUpBig\nflipOutX\nflipOutY\nlightSpeedOutLeft\nlightSpeedOutRight\nrollOut\nrotateOut\nrotateOutDownLeft\nrotateOutDownRight\nrotateOutUpLeft\nrotateOutUpRight\nslideOutDown\nslideOutLeft\nslideOutRight\nslideOutUp\nzoomOut\nzoomOutDown\nzoomOutLeft\nzoomOutRight\nzoomOutUp\n```\n\n:::\n\nYou can also go to the official Vue documention for more information about the use of these classes.\n\n### Modifier classes\n\nThere are additional classes which delay or repeat or change the speed of the animations (click to expand):\n\n::: details Modifier classes\n\n```js\nrepeat\nrepeat-1\nrepeat-2\ndelay-1s\ndelay-5s\nslower\nslow\nfast\nfaster\n```\n\n:::\n\nExample:\n\n```html\n\u003ctransition\n appear\n enter-active-class=\"animated fadeIn slower delay-5s repeat-2\"\n leave-active-class=\"animated fadeOut\"\n>\n \u003c!-- Wrapping only one DOM element, defined by QBtn -->\n \u003cq-btn color=\"secondary\" icon=\"mail\" label=\"Email\" />\n\u003c/transition>\n```\n\n### Wrapping Multiple Elements\n\nYou can also group components or DOM elements in a transition so that the same effects are applied to all of them simultaneously.\n\n```html Example with wrapping multiple DOM elements / components\n\u003ctransition-group\n appear\n enter-active-class=\"animated fadeIn\"\n leave-active-class=\"animated fadeOut\"\n>\n \u003c!-- We wrap a \"p\" tag and a QBtn -->\n \u003cp key=\"text\"> Lorem Ipsum \u003c/p>\n \u003cq-btn key=\"email-button\" color=\"secondary\" icon=\"mail\" label=\"Email\" />\n\u003c/transition-group>\n```\n\nPlease note some things in the above example:\n\n1. Note `\u003ctransition-group>` instead of `\u003ctransition>`.\n2. The components and DOM elements must be keyed, like `key=\"text\"` or `key=\"email-button\"` in the example above.\n3. Both examples above have the Boolean property `appear` specified, which makes the entering animation kick in right after component(s) have been rendered. This property is optional.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5692,"content_sha256":"8dff41fde7d4460ccad9258f19b17fff2b1cda074605635f78cdd7bbf69c2fd2"},{"filename":"references/docs/options/app-icons.md","content":"---\ntitle: App Icons\ndesc: Managing all the App icons and splash screens in a Quasar app.\n---\n\nIf you were to target all platforms that Quasar currently supports, you will need to make 100+ different files of 4 different media types (png, ico, icns and svg). If you just use a tool like Gimp, Photoshop or Affinity Designer, you will find that these files are rather large and the process of making them and naming them is prone to operator error. You will probably want to compress the PNG files at least, and also remove unnecessary app-metadata from the SVG.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/iconfactory.png\" style=\"float:right;max-width:15%;min-width:240px;padding-top:40px\">\n\n## Icon Genie CLI\n\n::: tip\nWe highly recommend using the [Icon Genie CLI](/icongenie/introduction), because it consumes a source icon and automatically clones, scales, minifies and places the icons in the appropriate directories for you. When needed, it also tells you what tags you'll need to add to your /index.html file.\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1014,"content_sha256":"165db69c97bcfd3a4a66657ed74f6850a97406a6bf2256b4675eb5e4b0e8ca07"},{"filename":"references/docs/options/app-internationalization.md","content":"---\ntitle: App Internationalization (i18n)\ndesc: How to use vue-i18n in a Quasar app.\nrelated:\n - /options/rtl-support\n - /options/quasar-language-packs\n---\n\nInternationalization is a design process that ensures a product (a website or application) can be adapted to various languages and regions without requiring engineering changes to the source code. Think of internationalization as readiness for localization.\n\n::: tip\nThe recommended package for handling website/app is vue-i18n. This package should be added through a [@quasar/app-vite Boot File](/quasar-cli-vite/boot-files) or a [@quasar/app-webpack Boot File](/quasar-cli-webpack/boot-files). On the Boot File documentation page you can see a specific example for plugging in vue-i18n.\n:::\n\n::: warning\nQuasar documentation assumes you are already familiar with vue-i18n. Below it's described only the basics of how to make use of it in a Quasar CLI project. For the full list of its features please visit the Vue I18n documentation.\n:::\n\n## Setup manually\n\nIf you missed enabling i18n during `yarn create quasar` (or `npm init quasar@latest` or the pnpm or Bun equivalent) wizard, here is how you can set it up manually.\n\n1. Install the `vue-i18n` dependency into your app.\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add vue-i18n\n\u003c\u003c| bash NPM |>>\n$ npm install --save vue-i18n\n\u003c\u003c| bash PNPM |>>\n$ pnpm add vue-i18n\n\u003c\u003c| bash Bun |>>\n$ bun add vue-i18n\n```\n\n2. Create a file `src/boot/i18n.js` with following content:\n\n```tabs\n\u003c\u003c| js JS |>>\nimport { defineBoot } from '#q-app/wrappers'\nimport { createI18n } from 'vue-i18n'\nimport messages from 'src/i18n'\n\nexport default defineBoot(({ app }) => {\n const i18n = createI18n({\n locale: 'en-US',\n globalInjection: true,\n messages\n })\n\n // Set i18n instance on app\n app.use(i18n)\n})\n\u003c\u003c| js TypeScript |>>\nimport { defineBoot } from '#q-app/wrappers';\nimport { createI18n } from 'vue-i18n';\n\nimport messages from 'src/i18n';\n\nexport type MessageLanguages = keyof typeof messages;\n// Type-define 'en-US' as the master schema for the resource\nexport type MessageSchema = typeof messages['en-US'];\n\n// See https://vue-i18n.intlify.dev/guide/advanced/typescript.html#global-resource-schema-type-definition\n/* eslint-disable @typescript-eslint/no-empty-object-type */\ndeclare module 'vue-i18n' {\n // define the locale messages schema\n export interface DefineLocaleMessage extends MessageSchema {}\n\n // define the datetime format schema\n export interface DefineDateTimeFormat {}\n\n // define the number format schema\n export interface DefineNumberFormat {}\n}\n/* eslint-enable @typescript-eslint/no-empty-object-type */\n\nexport default defineBoot(({ app }) => {\n const i18n = createI18n\u003c{ message: MessageSchema }, MessageLanguages>({\n locale: 'en-US',\u003c% if (sfcStyle === 'composition' || sfcStyle === 'composition-setup') { %>\n legacy: false,\u003c% } %>\n messages,\n });\n\n // Set i18n instance on app\n app.use(i18n);\n});\n```\n\n3. Create a folder (/src/i18n/) in your app which will hold the definitions for each language that you'll support. Example: src/i18n. Notice the \"import messages from 'src/i18n'\" from step 2. This is step where you write the content that gets imported.\n\n4. Now reference this file in `quasar.config` one in the `boot` section:\n\n```js /quasar.config file\nreturn {\n boot: [\n // ...\n 'i18n'\n ]\n\n // ...\n}\n```\n\nNow you are ready to use it in your pages.\n\n## Setting up Translation Blocks in your SFCs \u003cq-badge label=\"@quasar/app-vite only\" />\n\n::: warning\nThe following section applies to projects that use @quasar/app-vite only!\n:::\n\nIf we want to add support to the `\u003ci18n>` tag inside a SFC (single file component) in a Quasar CLI project then we need to modify the existing configuration.\n\nWe first install the `@intlify/unplugin-vue-i18n` package:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add --dev @intlify/unplugin-vue-i18n\n\u003c\u003c| bash NPM |>>\n$ npm install --save-dev @intlify/unplugin-vue-i18n\n\u003c\u003c| bash PNPM |>>\n$ pnpm add -D @intlify/unplugin-vue-i18n\n\u003c\u003c| bash Bun |>>\n$ bun add --dev @intlify/unplugin-vue-i18n\n```\n\nThen we edit the /quasar.config file:\n\n```js /quasar.config file\nimport { fileURLToPath } from 'node:url'\n\n// ...\n\nbuild: {\n vitePlugins: [\n [\n '@intlify/unplugin-vue-i18n/vite',\n {\n // if you want to use Vue I18n Legacy API, you need to set `compositionOnly: false`\n // compositionOnly: false,\n\n // if you want to use named tokens in your Vue I18n messages, such as 'Hello {name}',\n // you need to set `runtimeOnly: false`\n // runtimeOnly: false,\n\n ssr: ctx.modeName === 'ssr',\n\n // you need to set i18n resource including paths !\n include: [fileURLToPath(new URL('./src/i18n', import.meta.url))]\n }\n ]\n ]\n}\n```\n\n## How to use\n\nHere is an example displaying the main use cases:\n\n```html\n\u003ctemplate>\n \u003cq-page>\n \u003c!-- text interpolation, reactive -->\n {{ $t('hello') }}\n\n \u003c!-- prop/attr binding, reactive -->\n \u003cq-btn :label=\"$t('hello')\" />\n\n \u003c!-- v-html directive usage -->\n \u003cspan v-html=\"content\">\u003c/span>\n \u003c/q-page>\n\u003c/template>\n\n\u003cscript setup>\n import { computed } from 'vue'\n import { useI18n } from 'vue-i18n'\n\n const { t } = useI18n()\n\n // bound to a static variable, non-reactive\n // const staticContent = t('hello')\n // bound to a reactive variable, but one-time assignment, locale changes will not update the value\n // const reactiveStaticContent = ref(t('hello'))\n\n // bound to a reactive variable, locale changes will reflect the value\n const content = computed(() => t('hello'))\n\n function notify() {\n Notify.create({\n type: 'positive',\n message: t('hello')\n })\n }\n\u003c/script>\n```\n\n## Add new language\n\nLet's say you want to add new German language.\n\n1. Create the new file `src/i18n/de/index.js` and copy there the content of the file `src/i18n/en-US/index.js` then make changes to the language strings.\n2. Now change `src/i18n/index.js` and add the new `de` language there.\n\n```js\nimport enUS from './en-US'\nimport de from './de'\n\nexport default {\n 'en-US': enUS,\n de: de\n}\n```\n\n## Create language switcher\n\n```html Some Vue file\n\u003ctemplate>\n \u003c!-- ...... -->\n \u003cq-select\n v-model=\"locale\"\n :options=\"localeOptions\"\n label=\"Quasar Language\"\n dense\n borderless\n emit-value\n map-options\n options-dense\n style=\"min-width: 150px\"\n />\n \u003c!-- ...... -->\n\u003c/template>\n\n\u003cscript setup>\n import { useI18n } from 'vue-i18n'\n\n const { locale } = useI18n({ useScope: 'global' })\n\n const localeOptions: [\n { value: 'en-US', label: 'English' },\n { value: 'de', label: 'German' }\n ]\n\u003c/script>\n```\n\n## UPPERCASE\n\nMany languages, such as Greek, German and Dutch have non-intuitive rules for uppercase display, and there is an edge case that you should be aware of:\n\nQBtn component will use the CSS `text-transform: uppercase` rule to automatically turn its label into all-caps. According to the MDN webdocs, \"The language is defined by the lang HTML attribute or the xml:lang XML attribute.\" Unfortunately, this has spotty implementation across browsers, and the 2017 ISO standard for the uppercase German eszett `ß` has not really entered the canon. At the moment you have two options:\n\n1. use the prop `no-caps` in your label and write the string as it should appear\n2. use the prop `no-caps` in your label and rewrite the string with toLocaleUpperCase by using the locale as detected by `$q.lang.getLocale()`\n\n## Detecting Locale\n\nThere's also a method to determine user locale which is supplied by Quasar out of the box:\n\n```js\n// outside of a Vue file\nimport { Lang } from 'quasar'\nLang.getLocale() // returns a string\n\n// inside of a Vue file\nimport { useQuasar } from 'quasar'\n\nsetup () {\n const $q = useQuasar()\n $q.lang.getLocale() // returns a string\n}\n```\n\n::: warning\nIf you use Quasar's set method (`$q.lang.set()`), this will not be reflected by Quasar's getLocale above. The reason for this is that `getLocale()` will always return the _users_ locale (based on browser settings). The `set()` method refers to Quasars internal locale setting which is used to determine which language file to use. If you would like to see which language has been set using `set()` you can use `$q.lang.isoName`.\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":8236,"content_sha256":"9037db794f7ca8bf58c000008457ca0d2a4704efaea03387d203b268e5d1eb2b"},{"filename":"references/docs/options/global-node.md","content":"---\ntitle: Global node generation\ndesc: Some Quasar components and plugins to show floating elements will create global nodes appending them to the body.\n---\n\nYou can define custom className for this global node elements.\n\n## Installation\n\nYou don't need to do anything.\n\n## Configuration\n\nIn order to define custom class for global nodes, edit your /quasar.config file like below.\n\n```js /quasar.config file\nframework: {\n config: {\n globalNode: {\n className: 'my-class'\n }\n }\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":496,"content_sha256":"3e4867293a9b6237849233fa6080d7ffc03b68549d39d6cf07fe4f24086a15c6"},{"filename":"references/docs/options/installing-icon-libraries.md","content":"---\ntitle: Installing Icon Libraries\ndesc: How to use icon libraries in a Quasar app.\nrelated:\n - /options/quasar-icon-sets\n - /vue-components/icon\n---\n\n::: tip\n**This page refers to using [webfont icons](/vue-components/icon#webfont-icons) only.** [Svg icons](/vue-components/icon#svg-icons) do not need any installation step.\n:::\n\nYou'll most likely want icons in your website/app and Quasar offers an easy way out of the box for the following icon libraries: Material Icons, Material Symbols, Font Awesome, Ionicons, MDI, Eva Icons, Themify Icons, Line Awesome and Bootstrap Icons. But you can [add support for others](/vue-components/icon#custom-mapping) by yourself.\n\n::: tip\nIn regards to webfont icons, you can choose to install one or more of these icon libraries.\n:::\n\n## Installing Webfonts\n\nIf you are building a website only, then using a CDN (Content Delivery Network) approach can be an option you can follow. However, when building a mobile or Electron app, you most likely do not want to depend on an Internet connection and Quasar comes with a solution to this problem:\n\nEdit the `/quasar.config` file:\n\n```js\nextras: ['material-icons']\n```\n\nWebfont icons are available through @quasar/extras package. You don't need to import it in your app, just configure the `/quasar.config` file as indicated above.\n\nAdding more than one set:\n\n```js\nextras: [\n 'material-icons',\n 'mdi-v7',\n 'ionicons-v4', // last webfont was available in v4.6.3\n 'eva-icons',\n 'fontawesome-v6',\n 'themify',\n 'line-awesome',\n 'bootstrap-icons'\n]\n```\n\nFor all available options, visit the GitHub repository.\n\nYou're now ready to use the [QIcon](/vue-components/icon) component.\n\n## Using CDN as alternative\n\nIf you want to make use of a CDN (Content Delivery Network), all you need to do is to include style tags in your /index.html file which point to the CDN URL.\n\nIn case you follow this path, do not also add the icon sets that you want in `/quasar.config file > extras`. Play with the [UMD Installation Guide](/start/umd#installation) and edit /index.html as described there.\n\n## Using Fontawesome-Pro\n\nIf you have a Fontawesome v6 Pro license and want to use it instead of the Fontawesome Free version, follow these instructions:\n\n1. Open the Linked Accounts section in Fontawesome's user account page to grab the npm TOKENID (login if necessary).\n2. Create or append TOKENID into the `.npmrc` file (file path same as package.json):\n\n```\n@fortawesome:registry=https://npm.fontawesome.com/\n//npm.fontawesome.com/:_authToken=TOKENID\n```\n\n3. Install Fontawesome webfonts:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add @fortawesome/fontawesome-pro\n\u003c\u003c| bash NPM |>>\n$ npm install --save @fortawesome/fontawesome-pro\n\u003c\u003c| bash PNPM |>>\n$ pnpm add @fortawesome/fontawesome-pro\n\u003c\u003c| bash Bun |>>\n$ bun add @fortawesome/fontawesome-pro\n```\n\n4. Create new boot file:\n\n```bash\n$ quasar new boot fontawesome-pro [--format ts]\n```\n\n5. Edit the `/quasar.config` file:\n\n```js\nboot: [\n ...\n 'fontawesome-pro' // Add boot file\n],\nextras: [\n // 'fontawesome-v6' // Disable free version!\n],\nframework: {\n // if you want Quasar to use Fontawesome for its icons\n iconSet: 'fontawesome-v6-pro'\n}\n```\n\n6. Edit `/src/boot/fontawesome-pro.js`:\n\n```js\n// required\nimport '@fortawesome/fontawesome-pro/css/fontawesome.css'\nimport '@fortawesome/fontawesome-pro/css/light.css'\n// do you want these too?\n// import '@fortawesome/fontawesome-pro/css/thin.css'\n// import '@fortawesome/fontawesome-pro/css/duotone.css'\n// import '@fortawesome/fontawesome-pro/css/brands.css'\n// import '@fortawesome/fontawesome-pro/css/solid.css'\n// import '@fortawesome/fontawesome-pro/css/regular.css'\n```\n\n7. (Optional) Override default icons:\n\nSince the default `font-weight` for fontawesome-pro is `light` or `fal`, some icons used by the framework components may not be desirable. The best way to handle this is to override it in the boot file that you created.\n\nFor instance, to override the `fal` version of the close icon for chips, do this:\n\n_First_, find the icon used for chip close in Quasar Fontawesome v6 Pro icon-set source.\n\n(Alternatively, you can check inside the render function of the component you are overriding.)\n\n```js Example\nchip: {\n remove: 'fal fa-times-circle'\n```\n\n_Then_, override it in your `/src/boot/fontawesome-pro.js`\n\n```js\nimport '@fortawesome/fontawesome-pro/css/fontawesome.min.css'\nimport '@fortawesome/fontawesome-pro/css/solid.min.css'\nimport '@fortawesome/fontawesome-pro/css/light.min.css'\n\n// example\nexport default ({ app }) => {\n app.config.globalProperties.$q.iconSet.chip.remove = 'fas fa-times-circle'\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4609,"content_sha256":"573f6373c64ae9107ffd957ff39400b04807b056daffcf56f3ca4ba1cff449d8"},{"filename":"references/docs/options/platform-detection.md","content":"---\ntitle: Platform Detection\ndesc: How to detect the platform under which a Quasar app is running.\nexamples: Platform\n---\n\nHelpers are built into Quasar to detect the Platform (and its capabilities) within the context of which the code is running.\n\n::: tip\nBased on your needs, you might also want to check the [Style & Identity > Visibility](/style/visibility) page to see how you can achieve the same effect using CSS alone. This latter method will render your DOM elements or components regardless of platform though, so choose wisely on how you want to handle the performance of your app.\n:::\n\n\u003cDocApi file=\"Platform\" />\n\n## Usage\n\nUsage inside a Vue component JS:\n\n```js\nimport { useQuasar } from 'quasar'\n\nsetup () {\n const $q = useQuasar()\n\n $q.platform.is.mobile\n}\n```\n\nUsage inside a Vue component template:\n\n```js\n$q.platform.is.cordova\n```\n\nYou must import it when you use it outside of a Vue component :\n\n```js\nimport { Platform } from 'quasar'\n```\n\n`Platform.is` by itself returns an object containing details about the current platform. For example when running Chrome on a MacOS desktop machine, `Platform.is` would return something similar to:\n\n```js\n{\n chrome: true,\n desktop: true,\n mac: true,\n name: \"chrome\",\n platform: \"mac\",\n version: \"70.0.3538.110\",\n versionNumber: 70,\n webkit: true\n}\n```\n\nNow, let's say we want to render different components or DOM elements, based on the platform that the code is running under. We want to show something on desktop and something else on mobile. We would proceed like this:\n\n```html\n\u003cdiv v-if=\"$q.platform.is.desktop\"> I'm only rendered on desktop! \u003c/div>\n\n\u003cdiv v-if=\"$q.platform.is.mobile\"> I'm only rendered on mobile! \u003c/div>\n\n\u003cdiv v-if=\"$q.platform.is.electron\"> I'm only rendered on Electron! \u003c/div>\n```\n\n\u003cDocExample title=\"Your device\" file=\"Basic\" />\n\n## Properties\n\nThe following properties are available to the Platform object. It's not an exhaustive list though. See the API section below for more details.\n\n| Property | Type | Meaning |\n| --------------------------------- | ------- | ------------------------------------------------------------------------------- |\n| `Platform.is.mobile` | Boolean | Is the code running on a mobile device? |\n| `Platform.is.cordova` | Boolean | Is the code running within Cordova? |\n| `Platform.is.capacitor` | Boolean | Is the code running within Capacitor? |\n| `Platform.is.nativeMobile` | Boolean | Is the code running within a native mobile wrapper(_Cordova/Capacitor_)? |\n| `Platform.is.nativeMobileWrapper` | String | Name of the native mobile wrapper(_`'cordova'`, `'capacitor'`, or `undefined`_) |\n| `Platform.is.electron` | Boolean | Is the code running within Electron? |\n| `Platform.is.desktop` | Boolean | Is the code running on a desktop browser? |\n| `Platform.is.bex` | Boolean | Is the code running in a browser extension? |\n| `Platform.is.android` | Boolean | Is the app running on an Android device? |\n| `Platform.is.blackberry` | Boolean | Is the app running on a Blackberry device? |\n| `Platform.is.cros` | Boolean | Is the app running on device with the Chrome OS operating system? |\n| `Platform.is.ios` | Boolean | Is the app running on an iOS device? |\n| `Platform.is.ipad` | Boolean | Is the app running on an iPad? |\n| `Platform.is.iphone` | Boolean | Is the app running on an iPhone? |\n| `Platform.is.ipod` | Boolean | Is the app running on an iPod? |\n| `Platform.is.kindle` | Boolean | Is the app running on a Kindle device? |\n| `Platform.is.linux` | Boolean | Is the code running on a device with the Linux operating system? |\n| `Platform.is.mac` | Boolean | Is the code running on a device with the MacOS operating system? |\n| `Platform.is.win` | Boolean | Is the code running on a device with the Windows operating system? |\n| `Platform.is.winphone` | Boolean | Is the code running on a Windows Phone device? |\n| `Platform.is.playbook` | Boolean | Is the code running on a Blackberry Playbook device? |\n| `Platform.is.silk` | Boolean | Is the code running the Kindle Silk browser? |\n| `Platform.is.chrome` | Boolean | Is the code running inside the Google Chrome browser? |\n| `Platform.is.firefox` | Boolean | Is the code running inside the Firefox browser? |\n| `Platform.is.opera` | Boolean | Is the code running inside the Opera browser? |\n| `Platform.is.safari` | Boolean | Is the code running inside the Apple Safari browser? |\n| `Platform.is.vivaldi` | Boolean | Is the code running inside the Vivaldi browser? |\n| `Platform.is.edge` | Boolean | Is the code running inside the Microsoft Edge browser? |\n| `Platform.is.ie` | Boolean | Is the code running inside the Microsoft Internet Explorer browser? |\n| `Platform.is.webkit` | Boolean | Is the code running on Webkit or webkit-based? |\n| `Platform.has.touch` | Boolean | Is the code running on a touch capable screen? |\n| `Platform.within.iframe` | Boolean | Is the app running within an IFRAME? |\n\n::: tip\nRunning on mobile means you can have this code running on a mobile device (phone or tablet) but with a browser, not within a Cordova wrapper.\n:::\n\n## Note about SSR\n\nWhen building for SSR, use only the `$q.platform` form. Alternatively, when on server-side, this is one more example of how you can use it:\n\n```js\nimport { Platform } from 'quasar'\n\n// you need access to `ssrContext`\nfunction (ssrContext) {\n const platform = process.env.SERVER\n ? Platform.parseSSR(ssrContext)\n : Platform // otherwise we're on client\n\n // platform is equivalent to the global import as in non-SSR builds\n}\n```\n\nThe `ssrContext` is available in [@quasar/app-vite Boot File](/quasar-cli-vite/boot-files) or [@quasar/app-webpack Boot File](/quasar-cli-webpack/boot-files). And also in the [@quasar/app-vite preFetch](/quasar-cli-vite/prefetch-feature) or [@quasar/app-webpack preFetch](/quasar-cli-webpack/prefetch-feature) feature, where it is supplied as a parameter.\n\nThe reason for all this is that in a client-only app, every user will be using a fresh instance of the app in their browser. For server-side rendering we want the same: each request should have a fresh, isolated app instance so that there is no cross-request state pollution. So Platform needs to be bound to each request separately.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":7712,"content_sha256":"9c17b6012778a8a93966ac5fbcaf20216d3eed9b553ca39c8817e22e2858f1da"},{"filename":"references/docs/options/quasar-icon-sets.md","content":"---\ntitle: Quasar Icon Sets\ndesc: How to configure icon sets for Quasar components.\nkeys: IconSet,iconSet\nrelated:\n - /options/installing-icon-libraries\n - /vue-components/icon\n---\n\nQuasar components have their own icons. Rather than forcing you into using one icon library in particular (so that they can display correctly), Quasar lets you choose **which icons it should use for its components**. This is called a `Quasar Icon Set`.\n\nYou can install multiple icon libraries, but you must choose only one to use on Quasar's components.\n\nQuasar currently supports: Material Icons, Material Symbols, Font Awesome, Ionicons, MDI, Eva Icons, Themify Icons, Line Awesome and Bootstrap Icons.\n\nIt is also possible to use your own icon files (SVG or any image format) with any Quasar component, see [QIcon | Image icons](/vue-components/icon#image-icons) page for more details.\n\nYou can also provide an icon mapping function to add support for any other icon library or re-map some existing ones to your liking, see [QIcon | Custom mapping](/vue-components/icon#custom-mapping) for more details. You can use this to re-map long image file paths to short and understandable names, if using image icons, for example.\n\n::: tip\nRelated pages: [Installing Icon Libraries](/options/installing-icon-libraries) and [QIcon component](/vue-components/icon).\n:::\n\n\u003cDocApi file=\"IconSet\" />\n\n## Configuring the default Icon Set\n\n**There are two types of Quasar Icon Sets: webfont-based and svg-based.**\n\nUnless configured otherwise, Quasar uses Material Icons webfont as the icon set for its components. You can however tell Quasar to use some other Icon Set, but if it's a webfont-based one then be sure to include its icon library in your website/app (see [Installing Icon Libraries](/options/installing-icon-libraries)).\n\n### Hardcoded\n\nIf the default Quasar Icon Set is not dynamically determined (does not depends on cookies for example), then you can:\n\n#### Quasar CLI Way\n\nWe edit the `/quasar.config` file again:\n\n```js\nframework: {\n // webfont-based example\n iconSet: 'mdi-v7'\n}\n```\n\n```js\nframework: {\n // svg-based example\n iconSet: 'svg-mdi-v7'\n}\n```\n\nFor all available options, visit the GitHub repository.\n\nFull example of including MDI & Fontawesome and telling Quasar to use Fontawesome for its components.\n\n```js\nextras: [\n 'mdi-v7',\n 'fontawesome-v6'\n],\nframework: {\n iconSet: 'fontawesome-v6'\n}\n```\n\nThis will enable you to use both MDI & Fontawesome webfonts in your app, and all Quasar components will display Fontawesome icons.\n\n#### Quasar UMD Way\n\nInclude the Quasar Icon Set tag for your Quasar version and also tell Quasar to use it. Example:\n\n```html\n\u003c!-- include this after Quasar JS tag -->\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/quasar@v2/dist/icon-set/fontawesome-v6.umd.prod.js\">\u003c/script>\n\u003cscript>\n Quasar.IconSet.set(Quasar.IconSet.fontawesomeV6)\n\u003c/script>\n```\n\nCheck what tags you need to include in your HTML files on [UMD / Standalone](/start/umd) page.\n\n#### Quasar Vite Plugin Way\n\nWe edit your `main.js`:\n\n```js /main.js\n// ...\nimport { Quasar } from 'quasar'\n// ...\nimport iconSet from 'quasar/icon-set/fontawesome-v6'\nimport '@quasar/extras/fontawesome-v6/fontawesome-v6.css'\n// ...\napp.use(Quasar, {\n // ...,\n iconSet: iconSet\n})\n```\n\n### Dynamic (on non-SSR)\n\nQuasar CLI: If your desired Quasar Icon Set must be dynamically selected (example: depends on a cookie), then you need to create a boot file: `$ quasar new boot quasar-icon-set [--format ts]`. This will create `/src/boot/quasar-icon-set.js` file. Edit it to:\n\n```tabs /src/boot/quasar-icon-set.js\n\u003c\u003c| js With @quasar/app-vite |>>\nimport { defineBoot } from '#q-app/wrappers'\nimport { IconSet } from 'quasar'\n\n// relative path to your node_modules/quasar/..\n// change to YOUR path\nconst iconSetList = import.meta.glob('../../node_modules/quasar/icon-set/*.js')\n// or just a select few (example below with only mdi-v7 and fontawesome-v6):\n// import.meta.glob('../../node_modules/quasar/icon-set/(mdi-v7|fontawesome-v6).js')\n\nexport default defineBoot(async () => {\n const iconSetName = 'mdi-v7' // ... some logic to determine it (use Cookies Plugin?)\n\n try {\n iconSetList[ `../../node_modules/quasar/icon-set/${ iconSetName }.js` ]().then(lang => {\n IconSet.set(setDefinition.default)\n })\n }\n catch (err) {\n console.error(err)\n // Requested Quasar Icon Set does not exist,\n // let's not break the app, so catching error\n }\n})\n\u003c\u003c| js With @quasar/app-webpack |>>\nimport { defineBoot } from '#q-app/wrappers'\nimport { IconSet } from 'quasar'\n\nexport default defineBoot(async () => {\n const iconSetName = 'mdi-v7' // ... some logic to determine it (use Cookies Plugin?)\n\n try {\n await import(\n /* webpackInclude: /(mdi-v7|fontawesome-v6)\\.js$/ */\n 'quasar/icon-set/' + iconSetName\n ).then(setDefinition => {\n IconSet.set(setDefinition.default)\n })\n }\n catch (err) {\n // Requested Quasar Icon Set does not exist,\n // let's not break the app, so catching error\n }\n})\n```\n\nThen register this boot file into the `/quasar.config` file:\n\n```js\nboot: ['quasar-icon-set']\n```\n\n::: warning Always constrain a dynamic import\nNotice the use of the Webpack magic comment - `webpackInclude`. Otherwise all the available icon set files will be bundled, resulting in an increase in the compilation time and the bundle size. See [Caveat for dynamic imports](/quasar-cli-webpack/lazy-loading#caveat-for-dynamic-imports)\n:::\n\n### Dynamic (on SSR)\n\nWhen dealing with SSR, we can't use singleton objects because that would pollute sessions. As a result, as opposed to the dynamical example above (read it first!), you must also specify the `ssrContext` from your boot file:\n\n```tabs /src/boot/quasar-icon-set.js\n\u003c\u003c| js With @quasar/app-vite |>>\nimport { defineBoot } from '#q-app/wrappers'\nimport { IconSet } from 'quasar'\n\n// relative path to your node_modules/quasar/..\n// change to YOUR path\nconst iconSetList = import.meta.glob('../../node_modules/quasar/icon-set/*.js')\n// or just a select few (example below with only mdi-v7 and fontawesome-v6):\n// import.meta.glob('../../node_modules/quasar/icon-set/(mdi-v7|fontawesome-v6).js')\n\n// ! NOTICE ssrContext param:\nexport default defineBoot(async ({ ssrContext }) => {\n const iconSetName = 'mdi-v7' // ... some logic to determine it (use Cookies Plugin?)\n\n try {\n iconSetList[ `../../node_modules/quasar/icon-set/${ iconSetName }.js` ]().then(lang => {\n IconSet.set(setDefinition.default, ssrContext)\n })\n }\n catch (err) {\n console.error(err)\n // Requested Quasar Icon Set does not exist,\n // let's not break the app, so catching error\n }\n})\n\u003c\u003c| js With @quasar/app-webpack |>>\nimport { defineBoot } from '#q-app/wrappers'\nimport { IconSet } from 'quasar'\n\n// ! NOTICE ssrContext param:\nexport default defineBoot(async ({ ssrContext }) => {\n const iconSetName = 'mdi-v7' // ... some logic to determine it (use Cookies Plugin?)\n\n try {\n await import(\n /* webpackInclude: /(mdi-v7|fontawesome-v6)\\.js$/ */\n 'quasar/icon-set/' + iconSetName\n ).then(setDefinition => {\n IconSet.set(setDefinition.default, ssrContext)\n })\n }\n catch (err) {\n console.error(err)\n // Requested Quasar Icon Set does not exist,\n // let's not break the app, so catching error\n }\n})\n```\n\n## Change Quasar Icon Set at Runtime\n\n### Changing Icon Set\n\nQuasar Icon Set is reactive, so all components will update properly if you change the $q.iconSet object. Here is an example:\n\n```tabs\n\u003c\u003c| js Composition API |>>\nimport { useQuasar } from 'quasar'\nimport mdiIconSet from 'quasar/icon-set/mdi-v7.js'\n\nsetup () {\n const $q = useQuasar()\n\n function changeIconSetToMdiIconSet () {\n $q.iconSet.set(mdiIconSet)\n }\n\n return {\n changeIconSetToMdiIconSet\n }\n}\n\u003c\u003c| js Options API |>>\nimport mdiIconSet from 'quasar/icon-set/mdi-v7.js'\n\nmethods: {\n changeIconSetToMdiIconSet () {\n this.$q.iconSet.set(mdiIconSet)\n }\n}\n```\n\nIf you want to do this outside of a .vue file (and you are NOT on SSR mode) then you can\n\n```js /src/boot/some-boot-file.js\nimport { defineBoot } from '#q-app/wrappers'\nimport { IconSet } from 'quasar'\nimport mdiIconSet from 'quasar/icon-set/mdi-v7.js'\n\nexport default defineBoot(() {\n IconSet.set(mdiIconSet)\n})\n```\n\n### Changing a Specific Icon\n\nIf you want to change a specific icon to another, you can. Here is an example:\n\n```tabs\n\u003c\u003c| js Composition API |>>\nimport { useQuasar } from 'quasar'\n\nsetup () {\n const $q = useQuasar()\n\n function changeQEditorHeaderIcon () {\n $q.iconSet.editor.header1 = 'fas fa-font'\n }\n\n return { changeQEditorHeaderIcon }\n}\n\u003c\u003c| js Options API |>>\nmethods: {\n changeQEditorHeaderIcon () {\n this.$q.iconSet.editor.header1 = 'fas fa-font'\n }\n}\n```\n\nIf you want to do this outside of a .vue file (and you are NOT on SSR mode) then you can\n\n```js /src/boot/some-boot-file.js\nimport { IconSet } from 'quasar'\n\nexport default () {\n IconSet.props.editor.header1 = 'fas fa-font'\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":8972,"content_sha256":"e7fd5ce93d5caa9d4703d4a86911541f75eea5d9614082f5c8e9ea3706f20254"},{"filename":"references/docs/options/quasar-language-packs.md","content":"---\ntitle: Quasar Language Packs\ndesc: How to configure the Quasar language packs in a Quasar app.\nkeys: Lang,lang\nrelated:\n - /options/rtl-support\n - /options/app-internationalization\n---\n\nA Quasar Language Pack refers to the internationalization of Quasar's own components, some of which have labels.\n\n\u003cDocApi file=\"Lang\" />\n\n\u003cDocInstallation title=\"Configuration\" config=\"lang\" />\n\n::: warning\nIt should be noted that what is described below is the internationalization of Quasar components only. If you need to internationalize your own components, read [App Internationalization](/options/app-internationalization) documentation page.\n:::\n\nAs mentioned above, some Quasar components have their own labels. When it comes to internationalization, one option is to configure labels through the label properties on each instance of Quasar components (like QTable). This is how you can customize the text to match the selected language. This however, takes time and adds unnecessary complexity to your website/app. **Instead**, you can use the Quasar Language Packs which have a number of standard label definitions translated for you, like \"Cancel\", \"Clear\", \"Select\", \"Update\", etc. No need to translate these again! And it comes out of the box.\n\n::: tip\nFor a complete list of available Quasar Languages, check Quasar Languages on GitHub.\n\u003cbr>\u003cbr>**If your desired language is not on that list**, then feel free to submit a PR to add it. It takes from 5 to 10 minutes at most. We kindly welcome any language!\n:::\n\n## Configuring the default Language Pack\n\nUnless configured otherwise (see below), Quasar uses the `en-US` Language Pack by default.\n\n### Hardcoded\n\nIf the default Quasar Language Pack is not dynamically determined (does not depend on cookies for example), then you can:\n\n```tabs\n\u003c\u003c| js Quasar CLI |>>\n// quasar.config file\n\nframework: {\n lang: 'de'\n}\n\u003c\u003c| js Vite Plugin |>>\n// main.js file\n\n// ...\nimport { Quasar } from 'quasar'\n// ...\nimport langDe from 'quasar/lang/de'\n// ...\napp.use(Quasar, {\n // ...,\n lang: langDe\n})\n\u003c\u003c| html Quasar UMD |>>\n\u003c!-- include this after Quasar JS tag -->\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/quasar@2/dist/lang/de.umd.prod.js\">\u003c/script>\n\u003cscript>\n Quasar.Lang.set(Quasar.Lang.de)\n\u003c/script>\n```\n\n::: tip\nFor **Quasar UMD**, check what tags you may still need to include in your HTML files on [UMD / Standalone](/start/umd) page.\n:::\n\n### Dynamical (non-SSR)\n\nQuasar CLI: If your desired Quasar Language Pack must be dynamically selected (example: depends on a cookie), then you need to create a boot file: `$ quasar new boot quasar-lang-pack [--format ts]`. This will create `/src/boot/quasar-lang-pack.js` file. Edit it to:\n\n```tabs\n\u003c\u003c| js With @quasar/app-vite |>>\nimport { defineBoot } from '#q-app/wrappers'\nimport { Lang } from 'quasar'\n\n// relative path to your node_modules/quasar/..\n// change to YOUR path\nconst langList = import.meta.glob('../../node_modules/quasar/lang/*.js')\n// or just a select few (example below with only DE and FR):\n// import.meta.glob('../../node_modules/quasar/lang/(de|fr).js')\n\nexport default defineBoot(async () => {\n const langIso = 'de' // ... some logic to determine it (use Cookies Plugin?)\n\n try {\n langList[ `../../node_modules/quasar/lang/${ langIso }.js` ]().then(lang => {\n Lang.set(lang.default)\n })\n }\n catch (err) {\n console.error(err)\n // Requested Quasar Language Pack does not exist,\n // let's not break the app, so catching error\n }\n})\n\u003c\u003c| js With @quasar/app-webpack |>>\nimport { defineBoot } from '#q-app/wrappers'\nimport { Lang } from 'quasar'\n\nexport default defineBoot(async () => {\n const langIso = 'de' // ... some logic to determine it (use Cookies Plugin?)\n\n try {\n await import(\n /* webpackInclude: /(de|en-US)\\.js$/ */\n 'quasar/lang/' + langIso\n ).then(lang => {\n Lang.set(lang.default)\n })\n }\n catch (err) {\n console.error(err)\n // Requested Quasar Language Pack does not exist,\n // let's not break the app, so catching error\n }\n})\n```\n\nThen register this boot file into the `/quasar.config` file:\n\n```js\nboot: ['quasar-lang-pack']\n```\n\n::: warning Always constrain a dynamic import\nNotice the use of the Webpack magic comment - `webpackInclude`. Otherwise all the available language packs will be bundled, resulting in an increase in the compilation time and the bundle size. See [Caveat for dynamic imports](/quasar-cli-webpack/lazy-loading#caveat-for-dynamic-imports)\n:::\n\n### Dynamical (SSR)\n\nWhen dealing with SSR, we can't use singleton objects because that would pollute sessions. As a result, as opposed to the dynamical example above (read it first!), you must also specify the `ssrContext` from your boot file:\n\n```tabs\n\u003c\u003c| js With @quasar/app-vite |>>\nimport { defineBoot } from '#q-app/wrappers'\nimport { Lang } from 'quasar'\n\n// relative path to your node_modules/quasar/..\n// change to YOUR path\nconst langList = import.meta.glob('../../node_modules/quasar/lang/*.js')\n// or just a select few (example below with only DE and FR):\n// import.meta.glob('../../node_modules/quasar/lang/(de|fr).js')\n\n// ! NOTICE ssrContext param:\nexport default defineBoot(async ({ ssrContext }) => {\n const langIso = 'de' // ... some logic to determine it (use Cookies Plugin?)\n\n try {\n langList[ `../../node_modules/quasar/lang/${ langIso }.js` ]().then(lang => {\n Lang.set(lang.default, ssrContext)\n })\n }\n catch (err) {\n console.error(err)\n // Requested Quasar Language Pack does not exist,\n // let's not break the app, so catching error\n }\n})\n\u003c\u003c| js With @quasar/app-webpack |>>\nimport { defineBoot } from '#q-app/wrappers'\nimport { Lang } from 'quasar'\n\n// ! NOTICE ssrContext param:\nexport default defineBoot(async ({ ssrContext }) => {\n const langIso = 'de' // ... some logic to determine it (use Cookies Plugin?)\n\n try {\n await import(\n /* webpackInclude: /(de|en-US)\\.js$/ */\n 'quasar/lang/' + langIso\n ).then(lang => {\n Lang.set(lang.default, ssrContext)\n })\n }\n catch (err) {\n console.error(err)\n // Requested Quasar Language Pack does not exist,\n // let's not break the app, so catching error\n }\n})\n```\n\n## Change Quasar Language Pack at Runtime\n\n### Changing Language Pack\n\nExample with a QSelect to dynamically change the Quasar components language:\n\n```tabs\n\u003c\u003c| html With @quasar/app-vite |>>\n\u003ctemplate>\n \u003cq-select\n v-model=\"lang\"\n :options=\"langOptions\"\n label=\"Quasar Language\"\n dense\n borderless\n emit-value\n map-options\n options-dense\n style=\"min-width: 150px\"\n />\n \u003cdiv>{{ $q.lang.label.close }}\u003c/div>\n\u003c/template>\n\n\u003cscript>\nimport { useQuasar } from 'quasar'\nimport languages from 'quasar/lang/index.json'\nimport { ref, watch } from 'vue'\n\nconst modules = import.meta.glob('../../node_modules/quasar/lang/(de|en-US|es).js')\n\nconst appLanguages = languages.filter(lang =>\n ['de', 'en-US', 'es'].includes(lang.isoName)\n)\n\nconst langOptions = appLanguages.map(lang => ({\n label: lang.nativeName, value: lang.isoName\n}))\n\nexport default {\n setup () {\n const $q = useQuasar()\n const lang = ref($q.lang.isoName)\n\n watch(lang, val => {\n modules[`../../node_modules/quasar/lang/${val}.js`]().then(lang => {\n $q.lang.set(lang.default)\n })\n })\n\n return {\n lang,\n langOptions\n }\n }\n}\n\u003c/script>\n\u003c\u003c| html With @quasar/app-webpack |>>\n\u003ctemplate>\n \u003cq-select\n v-model=\"lang\"\n :options=\"langOptions\"\n label=\"Quasar Language\"\n dense\n borderless\n emit-value\n map-options\n options-dense\n style=\"min-width: 150px\"\n />\n\u003c/template>\n\n\u003cscript>\nimport { useQuasar } from 'quasar'\nimport languages from 'quasar/lang/index.json'\nimport { ref, watch } from 'vue'\n\nconst appLanguages = languages.filter(lang =>\n [ 'de', 'en-US' ].includes(lang.isoName)\n)\n\nconst langOptions = appLanguages.map(lang => ({\n label: lang.nativeName, value: lang.isoName\n}))\n\nexport default {\n setup () {\n const $q = useQuasar()\n const lang = ref($q.lang.isoName)\n\n watch(lang, val => {\n // dynamic import, so loading on demand only\n import(\n /* webpackInclude: /(de|en-US)\\.js$/ */\n 'quasar/lang/' + val\n ).then(lang => {\n $q.lang.set(lang.default)\n })\n })\n\n return {\n lang,\n langOptions\n }\n }\n}\n\u003c/script>\n```\n\n### Changing a Specific Label at Runtime\n\nIf you want to change a specific label to another, you can. Here is an example:\n\n```tabs\n\u003c\u003c| js Composition API |>>\nimport { useQuasar } from 'quasar'\n\nsetup () {\n const $q = useQuasar()\n\n function changeLabel () {\n $q.lang.table.noData = 'Hey... there is no data...'\n }\n\n return { changeLabel }\n}\n\u003c\u003c| js Options API |>>\nmethods: {\n changeLabel () {\n this.$q.lang.table.noData = 'Hey... there is no data...'\n }\n}\n```\n\nIf you want to do this outside of a .vue file (and you are NOT on SSR mode) then you can\n\n```js /src/boot/some-boot-file.js\nimport { defineBoot } from '#q-app/wrappers'\nimport { Lang } from 'quasar'\n\nexport default defineBoot(() {\n Lang.props.table.noData = 'Hey... there is no data...'\n})\n```\n\n## Using Quasar Language Pack in App Space\n\nAlthough the Quasar Language Packs **are designed only for Quasar components internal usage**, you can still use their labels for your own website/app components too.\n\n```\n\"Close\" label in current Quasar Language Pack is:\n{{ $q.lang.label.close }}\n```\n\nCheck a Quasar Language Pack on GitHub to see the structure of `$q.lang`.\n\n## Detecting Locale\n\nThere's also a method to determine user locale which is supplied by Quasar out of the box:\n\n```js\n// outside of a Vue file\nimport { Lang } from 'quasar'\nLang.getLocale() // returns a string\n\n// inside of a Vue file\nimport { useQuasar } from 'quasar'\n\nsetup () {\n const $q = useQuasar()\n $q.lang.getLocale() // returns a string\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9810,"content_sha256":"f5b53007bd00fc51dc9bbcddab49adb4c528d603404d00d33d4cfea0ad1dadc5"},{"filename":"references/docs/options/rtl-support.md","content":"---\ntitle: RTL Support\ndesc: Right to left support in a Quasar app.\nrelated:\n - /options/quasar-language-packs\n - /options/app-internationalization\n---\n\nRTL is referring to \"right to left\" UI for languages that need it.\n\n## Enabling RTL support\n\n### Quasar CLI with Vite\n\n- Edit `/postcss.config.js` file and uncomment the `import rtlcss from 'postcss-rtlcss'` line.\n- Yarn/npm/pnpm/bun install the `postcss-rtlcss` package.\n- If you are already running \"quasar dev\" command, restart it.\n\n```js [highlight=2,25] /postcss.config.js\nimport autoprefixer from 'autoprefixer'\nimport rtlcss from 'postcss-rtlcss'\n\nexport default {\n plugins: [\n // https://github.com/postcss/autoprefixer\n autoprefixer({\n overrideBrowserslist: [\n 'last 4 Chrome versions',\n 'last 4 Firefox versions',\n 'last 4 Edge versions',\n 'last 4 Safari versions',\n 'last 4 Android versions',\n 'last 4 ChromeAndroid versions',\n 'last 4 FirefoxAndroid versions',\n 'last 4 iOS versions'\n ]\n }),\n\n // https://github.com/elchininet/postcss-rtlcss\n // If you want to support RTL css, then\n // 1. yarn/pnpm/bun/npm install postcss-rtlcss\n // 2. optionally set quasar.config.js > framework > lang to an RTL language\n // 3. uncomment the following line (and its import statement above):\n rtlcss()\n ]\n}\n```\n\n### Quasar CLI with Webpack\n\nTo enable it, you need to edit the `/quasar.config` file:\n\n```js\nbuild: {\n rtl: true\n}\n```\n\n### Vite Plugin\n\nYou first need to install `postcss-rtlcss` package:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add --dev postcss-rtlcss\n\u003c\u003c| bash NPM |>>\n$ npm install --save-dev postcss-rtlcss\n\u003c\u003c| bash PNPM |>>\n$ pnpm add -D postcss-rtlcss\n\u003c\u003c| bash Bun |>>\n$ bun add --dev postcss-rtlcss\n```\n\nThen create `/postcss.config.js` file if you don't have it already, and add this to it:\n\n```js\nimport rtlcss from 'postcss-rtlcss'\n\nexport default {\n plugins: [\n rtlcss({\n /* opts */\n }) // \u003c\u003c\u003c\u003c in \"plugins\"\n ]\n}\n```\n\n### Quasar UMD\n\nTo enable RTL UIs in UMD you need to include the RTL equivalent CSS tag for your Quasar version and also pack in a Quasar RTL language pack (like Hebrew or Farsi). Example:\n\n```html\n\u003chtml>\n \u003chead>\n ...\n \u003c!-- Replace \"2.0.0\" (below) with your Quasar version. -->\n \u003clink\n href=\"https://cdn.jsdelivr.net/npm/quasar@2/dist/quasar.rtl.prod.css\"\n rel=\"stylesheet\"\n type=\"text/css\"\n />\n \u003c/head>\n\n \u003cbody>\n ...\n\n \u003c!--\n We also need an RTL Quasar language pack; let's take Hebrew as an example;\n include this after Quasar JS tag;\n Replace \"2.0.0\" (below) with your Quasar version.\n -->\n \u003cscript src=\"https://cdn.jsdelivr.net/npm/quasar@2/dist/lang/he.umd.prod.js\">\u003c/script>\n \u003cscript>\n Quasar.Lang.set(Quasar.Lang.he)\n \u003c/script>\n \u003c/body>\n\u003c/html>\n```\n\nCheck what tags you need to include in your HTML files by using our [UMD tag generator](/start/umd) and making sure that you tick the \"RTL CSS support\" checkbox.\nAlso notice the `\u003chtml dir=\"rtl\">` tag at the beginning of the generated html file -- you'll need that too.\n\n::: warning CAVEAT\nQuasar CLI automatically adds equivalent RTL CSS rules for your website/app code, but this is not the case for UMD where Quasar CLI is not being used. You'll have to manage writing the RTL equivalent of your website/app CSS code by yourself. It's only Quasar components that will have this handled automatically.\n:::\n\n## How it works\n\nRTL is tightly coupled to [Quasar Language Packs](/options/quasar-language-packs). **When Quasar is set to use an RTL language** (language pack has \"rtl\" prop set to \"true\") and **RTL support is enabled** (check the \"Enabling RTL support\" section above), then the UI will dynamically transform Quasar & your website/app code for RTL.\n\nLet's discuss about each of these requirements:\n\n1. _Quasar needs to be set to use an RTL language_.\n See [Quasar Language Packs](/options/quasar-language-packs) on how you can set a language. You can set a language as default or dynamically set one.\n\n2. _RTL support needs to be enabled_.\n Please double-check the \"Enabling RTL support\" section above. What this does is it compiles CSS for both your website/app code and for Quasar components and add corresponding RTL CSS rules automatically. Your CSS bundle will slightly increase in size due to the addition of these CSS rules.\n\n3. Optional: _Treat devland source CSS as RTL_.\n By default, Quasar assumes that all styles are written in LTR direction and generates corresponding RTL styles for them. Should you wish to write your own css directly in RTL then you need to:\n - (Quasar CLI with Webpack) set quasar.config file > \"build\" > rtl > \"source\" to `rtl`\n - (Quasar CLI with Vite / Quasar Vite plugin) set `postcssRtlCss({ source: 'rtl' })` in /postcss.config.js\n\n::: tip\nFull list of postcss-rtlcss options.\n:::\n\n## Things to keep in mind\n\n- Both RTL and non-RTL Quasar language packs will work together and dynamically switch to/from RTL. So only choosing an RTL Quasar language pack will trigger the RTL UI for you. You don't need separate builds of your app (one for non-RTL and one for RTL-only). The RTL is dynamically changed for you automatically.\n- You can dynamically detect if you are on RTL mode by taking a look at Boolean `$q.lang.rtl`. More info on [The $q object](/options/the-q-object).\n- You need to be careful when writing your own CSS. Like mentioned above, if RTL support is enabled then RTL (LTR if postcss-rtl config has \"source\" set to \"ltr\") rules will be automatically added based on your CSS code. So writing:\n\n ```css\n .my-class {\n margin-left: 10px;\n right: 5px;\n }\n ```\n\n ...will add this rule for RTL:\n\n ```css\n [dir='rtl'] .my-class {\n margin-right: 10px;\n left: 5px;\n }\n ```\n\n Any CSS rule that refers to \"left\" or \"right\" is automatically triggering an equivalent RTL CSS rule to be added.\n\n### Marking CSS rules as exceptions\n\nIf you need an exception so your CSS code will not add a corresponding RTL rule, then add this comment:\n\n```css\n.my-class {\n margin-left: 10px /* rtl:ignore */;\n}\n```\n\n...or SCSS with indented form:\n\n```sass\n.my-class\n margin-left: 10px #{\"/* rtl:ignore */\"}\n```\n\n...or default SCSS:\n\n```sass\n.my-class {\n margin-left: 10px #{\"/* rtl:ignore */\"};\n}\n```\n\nNow both RTL and non-RTL UI mode will have `margin-left` prop.\n\nSometimes you'll need to make exceptions for whole DOM elements / components. In this case, add `dir=\"ltr\"` or `dir=\"rtl\"` HTML attribute to the outermost DOM element / component template:\n\n```html\n\u003cdiv dir=\"rtl\">\n \u003c!--\n this DIV and all its content will use RTL mode\n regardless of Quasar language pack RTL settings\n -->\n\u003c/div>\n```\n\nOr, if you need your RTL UI to use left-to-right (ltr) mode for a DOM element / component:\n\n```html\n\u003cdiv dir=\"ltr\">\n \u003c!--\n this DIV and all its content will use non-RTL mode\n regardless of Quasar language pack RTL settings\n -->\n\u003c/div>\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":6945,"content_sha256":"81176161871098f2f0dcbcb2d8bf2cc21324ef45755fc2e8a409f2f819ead4f4"},{"filename":"references/docs/options/screen-plugin.md","content":"---\ntitle: Screen Plugin\ndesc: Quasar plugin that helps in writing a dynamic and responsive UI through Javascript code.\n---\n\nThe Quasar Screen plugin allows you to have a dynamic and responsive UI when dealing with your Javascript code. When possible, it is recommended to use the [responsive CSS classes](/style/visibility#window-width-related) instead, for performance reasons.\n\n\u003cDocApi file=\"Screen\" />\n\n## Usage\n\nNotice `$q.screen` below. This is just a simple usage example.\n\n```html\n\u003cq-list :dense=\"$q.screen.lt.md\">\n \u003cq-item>\n \u003cq-item-section>John Doe\u003c/q-item-section>\n \u003c/q-item>\n\n \u003cq-item>\n \u003cq-item-section>Jane Doe\u003c/q-item-section>\n \u003c/q-item>\n\u003c/q-list>\n```\n\n```js\n// script part of a Vue component\nimport { useQuasar } from 'quasar'\nimport { computed } from 'vue'\n\nexport default {\n setup() {\n const $q = useQuasar()\n const buttonColor = computed(() => {\n return $q.screen.lt.md ? 'primary' : 'secondary'\n })\n\n return { buttonColor }\n }\n}\n```\n\nWe can also use the Screen plugin outside of a Vue component:\n\n```js\nimport { Screen } from 'quasar'\n\n// Screen.gt.md\n// Screen.md\n// Screen.name ('xs', 'sm', ...)\n```\n\n## Body classes\n\n**If you enable it (see how to do it after the examples below)**, you can also style your content based on a particular set of CSS classes applied to document.body: `screen--xs`, `screen--sm`, ..., `screen-xl`.\n\n```css\nbody.screen--xs {\n .my-div {\n color: #000;\n }\n}\n\nbody.screen--sm {\n .my-div {\n color: #fff;\n }\n}\n```\n\nOr a sexy variant in Sass:\n\n```sass\n.my-div\n body.screen--xs &\n color: #000\n body.screen--sm &\n color: #fff\n```\n\n### How to enable body classes\n\nIn order to enable the behavior above, edit your /quasar.config file like below. Please note that this will increase a bit the time for First Meaningful Paint.\n\n```js /quasar.config file\nframework: {\n config: {\n screen: {\n bodyClasses: true // \u003c\u003c\u003c add this\n }\n }\n}\n```\n\n## Configuration\n\nThere are a few methods that can be used to tweak how Screen plugin works:\n\n| Method | Description | Example |\n| ------------------- | ----------------------------------------------------------------- | -------------------------------- |\n| setSizes(Object) | Change window breakpoints; does NOT also changes CSS breakpoints. | setSizes({ lg: 1024, xl: 2000 }) |\n| setDebounce(Number) | Change the default 100ms debounce to some other value. | setDebounce(500) // 500ms |\n\nExamples:\n\n```js Inside a Vue component\nimport { useQuasar } from 'quasar'\n\nsetup () {\n const $q = useQuasar()\n\n $q.screen.setSizes({ sm: 300, md: 500, lg: 1000, xl: 2000 })\n}\n```\n\n```js Outside of a Vue component\nimport { Screen } from 'quasar'\nScreen.setSizes({ sm: 300, md: 500, lg: 1000, xl: 2000 })\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2848,"content_sha256":"f6f38640d4e7145ad86886f58ff9249e7320311a594f439c902a6d4751f89272"},{"filename":"references/docs/options/seo.md","content":"---\ntitle: SEO with Quasar\ndesc: Managing the search engine optimizations in a Quasar app.\n---\n\nThe term SEO refers to Search Engine Optimization. And Quasar covers this aspect too through the [Quasar Meta Plugin](/quasar-plugins/meta).\n\n## Quasar Meta Plugin\n\nThe [Quasar Meta Plugin](/quasar-plugins/meta) can dynamically change page title, manage `\u003cmeta>` tags, manage `\u003chtml>` and `\u003cbody>` DOM element attributes, add/remove/change `\u003cstyle>` and `\u003cscript>` tags in the head of your document (useful for CDN stylesheets or for json-ld markup, for example), or manage `\u003cnoscript>` tags.\n\nTake full advantage of this feature by using it with **Quasar CLI**, especially **for the SSR (Server-Side Rendering) builds**. Note that for a SPA (Single Page Applications) the meta tags are added at runtime and not supplied directly by the webserver (as with SSR builds).\n\n::: tip\nThis Quasar plugin has the most tight integration with Quasar and so it has the best performance against any other similar solution.\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1011,"content_sha256":"f4f924dfbb4caa14989caca8384c3c651820232cec45cae78bb14d265e20d462"},{"filename":"references/docs/options/the-q-object.md","content":"---\ntitle: The $q object\ndesc: The $q object in Quasar. Why and how to use it.\nrelated:\n - /vue-composables/use-quasar\n---\n\nQuasar supplies a `$q` object that you can use for various purposes. You will notice it throughout the docs.\n\n| Prop name | Type | Description |\n| -------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `$q.version` | String | Quasar version. |\n| `$q.platform` | Object | Same object as [Platform](/options/platform-detection) import from Quasar. |\n| `$q.screen` | Object | Object supplied by [Screen Plugin](/options/screen-plugin). |\n| `$q.lang` | Object | Quasar Language pack management, containing labels etc (one of lang files). Designed for Quasar components, but you can use it in your app components too. More info: [Quasar Language Packs](/options/quasar-language-packs). |\n| `$q.iconSet` | Object | Quasar icon set management (one of icon set files). Designed for Quasar components, but you can use it in your app components too. More info: [Quasar Icon Sets](/options/quasar-icon-sets). |\n| `$q.cordova` | Object | Reference to Cordova global object. Available only when running under a Cordova app. |\n| `$q.capacitor` | Object | Reference to Capacitor global object. Available only when running under a Capacitor app. |\n\n## Usage\n\nThe following sections will teach you how to use it in .vue files (with both Composition API and Options API) and outside of them.\n\n### Composition API with \"script setup\"\n\nThe following is a .vue file:\n\n```html\n\u003ctemplate>\n \u003cdiv>\n \u003cdiv v-if=\"$q.platform.is.ios\"> Gets rendered only on iOS platform. \u003c/div>\n \u003c/div>\n\u003c/template>\n\n\u003cscript setup>\n import { useQuasar } from 'quasar'\n\n const $q = useQuasar()\n\n console.log($q.platform.is.ios)\n\n // showing an example on a method, but\n // can be any part of Vue script\n function show() {\n // prints out Quasar version\n console.log($q.version)\n }\n\u003c/script>\n```\n\n### Composition API without \"script setup\"\n\nThe following is a .vue file:\n\n```html\n\u003ctemplate>\n \u003cdiv>\n \u003cdiv v-if=\"$q.platform.is.ios\"> Gets rendered only on iOS platform. \u003c/div>\n \u003c/div>\n\u003c/template>\n\n\u003cscript>\n import { useQuasar } from 'quasar'\n\n export default {\n setup() {\n const $q = useQuasar()\n\n console.log($q.platform.is.ios)\n\n // showing an example on a method, but\n // can be any part of Vue script\n function show() {\n // prints out Quasar version\n console.log($q.version)\n }\n\n return {\n show\n }\n }\n }\n\u003c/script>\n```\n\n### Options API\n\nThe following is a .vue file:\n\n```html\n\u003ctemplate>\n \u003cdiv>\n \u003cdiv v-if=\"$q.platform.is.ios\"> Gets rendered only on iOS platform. \u003c/div>\n \u003c/div>\n\u003c/template>\n\n\u003cscript>\n // not available here outside\n // of the export\n\n export default {\n // inside a Vue component script\n ...,\n\n // showing an example on a method, but\n // can be any part of Vue script\n methods: {\n show () {\n // prints out Quasar version\n console.log(this.$q.version)\n }\n }\n }\n\u003c/script>\n```\n\n### Outside of a .vue file\n\n```js\nimport { Quasar, Platform } from 'quasar'\n\nconsole.log(Quasar.version)\nconsole.log(Platform.is.ios)\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4833,"content_sha256":"d7c4657350f16b75d9c3ac2a4984f84e76ae5567a7706fdf5a20ce67fbb91a6b"},{"filename":"references/docs/options/transitions/transitions.md","content":"---\ntitle: Quasar Components Transitions\ndesc: Out of the box CSS transitions for Quasar components.\n---\n\nThere are a few Quasar components that implement transitions through `transition-show` / `transition-hide` or `transition-prev` / `transition-next` or simply `transition` props:\n\n- `transition-show` / `transition-hide`\n - [QBtnDropdown](/vue-components/button-dropdown)\n - [QInnerLoading](/vue-components/inner-loading)\n - [QTooltip](/vue-components/tooltip)\n - [QMenu](/vue-components/menu)\n - [QDialog](/vue-components/dialog)\n - [QSelect](/vue-components/select) (through QMenu and QDialog)\n - [QPopupProxy](/vue-components/popup-proxy) (through QMenu and QDialog)\n\n- `transition-prev` / `transition-next`\n - [QCarousel](/vue-components/carousel)\n - [QTabPanels](/vue-components/tab-panels)\n - [QStepper](/vue-components/stepper)\n\n- `transition`\n - [QIntersection](/vue-components/intersection)\n\nWe're going to showcase these transitions here.\n\n\n\n\u003cTransitionList />\n\nUse the names indicated in the captions above for the transition props. Example:\n\n```html\n\u003cq-menu transition-show=\"jump-down\" transition-hide=\"jump-up\" />\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1146,"content_sha256":"cf8ff1a74e899879d48ad42e22ae0b328d19f4bb0d62b5755bdda7612d8bf963"},{"filename":"references/docs/quasar-cli-vite/ajax-requests.md","content":"---\ntitle: Ajax Requests\ndesc: (@quasar/app-vite) Using Axios for fetching data in a Quasar app.\n---\n\n> We recommend selecting Axios during project initialization.\n\nIf you haven't selected Axios during the project initialization then you should create a new boot file `axios.js` that looks like this:\n(Here you can also specify additional settings for your axios instance)\n\n```js /src/boot/axios.js\nimport { defineBoot } from '#q-app/wrappers'\nimport axios from 'axios'\n\nconst api = axios.create({ baseURL: 'https://api.example.com' })\n\nexport default defineBoot(({ app }) => {\n // for use inside Vue files (Options API) through this.$axios and this.$api\n\n app.config.globalProperties.$axios = axios\n // ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form)\n // so you won't necessarily have to import axios in each vue file\n\n app.config.globalProperties.$api = api\n // ^ ^ ^ this will allow you to use this.$api (for Vue Options API form)\n // so you can easily perform requests against your app's API\n})\n\nexport { axios, api }\n```\n\nAlso make sure to yarn/npm install the `axios` package.\n\n::: tip\nBe sure to check out [Prefetch Feature](/quasar-cli-vite/prefetch-feature) if you are using Quasar CLI.\n:::\n\nUsage in your single file components methods will be like below. Notice that in the next example we're using the Quasar's [Notify plugin](/quasar-plugins/notify) (through `$q = useQuasar()` and `$q.notify`) which you'll need to install (follow the link earlier).\n\n```js\nimport { ref } from 'vue'\nimport { api } from 'boot/axios'\nimport { useQuasar } from 'quasar'\n\nsetup () {\n const $q = useQuasar()\n const data = ref(null)\n\n function loadData () {\n api.get('/api/backend')\n .then((response) => {\n data.value = response.data\n })\n .catch(() => {\n $q.notify({\n color: 'negative',\n position: 'top',\n message: 'Loading failed',\n icon: 'report_problem'\n })\n })\n }\n\n return { data, loadData }\n}\n```\n\nUsage in Pinia Actions for globally adding headers to axios (such as during authentication):\n\n```js\nimport { api } from 'boot/axios'\n\nexport const useAuthStore = defineStore('auth', {\n actions: {\n register (form) {\n return api.post('/auth/register', form)\n .then(response => {\n api.defaults.headers.common['Authorization'] = 'Bearer ' + response.data.token\n // do something with { token: response.data.token, user: response.data.user }\n })\n }\n})\n```\n\nAlso look at Axios docs for more information.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2562,"content_sha256":"5b7a38f8f898aa3b28519aad0d6a3fd7bc7bb31f122af9c11f3e86199cc2af5d"},{"filename":"references/docs/quasar-cli-vite/api-proxying.md","content":"---\ntitle: API Proxying for Dev\ndesc: (@quasar/app-vite) How to use an API proxy with the Quasar dev server.\nrelated:\n - /quasar-cli-vite/quasar-config-file\n---\n\nWhen integrating a project folder (created by Quasar CLI) with an existing backend, a common need is to access the backend API when using the dev server. To achieve this, we can run the dev server and the API backend side-by-side (or remotely), and let the dev server proxy all API requests to the actual backend.\n\nThis is useful if you access relative paths in your API requests. Obviously, these relative paths will probably not work while you are developing. In order to create an environment similar to the one used by your deployed website/app, you can proxy your API requests.\n\nTo configure the proxy rules, edit the `/quasar.config` file in `devServer.proxy`. Under the hood, it uses `http-proxy`. Full list of its options here.\n\n```js /quasar.config file\ndevServer: {\n proxy: {\n // string shorthand: http://localhost:5173/foo -> http://localhost:4567/foo\n '/foo': 'http://localhost:4567',\n // with options: http://localhost:5173/api/bar-> http://jsonplaceholder.typicode.com/bar\n '/api': {\n target: 'http://jsonplaceholder.typicode.com',\n changeOrigin: true,\n rewrite: (path) => path.replace(/^\\/api/, ''),\n },\n // with RegExp: http://localhost:5173/fallback/ -> http://jsonplaceholder.typicode.com/\n '^/fallback/.*': {\n target: 'http://jsonplaceholder.typicode.com',\n changeOrigin: true,\n rewrite: (path) => path.replace(/^\\/fallback/, ''),\n },\n // Using the proxy instance\n '/api': {\n target: 'http://jsonplaceholder.typicode.com',\n changeOrigin: true,\n configure: (proxy, options) => {\n // proxy will be an instance of 'http-proxy'\n },\n },\n // Proxying websockets or socket.io: ws://localhost:5173/socket.io -> ws://localhost:5174/socket.io\n // Exercise caution using `rewriteWsOrigin` as it can leave the proxying open to CSRF attacks.\n '/socket.io': {\n target: 'ws://localhost:5174',\n ws: true,\n rewriteWsOrigin: true,\n },\n },\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2128,"content_sha256":"b9d0f1d791b2e916f30fb11d5b08743498269223bdf821764ef352b53b503f01"},{"filename":"references/docs/quasar-cli-vite/boot-files.md","content":"---\ntitle: Boot files\ndesc: (@quasar/app-vite) Managing your startup code in a Quasar app.\nrelated:\n - /quasar-cli-vite/quasar-config-file\n---\n\nA common use case for Quasar applications is to **run code before the root Vue app instance is instantiated**, like injecting and initializing your own dependencies (examples: Vue components, libraries...) or simply configuring some startup code of your app.\n\nSince you won't have access to any `/main.js` file (so that Quasar CLI can seamlessly initialize and build same codebase for SPA/PWA/SSR/Cordova/Electron) Quasar provides an elegant solution to that problem by allowing users to define so-called boot files.\n\nIn earlier Quasar versions, to run code before the root Vue instance was instantiated, you could alter the `/src/main.js` file and add any code you needed to execute.\n\nThere is a major problem with this approach: with a growing project, your `main.js` file was very likely to get cluttered and challenging to maintain, which breaks with Quasar's concept of encouraging developers to write maintainable and elegant cross-platform applications.\n\nWith boot files, it is possible to split each of your dependencies into self-contained, easy to maintain files. It is also trivial to disable any of the boot files or even contextually determine which of the boot files get into the build through the `quasar.config` file configuration.\n\n## Anatomy of a boot file\n\nA boot file is a simple JavaScript file which can optionally export a function. Quasar will then call the exported function when it boots the application and additionally pass **an object** with the following properties to the function:\n\n| Prop name | Description |\n| ------------ | ----------------------------------------------------------------------------------------------------------------- |\n| `app` | Vue app instance |\n| `router` | Instance of Vue Router from 'src/router/index.js' |\n| `store` | Instance of Pinia - **store only will be passed if your project uses Pinia (you have src/stores)** |\n| `ssrContext` | Available only on server-side, if building for SSR. [More info](/quasar-cli-vite/developing-ssr/ssr-context) |\n| `urlPath` | The pathname (path + search) part of the URL. It also contains the hash on client-side. |\n| `publicPath` | The configured public path. |\n| `redirect` | Function to call to redirect to another URL. Accepts String (full URL) or a Vue Router location String or Object. |\n\n```js\nimport { defineBoot } from '#q-app/wrappers'\nexport default defineBoot(({ app, router, store }) => {\n // something to do\n})\n```\n\nBoot files can also be async:\n\n```js\nimport { defineBoot } from '#q-app/wrappers'\nexport default defineBoot(async ({ app, router, store }) => {\n // something to do\n await something()\n})\n```\n\nNotice the `defineBoot` import. This is essentially a no-op function, but its purpose is to help with a better IDE autocomplete experience:\n\n```js\nimport { defineBoot } from '#q-app/wrappers'\n\nexport default defineBoot(async ({ app, router, store }) => {\n // something to do\n await something()\n})\n```\n\nNotice we are using the ES6 destructuring assignment. Only assign what you actually need/use.\n\nYou may ask yourself why we need to export a function. This is actually optional, but before you decide to remove the default export, you need to understand when you need it:\n\n```js\n// Outside of default export:\n// - Code here gets executed immediately,\n// - Good place for import statements,\n// - No access to router, Pinia instance, ...\n\nexport default defineBoot(async ({ app, router, store }) => {\n // Code here has access to the Object param above, connecting\n // with other parts of your app;\n // Code here can be async (use async/await or directly return a Promise);\n // Code here gets executed by Quasar CLI at the correct time in app's lifecycle:\n // - we have a Router instantiated,\n // - we have the optional Pinia instance,\n // - we have the root app's component [\"app\" prop in Object param] Object with\n // which Quasar will instantiate the Vue app\n // (\"new Vue(app)\" -- do NOT call this by yourself),\n // - ...\n})\n```\n\n## When to use boot files\n\n::: warning\nPlease make sure you understand what problem boot files solve and when it is appropriate to use them, to avoid applying them in cases where they are not needed.\n:::\n\nBoot files fulfill one special purpose: they run code **before** the App's Vue root component is instantiated while giving you access to certain variables, which is required if you need to initialize a library, interfere with Vue Router, inject Vue prototype or inject the root instance of the Vue app.\n\n### Examples of appropriate usage of boot files\n\n- Your Vue plugin has installation instructions, like needing to call `app.use()` on it.\n- Your Vue plugin requires instantiation of data that is added to the root instance - An example would be vue-i18n.\n- You want to add a global mixin using `app.mixin()`.\n- You want to add something to the Vue app globalProperties for convenient access - An example would be to conveniently use `this.$axios` (for Options API) inside your Vue files instead of importing Axios in each such file.\n- You want to interfere with the router - An example would be to use `router.beforeEach` for authentication\n- You want to interfere with Pinia\n- Configure aspects of libraries - An example would be to create an instance of Axios with a base URL; you can then inject it into Vue prototype and/or export it (so you can import the instance from anywhere else in your app)\n\n### Example of unneeded usage of boot files\n\n- For plain JavaScript libraries like Lodash, which don't need any initialization prior to their usage. Lodash, for example, might make sense to use as a boot file only if you want to inject Vue prototype with it, like being able to use `this.$_` inside your Vue files.\n\n## Usage of boot files\n\nThe first step is always to generate a new boot file using Quasar CLI:\n\n```bash\n$ quasar new boot \u003cname> [--format ts]\n```\n\nWhere `\u003cname>` should be exchanged by a suitable name for your boot file.\n\nThis command creates a new file: `/src/boot/\u003cname>.js` with the following content:\n\n```js\n// import something here\n\n// \"async\" is optional!\n// remove it if you don't need it\nexport default async defineBoot(({ /* app, router, store */ }) => {\n // something to do\n})\n```\n\nYou can also return a Promise:\n\n```js\n// import something here\n\nexport default defineBoot(\n (\n {\n /* app, router, store */\n }\n ) => {\n return new Promise((resolve, reject) => {\n // do something\n })\n }\n)\n```\n\n::: tip\nThe default export can be left out of the boot file if you don't need it. These are the cases where you don't need to access the \"app\", \"router\", \"store\" and so on.\n:::\n\nYou can now add content to that file depending on the intended use of your boot file.\n\n> Do not forget that your default export needs to be a function.\n> However, you can have as many named exports as you want, should the boot file expose something for later usage. In this case, you can import any of these named exports anywhere in your app.\n\nThe last step is to tell Quasar to use your new boot file. For this to happen you need to add the file in the `/quasar.config` one:\n\n```js\nboot: [\n // references /src/boot/\u003cname>.js\n '\u003cname>'\n]\n```\n\nWhen building a SSR app, you may want some boot files to run only on the server or only on the client, in which case you can do so like below:\n\n```js\nboot: [\n {\n server: false, // run on client-side only!\n path: '\u003cname>' // references /src/boot/\u003cname>.js\n },\n {\n client: false, // run on server-side only!\n path: '\u003cname>' // references /src/boot/\u003cname>.js\n }\n]\n```\n\nIn case you want to specify boot files from node_modules, you can do so by prepending the path with `~` (tilde) character:\n\n```js\nboot: [\n // boot file from an npm package\n '~my-npm-package/some/file'\n]\n```\n\nIf you want a boot file to be injected into your app only for a specific build type:\n\n```js\nboot: [ctx.mode.electron ? 'some-file' : '']\n```\n\n### Redirecting to another page\n\n::: warning\nPlease be mindful when redirecting as you might configure the app to go into an infinite redirect loop.\n:::\n\n```js\nexport default defineBoot(({ urlPath, redirect }) => {\n // ...\n const isAuthorized = // ...\n if (!isAuthorized && !urlPath.startsWith('/login')) {\n redirect({ path: '/login' })\n return\n }\n // ...\n})\n```\n\nThe `redirect()` method accepts a String (full URL) or a Vue Router location String or Object. On SSR it can receive a second parameter which should be a Number for any of the HTTP STATUS codes that redirect the browser (3xx ones).\n\n```js\n// Examples for redirect() with a Vue Router location:\nredirect('/1') // Vue Router location as String\nredirect({ path: '/1' }) // Vue Router location as Object\n\n// Example for redirect() with a URL:\nredirect('https://quasar.dev')\n```\n\n::: warning IMPORTANT!\nThe Vue Router location (in String or Object form) does not refer to URL path (and hash), but to the actual Vue Router routes that you have defined.\nSo **don't add the publicPath** to it and if you're using the Vue Router hash mode then don't add the hash to it.\n\n\u003cbr>Let's say that we have this Vue Router route defined:\u003cbr>\u003cbr>\n\n```js\n{\n path: '/one',\n component: PageOne\n}\n```\n\n\u003cbr>Then **regardless of our publicPath** we can call `redirect()` like this:\u003cbr>\u003cbr>\n\n```js\n// publicPath: /wiki; vueRouterMode: history\nredirect('/one') // good way\nredirect({ path: '/one' }) // good way\nredirect('/wiki/one') // WRONG!\n\n// publicPath: /wiki; vueRouterMode: hash\nredirect('/one') // good way\nredirect({ path: '/one' }) // good way\nredirect('/wiki/#/one') // WRONG!\n\n// no publicPath; vueRouterMode: hash\nredirect('/one') // good way\nredirect({ path: '/one' }) // good way\nredirect('/#/one') // WRONG!\n```\n\n:::\n\nAs it was mentioned in the previous sections, the default export of a boot file can return a Promise. If this Promise gets rejected with an Object that contains a \"url\" property, then Quasar CLI will redirect the user to that URL:\n\n```js\nexport default defineBoot(({ urlPath }) => {\n return new Promise((resolve, reject) => {\n // ...\n const isAuthorized = // ...\n if (!isAuthorized && !urlPath.startsWith('/login')) {\n // the \"url\" param here is of the same type\n // as for \"redirect\" above\n reject({ url: '/login' })\n return\n }\n // ...\n })\n})\n```\n\nOr a simpler equivalent:\n\n```js\nexport default defineBoot(() => {\n // ...\n const isAuthorized = // ...\n if (!isAuthorized && !urlPath.startsWith('/login')) {\n return Promise.reject({ url: '/login' })\n }\n // ...\n})\n```\n\n### Quasar App Flow\n\nIn order to better understand how a boot file works and what it does, you need to understand how your website/app boots:\n\n1. Quasar is initialized (components, directives, plugins, Quasar i18n, Quasar icon sets)\n2. Quasar Extras get imported (Roboto font -- if used, icons, animations, ...)\n3. Quasar CSS & your app's global CSS are imported\n4. App.vue is loaded (not yet being used)\n5. Pinia (if using) is injected into the Vue app instance\n6. Router is imported (in src/router)\n7. Boot files are imported\n8. Router default export function executed\n9. Boot files get their default export function executed\n10. (if on Electron mode) Electron is imported and injected into Vue prototype\n11. (if on Cordova mode) Listening for \"deviceready\" event and only then continuing with following steps\n12. Instantiating Vue with root component and attaching to DOM\n\n## Examples of boot files\n\n### Axios\n\n```js\nimport { defineBoot } from '#q-app/wrappers'\nimport axios from 'axios'\n\nconst api = axios.create({ baseURL: 'https://api.example.com' })\n\nexport default defineBoot(({ app }) => {\n // for use inside Vue files (Options API) through this.$axios and this.$api\n\n app.config.globalProperties.$axios = axios\n // ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form)\n // so you won't necessarily have to import axios in each vue file\n\n app.config.globalProperties.$api = api\n // ^ ^ ^ this will allow you to use this.$api (for Vue Options API form)\n // so you can easily perform requests against your app's API\n})\n\nexport { axios, api }\n```\n\n### vue-i18n\n\n```js\nimport { defineBoot } from '#q-app/wrappers'\nimport { createI18n } from 'vue-i18n'\nimport messages from 'src/i18n'\n\nexport default defineBoot(({ app }) => {\n // Create I18n instance\n const i18n = createI18n({\n locale: 'en-US',\n messages\n })\n\n // Tell app to use the I18n instance\n app.use(i18n)\n})\n```\n\n### Router authentication\n\nSome boot files might need to interfere with Vue Router configuration:\n\n```js\nimport { defineBoot } from '#q-app/wrappers'\n\nexport default defineBoot(({ router, store }) => {\n router.beforeEach((to, from, next) => {\n // Now you need to add your authentication logic here, like calling an API endpoint\n })\n})\n```\n\n## Accessing data from boot files\n\nSometimes you want to access data that you configure in your boot file in files where you don't have access to the root Vue instance.\n\nFortunately, because boot files are just normal JavaScript files you can add as many named exports to your boot file as you want.\n\nLet's take the example of Axios. Sometimes you want to access your Axios instance inside your JavaScript files, but you cannot access the root Vue instance. To solve this you can export the Axios instance in your boot file and import it elsewhere.\n\nConsider the following boot file for axios:\n\n```js axios boot file (src/boot/axios.js)\nimport { defineBoot } from '#q-app/wrapper'\nimport axios from 'axios'\n\n// We create our own axios instance and set a custom base URL.\n// Note that if we wouldn't set any config here we do not need\n// a named export, as we could just `import axios from 'axios'`\nconst api = axios.create({\n baseURL: 'https://api.example.com'\n})\n\n// for use inside Vue files through this.$axios and this.$api\n// (only in Vue Options API form)\nexport default defineBoot(({ app }) => {\n app.config.globalProperties.$axios = axios\n app.config.globalProperties.$api = api\n})\n\n// Here we define a named export\n// that we can later use inside .js files:\nexport { axios, api }\n```\n\nIn any JavaScript file, you'll be able to import the axios instance like this.\n\n```js\n// we import one of the named exports from src/boot/axios.js\nimport { api } from 'boot/axios'\n```\n\nFurther reading on syntax: ES6 import, ES6 export.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":14858,"content_sha256":"19a44a6f680d44295e2553d1a66b11516e14f5c08b86c4fd6dbd39346c5f88e2"},{"filename":"references/docs/quasar-cli-vite/browser-compatibility.md","content":"---\ntitle: Browser compatibility\ndesc: (@quasar/app-vite) How to handle the browser support with Quasar CLI.\nrelated:\n - /quasar-cli-vite/quasar-config-file\n---\n\nIn order to configure the browser compatibility for your app, you will need to edit the `/quasar.config` file:\n\n```js /quasar.config file\nbuild: {\n target: {\n browser: 'baseline-widely-available',\n node: 'node22'\n }\n}\n```\n\nBased on the Quasar Mode that you will be using (SPA/SSR/PWA/Electron/... etc) you will have client-side files (that run in the browser) and possibly Node.js running files. This is what the two keys of `target` Object above are for.\n\nAlso, independent of this configuration, you need to decide if you want the module preload polyfill since all the script tags will be injected as modules. By default, the polyfill is NOT included:\n\n```js /quasar.config file\nbuild: {\n polyfillModulePreload: false\n}\n```\n\nFurthermore, based on your `/postcss.config.js` file content, your CSS will also pass through `autoprefixer` for which you can configure the browser levels that you are interested in:\n\n```js /postcss.config.js\nautoprefixer({\n overrideBrowserslist: [\n 'last 4 Chrome versions',\n 'last 4 Firefox versions',\n 'last 4 Edge versions',\n 'last 4 Safari versions',\n 'last 4 Android versions',\n 'last 4 ChromeAndroid versions',\n 'last 4 FirefoxAndroid versions',\n 'last 4 iOS versions'\n ]\n})\n```\n\nMore info on how to specify `autoprefixer` browser ranges: browserslist.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1486,"content_sha256":"017425999643c70cc40a05276bf03655d72b956814dfddf5de06412b69f09305"},{"filename":"references/docs/quasar-cli-vite/commands-list.md","content":"---\ntitle: Commands List\ndesc: (@quasar/app-vite) The entire list of Quasar CLI commands.\n---\n\nFamiliarize yourself with the list of available commands inside a Quasar project:\n\n```bash\n$ quasar -h\n\n Example usage\n $ quasar \u003ccommand> \u003coptions>\n\n Help for a command\n $ quasar \u003ccommand> --help\n $ quasar \u003ccommand> -h\n\n Options\n --version, -v Print Quasar App CLI version\n\n Commands\n dev, d Start a dev server for your App\n build, b Build your app for production\n prepare, p Prepare the app for linting, type-checking, IDE integration, etc.\n clean, c Clean dev/build cache, /dist folder & entry points\n new, n Quickly scaffold page/layout/component/... vue file\n mode, m Add/remove Quasar Modes for your App\n inspect Inspect Vite/esbuild configs used under the hood\n - keeps into account your quasar.config file\n and your installed App Extensions\n ext, e Manage Quasar App Extensions\n run, r Run specific command provided by an installed\n Quasar App Extension\n describe Describe a Quasar API (component)\n info, i Display info about your machine and your App\n help, h Displays this message\n\n If the specified command is not found, then \"quasar run\"\n will be executed with the provided arguments.\n\n Commands supplied by @quasar/cli global installation:\n\n upgrade Check (and optionally) upgrade Quasar packages\n from a Quasar project folder\n serve Create an ad-hoc server on App's distributables\n```\n\nSee help for any command:\n\n```bash\n$ quasar [command-name] --help\n```\n\n## Upgrade\n\nCheck (and optionally) upgrade Quasar packages from a Quasar project folder:\n\n```bash\n# view all options:\n$ quasar upgrade -h\n\n# checks for non-breaking change upgrades and displays them,\n# but will not carry out the install\n$ quasar upgrade\n\n# checks for pre-releases (alpha/beta):\n$ quasar upgrade -p\n\n# checks for major new releases (includes breaking changes):\n$ quasar upgrade -m\n\n# use another npm registry url than what your machine is configured with:\n# (added in @quasar/cli v2.4)\n$ quasar upgrade -r https://registry.npmjs.org/\n\n# to perform the actual upgrade,\n# combine any of the params above and add \"-i\" (or \"--install\"):\n$ quasar upgrade -i\n```\n\n::: warning Note for code editor terminals\nIf you're using a code editor terminal instead of the real one, you run `quasar upgrade` and get an error _Command not found_ or _@quasar/cli_ version appears to be _undefined_, you will need to go to the settings of your code editor terminal and untick the option (or its equivalent) _Add 'node_modules/.bin' from the project root to %PATH%_ then restart your code editor.\n:::\n\n## Info\n\nThe Quasar CLI is equipped with a stable combination of multiple NPM build packages (Vite, Vue, etc) which gets updated frequently after heavy testing.\n\nIn order for you to see what versions of Node, Quasar CLI, Quasar, Vue (and many others) you are using, issue this command in a Quasar project folder:\n\n```bash\n$ quasar info\n```\n\n## Dev\n\n```bash\n$ quasar dev -h\n\n Description\n Starts the app in development mode (hot-code reloading, error\n reporting, etc)\n\n Usage\n $ quasar dev\n $ quasar dev -p \u003cport number>\n\n $ quasar dev -m ssr\n\n # alias for \"quasar dev -m capacitor -T ios\"\n $ quasar dev -m ios\n\n # alias for \"quasar dev -m capacitor -T android\"\n $ quasar dev -m android\n\n # passing extra parameters and/or options to\n # underlying \"cordova\" or \"electron\" executables:\n $ quasar dev -m cordova -T ios -- some params --and options --here\n $ quasar dev -m electron -- --no-sandbox --disable-setuid-sandbox\n # when on Windows and using Powershell:\n $ quasar dev -m cordova -T ios '--' some params --and options --here\n $ quasar dev -m electron '--' --no-sandbox --disable-setuid-sandbox\n\n Options\n --mode, -m App mode [spa|ssr|pwa|cordova|capacitor|electron|bex] (default: spa)\n --port, -p A port number on which to start the application\n --hostname, -H A hostname to use for serving the application\n --devtools, -d Open remote Vue Devtools\n --help, -h Displays this message\n\n Only for Cordova mode:\n --target, -T (required) App target [android|ios]\n --emulator, -e (optional) Emulator name\n Examples: iPhone-7, iPhone-X\n iPhone-X,com.apple.CoreSimulator.SimRuntime.iOS-12-2\n --ide, -i Open IDE (Android Studio / XCode) instead of letting Cordova\n boot up the emulator / building in terminal, in which case\n the \"--emulator\" param will have no effect\n\n\n Only for Capacitor mode:\n --target, -T (required) App target [android|ios]\n\n Only for BEX mode:\n --target, -T (required) Browser family target [chrome|firefox]\n```\n\nThe Quasar development server allows you to develop your App by compiling and maintaining code in-memory. A web server will serve your App while offering hot-reload out of the box. Running in-memory offers faster rebuilds when you change your code.\n\n> Hot Reload is much more than just refreshing your browser when code changes. It skips the refresh and updates your code on the fly, while maintaining your App's state (like your Vue's model data). Please note that there are cases when this is impossible, so the dev webserver will simply refresh your browser. (Always ensure you are running only one instance of Quasar CLI at a time, otherwise Hot-Reload and other stuff will break!)\n\nBased on what you want to develop, you can start the development server by using \"quasar dev\" command as follows:\n\n```bash\n# Developing a SPA\n$ quasar dev\n# ...or\n$ quasar dev -m spa\n\n# Developing for SSR\n$ quasar dev -m ssr\n\n# Developing a PWA\n$ quasar dev -m pwa\n\n# Developing a BEX for production\n$ quasar dev -m bex\n\n# Developing a Mobile App (through Cordova)\n$ quasar dev -m cordova -T [android|ios]\n# or the short form:\n$ quasar dev -m [android|ios]\n\n# Developing an Electron App\n$ quasar dev -m electron\n\n# Developing a Browser Extension (BEX)\n$ quasar dev -m bex -T [chrome|firefox]\n\n# passing extra parameters and/or options to\n# underlying \"cordova\" or \"electron\" executables:\n$ quasar dev -m ios -- some params --and options --here\n$ quasar dev -m electron -- --no-sandbox --disable-setuid-sandbox\n# when on Windows and using Powershell:\n$ quasar dev -m ios '--' some params --and options --here\n$ quasar dev -m electron '--' --no-sandbox --disable-setuid-sandbox\n```\n\nIf you wish to change the hostname or port serving your App you have 3 options:\n\n- Edit the '/quasar.config' file:\n ```js\n devServer: {\n host: '...',\n port: ...\n }\n ```\n- Through '-H' (hostname) and '-p' (port) command options.\n- If this is a one time thing, specify the hostname and/or port as an environment variable:\n ```bash\n $ PORT=3000 quasar dev\n $ HOSTNAME=1.1.1.14 quasar dev\n ```\n\nIf there appears to be an issue with hot reload, you can try two fixes:\n\n- Change the permissions for the project folder with\n\n ```bash\n sudo chown -R username: .\n ```\n\n- or run the dev server with root privileges\n\n ```bash\n sudo quasar dev\n ```\n\n## Build\n\n```bash\n$ quasar build -h\n\n Description\n Builds distributables of your app.\n\n Usage\n $ quasar build\n $ quasar build -p \u003cport number>\n\n $ quasar build -m ssr\n\n # alias for \"quasar build -m cordova -T ios\"\n $ quasar build -m ios\n\n # alias for \"quasar build -m cordova -T android\"\n $ quasar build -m android\n\n # passing extra parameters and/or options to\n # underlying \"cordova\" executable:\n $ quasar build -m ios -- some params --and options --here\n # when on Windows and using Powershell:\n $ quasar build -m ios '--' some params --and options --here\n\n Options\n --mode, -m App mode [spa|ssr|pwa|cordova|capacitor|electron|bex] (default: spa)\n --target, -T App target\n - Cordova (default: all installed)\n [android|ios]\n - Capacitor\n [android|ios]\n - Electron with default \"@electron/packager\" bundler (default: yours)\n [darwin|win32|linux|mas|all]\n - Electron with \"electron-builder\" bundler (default: yours)\n [darwin|mac|win32|win|linux|all]\n - Bex\n [chrome|firefox]\n --publish, -P Also trigger publishing hooks (if any are specified)\n - Has special meaning when building with Electron mode and using\n electron-builder as bundler\n --debug, -d Build for debugging purposes\n --skip-pkg, -s Build only UI (skips creating Cordova/Capacitor/Electron executables)\n - Cordova (it only fills in /src-cordova/www folder with the UI code)\n - Capacitor (it only fills in /src-capacitor/www folder with the UI code)\n - Electron (it only creates the /dist/electron/UnPackaged folder)\n --help, -h Displays this message\n\n ONLY for Cordova and Capacitor mode:\n --ide, -i Open IDE (Android Studio / XCode) instead of finalizing with a\n terminal/console-only build\n\n ONLY for Electron mode:\n --bundler, -b Bundler (@electron/packager or electron-builder)\n [packager|builder]\n --arch, -A App architecture (default: yours)\n - with default \"@electron/packager\" bundler:\n [ia32|x64|armv7l|arm64|mips64el|all]\n - with \"electron-builder\" bundler:\n [ia32|x64|armv7l|arm64|all]\n\n ONLY for electron-builder (when using \"publish\" parameter):\n --publish, -P Publish options [onTag|onTagOrDraft|always|never]\n - see https://www.electron.build/configuration/publish\n\n Only for BEX mode:\n --target, -T (required) Browser family target [chrome|firefox]\n```\n\nThe Quasar CLI can pack everything together and optimize your App for production. It minifies source code, extracts vendor components, leverages browser cache and much more.\n\n```bash\n# Build a SPA for production\n$ quasar build\n# ...or\n$ quasar build -m spa\n\n# Build a SSR for production\n$ quasar build -m ssr\n\n# Build a PWA for production\n$ quasar build -m pwa\n\n# Build a BEX for production\n$ quasar build -m bex -T [chrome|firefox]\n\n# Build a Mobile App (through Cordova)\n$ quasar build -m cordova -T [android|ios]\n# or the short form:\n$ quasar build -m [android|ios]\n\n# Build an Electron App for production\n$ quasar build -m electron\n\n# passing extra parameters and/or options to\n# underlying \"cordova\" executable:\n$ quasar build -m ios -- some params --and options --here\n# when on Windows and using Powershell:\n$ quasar build -m ios '--' some params --and options --here\n\n# Create a production build with ability to debug it\n# (has source-maps and code is NOT minified)\n$ quasar build -d [-m \u003cmode>]\n```\n\n## Prepare\n\nPrepares your project folder for the IDE, making autocompletion and other IDE features work correctly.\n\n```bash\n$ quasar prepare\n```\n\n## Clean\n\nCleans up all the build assets:\n\n```bash\n$ quasar clean\n# requires \"quasar prepare\" to be called again\n```\n\n## New\n\nGenerates Components, Pages, Layouts, Pinia Store.\n\n::: tip\nThis command is simply a helper in order to quickly scaffold a page/layout/component/pinia store module. You are not required to use it, but can help you when you don't know how to start.\n:::\n\n```bash\n$ quasar new -h\n\n Description\n Quickly scaffold files.\n\n Usage\n $ quasar new \u003cp|page> [-f \u003cjs|ts>] \u003cpage_file_name>\n $ quasar new \u003cl|layout> [-f \u003cjs|ts>] \u003clayout_file_name>\n $ quasar new \u003cc|component> [-f \u003cjs|ts>] \u003ccomponent_file_name>\n $ quasar new \u003cb|boot> [-f \u003cjs|ts>] \u003cboot_name>\n $ quasar new \u003cs|store> [-f \u003cjs|ts>] \u003cstore_module_name>\n $ quasar new ssrmiddleware [-f \u003cjs|ts>] \u003cmiddleware_name>\n\n Examples\n # Create src/pages/MyNewPage.vue:\n $ quasar new p MyNewPage\n\n # Create src/pages/MyNewPage.vue and src/pages/OtherPage.vue:\n $ quasar new p MyNewPage OtherPage\n\n # Create src/layouts/shop/Checkout.vue\n $ quasar new layout shop/Checkout.vue\n\n # Create src/layouts/shop/Checkout.vue (forcing TypeScript)\n $ quasar new layout -f ts shop/Checkout.vue\n\n # Create a store with TypeScript (-f ts is optional if tsconfig.json is present)\n $ quasar new store -f ts myStore\n\n Options\n --help, -h Displays this message\n\n --format -f \u003coption> (optional) Use a supported format for the template.\n This gets inferred automatically for your project.\n Possible overriding values:\n * js - JS template\n * ts - TS template\n```\n\n## Mode\n\n```bash\n$ quasar mode -h\n\n Description\n Add/Remove support for PWA / BEX / Cordova / Capacitor / Electron modes.\n\n Usage\n $ quasar mode [add|remove] [pwa|ssr|bex|cordova|capacitor|electron] [--yes]\n\n # determine what modes are currently installed:\n $ quasar mode\n\n Options\n --yes, -y Skips the \"Are you sure?\" question\n when removing a Quasar mode\n --help, -h Displays this message\n```\n\nWhen you initialize a project with the CLI, you can build SPA (Single Page Website/Application), SSR (Server-side Render Website/Application with optional PWA client takeover), PWA (Progressive Web App), Mobile App (through Cordova), and/or Electron Apps. When you develop for SSR, PWA, Cordova or Electron, you need these modes installed. If you issue \"quasar dev\" or \"quasar build\" they will automatically be installed.\n\nThese modes will add a \"src-\\*\" folder into your project with very specific code for it:\n\n| Folder | Mode | Description |\n| ------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| src-ssr | ssr | Contains the production Node.js server files. |\n| src-pwa | pwa | Contains the Service Worker file that you can tweak. |\n| src-cordova | cordova | Is a Cordova project folder that will be using your 'src' as content. Tweak Cordova config, add/remove platforms, splash screens, Cordova plugins and so on from this folder. Do NOT touch \"src-cordova/www\" folder though as it will get overwritten at every build. |\n| src-electron | electron | Has code for the main Electron thread. The renderer thread will be your app in 'src'. |\n| src-bex | bex | Contains the specific files for Browser Extensions mode. |\n\nIf for some reason you decide you don't need a mode, you can remove it. **This will permanently delete** the respective \"src-\\*\" folder.\n\n```bash\n$ quasar mode remove pwa\n```\n\n## Describe\n\nThis command is useful to describe the API of any Quasar components/directives/plugins that your project is using. **It is specific to your Quasar version installed in your project folder.**\n\nExamples: `$ quasar describe QIcon`, `$ quasar describe TouchPan`, `$ quasar describe Cookies`.\n\n```bash\n$ quasar describe -h\n\n Description\n Describes a component API for project's Quasar version being used\n\n Usage\n $ quasar describe \u003ccomponent/directive/Quasar plugin>\n\n # list all available API entries:\n $ quasar describe list\n # list available API entries that contain a String (ex \"storage\"):\n $ quasar describe list storage\n\n # display everything:\n $ quasar describe QIcon\n\n # displaying only props:\n $ quasar describe QIcon -p\n # displaying props and methods only:\n $ quasar describe QIcon -p -m\n # filtering by \"si\":\n $ quasar describe QIcon -f si\n # filtering only props by \"co\":\n $ quasar describe QIcon -p -f co\n\n # Open docs URL:\n $ quasar describe QIcon -d\n\n Options\n --filter, -f \u003cfilter> Filters the API\n --props, -p Displays the API props\n --slots, -s Displays the API slots\n --events, -e Displays the API events\n --methods, -m Displays the API methods\n --computedProps, -c Displays the API computed props\n --value, -v Displays the API value\n --arg, -a Displays the API arg\n --modifiers, -M Displays the API modifiers\n --injection, -i Displays the API injection\n --quasar, -q Displays the API quasar conf options\n --docs, -d Opens the docs API URL\n --help, -h Displays this message\n```\n\n```bash\n$ quasar describe QIcon\n\n Describing QIcon component API\n Description is based on your project's Quasar version\n\n Properties\n\n name (String)\n Description: Name of the icon, following Quasar convention\n Examples:\n map\n ion-add\n\n color (String)\n Description: Color name for component from the Quasar Color Palette\n Examples:\n primary\n teal-10\n\n size (String)\n Description: Size in CSS units, including unit name\n Examples:\n 16px\n 2rem\n\n left (Boolean)\n Description: Apply a standard margin on the left side. Useful if icon is on the right side of something.\n\n right (Boolean)\n Description: Apply a standard margin on the right side. Useful if icon is on the left side of something.\n\n Slots\n\n default\n Suggestions: QTooltip or QMenu\n\n Scoped Slots\n\n *No scoped slots*\n\n Events\n\n *No events*\n\n Methods\n\n *No methods*\n```\n\n## Inspect\n\nThis command can be used to inspect the Vite config generated by Quasar CLI.\n\n```bash\n$ quasar inspect -h\n\n Description\n Inspect Quasar generated Vite config\n\n Usage\n $ quasar inspect\n $ quasar inspect -c build\n $ quasar inspect -m electron -p 'build.outDir'\n\n Options\n --cmd, -c Quasar command [dev|build] (default: dev)\n --mode, -m App mode [spa|ssr|pwa|bex|cordova|capacitor|electron] (default: spa)\n --depth, -d Number of levels deep (default: 2)\n --path, -p Path of config in dot notation\n Examples:\n -p module.rules\n -p plugins\n --thread, -t Display only one specific app mode config thread\n --help, -h Displays this message\n```\n\n## Ext\n\nThis command is used to manage [App Extensions](/app-extensions/introduction).\n\n```bash\n$ quasar ext -h\n\n Description\n Manage Quasar App Extensions\n\n Usage\n # display list of installed extensions\n $ quasar ext\n\n # Add Quasar App Extension\n $ quasar ext add \u003cext-id>\n\n # Remove Quasar App Extension\n $ quasar ext remove \u003cext-id>\n\n # Add Quasar App Extension, but\n # skip installing the npm package\n # (assumes it's already installed)\n $ quasar ext invoke \u003cext-id>\n\n # Remove Quasar App Extension, but\n # skip uninstalling the npm package\n $ quasar ext uninvoke \u003cext-id>\n\n Options\n --help, -h Displays this message\n```\n\n## Run\n\nThis command is used to run commands supplied by the [App Extensions](/app-extensions/introduction) that you've installed into your project folder.\n\n```bash\n$ quasar run -h\n\n Description\n Run app extension provided commands\n\n Usage\n $ quasar run \u003cextension-id> \u003ccmd> [args, params]\n $ quasar \u003cextension-id> \u003ccmd> [args, params]\n\n $ quasar run iconify create pic -s --mark some_file\n $ quasar iconify create pic -s --mark some_file\n # Note: \"iconify\" is an example and not a real extension.\n # Looks for installed extension called \"iconify\"\n # (quasar-app-extension-iconify extension package)\n # and runs its custom defined \"create\" command\n # with \"pic\" argument and \"-s --mark some_file\" params\n\n Options\n --help, -h Displays this message\n```\n\n## Serve\n\nThis command can be used in production too and it is being supplied by the global installation of `@quasar/cli` package.\n\n```bash\n$ quasar serve -h\n\n Description\n Start a HTTP(S) server on a folder.\n\n Usage\n $ quasar serve [path]\n $ quasar serve . # serve current folder\n\n If you serve a SSR folder built with the CLI then\n control is yielded to /index.js and params have no effect.\n\n Options\n --port, -p Port to use (default: 4000)\n --hostname, -H Address to use (default: 0.0.0.0)\n --gzip, -g Compress content (default: true)\n --silent, -s Suppress log message\n --colors Log messages with colors (default: true)\n --open, -o Open browser window after starting\n --cache, -c \u003cnumber> Cache time (max-age) in seconds;\n Does not apply to /service-worker.js\n (default: 86400 - 24 hours)\n --micro, -m \u003cseconds> Use micro-cache (default: 1 second)\n\n --history Use history api fallback;\n All requests fallback to /index.html,\n unless using \"--index\" parameter\n --index, -i \u003cfile> History mode (only!) index url path\n (default: index.html)\n\n --https Enable HTTPS\n --cert, -C [path] Path to SSL cert file (Optional)\n --key, -K [path] Path to SSL key file (Optional)\n --proxy \u003cfile.mjs> Proxy specific requests defined in file;\n File must export Array ({ path, rule })\n See example below. \"rule\" is defined at:\n https://github.com/chimurai/http-proxy-middleware\n --cors Enable CORS for all requests\n --help, -h Displays this message\n\n Proxy file example\n export default [\n {\n path: '/api',\n rule: { target: 'http://www.example.org' }\n }\n ]\n --> will be transformed into app.use(path, httpProxyMiddleware(rule))\n```\n\n### Custom Node.js server\n\nWhen building a SPA or PWA, the distributable folder can be served by any static webserver. To test it out (assuming you don't have a specific publicPath or not using Vue Router \"history\" mode), you can use the \"http-server\" npm package.\n\nOr you can build your own server. Here are some examples:\n\n```js When using default Vue Router 'hash' mode\nimport express from 'express'\nimport serveStatic from 'serve-static'\n\nconst port = process.env.PORT || 5000\nconst app = express()\n\napp.use(serveStatic(...path-to-dist...))\napp.listen(port)\n```\n\n```js When using Vue Router 'history' mode\nimport express from 'express'\nimport serveStatic from 'serve-static'\nimport history from 'connect-history-api-fallback'\n\nconst port = process.env.PORT || 5000\nconst app = express()\n\napp.use(history())\napp.use(serveStatic(...path-to-dist...))\napp.listen(port)\n```\n\nIf you need URL rewrites of API, or simply put you want to proxy your API requests, then you can use \"http-proxy-middleware\" package:\n\n```js\n// add this to one of the two previous examples:\nimport { createProxyMiddleware } from 'http-proxy-middleware'\n\n// ...\napp.use(\n '/api',\n createProxyMiddleware({\n target: `http://my-api.com:5050`,\n pathRewrite: { '^/api': '' }\n })\n)\n\n// then app.listen(...)\n```\n\nFinally, run one of these files:\n\n```bash\n$ node my-server.js\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":24481,"content_sha256":"993c99b2483ec7c586dc7ce8f1c9902bf843f5e21bc041663a647956b74c5186"},{"filename":"references/docs/quasar-cli-vite/convert-to-quasar-cli-with-vite.md","content":"---\ntitle: Convert project to Quasar CLI with Vite\ndesc: (@quasar/app-vite) How to convert a Quasar CLI with Webpack project to a Quasar CLI with Vite one.\n---\n\nThis page will guide you on how to convert a Quasar CLI with Webpack (`@quasar/app-webpack v4`) project into a Quasar CLI with Vite one (`@quasar/app-vite v2`).\n\n### Step 1: Edit package.json\n\nA Quasar CLI with Webpack project relies on `/package.json > browserslist` to specify which browsers you are targeting. That property no longer has any meaning. Projects managed by Quasar CLI with Vite work completely different and you might want to check the [Browser Compatibility](/quasar-cli-vite/browser-compatibility) page.\n\n```diff /package.json\ndependencies: {\n- core-js\n},\n\ndevDependencies: {\n- \"@quasar/app-webpack\": \"^4.0.0\"\n+ \"@quasar/app-vite\": \"^2.0.0\"\n\n+ \"postcss\": \"^8.5.8\"\n+ \"postcss-rtlcss\": \"^5.4.0\" // if using RTL support\n\n- eslint-webpack-plugin\n- ts-loader\n- workbox-webpack-plugin\n}\n\n- browserslist: {}\n```\n\nRemember to yarn/npm/pnpm/bun install.\n\n### Step 2: Various files\n\n- Delete `/babel.config.js`. It will serve no purpose now.\n- If you are using using the RTL support, then edit `/postcss.config.js`. You will need to manually install `postcss-rtlcss` and make the following edit:\n\n ```diff /postcss.config.js\n + import rtlcss from 'postcss-rtlcss'\n\n export default {\n plugins: [\n + rtlcss()\n ]\n }\n ```\n\n### Step 3: Copy folders from original folder\n\nFrom your original project folder, copy these as they are:\n\n- /src\n- /src-cordova\n- /src-capacitor\n- /src-electron\n- /src-pwa\n- /src-ssr (with small caveat; see next steps)\n- /src-bex (with small caveat; see next steps)\n\n### Step 4: Explicitly specify extensions on all your import statements\n\nMake sure that all your Vue component files (SFC) are imported with their `.vue` extension explicitly specified. Omitting the file extension works with Webpack (due to Quasar CLI configured list of extensions for it to try), but not with Vite too.\n\n```js\n// BAD! Will not work:\nimport MyComponent from './MyComponent'\n\n// GOOD:\nimport MyComponent from './MyComponent.vue'\n```\n\n### Step 5: Check the new quasar.config file\n\nThe following props are detailed in the [quasar.config file](/quasar-cli-vite/quasar-config-file) page.\n\n```diff\n- eslint: {\n- // fix: true,\n- // include: [],\n- // exclude: [],\n- // cache: false,\n- // rawEsbuildEslintOptions: {},\n- // rawWebpackEslintPluginOptions: {},\n- warnings: true,\n- errors: true\n- },\n\nbuild: {\n- esbuildTarget: {\n- browser: [ 'es2022', 'firefox115', 'chrome115', 'safari14' ],\n+ target: {\n+ browser: 'baseline-widely-available',\n node: 'node22'\n },\n\n- webpackTranspile\n- webpackTranspileDependencies\n- webpackDevtool\n\n- htmlFilename\n- rtl\n- showProgress\n- gzip\n- vueCompiler\n\n- extendWebpack () {}\n- chainWebpack () {}\n+ extendViteConf (viteConf, { isServer, isClient }) {}\n\n+ viteVuePluginOptions\n+ vitePlugins\n\n+ useFilenameHashes\n+ polyfillModulePreload\n\n- uglifyOptions\n- scssLoaderOptions\n- sassLoaderOptions\n- stylusLoaderOptions\n- lessLoaderOptions\n- vueLoaderOptions\n- tsLoaderOptions\n},\n\ndevServer: {\n- server: {\n- type: 'http'\n- }\n},\n\nsourceFiles: {\n- indexHtmlTemplate: 'index.html'\n}\n```\n\n### Step 6: SSR related\n\n```diff /src-ssr/server.js\nexport const renderPreloadTag = defineSsrRenderPreloadTag((file/* , { ssrContext } */) => {\n if (jsRE.test(file) === true) {\n- return `\u003cscript src=\"${file}\" defer crossorigin>\u003c/script>`;\n+ return `\u003clink rel=\"modulepreload\" href=\"${file}\" crossorigin>`;\n }\n```\n\n### Step 7: BEX related\n\n```diff /src-bex/background.js\n- declare module '@quasar/app-webpack' {\n+ declare module '@quasar/app-vite' {\n interface BexEventMap {\n // ...\n }\n}\n```\n\n```diff /src-bex/my-content-script.js\n// for ALL content script files:\n\n- declare module '@quasar/app-webpack' {\n+ declare module '@quasar/app-vite' {\n interface BexEventMap {\n // ...\n }\n}\n```\n\n### Step 8: Linting\n\nIf you are using ESLint, you might want to check the requirements for it [here](/quasar-cli-vite/linter).\n\n### Step 9: And we're done\n\n```bash\n$ quasar prepare\n$ quasar dev\n$ quasar build\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4131,"content_sha256":"6d98ed1c71e6362712f393c9688f506a9ac3ca7de07cd38331d116f3c86cd8d4"},{"filename":"references/docs/quasar-cli-vite/css-preprocessors.md","content":"---\ntitle: CSS Preprocessors\ndesc: (@quasar/app-vite) Sass/SCSS are the out of the box supported css preprocessors in Quasar\nrelated:\n - /style/sass-scss-variables\n---\n\n**Sass** or **SCSS** (recommending any of the two flavours) are the out of the box supported css preprocessors through Quasar CLI, should you want to use them.\n\n## Configuration\n\nYou can configure how your CSS is handled through `/postcss.config.js` and through extending the Vite config:\n\n```js /quasar.config file\nbuild: {\n extendViteConf (viteConf, { isClient, isServer }) {\n viteConf.css.modules = ...\n viteConf.css.postcss = ...\n viteConf.css.preprocessorOptions\n }\n}\n```\n\nMore info: css.modules, css.postcss, css.preprocessorOptions.\n\n## Usage\n\nYour Vue files can contain Sass/SCSS code through the `\u003cstyle>` tag.\n\n```html\n\u003c!-- Notice lang=\"sass\" -->\n\u003cstyle lang=\"sass\">\n div\n color: #444\n background-color: #dadada\n\u003c/style>\n```\n\n```html\n\u003c!-- Notice lang=\"scss\" -->\n\u003cstyle lang=\"scss\">\n div {\n color: #444;\n background-color: #dadada;\n }\n\u003c/style>\n```\n\nAnd, of course, standard CSS is also supported:\n\n```html\n\u003cstyle>\n div {\n color: #444;\n background-color: #dadada;\n }\n\u003c/style>\n```\n\n## Variables\n\nQuasar also supplies variables (`$primary`, `$grey-3`, ...and many more) and you can directly use them. Read more about [Sass/SCSS variables](/style/sass-scss-variables).\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1378,"content_sha256":"1d9a7e347d1513f0ec22a9bf390c103ad331be8820126cb7235244d181b996e1"},{"filename":"references/docs/quasar-cli-vite/developing-browser-extensions/app-icons-browser-extension.md","content":"---\ntitle: App Icons for (BEX)\ndesc: (@quasar/app-vite) How to manage the app icons for a Quasar Browser Extension (BEX).\nscope:\n tree:\n l: src-bex\n c:\n - l: icons\n c:\n - l: icon-16x16.png\n e: Favicon on extension pages\n - l: icon-48x48.png\n e: Extension management page\n - l: icon-128x128.png\n e: Installation and web store\n---\n\nThis build target includes the icons required for browser extensions. You need all of them - and if you discover one that is new or missing, please open an issue.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/iconfactory.png\" style=\"float:right;max-width:15%;min-width:240px;padding-top:40px\">\n\n## Icon Genie CLI\n\n::: tip\nWe highly recommend using the [Icon Genie CLI](/icongenie/introduction), because it consumes a source icon and automatically clones, scales, minifies and places the icons in the appropriate directories for you. When needed, it also tells you what tags you'll need to add to your /index.html file.\n:::\n\nQuickly bootstrap the necessary images with Icon Genie CLI. For a complete list of options, please visit the [Icon Genie CLI](/icongenie/command-list) command list page.\n\n```bash\n$ icongenie generate -m bex -i /path/to/source/icon.png\n```\n\n## Manual instructions\n\n\u003cDocTree :def=\"scope.tree\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1319,"content_sha256":"61821a9424380409cad70ecb50a68c9404b6c93953faded094c05ab5125884d4"},{"filename":"references/docs/quasar-cli-vite/developing-browser-extensions/background-script.md","content":"---\ntitle: Background Script\ndesc: (@quasar/app-vite) How to communicate using your background script with other parts of your Browser Extension (BEX).\n---\n\nThe background script runs in the context of the BEX itself and can listen to all available browser extension events.\n\n::: warning\nIn Chrome with Manifest v3 your background script is actually a Service Worker. This does not currently apply to Firefox with Manifest v3 (yet).\n:::\n\n## Registering a background script\n\nYour `/src-bex/manifest.json` is the central point that defines your BEX. This is the place where you also define your background script(s):\n\n```json /src-bex/manifest.json\n\"chrome\": {\n \"background\": {\n \"service_worker\": \"background.js\"\n }\n},\n\n\"firefox\": {\n \"background\": {\n \"scripts\": [ \"background.js\" ]\n }\n}\n```\n\n::: warning For TS devs\nYour background and content scripts have the `.ts` extension. Use that extension in the manifest.json file as well! Examples: \"background.ts\", \"my-content-script.ts\". While the browser vendors do support only the `.js` extension, Quasar CLI will convert the file extensions automatically.\n:::\n\n## Case study\n\nLet's say we want to listen for a new tab being opened in the web browser and then react to it in our Quasar App. First, we'd need to listen for the new tab being opened and emit a new event to tell the Quasar App this has happened:\n\n```js /src-bex/background.js\n/**\n * Importing the file below initializes the extension background.\n *\n * Warnings:\n * 1. Do NOT remove the import statement below. It is required for the extension to work.\n * If you don't need createBridge(), leave it as \"import '#q-app/bex/background'\".\n * 2. Do NOT import this file in multiple background scripts. Only in one!\n * 3. Import it in your background service worker (if available for your target browser).\n */\nimport { createBridge } from '#q-app/bex/background'\n\nconst bridge = createBridge({ debug: false })\n\nchrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {\n bridge.send('bex.tab.opened', { url: tab.url })\n})\n```\n\nThen in our Quasar App, we'd listen for this in one of our component lifecycle hooks, like so:\n\n```js /Quasar App, /src\nimport { useQuasar } from 'quasar'\nimport { onBeforeUnmount } from 'vue'\n\nexport default {\n setup() {\n const $q = useQuasar()\n\n // Our function which receives the URL sent by the background script.\n function doOnTabOpened(url) {\n console.log('New Browser Tab Openend: ', url)\n }\n\n // Add our listener\n $q.bex.on('bex.tab.opened', doOnTabOpened)\n\n // Don't forget to clean it up\n onBeforeUnmount(() => {\n $q.bex.off('bex.tab.opened', doOnTabOpened)\n })\n\n return {}\n }\n}\n```\n\nThere are wide variety of events available to the browser extension background script - Google is your friend if you're trying to do something in this area.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2843,"content_sha256":"783a65bebd87fcd97838284c10c77242f2fb0f48ed8f6223e342b8a6ab61fe77"},{"filename":"references/docs/quasar-cli-vite/developing-browser-extensions/bex-bridge.md","content":"---\ntitle: BEX Bridge Communication\ndesc: (@quasar/app-vite) How to communicate between different parts of your Browser Extension (BEX) in Quasar.\n---\n\nAllowing a Quasar App to communicate with the various parts of the BEX is essential. Quasar closes this gap using a `bridge`.\n\nThere are 3 areas in a BEX which will need a communication layer:\n\n1. The Quasar App itself - this is true for all types of BEX i.e Popup, Options Page, Dev Tools or Web Page\n2. Background Script\n3. Content Script\n\n## Communication Rules\n\nYou can use our BEX bridge to directly communicate between the background script, instances of the content scripts and the popup/devtools/options page.\n\nThe use of the BEX bridge is optional for each part of the BEX, however if you want to be able to directly communicate between any bex part, then you need to create it in your background script. Under the hood, the background script acts as the main point of communication. All messages go through the bridge in the background script (and get redirected to the right recipient).\n\n## The Bridge\n\nThe bridge is a promise based event system which is shared between all parts of the BEX and as such allows you to listen for events in your Quasar App, emit them from other parts or vice versa. This is what gives Quasar BEX mode it's power.\n\nTo access the bridge from within your Quasar App (/src) you can use `$q.bex`. In other areas, the bridge is made available via creating an instance of it.\n\nLet's see how it works.\n\n### The background script\n\n::: warning\nYou can have multiple background scripts specified in your manifest.json, however, create the BEX bridge ONLY in one of those background scripts. Do not use multiple bridge instances for the background part of your BEX.\n:::\n\n```js\n/**\n * Importing the file below initializes the extension background.\n *\n * Warnings:\n * 1. Do NOT remove the import statement below. It is required for the extension to work.\n * If you don't need createBridge(), leave it as \"import '#q-app/bex/background'\".\n * 2. Do NOT import this file in multiple background scripts. Only in one!\n * 3. Import it in your background service worker (if available for your target browser).\n */\nimport { createBridge } from '#q-app/bex/background'\n\n/**\n * Call createBridge() to enable communication with the app & content scripts\n * (and between the app & content scripts), otherwise skip calling\n * createBridge() and use no bridge.\n */\nconst bridge = createBridge({ debug: false })\n```\n\n### Content scripts\n\n```js\n/**\n * Importing the file below initializes the content script.\n *\n * Warning:\n * Do not remove the import statement below. It is required for the extension to work.\n * If you don't need createBridge(), leave it as \"import '#q-app/bex/content'\".\n */\nimport { createBridge } from '#q-app/bex/content'\n\n// The use of the bridge is optional.\nconst bridge = createBridge({ debug: false })\n/**\n * bridge.portName is 'content@\u003cpath>-\u003cnumber>'\n * where \u003cpath> is the relative path of this content script\n * filename (without extension) from /src-bex\n * (eg. 'my-content-script', 'subdir/my-script')\n * and \u003cnumber> is a unique instance number (1-10000).\n */\n\n// Attach initial bridge listeners...\n\n/**\n * Leave this AFTER you attach your initial listeners\n * so that the bridge can properly handle them.\n *\n * You can also disconnect from the background script\n * later on by calling bridge.disconnectFromBackground().\n *\n * To check connection status, access bridge.isConnected\n */\nbridge\n .connectToBackground()\n .then(() => {\n console.log('Connected to background')\n })\n .catch(err => {\n console.error('Failed to connect to background:', err)\n })\n```\n\n### Popup/devtools/options page\n\n```tabs App (/src/...) vue components\n\u003c\u003c| html Composition API + script setup |>>\n\u003ctemplate>\n \u003cdiv />\n\u003c/template>\n\n\u003cscript setup>\nimport { useQuasar } from 'quasar'\nconst $q = useQuasar()\n\n// Use $q.bex (the bridge)\n// $q.bex.portName is \"app\"\n\u003c/script>\n\u003c\u003c| html Composition API + script |>>\n\u003ctemplate>\n \u003cdiv />\n\u003c/template>\n\n\u003cscript>\nimport { useQuasar } from 'quasar'\n\nexport default {\n setup () {\n const $q = useQuasar()\n // Use $q.bex (the bridge)\n // $q.bex.portName is \"app\"\n }\n}\n\u003c/script>\n\u003c\u003c| html Options API |>>\n\u003ctemplate>\n \u003cdiv />\n\u003c/template>\n\n\u003cscript>\nexport default {\n // Use this.$q.bex (the bridge)\n // this.$q.bex.portName is \"app\"\n}\n\u003c/script>\n```\n\nPlease note that the devtools/popup/options page portName will be `app`.\n\n### Messaging through the bridge\n\n```js\n// Listen to a message from the client\nbridge.on('test', message => {\n console.log(message)\n console.log(message.payload)\n console.log(message.from)\n})\n\n// Send a message and split payload into chunks\n// to avoid max size limit of BEX messages.\n// Warning! This happens automatically when the payload is an array.\n// If you actually want to send an Array, wrap it in an object.\nbridge.send({\n event: 'test',\n to: 'app',\n payload: [ 'chunk1', 'chunk2', 'chunk3', ... ]\n}).then(responsePayload => { ... }).catch(err => { ... })\n\n// Send a message and wait for a response\nbridge.send({\n event: 'test',\n to: 'background',\n payload: { banner: 'Hello from content-script' }\n}).then(responsePayload => { ... }).catch(err => { ... })\n\n// Listen to a message from the client and respond synchronously\nbridge.on('test', message => {\n console.log(message)\n return { banner: 'Hello from a content-script!' }\n})\n\n// Listen to a message from the client and respond asynchronously\nbridge.on('test', async message => {\n console.log(message)\n const result = await someAsyncFunction()\n return result\n})\nbridge.on('test', message => {\n console.log(message)\n return new Promise(resolve => {\n setTimeout(() => {\n resolve({ banner: 'Hello from a content-script!' })\n }, 1000)\n })\n})\n\n// Broadcast a message to app & content scripts\nbridge.portList.forEach(portName => {\n bridge.send({ event: 'test', to: portName, payload: 'Hello from background!' })\n})\n\n// Find any connected content script and send a message to it\nconst contentPort = bridge.portList.find(portName => portName.startsWith('content@'))\nif (contentPort) {\n bridge.send({ event: 'test', to: contentPort, payload: 'Hello from background!' })\n}\n\n// Send a message to a certain content script\nbridge\n .send({ event: 'test', to: 'content@my-content-script-2345', payload: 'Hello from a content-script!' })\n .then(responsePayload => { ... })\n .catch(err => { ... })\n\n// Listen for connection events\n// (the \"@quasar:ports\" is an internal event name registered automatically by the bridge)\n// --> ({ portList: string[], added?: string } | { portList: string[], removed?: string })\nbridge.on('@quasar:ports', ({ portList, added, removed }) => {\n console.log('Ports:', portList)\n if (added) {\n console.log('New connection:', added)\n } else if (removed) {\n console.log('Connection removed:', removed)\n }\n})\n\n// Current bridge port name (can be 'background', 'app', or 'content@\u003cname>-\u003cxxxxx>')\nconsole.log(bridge.portName)\n```\n\n::: warning Warning! Sending large amounts of data\nAll browser extensions have a hard limit on the amount of data that can be passed as communication messages (example: 50MB). If you exceed that amount on your payload, you can send chunks (**`payload` param should be an Array**).\n\n\u003cbr>\n\n```js\nbridge.send({\n event: 'some.event',\n to: 'app',\n payload: [chunk1, chunk2, ...chunkN]\n})\n```\n\n\u003cbr>\n\nWhen calculating the payload size, have in mind that the payload is wrapped in a message built by the Bridge that contains some other properties too. That takes a few bytes as well. So your chunks' size should be with a few bytes below the browser's threshold.\n:::\n\n::: warning Warning! Performance on sending an Array\nLike we've seen on the warning above, if `payload` is Array then the bridge will send a message for each of the Array's elements.\nWhen you actually want to send an Array (not split the payload into chunks), this will be **VERY** inefficient.\n\n\u003cbr>\n\nThe solution is to wrap your Array in an Object (so only one message will be sent):\n\n\u003cbr>\n\n```js\nbridge.send({\n event: 'some.event',\n to: 'background',\n payload: {\n myArray: [\n /*...*/\n ]\n }\n})\n```\n\n:::\n\n### Bridge debug mode\n\nIf you encounter problems with sending messages between the BEX parts, you could enable the debug mode for the bridges that interest you. In doing so, the communication will also be outputted to the browser console:\n\n```js Bridge debug mode\n// Dynamically set debug mode\nbridge.setDebug(true) // boolean\n\n// Log a message on the console (if debug is enabled)\nbridge.log('Hello world!')\nbridge.log('Hello', 'world!')\nbridge.log('Hello world!', { some: 'data' })\nbridge.log('Hello', 'world', '!', { some: 'object' })\n// Log a warning on the console (regardless of the debug setting)\nbridge.warn('Hello world!')\nbridge.warn('Hello', 'world!')\nbridge.warn('Hello world!', { some: 'data' })\nbridge.warn('Hello', 'world', '!', { some: 'object' })\n```\n\n### Clean up your listeners\n\nDon't forget to remove the listeners that are no longer needed, during the lifetime of your BEX:\n\n```js\nbridge.off('some.event', this.someFunction)\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9148,"content_sha256":"f81085e066fa7c2c3d666c745181d185e3198dd6beb15757a9bcd6d9cc4b7444"},{"filename":"references/docs/quasar-cli-vite/developing-browser-extensions/build-commands.md","content":"---\ntitle: BEX Build Commands\ndesc: (@quasar/app-vite) The Quasar CLI list of commands when developing or building a Browser Extension (BEX).\nscope:\n devTree:\n l: '.'\n c:\n - l: dist/bex-[chrome|firefox]--dev\n c:\n - l: '...files'\n e: Built code from /src-bex\n - l: www/\n e: Built code from /src\n prodTree:\n l: '.'\n c:\n - l: dist/bex-[chrome|firefox]\n c:\n - l: '...files'\n e: Built code from /src-bex\n - l: www/\n e: Built code from /src\n - l: Packaged.your-project-name.zip\n e:\n A zip file ready for submission to the Chrome Browser Extension Store /\n Other Chromium based stores.\n---\n\n## Developing\n\nStart developing a Browser Extension with just one command.\n\n```bash\n$ quasar dev -m bex -T [chrome|firefox]\n\n# ..or the longer form:\n$ quasar dev --mode bex -T [chrome|firefox]\n```\n\nYou may or may not have already had a `src-bex` folder, but you will definitely have one now. Now that we've created a development environment, we need to load generated browser extension into your browser.\n\nWhile you develop your BEX, you will notice that Quasar CLI builds the actual extension in the dist folder (normally in `/dist/bex-chrome--dev/` or `/dist/bex-firefox--dev` based on the dev target in \"quasar dev\" command):\n\n\u003cDocTree :def=\"scope.devTree\" />\n\n### Chrome\n\n\n\nIn line with the screenshot above, the following steps must be taken:\n\n1. In Chrome, navigate to `chrome://extensions`\n2. Toggle \"Developer Mode\".\n3. Click \"Load unpacked\". This will present you with the _folder_ selection dialog. Navigate to and select your `/dist/bex-chrome--dev/` folder.\n4. You should now see your BEX mounted in Chrome.\n\nMore information about debugging Chrome Browser Extensions can be found in the official documentation.\n\n### Other Chromium Browsers\n\nAlthough we haven't tested all the various Chromium based browsers, BEX mode should be compatible with them. Please refer to the appropriate browser documentation on how to add a browser extension to that particular browser.\n\n### Firefox\n\n\n\nIn line with the screenshot above, the following steps must be taken:\n\n1. In Firefox, navigate to `about:debugging`\n2. Click on \"This Firefox\"\n3. Click \"Load Temporary Add-on...\". This will present you with the _file_ selection dialog. Navigate to and select your `/dist/bex-firefox--dev/manifest.json` file. **Note:** Firefox requires the manifest file, not the `/dist/bex-firefox--dev` folder like Chromium browsers.\n4. You should now see your BEX mounted in Firefox.\n\nMore information about debugging Firefox temporary addons can be found in the Firefox Extension Workshop.\n\n### Hot Module Reloading (HMR)\n\nThe best developer experience that you will have is with Chrome. We've managed to make HMR fully work for it:\n\n- Full HMR for devtools/options/popup page\n- When changing the background script, the extension will automatically reload.\n- When changing a content script, the extension will automatically reload & the tabs using those content scripts will auto-refresh.\n- The popup/page will not need to be compiled in its entirety. Instead, you will be able to benefit from on-the-fly compilation only for the browser requested files, which is VERY fast.\n\nOn the other hand, we cannot offer the same experience for Firefox too. However, Firefox watches for file changes and tries to auto-reload the extension on changes, but none of the HMR features above (specified for Chrome) will work.\n\n## Debugging\n\nBrowser extensions runs in three different environments (more on upcoming pages) and it requires various environments for debugging.\n\n### With Chrome\n\nYou can find following places to investigate the errors and outputs from the console in DevTools:\n\n1. Popup - right click on the page or on the extension icon and choose `Inspect popup` for DevTools.\n2. Background scripts (e.g.: background-hooks.js) - open DevTools from `Manage extensions - background page`.\n3. Content scripts - page where your script is injected.\n4. Extension Errors - list of errors related to the extension (e.g. manifest configuration) are available in `Manage extension - Errors`.\n\n\n\n\n\nIf your code changes are not propagated to the browser you can try to: - Update or Reload extension - from the Extensions list (screenshots) - Restart browser - Restart dev process\n\nFor more information, please visit Debugging extensions.\n\n## Building for Production\n\n```bash\n$ quasar build -m bex -T [chrome|firefox]\n\n# ..or the longer form:\n$ quasar build --mode bex -T [chrome|firefox]\n```\n\nYou will be instructed which is the output folder. Normally, it's `/dist/bex-chrome/` and `/dist/bex-firefox`, based on the target specified for the \"quasar build\" command.\n\n\u003cDocTree :def=\"scope.prodTree\" />\n\n::: tip\nIf you want to test out the `your-project-name.zip` file, you can do this by dragging the file into the same place you load the Extension in development mode; for Chrome `chrome://extensions` and Firefox `about:debugging`. See the development screenshots above for more information.\n:::\n\n### A Note on Minification\n\nPart of the review process for Browser Extensions in both Chrome and Firefox must allow the relative teams to examine the code being deployed as a live extension. With this in mind, minified code is not allowed. So, to allow for the review process, Quasar will not obfuscate and minify the built code for Browser Extensions.\n\nGiven any extension will be ran directly on the user's computer, upload speed isn't a factor to worry about here, so minifying the code isn't necessary.\n\n## Publishing to the Stores\n\nSince Quasar removes the burden of building and packaging your Browser Extension, once you are finished developing your extension, it is ready to be published. The publishing process differs between browsers, but the official documentation will guide you through the process.\n\n**Chrome** - Publishing a Chrome Browser Extension\n\n**Firefox** - Publishing a Firefox Add On (Browser Extension)\n\n::: tip\nBEX mode should be compatible with all chromium based browsers. Please refer to their relative documentation on publishing extensions.\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":6191,"content_sha256":"74f046a92ce46eb5e2e1b5294376be18d6f8590ce127c01fd485e5b85e749517"},{"filename":"references/docs/quasar-cli-vite/developing-browser-extensions/configuring-bex.md","content":"---\ntitle: Configuring BEX\ndesc: (@quasar/app-vite) How to manage your Browser Extensions with Quasar CLI.\n---\n\nBefore we can configure anything, we need to understand how the BEX is structured. A BEX can be one (or more) of the following:\n\n1. Runs in its own tab in the browser\n2. Runs in the Developer Tools window.\n3. Runs in a Popup window.\n4. Runs as Options window.\n5. Runs in the context of a web page (injected into a website)\n\nYou do not need a new Quasar App per BEX type above as a single Quasar Application can run in **all** of the instances above. You can find out more about these in the [types section](/quasar-cli-vite/developing-browser-extensions/types-of-bex).\n\n## quasar.config file\n\n```js /quasar.config file > sourceFiles\n// should you wish to change default files\nsourceFiles: {\n bexManifestFile?: 'src-bex/manifest.json',\n}\n```\n\n```js /quasar.config file > bex\nbex: {\n /**\n * The list of extra scripts (js/ts) not in your bex manifest that you want to\n * compile and use in your browser extension. Maybe dynamic use them?\n *\n * Each entry in the list should be a relative filename to /src-bex/\n *\n * @example [ 'my-script.ts', 'sub-folder/my-other-script.js' ]\n */\n extraScripts?: string[];\n\n /**\n * Extend the Esbuild config that is used for the bex scripts\n * (background, content scripts, dom script)\n */\n extendBexScriptsConf?: (config: EsbuildConfiguration) => void;\n\n /**\n * Should you need some dynamic changes to the Browser Extension manifest file\n * (/src-bex/manifest.json) then use this method to do it.\n */\n extendBexManifestJson?: (json: object) => void;\n}\n```\n\n## UI in /src\n\nShould you want to tamper with the Vite config for UI in /src:\n\n```js /quasar.config file\nexport default defineConfig(ctx => {\n return {\n build: {\n extendViteConf(viteConf) {\n if (ctx.mode.bex) {\n // do something with viteConf\n // or return an object to deeply merge with current viteConf\n }\n }\n }\n }\n})\n```\n\nThe UI files will be injected and available as `www` folder when you build (or develop) the browser extension.\n\n## Manifest.json\n\nThe most important config file for your BEX is `/src-bex/manifest.json`. It is recommended that you read up on this file before starting your project.\n\nWhen you first add the BEX mode, you will notice that the manifest file contains three root props: `all`, `chrome` & `firefox`. The manifest for chrome is deeply merged from all+chrome, while the firefox one is generated from all+firefox. You could even have different manifest versions for each target:\n\n```json /src-bex/manifest.json\n{\n \"all\": {\n \"manifest_version\": 3,\n\n \"icons\": {\n \"16\": \"icons/icon-16x16.png\",\n \"48\": \"icons/icon-48x48.png\",\n \"128\": \"icons/icon-128x128.png\"\n },\n\n \"permissions\": [\"storage\", \"tabs\"],\n\n \"host_permissions\": [\"*://*/*\"],\n \"content_security_policy\": {\n \"extension_pages\": \"script-src 'self'; object-src 'self';\"\n },\n \"web_accessible_resources\": [\n {\n \"resources\": [\"*\"],\n \"matches\": [\"*://*/*\"]\n }\n ],\n\n \"action\": {\n \"default_popup\": \"www/index.html\"\n },\n\n \"content_scripts\": [\n {\n \"matches\": [\"\u003call_urls>\"],\n \"css\": [\"assets/content.css\"],\n \"js\": [\"my-content-script.ts\"]\n }\n ]\n },\n\n \"chrome\": {\n \"background\": {\n \"service_worker\": \"background.ts\"\n }\n },\n\n \"firefox\": {\n \"background\": {\n \"scripts\": [\"background.ts\"]\n }\n }\n}\n```\n\n::: warning For TS devs\nYour background and content scripts have the `.ts` extension. Use that extension in the manifest.json file as well! Examples: \"background.ts\", \"my-content-script.ts\". While the browser vendors do support only the `.js` extension, Quasar CLI will convert the file extensions automatically.\n:::\n\n## Background And Content Scripts\n\nBehind every BEX is a content script and a background script (manifest v2) / service-worker (manifest v3+). It's a good idea to understand what each of these are before writing your first BEX.\n\nIn summary:\n\n- **Background Script** - runs in the context of the BEX itself and can listen to all available browser extension events.\n- **Content Script** - runs in the context of the web page. There will be a new content script instance per tab running the extension.\n\n::: tip\nGiven content scripts run in the web page context, this means that only BEX's that interact with a web page can use content scripts. Popups, Options and Devtools **will not** have a _content script_ running behind them. They will all however have the _background script_.\n:::\n\n::: warning\nIn Chrome with Manifest v3 your background script is actually a Service Worker. This does not currently apply to Firefox with Manifest v3 (yet).\n:::\n\n## CSS\n\nAny styles you want to be made available to your web page (not your Quasar App) should be included as a file in `src-bex/assets/\u003cname>.css`. When adding such a file, please make sure that you reference it from your `/src-bex/manifest.json` around the content scripts that need it:\n\n```json /src-bex/manifest.json\n// example linking /src-bex/assets/content.css\n\"content_scripts\": [\n {\n \"matches\": [ \"\u003call_urls>\" ],\n \"css\": [ \"assets/content.css\" ],\n \"js\": [ /*...*/ ]\n }\n]\n```\n\n::: warning\nThis must be native CSS as it's not preprocessed via Sass.\n:::\n\n## Dynamic/other scripts\n\nShould you need other scripts to be dynamically loaded or compiled for your BEX, you can add them by editing your quasar.config file:\n\n```js /quasar.config file\nbex: {\n /**\n * The list of extra scripts (js/ts) not in your bex manifest that you want to\n * compile and use in your browser extension. Maybe dynamic use them?\n *\n * Each entry in the list should be a relative filename to /src-bex/\n *\n * @example [ 'my-script.ts', 'sub-folder/my-other-script.js' ]\n */\n extraScripts?: string[];\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5879,"content_sha256":"fe2c2a62e2550ef46464301c9a00da58cbfb1d13f7463b652a795a45443dcb0a"},{"filename":"references/docs/quasar-cli-vite/developing-browser-extensions/content-scripts.md","content":"---\ntitle: Content Scripts\ndesc: (@quasar/app-vite) How to communicate using your content script with your Quasar App and Background Script in Quasar Browser Extension mode.\n---\n\nThe content script(s) run in the context of the web page. There will be a new content script instance per tab running the extension.\n\n## Communication / Events\n\nYou communicate between the BEX parts of your app (background, content scripts & devtools/popup/options page) through our [BEX Bridge](/quasar-cli-vite/developing-browser-extensions/bex-bridge).\n\n## Registering a content script\n\nYour `/src-bex/manifest.json` is the central point that defines your BEX. This is the place where you also define your content script(s):\n\n```json /src-bex/manifest.json\n\"content_scripts\": [\n {\n \"matches\": [ \"\u003call_urls>\" ],\n \"css\": [ \"assets/content.css\" ],\n \"js\": [ \"my-content-script.ts\" ]\n }\n]\n```\n\n::: warning For TS devs\nYour background and content scripts have the `.ts` extension. Use that extension in the manifest.json file as well! Examples: \"background.ts\", \"my-content-script.ts\". While the browser vendors do support only the `.js` extension, Quasar CLI will convert the file extensions automatically.\n:::\n\n## Case study\n\nLet's say we want to react to a button being pressed on our Quasar App and highlight some text on the underlying web page, this would be done via the content scripts like so:\n\n```js Quasar App, /src\nsetup () {\n const $q = useQuasar()\n\n async function myButtonClickHandler () {\n await $q.bex.send('highlight.content', { selector: '.some-class' })\n $q.notify('Text has been highlighted')\n }\n\n return { myButtonClickHandler }\n}\n```\n\n```css /src-bex/assets/content.css\n.bex-highlight {\n background-color: red;\n}\n```\n\n```js /src-bex/my-content-script.js:\n/**\n * Importing the file below initializes the content script.\n *\n * Warning:\n * Do not remove the import statement below. It is required for the extension to work.\n * If you don't need createBridge(), leave it as \"import '#q-app/bex/content'\".\n */\nimport { createBridge } from '#q-app/bex/content'\n\n// The use of the bridge is optional.\nconst bridge = createBridge({ debug: false })\n\nbridge.on('highlight.content', ({ payload }) => {\n const el = document.querySelector(data.selector)\n if (el !== null) {\n el.classList.add('bex-highlight')\n }\n})\n\nbridge\n .connectToBackground()\n .then(() => {\n console.log('Connected to background')\n })\n .catch(err => {\n console.error('Failed to connect to background:', err)\n })\n```\n\nContent scripts live in an isolated world, allowing a content script to makes changes to its JavaScript environment without conflicting with the page or additional content scripts.\n\nIsolated worlds do not allow for content scripts, the extension, and the web page to access any variables or functions created by the others. This also gives content scripts the ability to enable functionality that should not be accessible to the web page.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2956,"content_sha256":"91b54368a51961ea9d0a629408eb1545a4d2d46646a66fcd6ddd9f8a8e129fe6"},{"filename":"references/docs/quasar-cli-vite/developing-browser-extensions/introduction.md","content":"---\ntitle: What is a Browser Extension\ndesc: (@quasar/app-vite) Introduction on what a Browser Extension (BEX) is.\n---\n\nA Browser Extension (BEX) is an application that runs in the browsers context and is used to customize the web browser in some way.\n\nThey are built on web technologies such as HTML, JavaScript, and CSS and will aim to fulfill a single purpose. A single BEX\ncan be built in any way the user deems fit but must contribute towards fulfilling that single purpose.\n\nHere a few things a BEX can do:\n\n- Override page content\n- Add to (or alter) the browser's interface\n- Intercept page requests\n- Be a full featured app that runs in the browser.\n- Interact with and alter the development tools of the browser.\n\nWe've all used Browser Extensions in some capacity. Quasar BEX allows you to do anything a browser extension allows but with the simplicity Quasar offers in all other modes.\n\n### Supported Browsers\n\nWhilst BEX mode has been tested and developed on Firefox and Chrome, all Chromium based browsers should be supported. Where Chrome is mentioned in the documentation, you can safely assume this will apply to the various Chromium browsers as well. If in doubt, refer to the specific browser documentation for clarification.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1245,"content_sha256":"5f0e652f07b925691f5d62f5a08ad60052ecdf2a4018dfb8119cfed7542e8cc6"},{"filename":"references/docs/quasar-cli-vite/developing-browser-extensions/preparation.md","content":"---\ntitle: Preparation for BEX\ndesc: (@quasar/app-vite) How to add the Browser Extension (BEX) mode into a Quasar app.\nscope:\n tree:\n l: src-bex\n c:\n - l: assets\n c:\n - l: content.css\n e: CSS file which is auto injected into the consuming webpage via the manifest.json\n - l: icons\n e: Icons of your app for all platforms\n c:\n - l: 'icon-128x128.png '\n e: Icon file at 128px x 128px\n - l: icon-16x16.png\n e: Icon file at 16px x 16px\n - l: icon-48x48.png\n e: Icon file at 48px x 48px\n - l: _locales/\n e: Optional BEX locales files that you might define in manifest\n - l: manifest.json\n e: The browser extension manifest file\n - l: background.js\n e: (or .ts) Standard background script BEX file (auto injected via manifest.json)\n - l: my-content-script.js\n e:\n (or .ts) Standard content script BEX file - auto injected via manifest.json (you can\n have multiple content scripts)\n---\n\nThe difference between building a SPA, Mobile App, Electron App, BEX or SSR is simply determined by the \"mode\" parameter in \"quasar dev\" and \"quasar build\" commands.\n\n## Add Quasar BEX Mode\n\nIn order to build a BEX, we first need to add the BEX mode to our Quasar project:\n\n```bash\n$ quasar mode add bex\n```\n\nIf you want to jump right in and start developing, you can skip the \"quasar mode\" command and issue:\n\n```bash\n$ quasar dev -m bex -T [chrome|firefox]\n```\n\nThis will add BEX mode automatically, if it is missing, by creating the `/src-bex` folder into your project.\n\n::: tip\nThe `src-bex` folder is just a standard browser extension folder so you are free to use it as you would any other browser extension project folder. Please refer to supported Browser Extension documentation to learn more.\n\n- Firefox Browser Extension Documentation\n- Google Chrome Browser Extension Documentation\n- **Other Chromium Based Browsers** - Refer to their specific documentation.\n :::\n\n## The Anatomy of \"/src-bex\"\n\nThe new folder has the following structure:\n\n\u003cDocTree :def=\"scope.tree\" />\n\nThe next section will discuss these in more detail.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2200,"content_sha256":"9464edc17cac9418a5085d34c9dd74914a3c192666bd94069d67d7b872f7248f"},{"filename":"references/docs/quasar-cli-vite/developing-browser-extensions/types-of-bex.md","content":"---\ntitle: Types of BEX\ndesc: (@quasar/app-vite) How to configure each type of Browser Extensions in Quasar.\n---\n\nAs already discussed, Quasar can handle the various places where a browser extension can live, namely New Tab, Web Page, Dev Tools Options or Popup. You don't need a separate Quasar App for each of these. You can do some handy work with the router.\n\n## New Tab\n\nThis is the default way in which a BEX will run. It is accessed by clicking on the BEX icon in your browser. The Quasar App will run in that new (blank) tab.\n\n## Dev Tools, Options and Popup\n\nThese all follow the same pattern, set up a route and configure the `manifest.json` file to look at that route when it's trying to show either one of the types. For instance:\n\n```js routes.js:\nconst routes = [\n { path: '/options', component: () => import('pages/OptionsPage.vue') },\n { path: '/popup', component: () => import('pages/PopupPage.vue') },\n { path: '/devtools', component: () => import('pages/DevToolsPage.vue') }\n]\n```\n\nYou could configure your `manifest.json` file with the following so the options page is loaded from that route:\n\n#### manifest v2\n\n```json\n{\n \"manifest_version\": 2,\n\n \"options_page\": \"www/index.html#/options\", // Options Page\n \"browser_action\": {\n \"default_popup\": \"www/index.html#/popup\" // Popup Page\n },\n \"devtools_page\": \"www/index.html#/devtools\" // Dev Tools\n}\n```\n\n#### manifest v3\n\n```json\n{\n \"manifest_version\": 3,\n\n \"action\": {\n \"default_popup\": \"www/index.html#/popup\" // Popup Page\n },\n \"options_page\": \"www/index.html#/options\", // Options Page\n \"devtools_page\": \"www/index.html#/devtools\" // Dev Tools\n}\n```\n\n## Case study: Web Page\n\nThis is where the real power comes in. With a little ingenuity we can inject our Quasar application into a web page and use it as an overlay making it seem like our Quasar App is part of the page experience.\n\nHere's a brief rundown of how you could achieve this:\n\n- `src-bex/my-content-script.js`\n\nThe idea here is to create an IFrame and add our Quasar app into it, then inject that into the page.\n\nGiven our Quasar App might need to take the full height of the window (and thus stop any interaction with the underlying page) we have an event to handle setting the height of the IFrame. By default the IFrame height is just high enough to allow for the Quasar toolbar to show (and in turn allowing interaction with the rest of the page).\n\n```js /src-bex/my-content-script.js\n/**\n * Importing the file below initializes the content script.\n *\n * Warning:\n * Do not remove the import statement below. It is required for the extension to work.\n * If you don't need createBridge(), leave it as \"import '#q-app/bex/content'\".\n */\nimport { createBridge } from '#q-app/bex/content'\n\nconst bridge = createBridge({ debug: false })\n\n/**\n * When the drawer is toggled set the iFrame height to take the whole page.\n * Reset when the drawer is closed.\n */\nbridge.on('wb.drawer.toggle', ({ data, respond }) => {\n if (data.open) {\n setIFrameHeight('100%')\n } else {\n resetIFrameHeight()\n }\n respond()\n})\n\nconst iFrame = document.createElement('iframe')\nconst defaultFrameHeight = '62px'\n\n/**\n * Set the height of our iFrame housing our BEX\n * @param height\n */\nfunction setIFrameHeight(height) {\n iFrame.height = height\n}\n\n/**\n * Reset the iFrame to its default height e.g The height of the top bar.\n */\nfunction resetIFrameHeight() {\n setIFrameHeight(defaultFrameHeight)\n}\n\n/**\n * The code below will get everything going. Initialize the iFrame with defaults and add it to the page.\n * @type {string}\n */\niFrame.id = 'bex-app-iframe'\niFrame.width = '100%'\nresetIFrameHeight()\n\n// Assign some styling so it looks seamless\nObject.assign(iFrame.style, {\n position: 'fixed',\n top: '0',\n right: '0',\n bottom: '0',\n left: '0',\n border: '0',\n zIndex: '9999999', // Make sure it's on top\n overflow: 'visible'\n})\n;(function () {\n // When the page loads, insert our browser extension app.\n iFrame.src = chrome.runtime.getURL('www/index.html')\n document.body.prepend(iFrame)\n})()\n```\n\nWe can call this event from our Quasar App any time we know we're opening the drawer and thus changing the height of the IFrame to allow the whole draw to be visible.\n\n- `src-bex/assets/content.css`\n\nAdd a margin to the top of our document so our Quasar toolbar doesn't overlap the actual page content.\n\n```css\n.target-some-header-class {\n margin-top: 62px;\n}\n```\n\n- `Quasar App (/src)`\n\nThen in our Quasar app (/src), we have a function that toggles the drawer and sends an event to the content script telling it to\nresize the IFrame thus allowing our whole app to be visible:\n\n```html\n\u003cq-drawer :model-value=\"drawerIsOpen\" @update:model-value=\"drawerToggled\">\n Some Content\n\u003c/q-drawer>\n```\n\n```js\nimport { useQuasar } from 'quasar'\nimport { ref } from 'vue'\n\nsetup () {\n const $q = useQuasar()\n const drawerIsOpen = ref(true)\n\n async function drawerToggled () {\n await $q.bex.send('wb.drawer.toggle', {\n open: drawerIsOpen.value // So it knows to make it bigger / smaller\n })\n\n // Only set this once the promise has resolved so we can see the entire slide animation.\n drawerIsOpen.value = !drawerIsOpen.value\n }\n\n return { drawerToggled }\n}\n```\n\nNow you have a Quasar App running in a web page. You can now trigger other events from the Quasar App that the content\nscript can listen to and interact with the underlying page.\n\n::: warning\nBe sure to check your manifest.json file, especially around the reference to `my-content-script.js`. Note that **you can have multiple content scripts**. Whenever you create a new one, you need to reference it in the manifest file. Same for any css files created in `/src-bex/assets` folder.\n\n\u003cbr>\n\n```json /src-bex/manifest.json\n\"content_scripts\": [\n {\n \"matches\": [ \"\u003call_urls>\" ],\n \"css\": [ \"assets/content.css\" ],\n \"js\": [ \"my-content-script.js\" ]\n }\n]\n```\n\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5897,"content_sha256":"9b415781ba5ef89181f1be5516eef264266683d8be2eec95c823679ab7dc6669"},{"filename":"references/docs/quasar-cli-vite/developing-capacitor-apps/app-icons-capacitor.md","content":"---\ntitle: App Icons for Capacitor\ndesc: (@quasar/app-vite) How to manage the app icons for a Quasar hybrid mobile app with Capacitor.\nscope:\n tree:\n l: '.'\n c:\n - l: android\n c:\n - l: app\n c:\n - l: src\n c:\n - l: main\n c:\n - l: res\n c:\n - l: drawable\n c:\n - l: splash.png\n - l: drawable-land-hdpi\n c:\n - l: splash.png\n - l: drawable-land-mdpi\n c:\n - l: splash.png\n - l: drawable-land-xhdpi\n c:\n - l: splash.png\n - l: drawable-land-xxhdpi\n c:\n - l: splash.png\n - l: drawable-land-xxxhdpi\n c:\n - l: splash.png\n - l: drawable-port-hdpi\n c:\n - l: splash.png\n - l: drawable-port-mdpi\n c:\n - l: splash.png\n - l: drawable-port-xhdpi\n c:\n - l: splash.png\n - l: drawable-port-xxhdpi\n c:\n - l: splash.png\n - l: drawable-port-xxxhdpi\n c:\n - l: splash.png\n - l: mipmap-hdpi\n c:\n - l: ic_launcher.png\n - l: ic_launcher_foreground.png\n - l: ic_launcher_round.png\n - l: mipmap-mdpi\n c:\n - l: ic_launcher.png\n - l: ic_launcher_foreground.png\n - l: ic_launcher_round.png\n - l: mipmap-xhdpi\n c:\n - l: ic_launcher.png\n - l: ic_launcher_foreground.png\n - l: ic_launcher_round.png\n - l: mipmap-xxhdpi\n c:\n - l: ic_launcher.png\n - l: ic_launcher_foreground.png\n - l: ic_launcher_round.png\n - l: mipmap-xxhdpi\n c:\n - l: ic_launcher.png\n - l: ic_launcher_foreground.png\n - l: ic_launcher_round.png\n - l: ios\n c:\n - l: App\n c:\n - l: App\n c:\n - l: Assets.xcassets\n c:\n - l: AppIcon.appiconset\n c:\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: Splash.imageset\n c:\n - l: splash-2732x2732-1.png\n - l: splash-2732x2732-2.png\n - l: splash-2732x2732.png\n---\n\nCapacitor is one of the most complicated of all of the build targets as far as icons go, because not only do you need to place the icons in specific folders, you also need to register them in config files for both platforms (Android, iOS).\n\nIf you discover one file that is new or missing, please open an issue.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/iconfactory.png\" style=\"float:right;max-width:15%;min-width:240px;padding-top:40px\">\n\n## Icon Genie CLI\n\n::: tip\nWe highly recommend using the [Icon Genie CLI](/icongenie/introduction), because it consumes a source icon and automatically clones, scales, minifies and places the icons in the appropriate directories for you. When needed, it also tells you what tags you'll need to add to your /index.html file.\n:::\n\nQuickly bootstrap the necessary images with Icon Genie CLI. For a complete list of options, please visit the [Icon Genie CLI](/icongenie/command-list) command list page.\n\n```bash\n$ icongenie generate -m capacitor -i /path/to/source/icon.png [-b /path/to/background.png]\n```\n\nDepending on what packager (@electron/packager or electron-builder) you will be using, please see their docs on how to hook the icons.\n\n## Manual instructions\n\nUnless you are using the Icon Genie app extension, these are the files that you need to replace:\n\n\u003cDocTree :def=\"scope.tree\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5751,"content_sha256":"45e2beacd0f240902d30eee04f641ba5f540d93fd931bdb48065a38d6e9b0311"},{"filename":"references/docs/quasar-cli-vite/developing-capacitor-apps/build-commands.md","content":"---\ntitle: Capacitor Build Commands\ndesc: (@quasar/app-vite) The Quasar CLI list of commands when developing or building a hybrid mobile app with Capacitor.\n---\n\n## Developing\n\n```bash\n$ quasar dev -m capacitor -T [ios|android]\n\n# ..or the longer form:\n$ quasar dev --mode capacitor --target [ios|android]\n```\n\nIt will open the IDE (Android Studio / Xcode) and from there you can manually select the emulator (or multiple ones simultaneously!) and install the dev app on it/them. You can also run the dev app on a real mobile/tablet device.\n\n::: warning\nIn Android Studio, you will be greeted with a message recommending to upgrade the Gradle version. **DO NOT UPGRADE GRADLE** as it will break the Capacitor project. Same goes for any other requested upgrades.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-upgrade-notice.png\" alt=\"Gradle upgrade\" class=\"q-my-md rounded-borders\" style=\"max-width: 350px\">\n\nIf you encounter any IDE errors then click on File > Invalidate caches and restart.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-invalidate-cache.png\" alt=\"Gradle upgrade\" class=\"q-mt-md rounded-borders\" style=\"max-width: 350px\">\n\n:::\n\nIn order for you to be able to develop on a device emulator or directly on a phone (with Hot Module Reload included), Quasar CLI follows these steps:\n\n1. Detects your machine's external IP address. If there are multiple such IPs detected, then it asks you to choose one. If you'll be using a mobile phone to develop then choose the IP address of your machine that's pingable from the phone/tablet.\n2. It starts up a development server on your machine.\n3. It tells Capacitor to use the IP previously detected. This allows the app to connect to the development server.\n4. It uses the Capacitor CLI to update all of your plugins.\n5. Finally, it opens your native IDE. Run your app here, and it will automatically connect to the dev server.\n\n::: danger\nIf developing on a mobile phone/tablet, it is very important that the external IP address of your build machine is accessible from the phone/tablet, otherwise you'll get a development app with white screen only. Also check your machine's firewall to allow connections to the development chosen port.\n:::\n\n## Building for Production\n\n```bash\n$ quasar build -m capacitor -T [ios|android]\n\n# ..or the longer form:\n$ quasar build --mode capacitor --target [ios|android]\n```\n\n- These commands parse and build your `/src` folder then overwrite `/src-capacitor/www` then use the Gradle/xcodebuild to generate the final assets that go into a phone/tablet.\n\n- Built packages will be located in `/dist/capacitor` unless configured otherwise.\n\n- If you wish to skip the Gradle/xcodebuild step and only fill `/src-capacitor/www` folder:\n\n```bash\n$ quasar build -m capacitor -T [ios|android] --skip-pkg\n```\n\n- Should you wish to manually build the final assets using the IDE (Android Studio / Xcode) instead of doing a terminal build, then:\n\n```bash\n$ quasar build -m capacitor -T [ios|android] --ide\n```\n\n::: warning\nIn Android Studio, you will be greeted with a message recommending to upgrade the Gradle version. **DO NOT UPGRADE GRADLE** as it will break the Capacitor project. Same goes for any other requested upgrades.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-upgrade-notice.png\" alt=\"Gradle upgrade\" class=\"q-my-md rounded-borders\" style=\"max-width: 350px\">\n\nIf you encounter any IDE errors then click on File > Invalidate caches and restart.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-invalidate-cache.png\" alt=\"Gradle upgrade\" class=\"q-mt-md rounded-borders\" style=\"max-width: 350px\">\n\n:::\n\nIf you want a production build with debugging enabled for the UI code:\n\n```bash\n$ quasar build -m capacitor -T [ios|android] -d\n\n# ..or the longer form\n$ quasar build -m capacitor -T [ios|android] --debug\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3795,"content_sha256":"a2f831b8ecf0d77735d8cdee95e80ef9d0f9ade02af745cd3b5685ec38bae5d9"},{"filename":"references/docs/quasar-cli-vite/developing-capacitor-apps/capacitor-api.md","content":"---\ntitle: Capacitor APIs\ndesc: (@quasar/app-vite) How to use the Capacitor plugins in a Quasar app.\n---\n\nYou can hook into the native device APIs by using Capacitor APIs.\n\n## Capacitor APIs\n\nA few examples of such APIs:\n\n- Background Task\n- Camera\n- Console\n- Device\n- Filesystem\n- Geolocation\n- Motion\n- Network\n- Push Notifications\n- Share\n- Splash Screen\n- Status Bar\n\n## Using a Capacitor API\n\nLet's learn by taking some examples, assuming you've added Capacitor mode to your Quasar project already.\n\n### Example: Geolocation\n\nFirst step is to read the documentation of the Capacitor API that we want to use. We look at Capacitor's Geolocation API.\n\nNow let's put this plugin to some good use. In one of your Quasar project's pages/layouts/components Vue file, we write:\n\n```html\n// some Vue file // remember this is simply an example; // only look at how we\nuse the API described in the plugin's page; // the rest of things here are of no\nimportance\n\n\u003ctemplate>\n \u003cdiv> GPS position: \u003cstrong>{{ position }}\u003c/strong> \u003c/div>\n\u003c/template>\n\n\u003cscript>\n import { ref, onMounted, onBeforeUnmount } from 'vue'\n import { Geolocation } from '@capacitor/geolocation'\n\n export default {\n setup() {\n const position = ref('determining...')\n\n function getCurrentPosition() {\n Geolocation.getCurrentPosition().then(newPosition => {\n console.log('Current', newPosition)\n position.value = newPosition\n })\n }\n\n let geoId\n\n onMounted(() => {\n getCurrentPosition()\n\n // we start listening\n geoId = Geolocation.watchPosition({}, (newPosition, err) => {\n console.log('New GPS position')\n position.value = newPosition\n })\n })\n\n onBeforeUnmount(() => {\n // we do cleanup\n Geolocation.clearWatch(geoId)\n })\n\n return {\n position\n }\n }\n }\n\u003c/script>\n```\n\n### Example: Camera\n\nFirst step is to read the documentation of the Capacitor API that we want to use. We look at Capacitor's Camera API.\n\nNow let's put this API to some good use. In one of your Quasar project's pages/layouts/components Vue file, we write:\n\n```html\n// some Vue file // remember this is simply an example; // only look at how we\nuse the API described in the plugin's page; // the rest of things here are of no\nimportance\n\n\u003ctemplate>\n \u003cdiv>\n \u003cq-btn color=\"primary\" label=\"Get Picture\" @click=\"captureImage\" />\n\n \u003cimg :src=\"imageSrc\" />\n \u003c/div>\n\u003c/template>\n\n\u003cscript>\n import { ref } from 'vue'\n import { Camera, CameraResultType } from '@capacitor/camera'\n\n export default {\n setup() {\n const imageSrc = ref('')\n\n async function captureImage() {\n const image = await Camera.getPhoto({\n quality: 90,\n allowEditing: true,\n resultType: CameraResultType.Uri\n })\n\n // The result will vary on the value of the resultType option.\n // CameraResultType.Uri - Get the result from image.webPath\n // CameraResultType.Base64 - Get the result from image.base64String\n // CameraResultType.DataUrl - Get the result from image.dataUrl\n imageSrc.value = image.webPath\n }\n\n return {\n imageSrc,\n captureImage\n }\n }\n }\n\u003c/script>\n```\n\nSome Capacitor plugins, such as Camera, have a web-based UI available when not running natively but in a standard web browser. To enable these controls, add @ionic/pwa-elements to your project:\n\n```bash\n$ npm install @ionic/pwa-elements\n```\n\nThen create a boot file to initialize them, for example `src/boot/capacitor.js`:\n\n```js\nimport { defineCustomElements } from '@ionic/pwa-elements/loader'\n\nexport default () => {\n defineCustomElements(window)\n}\n```\n\nDon't forget to call the boot script in the `quasar.config` file:\n\n```js\nboot: ['capacitor']\n```\n\nNow you are able to use the Camera API not just in native Android or iOS, but also in web based projects like a SPA or PWA.\n\n### Example: Device\n\nFirst step is to read the documentation of the Capacitor API that we want to use. Look at the Capacitor's Device API.\n\nNow let's put this API to some good use. In one of your Quasar project's pages/layouts/components Vue file, we write:\n\n```html\n// some Vue file // remember this is simply an example; // only look at how we\nuse the API described in the plugin's page; // the rest of things here are of no\nimportance\n\n\u003ctemplate>\n \u003cdiv>\n \u003cdiv>Model: {{ model }}\u003c/div>\n \u003cdiv>Manufacturer: {{ manufacturer }}\u003c/div>\n \u003c/div>\n\u003c/template>\n\n\u003cscript>\n import { ref, onMounted } from 'vue'\n import { Device } from '@capacitor/device'\n\n export default {\n setup() {\n const model = ref('Please wait...')\n const manufacturer = ref('Please wait...')\n\n onMounted(() => {\n Device.getInfo().then(info => {\n model.value = info.model\n manufacturer.value = info.manufacturer\n })\n })\n\n return {\n model,\n manufacturer\n }\n }\n }\n\u003c/script>\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4963,"content_sha256":"513b8d776be23654211f5661dd06b725d41e68855cd857d8216839aacbaeeb80"},{"filename":"references/docs/quasar-cli-vite/developing-capacitor-apps/capacitor-version-support.md","content":"---\ntitle: Capacitor versions\ndesc: (@quasar/app-vite) Supported Capacitor versions in Quasar. How to upgrade to a newer Capacitor version.\n---\n\nThe officially supported versions of Capacitor are v1 through v6.\n\n## Upgrading Capacitor\n\nIf you previously used a lower version of Capacitor and you want to upgrade to a newer version, then:\n\n1. Delete the /src-capacitor/ios and /src-capacitor/android folders, but make sure that you are aware of any changes that you made in those folders as you will have to redo them after step 4.\n2. Change /src-capacitor/package.json to reflect the correct versions of Capacitor dependencies (you can read them in the next appropriate section related to your desired Capacitor version).\n3. Delete yarn.lock/package-lock.json then run `yarn` / `npm install` in /src-capacitor.\n4. At this point, you will have Capacitor installed. Now you can run `quasar dev -m capacitor -T [ios|android]` or `quasar build -m capacitor -T [ios|android]` and it will add the upgraded iOS/Android platform that corresponds to your Capacitor version.\n\nIt would also be wise to check the changelog of Capacitor itself to see what breaking changes it has.\n\n## Capacitor v8\n\n::: warning Requirements\n\n- Node v22.21.1+\n- Xcode 16+ (for iOS)\n- Xcode Command Line Tools\n- Homebrew\n- Cocoapods\n- Android Studio 2024.2.1+\n- Android SDK (API 23+)\n :::\n\nAssuming that you've installed Capacitor mode already, this is how your dependencies in `/src-capacitor/package.json` should look like:\n\n```json /src-capacitor/package.json\ndependencies: {\n \"@capacitor/app\": \"^8.0.0\",\n \"@capacitor/cli\": \"^8.0.0\",\n \"@capacitor/core\": \"^8.0.0\",\n \"@capacitor/splash-screen\": \"^8.0.0\"\n}\n```\n\nThe `@capacitor/app` and `@capacitor/splash-screen` are optional, but it helps Quasar with some UI functionality if they are installed.\n\n## Capacitor v7\n\n::: warning Requirements\n\n- Xcode 16+ (for iOS)\n- Xcode Command Line Tools\n- Homebrew\n- Cocoapods\n- Android Studio 2024.2.1+\n- Android SDK (API 23+)\n :::\n\nAssuming that you've installed Capacitor mode already, this is how your dependencies in `/src-capacitor/package.json` should look like:\n\n```json /src-capacitor/package.json\ndependencies: {\n \"@capacitor/app\": \"^7.0.0\",\n \"@capacitor/cli\": \"^7.0.0\",\n \"@capacitor/core\": \"^7.0.0\",\n \"@capacitor/splash-screen\": \"^7.0.0\"\n}\n```\n\nThe `@capacitor/app` and `@capacitor/splash-screen` are optional, but it helps Quasar with some UI functionality if they are installed.\n\n## Capacitor v6\n\n::: warning Requirements\n\n- Xcode 15+ (for iOS)\n- Android Studio Jellyfish 2023.3.1.18 or newer (for Android)\n :::\n\nAssuming that you've installed Capacitor mode already, this is how your dependencies in `/src-capacitor/package.json` should look like:\n\n```json /src-capacitor/package.json\ndependencies: {\n \"@capacitor/app\": \"^6.0.0\",\n \"@capacitor/cli\": \"^6.0.0\",\n \"@capacitor/core\": \"^6.0.0\",\n \"@capacitor/splash-screen\": \"^6.0.0\"\n}\n```\n\nThe `@capacitor/app` and `@capacitor/splash-screen` are optional, but it helps Quasar with some UI functionality if they are installed.\n\n## Capacitor v5\n\n::: warning Requirements\n\n- Xcode 14.1+ (for iOS)\n- Android Studio Flamingo 2022.2.1 or newer (for Android)\n :::\n\nAssuming that you've installed Capacitor mode already, this is how your dependencies in `/src-capacitor/package.json` should look like:\n\n```json /src-capacitor/package.json\ndependencies: {\n \"@capacitor/app\": \"^5.0.0\",\n \"@capacitor/cli\": \"^5.0.0\",\n \"@capacitor/core\": \"^5.0.0\",\n \"@capacitor/splash-screen\": \"^5.0.0\"\n}\n```\n\nThe `@capacitor/app` and `@capacitor/splash-screen` are optional, but it helps Quasar with some UI functionality if they are installed.\n\n## Capacitor v4\n\nAssuming that you've installed Capacitor mode already, this is how your dependencies in `/src-capacitor/package.json` should look like:\n\n```json /src-capacitor/package.json\ndependencies: {\n \"@capacitor/app\": \"^4.0.0\",\n \"@capacitor/cli\": \"^4.0.0\",\n \"@capacitor/core\": \"^4.0.0\",\n \"@capacitor/splash-screen\": \"^4.0.0\"\n}\n```\n\nThe `@capacitor/app` and `@capacitor/splash-screen` are optional, but it helps Quasar with some UI functionality if they are installed.\n\n## Capacitor v3\n\n::: warning Known issue\nHTTPS devserver (through quasar.config file > devServer > https: true) is not supported. If you are using Capacitor plugins that depend on it, it's better to upgrade to the newer supported Capacitor versions.\n:::\n\nAssuming that you've installed Capacitor mode already, this is how your dependencies in `/src-capacitor/package.json` should look like:\n\n```json /src-capacitor/package.json\ndependencies: {\n \"@capacitor/app\": \"^1.0.0\",\n \"@capacitor/cli\": \"^3.0.0\",\n \"@capacitor/core\": \"^3.0.0\",\n \"@capacitor/splash-screen\": \"^1.0.0\"\n}\n```\n\nThe `@capacitor/app` and `@capacitor/splash-screen` are optional, but it helps Quasar with some UI functionality if they are installed.\n\nMore info for Switch to automatic Android plugin loading.\n\n## Capacitor v2\n\nAssuming that you've installed Capacitor mode already, this is how your dependencies in `/src-capacitor/package.json` should look like:\n\n```json /src-capacitor/package.json\ndependencies: {\n \"@capacitor/cli\": \"^2.0.0\",\n \"@capacitor/core\": \"^2.0.0\"\n}\n```\n\n## Capacitor v1\n\nAssuming that you've installed Capacitor mode already, this is how your dependencies in `/src-capacitor/package.json` should look like:\n\n```json /src-capacitor/package.json\ndependencies: {\n \"@capacitor/cli\": \"^1.0.0\",\n \"@capacitor/core\": \"^1.0.0\"\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5452,"content_sha256":"d4412c5703f2f0a5136b27ecce856e28e77a6a3f17b6f9c796a29c2f8b166d8b"},{"filename":"references/docs/quasar-cli-vite/developing-capacitor-apps/configuring-capacitor.md","content":"---\ntitle: Configuring Capacitor\ndesc: (@quasar/app-vite) How to manage your Capacitor apps with Quasar CLI.\nrelated:\n - /quasar-cli-vite/quasar-config-file\n---\n\nWe'll be using Quasar CLI to develop and build a Mobile App. The difference between building a SPA, PWA, Electron App or a Mobile App is simply determined by the \"mode\" parameter in \"quasar dev\" and \"quasar build\" commands.\n\nThere are two configuration files of great importance to your mobile apps. We'll go over each one.\n\n## capacitor.config.json\n\nThe most important config file for your mobile app is `/src-capacitor/capacitor.config.json`. The `/src-capacitor` folder is a Capacitor project, so please refer to Capacitor documentation in order to understand what each file from there does. But for now, have a few moments to read about capacitor.config.json.\n\nSome properties from this file will get overwritten as we'll see in next section.\n\n## quasar.config file\n\nThere are two places in the `/quasar.config` file where you can configure Quasar specific features for Capacitor.\n\n```js /quasar.config file\nreturn {\n capacitor: {\n /**\n * Automatically hide the Capacitor Splashscreen when app is ready,\n * (is using the Splashscreen Capacitor plugin).\n *\n * @default true\n */\n hideSplashscreen?: boolean;\n\n /**\n * Preparation params with which the Capacitor CLI is called\n *\n * @default [ 'sync', ctx.targetName ]\n */\n capacitorCliPreparationParams?: string[];\n\n /** If not present, will look for `package.json > name` */\n appName?: string;\n /** If not present, will look for `package.json > version` */\n version?: string;\n /** If not present, will look for `package.json > description` */\n description?: string;\n }\n}\n```\n\nAnd you can also configure:\n\n```js /quasar.config file\nreturn {\n framework: {\n config: {\n capacitor: {\n iosStatusBarPadding: true / false // add the dynamic top padding on iOS mobile devices\n }\n }\n }\n}\n```\n\nFinally, you can also disable or configure the back button hook (used for Dialogs):\n\n```js /quasar.config file\nreturn {\n framework: {\n config: {\n capacitor: {\n // Quasar handles app exit on mobile phone back button.\n backButtonExit: true / false / '*' / ['/login', '/home', '/my-page'],\n\n // On the other hand, the following completely\n // disables Quasar's back button management.\n backButton: true / false\n }\n }\n }\n}\n```\n\nShould you want to tamper with the Vite config for UI in /src:\n\n```js /quasar.config file\nexport default defineConfig(ctx => {\n return {\n build: {\n extendViteConf(viteConf) {\n if (ctx.mode.capacitor) {\n // do something with viteConf\n // or return an object to deeply merge with current viteConf\n }\n }\n }\n }\n})\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2832,"content_sha256":"47a4519c63148fac7add7192d7af5738978518069dae960df64a4ce37d5c7cd3"},{"filename":"references/docs/quasar-cli-vite/developing-capacitor-apps/introduction.md","content":"---\ntitle: What is Capacitor\ndesc: (@quasar/app-vite) Introduction on one of the technologies behind Quasar mobile apps.\n---\n\nCapacitor is a cross-platform native runtime for deploying web applications to mobile. It is maintained by Ionic and designed as a modern successor to Cordova. It supports most, but not all Cordova plugins, as well as Capacitor-specific plugins (called APIs). It exposes native device APIs in the form of JavaScript modules.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":451,"content_sha256":"cd27783abef6620643a4ebd9ae768ddf0dc3c3edf42d0b341bc9423f1e7b0250"},{"filename":"references/docs/quasar-cli-vite/developing-capacitor-apps/live-updates.md","content":"---\ntitle: Live Updates\ndesc: (@quasar/app-vite) How to enable live updates for a Quasar hybrid mobile app with Capacitor.\n---\n\nLive Updates, also known as Over-the-Air (OTA) or hot code updates, are a way to push updates to your app without going through the app store review process. This is particularly useful for bug fixes or minor updates that don't require a full app release.\n\n## Installation\n\nTo enable Live Updates in your Quasar Capacitor app, you need to install the `@capawesome/capacitor-live-update` plugin. First, navigate to your Capacitor project directory:\n\n```bash\ncd src-capacitor\n```\n\nThen, install the plugin:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add @capawesome/capacitor-live-update\n\u003c\u003c| bash NPM |>>\n$ npm install --save @capawesome/capacitor-live-update\n\u003c\u003c| bash PNPM |>>\n$ pnpm add @capawesome/capacitor-live-update\n\u003c\u003c| bash Bun |>>\n$ bun add @capawesome/capacitor-live-update\n```\n\nAfter that, you need to sync the changes with your native projects:\n\n```bash\nnpx cap sync\n```\n\n## Configuration\n\nNext, you need to configure the plugin to work with Capawesome Cloud.\n\n### App ID\n\nIn order for your app to identify itself to Capawesome Cloud, you need to set the `appId` in your `capacitor.config` file. For this, you need to create an app on the Capawesome Cloud Console and get the App ID.\n\n```json /src-capacitor/capacitor.config file\n{\n \"plugins\": {\n \"LiveUpdate\": {\n \"appId\": \"00000000-0000-0000-0000-000000000000\"\n }\n }\n}\n```\n\nReplace `00000000-0000-0000-0000-000000000000` with your actual App ID from the Capawesome Cloud Console.\n\nAfter configuring the App ID, sync your Capacitor project again:\n\n```bash\nnpx cap sync\n```\n\n## Usage\n\nThe most basic usage of the Live Update plugin is to call the `sync(...)` method when the app starts. This method checks for updates, downloads them if available, and sets them as the next bundle to be applied. You can then call the `reload()` method to apply the update immediately. If the `reload()` method is not called, the new bundle will be used on the next app start.\n\n```js\nimport { LiveUpdate } from '@capawesome/capacitor-live-update'\n\nconst sync = async () => {\n const result = await LiveUpdate.sync()\n if (result.nextBundleId) {\n await LiveUpdate.reload()\n }\n}\n```\n\n## Publishing updates\n\nTo publish your first update, you need to create a bundle on Capawesome Cloud. For this, you need a bundle artifact. A bundle artifact is the build output of your web app. In Quasar, this is the `src-capacitor/www` folder. You can create a bundle artifact by running the following command:\n\n```bash\nquasar build -m capacitor -T [android|ios]\n```\n\nThis will create a `src-capacitor/www` folder with the build output of your web app. You can then upload this folder to Capawesome Cloud using the Capawesome CLI.\nTo install the Capawesome CLI, run the following command:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn global add @capawesome/cli\n\u003c\u003c| bash NPM |>>\n$ npm i -g @capawesome/cli\n\u003c\u003c| bash PNPM |>>\n$ pnpm add -g @capawesome/cli\n\u003c\u003c| bash Bun |>>\n$ bun install -g @capawesome/cli\n```\n\nAfter installing the Capawesome CLI, you need to log in to your Capawesome Cloud account. Run the following command and follow the instructions:\n\n```bash\nnpx capawesome login\n```\n\nOnce you are logged in, you can create a bundle by running the following command:\n\n```bash\nnpx capawesome apps:bundles:create --path src-capacitor/www\n```\n\nCongratulations! You have successfully published your first live update. You can now test it by running your app on a device or emulator. The app will check for updates and apply them if available.\nFeel free to check out the documentation of the Live Update plugin to see what else you can do with it.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3697,"content_sha256":"0acb067b09dbdd1c88cba3afb6b0e49f78bed235ff7f732cd34186ca19512fc1"},{"filename":"references/docs/quasar-cli-vite/developing-capacitor-apps/managing-google-analytics.md","content":"---\ntitle: Managing Google Analytics\ndesc: (@quasar/app-vite) How to use analytics in a Quasar hybrid mobile app with Capacitor.\n---\n\nGetting to know your users and measuring user behavior is an important step in App Development. Unfortunately, it takes a bit of non-standard work to get Google Analytics to work after wrapping your mobile app with Capacitor. Setting up Google Analytics in a pure web application is quite easy, but Capacitor somehow prevents pageviews and events from being sent to Google Analytics.\n\nFollow this guide to implement Google Analytics into your Capacitor powered Quasar App.\n\n::: warning\nYou'll need to include a `\u003cscript>` tag provided by Google in `/index.html`, which will make your App depend on an Internet connection!\n:::\n\n## Prerequisites\n\n- Make sure all your routes have a name and path parameter specified. Otherwise, they cannot be posted to the `ga.logPage` function. Please refer to [Routing](/quasar-cli-vite/routing) for more info on routing.\n- Have Basic knowledge of Google Analytics\n\n## Preparation\n\nBefore we can start implementing Google Analytics into your application, you'll need an account for Google Analytics and Google Tagmanager. So let's do that first. When you have these accounts, it's time to configure Tag manager. Follow the steps in this Multiminds article to do so.\n\n## Implementing this into application\n\n> For this guide, we'll assume you have a fixed sessionId that you send to Google Analytics. Google Analytics uses a sessionId to distinguish different users from each other. If you want to create an anonymous sessionId, see Analytics Documentation on user id.\n\nPlace the Tag Manager snippet into head of your `index.html` file (if you've followed the Multiminds article, you already have this.) Create a new file in your codebase called `analytics.js` with the following contents:\n\n```javascript\nexport default {\n logEvent(category, action, label, sessionId = null) {\n window.dataLayer.push({\n appEventCategory: category,\n appEventAction: action,\n appEventLabel: label,\n sessionId: sessionId\n })\n window.dataLayer.push({ event: 'appEvent' })\n },\n\n logPage(path, name, sessionId = null) {\n window.dataLayer.push({\n screenPath: path,\n screenName: name,\n sessionId: sessionId\n })\n window.dataLayer.push({ event: 'appScreenView' })\n }\n}\n```\n\nTo make sure all the pages in your application are automatically posted to Google Analytics, we create an app boot file:\n\n```bash\n$ quasar new boot google-analytics [--format ts]\n```\n\nThen we edit the newly created file: `/src/boot/google-analytics.js`:\n\n```js\nimport { defineRouter } from '#q-app/wrappers'\nimport ga from 'analytics.js'\n\nexport default defineRouter(({ router }) => {\n router.afterEach((to, from) => {\n ga.logPage(to.path, to.name, sessionId)\n })\n})\n```\n\nFinally we register the app boot file in the `/quasar.config` file. We can do so only for Capacitor wrapped apps if we want:\n\n```js\nboot: [ctx.mode.capacitor ? 'google-analytics' : '']\n```\n\nMore information about events can be found in the Analytics documentation on events.\n\nYou'll see the events and pageviews coming in when you run your app. It usually takes around 5 to 10 seconds for a pageview to be registered in the realtime view.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3286,"content_sha256":"86d10d2894da29027365a773b076517857329a9a17dcf2d7ac4aea0e0941d187"},{"filename":"references/docs/quasar-cli-vite/developing-capacitor-apps/preparation.md","content":"---\ntitle: Preparation for Capacitor App\ndesc: (@quasar/app-vite) What you need to do before developing a Quasar hybrid mobile app with Capacitor.\n---\n\nBefore we dive in to the actual development, we need to do some preparation work.\n\n## Step 1: Installation\n\n### Android setup\n\n- You will need to install Android Studio and the Android platform SDK on your machine. You can download the Android Studio here and follow these installation steps afterwards.\n\n- Make sure that after you install the Android SDK you then accept its licenses. Open the terminal and go to the folder where the SDK was installed, in tools/bin and call `sdkmanager --licenses`.\n\n::: warning\nThe environmental variable `ANDROID_HOME` has been deprecated and replaced with `ANDROID_SDK_ROOT`. Depending on your version of Android Studio you may need one or the other. It doesn't hurt to have both set.\n:::\n\n- Add Android installation to your path:\n\n#### Unix (macOS, linux)\n\n```bash\nexport ANDROID_HOME=\"$HOME/Android/Sdk\"\nexport ANDROID_SDK_ROOT=\"$HOME/Android/Sdk\"\nPATH=$PATH:$ANDROID_SDK_ROOT/tools; PATH=$PATH:$ANDROID_SDK_ROOT/platform-tools\n```\n\n> Please note that sometimes the `/Android/Sdk` folder is added inside `/Library/` inside your user folder. Check your user folder and if the `/Android/` folder is only inside `/Library/` do: `export ANDROID_SDK_ROOT=\"$HOME/Library/Android/Sdk\"` or `export ANDROID_HOME=\"$HOME/Library/Android/Sdk\"` instead.\n\n#### Windows\n\n```bash\nsetx ANDROID_HOME \"%USERPROFILE%\\AppData\\Local\\Android\\Sdk\"\nsetx ANDROID_SDK_ROOT \"%USERPROFILE%\\AppData\\Local\\Android\\Sdk\"\nsetx path \"%path%;%ANDROID_SDK_ROOT%\\tools;%ANDROID_SDK_ROOT%\\platform-tools\"\n```\n\n- Start Android studio (check the executable in the folder that you installed it in). Next step is to install the individual SDKs:\n\n- Open the \"Configure\" menu at the bottom of the window:\n\n \n\n- Select the desired SDKs and click on \"Apply\" to install the SDKs.\n\n \n\n### iOS setup\n\nYou will need a macOS with Xcode installed. After you've installed it, open Xcode in order to get the license prompt. Accept the license, then you can close it.\n\n#### CocoaPods\n\nIf you haven't installed CocoaPods, please install it by using the command: `sudo gem install cocoapods`. Otherwise, you may encounter errors during development or building, such as:\n\n::: warning terminal warning\n[warn] Skipping pod install because CocoaPods is not installed,\n:::\n\n::: danger Xcode Error\n/path-to/your-project/src-capacitor/ios/App/Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig:1:1 unable to open configuration settings file\n:::\n\n## Step 2: Add Capacitor Quasar Mode\n\nIn order to develop/build a Mobile app, we need to add the Capacitor mode to our Quasar project. This will use the Capacitor CLI to generate a Capacitor project in `/src-capacitor` folder.\n\n```bash\n$ quasar mode add capacitor\n```\n\n## Step 3: Start Developing\n\nTo start a dev server with HMR, run the command below:\n\n```bash\n$ quasar dev -m capacitor -T [android|ios]\n```\n\nOnce the dev server is ready, your IDE will open (Android Studio or Xcode) and from there you can manually select the emulator (or multiple ones simultaneously!) and install the dev app on it/them. You can also run the dev app on a connected mobile/tablet device.\n\n::: warning\nIn Android Studio, you will be greeted with a message recommending to upgrade the Gradle version. **DO NOT UPGRADE GRADLE** as it will break the Capacitor project. Same goes for any other requested upgrades.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-upgrade-notice.png\" alt=\"Gradle upgrade\" class=\"q-my-md rounded-borders\" style=\"max-width: 350px\">\n\nIf you encounter any IDE errors then click on File > Invalidate caches and restart.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-invalidate-cache.png\" alt=\"Gradle upgrade\" class=\"q-mt-md rounded-borders\" style=\"max-width: 350px\">\n\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3858,"content_sha256":"cdcc6ae4c9c3a7493ec5a8f6ae752ecb4247f0890edf43a829032b8339fa8671"},{"filename":"references/docs/quasar-cli-vite/developing-capacitor-apps/publishing-to-store.md","content":"---\ntitle: Publishing to Store\ndesc: (@quasar/app-vite) How to publish a Quasar hybrid mobile app with Capacitor to Google Play Store and to Apple App Store.\n---\n\nSo, you've finished working on your Mobile App. Now it's time to deploy it. Let's learn how.\n\n## Android Publishing\n\nTo generate a release build for Android, we can use the following Quasar CLI command:\n\n```bash\n$ quasar build -m capacitor -T android\n```\n\nThis will compile the web assets (and if \"--ide\" param is also specified, it will open up Android Studio IDE where you need to trigger a release build).\n\nNext, we find our unsigned APK file generated by the Android Studio. Now, we need to sign the unsigned APK and run an alignment utility on it to optimize it and prepare it for the app store. If you already have a signing key, skip these steps and use that one instead.\n\nLet’s generate our private key using the keytool command that comes with the JDK. If this tool isn’t found, refer to the installation guide:\n\n```bash\n$ keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 20000\n```\n\nYou’ll first be prompted to create a password for the keystore. Then, answer the rest of the nice tool’s questions and when it’s all done, you should have a file called my-release-key.keystore created in the current directory.\n\n::: danger\nMake sure to save this file somewhere safe and secure, if you lose it you won’t be able to submit updates to your app!\n:::\n\nNext, we need to _zip align_ and to sign the APK. For this we use a couple of applications that can be found in the Android SDK `build-tools` folder, something like `/path/to/Android/Sdk/build-tools/VERSION/`. For example, on OS X with Android Studio installed, `zipalign` is in `~/Library/Android/Sdk/build-tools/VERSION/`.\n\nTo zip align the APK:\n\n```bash\n$ zipalign -v 4 \u003cpath-to-same-apk-file> HelloWorld.apk\n```\n\nTo sign the APK:\n\n```bash\napksigner sign --ks my-release-key.keystore --ks-key-alias alias_name \u003cpath-to-unsigned-apk-file>\n```\n\nNow we have our final release binary called HelloWorld.apk and we can release this on the Google Play Store for all the world to enjoy!\n\n(There are a few other ways to sign APKs. Refer to the official Android App Signing documentation for more information.)\n\n### Google Play Store\n\nNow that we have our release APK ready for the Google Play Store, we can create a Play Store listing and upload our APK.\n\nTo start, you’ll need to visit the Google Play Store Developer Console and create a new developer account. Unfortunately, this is not free. However, the cost is only $25 compared to Apple’s $99.\n\nOnce you have a developer account, you can go ahead and click “Publish an Android App on Google Play”.\n\nThen, you can go ahead and click the button to edit the store listing (We will upload an APK later). You’ll want to fill out the description for the app.\n\nWhen you are ready, upload the APK for the release build and publish the listing. Be patient and your hard work should be live in the wild!\n\n### Updating your App\n\nAs you develop your app, you’ll want to update it periodically.\n\nIn order for the Google Play Store to accept updated APKs, you’ll need to bump the app version (from `/package.json` or from `/quasar.config file > capacitor > version`, then rebuild the app for release.\n\n## iOS Publishing\n\nFirst, you need to enroll in Apple Developer Program. As with Google, if you have a personal account with Apple, you can create an additional one for your applications.\n\n### Connecting Xcode with your developer account\n\nAfter you receive your developer status, open Xcode on your Mac and go to Preferences > Accounts. Add your account to Xcode by clicking the `+` button on the lower left-hand side and follow the instructions.\n\n### Signing\n\nNow that you linked Xcode with your developer account, go to Preferences > Accounts, select your Apple Id on the left-hand side and then click the View Details button shown on the previous image.\n\nClick the Create button next to the iOS Distribution option.\n\nYou can learn more about maintaining your signing identities and certificates from the official documentation.\n\n### Setting up the app identifier\n\nNext, through the Apple Developer Member Center we’ll set up the app ID identifier details. Identifiers are used to allow an app to have access to certain app services like for example Apple Pay. You can login to Apple Developer Member Center with your Apple ID and password.\n\nOnce you’re logged in you should choose Certificates, Identifiers, and Profiles option. Also select the Identifiers option under the iOS Apps. Then select the `+` button in order to add a new iOS App ID.\n\nThen you’ll have to set the name of your app, use the Explicit App ID option and set the Bundle ID to the value of the id in your capacitor.config.json.\n\nAdditionally, you’ll have to choose any of the services that need to be enabled. For example, if you use Apple Pay or Wallet in your app, you need to choose those option.\n\nYou can learn more about registering app identifiers from the official documentation.\n\n### Creating the app listing\n\nApple uses iTunes Connect to manage app submissions. After your login, you should select the My Apps button, and on the next screen select the `+` button, just below the iTunes Connect My Apps header.\n\nThis will show three options in a dropdown, and you should select the New App. After this the popup appears where you have to choose the name of the application, platform, primary language, bundle ID and SKU.\n\nOnce you’re done, click on the Create button and you’ll be presented with a screen where you’ll have to set some basic options like Privacy Policy URL, category and sub category.\n\nNow, before we fill out everything in the listing, we’ll build our app and get it uploaded with Xcode. Then you’ll come back to finish the listing.\n\nYou can learn more about managing your app in iTunes Connect from the official documentation.\n\n### Building the app for production\n\n```bash\n$ quasar build -m capacitor -T ios\n```\n\nThis will compile the web assets (and if \"--ide\" param is also specified, it will open up Xcode where you need to trigger a release build).\n\n### Configuring the project in Xcode\n\nOnce Xcode opens up the project (\"--ide\" param required), you should see the details about your app in the general view.\n\nYou should just check that the bundle identifier is set up correctly, so that it’s the same as the value you specified earlier in the app ID. Also, make sure that the version and build numbers are correct. Team option should be set to your Apple developer account. Under the deployment target you can choose which devices your application will support.\n\n### Creating an archive of the application\n\nIn Xcode, select Product > Scheme > Edit Scheme to open the scheme editor. Next, select the Archive from the list on the left-hand side. Make sure that the Build configuration is set to Release.\n\nTo create an archive, choose a Generic iOS Device, or your device if it’s connected to your Mac (you can’t create an archive if simulator is selected), from the Scheme toolbar menu in the project editor.\n\nNext, select Product > Archive, and the Archive organizer appears and displays the new archive.\n\nAt this point you can click the `Upload to App Store...` button, and if everything goes fine you’ll have an uploaded app, and the only thing that’s left to do is to complete the iTunes Connect listing and submit it for review!\n\nAt this point you should get an email from iTunes Connect shortly after you uploaded the archive with the content.\n\n### Finishing the app list process\n\nNow you should head back to the iTunes Connect portal and login. Next, click on the Pricing and Availability on the left-hand side under APP STORE INFORMATION.\n\nYou don’t have to worry about forgetting to insert any crucial and required information about your application, since you’ll be notified about what’s missing and what needs to be added/changed if you try to submit the app for review before all details are filled in.\n\nNext, click on the 1.0 Prepare for Submission button on the left-hand side, as shown on the image below. When we uploaded our archive, iTunes Connect automatically determined which device sizes are supported. You’ll need to upload at least one screenshot image for each of the various app sizes that were detected by iTunes Connect.\n\nNext, you’ll have to insert Description, Keywords, Support URL and Marketing URL (optionally).\n\nIn the Build section you have to click on the `+` button and select the build that was uploaded through Xcode in the previous steps.\n\nNext, you’ll have to upload the icon, edit the rating, and set some additional info like copyright and your information. Note that the size of the icon that you’ll have to upload here will have to be 1024 by 1024 pixels. Thankfully, you can use the splash.png from the second tutorial. If you’re the sole developer then the data in the App Review Information should be your own. Finally, as the last option, you can leave the default checked option that once your app is approved that it is automatically released to the App Store.\n\nNow that we’re finished with adding all of the details to the app listing, we can press Save and then Submit for Review. Finally, you’ll be presented with the last form that you’ll have to fill out.\n\nAfter you submit your app for review you’ll see the status of it in the My Apps as Waiting for review, as shown on the image below. Also, shortly after you submit your app for review you’ll get a confirmation email from iTunes Connect that your app is in review.\n\nApple prides itself with a manual review process, which basically means it can take several days for your app to be reviewed. You’ll be notified of any issues or updates to your app status.\n\n### Updating the app\n\nSince you’ll probably want to update your app at some point you’ll first need to bump the app version (from `/package.json`), then rebuild the app for release. Once Xcode opens, follow the same steps all over again.\n\nOnce you submit for the review, you’ll have to wait for the review process again.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":10195,"content_sha256":"8921ebfcfc2e59e12a1c38edc1cb4cc0459ee3365fe549e90a433855603ca1de"},{"filename":"references/docs/quasar-cli-vite/developing-capacitor-apps/troubleshooting-and-tips.md","content":"---\ntitle: Capacitor Troubleshooting and Tips\ndesc: (@quasar/app-vite) Tips and tricks for a Quasar hybrid mobile app with Capacitor.\n---\n\n## $q.capacitor\n\nWhile you are developing a Mobile App with Capacitor Mode, you can access `$q.capacitor` in your Vue files. This is an alias to the global `Capacitor` Object.\n\n## Android Tips\n\n### Android remote debugging\n\nIf you are debugging Android Apps, you can use Google Chrome Remote Debugging through a USB cable attached to your Android phone/tablet. It can be used for emulator too.\n\nThis way you have Chrome Dev Tools directly for your App running on the emulator/phone/table. Inspect elements, check console output, and so on and so forth.\n\n\n\n\n### Accept Licenses\n\nIf you are having problems getting Android builds to finish and you see a message like:\n\n```\n> Failed to install the following Android SDK packages as some licenses have not been accepted.\n```\n\nIf this is the case you need to accept ALL the licenses. Thankfully there is a tool for this:\n\n- Linux: `sdkmanager --licenses`\n- macOS: `~/Library/Android/sdk/tools/bin/sdkmanager --licenses`\n- Windows: `%ANDROID_SDK_ROOT%/tools/bin/sdkmanager --licenses`\n\n### Android SDK not found after installation of the SDK\n\n::: warning\nThe environmental variable `ANDROID_HOME` has been deprecated and replaced with `ANDROID_SDK_ROOT`. Depending on your version of Android Studio you may need one or the other. It doesn't hurt to have both set.\n:::\n\nSome newer Debian-based OS (e.g. ubuntu, elementary OS) might leave you with a `Android SDK not found.` after you installed and (correctly) configured the environment.\n\nThis could have two different reasons: Usually the paths aren't configured correctly. The first step is to verify if your paths are set correctly. This can be done by running the following commands:\n\n```bash\n$ echo $ANDROID_HOME\n\n# or\n\n$ echo $ANDROID_SDK_ROOT\n\n```\n\nThe expected output should be a path similar to this `$HOME/Android/Sdk`. After this run:\n\n```bash\n$ ls -la $ANDROID_HOME\n\n# or\n\n$ ls -la $ANDROID_SDK_ROOT\n```\n\nTo ensure the folder contains the SDK. The expected output should contain folders like 'tools', 'sources', 'platform-tools', etc.\n\n```bash\n$ echo $PATH\n```\n\nThe output should contain each one entry for the Android SDK 'tools'-folder and 'platform-tools'-tools. This could look like this:\n\n```bash\n/home/your_user/bin:/home/your_user/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/your_user/Android/Sdk/tools:/home/your_user/Android/Sdk/platform-tools\n```\n\n> If you ensured your paths are set correctly and still get the error, you can try the following fix: Replacing the Android Studio 'tools' folder manually\n\n### Android Studio\n\nIn Android Studio (if you open it on `/src-capacitor/android`), you will be greeted with a message recommending to upgrade the Gradle version. **DO NOT UPGRADE GRADLE** as it will break the Capacitor project. Same goes for any other requested upgrades.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-upgrade-notice.png\" alt=\"Gradle upgrade\" class=\"q-mb-md rounded-borders\" style=\"max-width: 350px\">\n\nIf you encounter any IDE errors then click on File > Invalidate caches and restart.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-invalidate-cache.png\" alt=\"Gradle upgrade\" class=\"rounded-borders\" style=\"max-width: 350px\">\n\n### Setting up device on Linux\n\nYou may bump into `?????? no permissions` problem when trying to run your App directly on an Android phone/tablet.\n\nHere's how you fix this:\n\n```bash\n# create the .rules file and insert the content\n# from below this example\nsudo vim /etc/udev/rules.d/51-android.rules\nsudo chmod 644 /etc/udev/rules.d/51-android.rules\nsudo chown root. /etc/udev/rules.d/51-android.rules\nsudo service udev restart\nsudo killall adb\n```\n\nThe content for `51-android.rules`:\n\n```\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0bb4\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0e79\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0502\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0b05\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"413c\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0489\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"091e\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"18d1\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0bb4\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"12d1\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"24e3\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"2116\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0482\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"17ef\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"1004\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"22b8\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0409\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"2080\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0955\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"2257\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"10a9\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"1d4d\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0471\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"04da\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"05c6\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"1f53\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"04e8\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"04dd\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0fce\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0930\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"19d2\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"1bbb\", MODE=\"0666\"\n```\n\nNow running `adb devices` should discover your device.\n\n## iOS Tips\n\n### iOS remote debugging\n\nIf you are debugging iOS Apps, you can use the Safari developer tools to remotely debug through a USB cable attached to your iOS phone/tablet. It can be used for emulator too.\n\nThis way you have Safari developer tools directly for your App running on the emulator/phone/table. Inspect elements, check console output, and so on and so forth.\n\nFirst enable the \"developer\" menu option in the Settings of Safari. Then if you navigate to the \"developer\" menu option you will see your emulator or connected device listed near the top. From here you can open the developer tools.\n\n### Status bar and notch safe-areas\n\nSince mobile phones have a status bar and/or notches, your app's styling might need some tweaking when building on Capacitor. In order to prevent parts of your app from going behind the status bar, there is a global CSS variable that can be used for creating a \"safe-area\". This variable can then be applied in your app's top and bottom padding or margin.\n\nQuasar has support for these CSS safe-areas by default in QHeader/QFooter and Notify. However it's important to always check your Capacitor build on several models to see if all cases of your app are dealing with the safe areas correctly.\n\nIn cases you need to manually tweak your CSS you can do so with:\n\n```\n// for your app's header\npadding-top: constant(safe-area-inset-top) // for iOS 11.0\npadding-top: env(safe-area-inset-top) // for iOS 11.2 +\n// for your app's footer\npadding-bottom: constant(safe-area-inset-bottom)\npadding-bottom: env(safe-area-inset-bottom)\n```\n\nOf course you can also use the above example with `margin` instead of `padding` depending on your app.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":7359,"content_sha256":"2a56add4b7bd735293ca3ae40ba15deca63154c7a1d01335ed4c10fa4b09a11f"},{"filename":"references/docs/quasar-cli-vite/developing-cordova-apps/app-icons-cordova.md","content":"---\ntitle: App Icons for Cordova\ndesc: (@quasar/app-vite) How to manage the app icons for a Quasar hybrid mobile app with Cordova.\nscope:\n tree:\n l: src-cordova\n c:\n - l: res\n c:\n - l: android\n c:\n - l: ldpi.png\n e: 36x36\n - l: mdpi.png\n e: 48x48\n - l: hdpi.png\n e: 72x72\n - l: xhdpi.png\n e: 96x96\n - l: xxhdpi.png\n e: 144x144\n - l: xxxhdpi.png\n e: 192x192\n - l: ios\n c:\n - l: icon.png\n e: 57x57\n - l: [email protected]\n e: 144x144\n - l: [email protected]\n - l: [email protected]\n - l: icon-29.png\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: icon-20.png\n - l: [email protected]\n - l: icon-40.png\n - l: icon-50.png\n - l: [email protected]\n - l: icon-72.png\n - l: [email protected]\n - l: icon-76.png\n - l: [email protected]\n - l: [email protected]\n - l: icon-1024.png\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: screen\n c:\n - l: android\n c:\n - l: splash-land-ldpi.png\n e: ''\n - l: splash-port-ldpi.png\n e: ''\n - l: splash-land-mdpi.png\n e: ''\n - l: splash-port-mdpi.png\n e: ''\n - l: splash-land-hdpi.png\n e: ''\n - l: splash-port-hdpi.png\n e: ''\n - l: splash-land-xhdpi.png\n e: ''\n - l: splash-port-xhdpi.png\n e: ''\n - l: splash-land-xxhdpi.png\n e: ''\n - l: splash-port-xxhdpi.png\n e: ''\n - l: splash-land-xxxhdpi.png\n e: ''\n - l: splash-port-xxxhdpi.png\n e: ''\n - l: ios\n c:\n - l: Default@2x~iphone~comcom.png\n - l: Default@2x~iphone~comany.png\n - l: Default@2x~iphone~anyany.png\n - l: Default@3x~iphone~anycom.png\n - l: Default@3x~iphone~comany.png\n - l: Default@3x~iphone~anyany.png\n - l: Default@2x~ipad~comany.png\n - l: Default@2x~ipad~anyany.png\n---\n\nCordova is one of the most complicated of all of the build targets as far as icons go, because not only do you need to place the icons in specific folders, you also need to register them in the `src-cordova/config.xml` file. Further, if you are using splash screens (which you should), you will also need to install `cordova-plugin-splashscreen` and register it in your config.xml.\n\nIf you discover one file that is new or missing, please open an issue.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/iconfactory.png\" style=\"float:right;max-width:15%;min-width:240px;padding-top:40px\">\n\n## Icon Genie CLI\n\n::: tip\nWe highly recommend using the [Icon Genie CLI](/icongenie/introduction), because it consumes a source icon and automatically clones, scales, minifies and places the icons in the appropriate directories for you. When needed, it also tells you what tags you'll need to add to your /index.html file.\n:::\n\nQuickly bootstrap the necessary images with Icon Genie CLI. For a complete list of options, please visit the [Icon Genie CLI](/icongenie/command-list) command list page.\n\n```bash\n$ icongenie generate -m cordova -i /path/to/source/icon.png [-b /path/to/background.png]\n```\n\n## Manual instructions\n\nUnless you are using the Icon Genie CLI, this is what you need to do:\n\n```bash\n$ cd src-cordova\n$ cordova plugin add cordova-plugin-splashscreen\n$ cordova plugin save\n```\n\n\u003cDocTree :def=\"scope.tree\" />\n\nAnd here is part of what your config.xml should look like:\n\n```xml\n\u003cplatform name=\"android\">\n \u003cicon density=\"ldpi\" src=\"res/android/ldpi.png\" />\n \u003cicon density=\"mdpi\" src=\"res/android/mdpi.png\" />\n \u003cicon density=\"xxxhdpi\" src=\"res/android/xxxhdpi.png\" />\n \u003csplash density=\"land-ldpi\" src=\"res/screen/android/splash-land-ldpi.png\" />\n \u003csplash density=\"port-ldpi\" src=\"res/screen/android/splash-port-ldpi.png\" />\n \u003csplash density=\"land-mdpi\" src=\"res/screen/android/splash-land-mdpi.png\" />\n \u003cicon density=\"hdpi\" src=\"res/android/hdpi.png\" />\n \u003cicon density=\"xxhdpi\" src=\"res/android/xxhdpi.png\" />\n \u003csplash density=\"port-mdpi\" src=\"res/screen/android/splash-port-mdpi.png\" />\n \u003csplash density=\"land-hdpi\" src=\"res/screen/android/splash-land-hdpi.png\" />\n \u003csplash density=\"land-xxhdpi\" src=\"res/screen/android/splash-land-xxhdpi.png\" />\n \u003csplash density=\"port-xxhdpi\" src=\"res/screen/android/splash-port-xxhdpi.png\" />\n \u003csplash density=\"land-xxxhdpi\" src=\"res/screen/android/splash-land-xxxhdpi.png\" />\n \u003csplash density=\"port-xxxhdpi\" src=\"res/screen/android/splash-port-xxxhdpi.png\" />\n \u003cicon density=\"xhdpi\" src=\"res/android/xhdpi.png\" />\n \u003csplash density=\"port-hdpi\" src=\"res/screen/android/splash-port-hdpi.png\" />\n \u003csplash density=\"land-xhdpi\" src=\"res/screen/android/splash-land-xhdpi.png\" />\n \u003csplash density=\"port-xhdpi\" src=\"res/screen/android/splash-port-xhdpi.png\" />\n\u003c/platform>\n\u003cplatform name=\"ios\">\n \u003cicon height=\"57\" src=\"res/ios/icon.png\" width=\"57\" />\n \u003cicon height=\"114\" src=\"res/ios/[email protected]\" width=\"114\" />\n \u003csplash src=\"res/screen/ios/Default@2x~iphone~comcom.png\" />\n \u003cicon height=\"60\" src=\"res/ios/[email protected]\" width=\"60\" />\n \u003cicon height=\"29\" src=\"res/ios/icon-29.png\" width=\"29\" />\n \u003cicon height=\"58\" src=\"res/ios/[email protected]\" width=\"58\" />\n \u003cicon height=\"87\" src=\"res/ios/[email protected]\" width=\"87\" />\n \u003cicon height=\"80\" src=\"res/ios/[email protected]\" width=\"80\" />\n \u003cicon height=\"120\" src=\"res/ios/[email protected]\" width=\"120\" />\n \u003cicon height=\"180\" src=\"res/ios/[email protected]\" width=\"180\" />\n \u003cicon height=\"20\" src=\"res/ios/icon-20.png\" width=\"20\" />\n \u003cicon height=\"40\" src=\"res/ios/[email protected]\" width=\"40\" />\n \u003cicon height=\"100\" src=\"res/ios/[email protected]\" width=\"100\" />\n \u003cicon height=\"72\" src=\"res/ios/icon-72.png\" width=\"72\" />\n \u003cicon height=\"144\" src=\"res/ios/[email protected]\" width=\"144\" />\n \u003cicon height=\"76\" src=\"res/ios/icon-76.png\" width=\"76\" />\n \u003cicon height=\"152\" src=\"res/ios/[email protected]\" width=\"152\" />\n \u003cicon height=\"167\" src=\"res/ios/[email protected]\" width=\"167\" />\n \u003cicon height=\"1024\" src=\"res/ios/icon-1024.png\" width=\"1024\" />\n \u003cicon height=\"48\" src=\"res/ios/[email protected]\" width=\"48\" />\n \u003cicon height=\"55\" src=\"res/ios/[email protected]\" width=\"55\" />\n \u003cicon height=\"88\" src=\"res/ios/[email protected]\" width=\"88\" />\n \u003cicon height=\"172\" src=\"res/ios/[email protected]\" width=\"172\" />\n \u003cicon height=\"196\" src=\"res/ios/[email protected]\" width=\"196\" />\n \u003csplash src=\"res/screen/ios/Default@2x~iphone~anyany.png\" />\n \u003csplash src=\"res/screen/ios/Default@3x~iphone~anyany.png\" />\n \u003csplash src=\"res/screen/ios/Default@3x~iphone~anycom.png\" />\n \u003csplash src=\"res/screen/ios/Default@3x~iphone~comany.png\" />\n \u003csplash src=\"res/screen/ios/Default@2x~ipad~anyany.png\" />\n \u003csplash src=\"res/screen/ios/Default@2x~ipad~comany.png\" />\n \u003cicon height=\"40\" src=\"res/ios/icon-40.png\" width=\"40\" />\n \u003cicon height=\"50\" src=\"res/ios/icon-50.png\" width=\"50\" />\n \u003csplash src=\"res/screen/ios/Default@2x~iphone~comany.png\" />\n \u003csplash src=\"res/screen/ios/Default-Landscape-2436h.png\" />\n \u003csplash src=\"res/screen/ios/Default@2x~iphone~anyany\" />\n \u003csplash src=\"res/screen/ios/Default@2x~iphone~comany\" />\n \u003csplash src=\"res/screen/ios/Default@2x~iphone~comcom\" />\n \u003csplash src=\"res/screen/ios/Default@3x~iphone~anyany\" />\n \u003csplash src=\"res/screen/ios/Default@3x~iphone~anycom\" />\n \u003csplash src=\"res/screen/ios/Default@3x~iphone~comany\" />\n \u003csplash src=\"res/screen/ios/Default@2x~ipad~anyany\" />\n \u003csplash src=\"res/screen/ios/Default@2x~ipad~comany\" />\n\u003c/platform>\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":8327,"content_sha256":"66c71d2626fd9fc447db2fb436c2dc30932c5174e7c7a8d3a7e31f4d7b130cb0"},{"filename":"references/docs/quasar-cli-vite/developing-cordova-apps/build-commands.md","content":"---\ntitle: Mobile App Build Commands\ndesc: (@quasar/app-vite) The Quasar CLI list of commands when developing or building a hybrid mobile app with Cordova.\n---\n\nBefore we dive in, make sure you got the Cordova CLI installed.\n\n```bash\n$ npm install -g cordova\n```\n\n## Developing\n\n```bash\n$ quasar dev -m [ios|android]\n\n# ..or the explicit form:\n$ quasar dev -m cordova -T [ios|android]\n\n# ..or the longer form:\n$ quasar dev --mode cordova --target [ios|android]\n\n# using a specific emulator (--emulator, -e)\n$ quasar dev -m ios -e iPhone-7\n# or\n$ quasar dev -m ios -e iPhone-X,com.apple.CoreSimulator.SimRuntime.iOS-12-2\n\n# passing extra parameters and/or options to\n# underlying \"cordova\" executable:\n$ quasar dev -m ios -- some params --and options --here\n# when on Windows and using Powershell:\n$ quasar dev -m ios '--' some params --and options --here\n```\n\nHowever, if you wish to open the IDE (Android Studio / Xcode) and from there to manually select the emulator (or multiple ones simultaneously!) to run the dev app on it/them (or to run the dev app on a real mobile/tablet device):\n\n```bash\n$ quasar dev -m [ios|android] --ide\n```\n\n::: warning\nIn Android Studio, you will be greeted with a message recommending to upgrade the Gradle version. **DO NOT UPGRADE GRADLE** as it will break the Cordova project. Same goes for any other requested upgrades.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-upgrade-notice.png\" alt=\"Gradle upgrade\" class=\"q-my-md rounded-borders\" style=\"max-width: 350px\">\n\nIf you encounter any IDE errors then click on File > Invalidate caches and restart.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-invalidate-cache.png\" alt=\"Gradle upgrade\" class=\"q-mt-md rounded-borders\" style=\"max-width: 350px\">\n\n:::\n\nIn order for you to be able to develop on a device emulator or directly on a phone (with Hot Module Reload included), Quasar CLI follows these steps:\n\n1. Detects your machine's external IP address. If there are multiple such IPs detected, then it asks you to choose one. If you'll be using a mobile phone to develop then choose the IP address of your machine that's pingable from the phone/tablet.\n2. It starts up a development server on your machine.\n3. It temporarily changes the `\u003ccontent/>` tag in `/src-cordova/config.xml` to point to the IP previously detected. This allows the app to connect to the development server.\n4. It defers to Cordova CLI to build a native app with the temporarily changed config.xml.\n5. Cordova CLI checks if a mobile phone / tablet is connected to your development machine. If it is, it installs the development app on it. If none is found, then it boots up an emulator and runs the development app.\n6. Finally, it reverts the temporary changes made to `/src-cordova/config.xml`.\n\n::: danger\nIf developing on a mobile phone/tablet, it is very important that the external IP address of your build machine is accessible from the phone/tablet, otherwise you'll get a development app with white screen only. Also check your machine's firewall to allow connections to the development chosen port.\n:::\n\n### Enabling iOS modern build\n\nBy default, Xcode modern build for iOS is disabled due to Cordova issues. However, if you know what you are doing and you want to enable it, do so from the `/quasar.config` file:\n\n```js\ncordova: {\n noIosLegacyBuildFlag: true\n}\n```\n\nThe above applies also if you want to specify the build type in your \"build.json\".\n\n## Building for Production\n\n```bash\n$ quasar build -m [android|ios]\n\n# ..or the explicit form:\n$ quasar build -m cordova -T [ios|android]\n\n# ..or the longer form:\n$ quasar build --mode cordova --target [ios|android]\n\n# this skips .app or .apk creation and just fills in /src-cordova/www\n$ quasar build -m [ios|android] --skip-pkg\n\n# passing extra parameters and/or options to\n# underlying \"cordova\" executable:\n$ quasar build -m ios -- some params --and options --here\n```\n\n- These commands parse and build your `/src` folder then overwrite `/src-cordova/www` then defer to Cordova CLI to trigger the actual native app creation.\n\n- Built packages will be located in `/dist/cordova` unless configured otherwise.\n\n- If you wish to skip the Cordova CLI packaging step and only fill `/src-cordova/www` folder:\n\n```bash\n$ quasar build -m [ios|android] --skip-pkg\n```\n\n- Should you wish to manually build the final assets using the IDE (Android Studio / Xcode) instead of doing a terminal build, then:\n\n```bash\n$ quasar build -m [ios|android] --ide\n```\n\n::: warning\nIn Android Studio, you will be greeted with a message recommending to upgrade the Gradle version. **DO NOT UPGRADE GRADLE** as it will break the Cordova project. Same goes for any other requested upgrades.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-upgrade-notice.png\" alt=\"Gradle upgrade\" class=\"q-my-md rounded-borders\" style=\"max-width: 350px\">\n\nIf you encounter any IDE errors then click on File > Invalidate caches and restart.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-invalidate-cache.png\" alt=\"Gradle upgrade\" class=\"q-mt-md rounded-borders\" style=\"max-width: 350px\">\n\n:::\n\nIf you want a production build with debugging enabled for the UI code:\n\n```bash\n$ quasar build -m [ios|android] -d\n\n# ..or the longer form\n$ quasar build -m [ios|android] --debug\n```\n\n::: tip\nAlso check `getCordovaBuildParams()` and `getCordovaBuildOutputFolder()` (quasar.config > cordova options) from [Configuring Cordova](/quasar-cli-vite/developing-cordova-apps/configuring-cordova#quasar-config-file) page.\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5482,"content_sha256":"93eb12be0de36053badd70d2b740eb23f32dced0bf9f034243d9f5557caf871e"},{"filename":"references/docs/quasar-cli-vite/developing-cordova-apps/configuring-cordova.md","content":"---\ntitle: Configuring Cordova\ndesc: (@quasar/app-vite) How to manage your Cordova apps with Quasar CLI.\nrelated:\n - /quasar-cli-vite/quasar-config-file\n---\n\nWe'll be using Quasar CLI (and Cordova CLI) to develop and build a Mobile App. The difference between building a SPA, PWA, Electron App or a Mobile App is simply determined by the \"mode\" parameter in \"quasar dev\" and \"quasar build\" commands.\n\nThere are two configuration files of great importance to your mobile apps. We'll go over each one.\n\n## config.xml\n\nThe most important config file for your mobile app is `/src-cordova/config.xml`. The `/src-cordova` folder is a Cordova project, so please refer to Cordova documentation in order to understand what each file from there does. But for now, have a few moments to read about config.xml.\n\nSome properties from this file will get overwritten as we'll see in next section.\n\n## quasar.config file\n\nQuasar CLI helps you in setting some properties of the mobile Apps automatically (from config.xml): the Cordova \"id\", app version, description and android-versionCode. This is for convenience so you'll be able to have a single point where, for example, you change the version of your app, not multiple files that you need to simultaneously touch which is error prone.\n\nFor determining the values for each of the properties mentioned above, Quasar CLI:\n\n1. Looks in the `/quasar.config` file for a \"cordova\" Object. Does it have \"version\", \"description\" and/or \"androidVersionCode\"? If yes, it will use them.\n2. If not, then it looks into your `/package.json` for \"cordovaId\", \"version\" and \"description\" fields.\n\n```js /quasar.config file > cordova\ncordova: {\n /** If not present, will look for `package.json > version` */\n version?: string;\n /** If not present, will look for `package.json > description` */\n description?: string;\n androidVersionCode?: string;\n /**\n * Enable Xcode modern build even if after considering iOS-Cordova issues.\n * You can enable it if you know what you are doing,\n * for example if you want to specify the build type in your “build.json”.\n *\n * @default false\n */\n noIosLegacyBuildFlag?: boolean;\n\n /**\n * Function to return the Cordova build command parameters that\n * will be executed after the UI has compiled.\n *\n * @param context.debug - True if in debug mode\n * @param context.target - The target platform (ios/android)\n * @returns Array of strings (command parameters)\n *\n * @default: [ 'build', '--debug'/'--release', '--device', 'ios'/'android' ]\n * @example: ({ isDebug, target }) => [ 'build', `--${isDebug ? 'debug' : 'release'}`, '--device', 'target' ]\n */\n getCordovaBuildParams?: (context: { debug: boolean; target: 'ios' | 'android' }) => string[];\n\n /**\n * Function to return the Cordova output folder after the \"cordova build\"\n * command is executed.\n * The relative to /src-cordova path is used to copy the Cordova output\n * to the /dist folder.\n *\n * @param context.debug - True if in debug mode\n * @param context.target - The target platform (ios/android)\n * @returns string | string[] | undefined - (relative path(s) from /src-cordova)\n *\n * @default ios: platforms/ios/build/... and android: platforms/android/app/build/outputs\n * @example:\n * ({ isDebug, target }) => {\n * return target === 'ios'\n * ? `platforms/ios/build/${isDebug ? 'Debug' : 'Release'}-iphoneos\n * : 'platforms/android/app/build/outputs'\n * }\n * @example: (when interested in only one platform, leaving the other to the default value)\n * ({ isDebug, target }) => {\n * if (target === 'ios') {\n * return `platforms/ios/build/${isDebug ? 'Debug' : 'Release'}-iphoneos`\n * }\n * }\n * @example: ()\n * ({ isDebug, target }) => {\n * if (target === 'ios') {\n * // try these two folders\n * return [ 'platforms/ios/build/device', 'platforms/ios/build/emulator' ]\n * }\n * }\n */\n getCordovaBuildOutputFolder?: (context: { debug: boolean; target: 'ios' | 'android' }) => string | string[] | undefined;\n}\n```\n\nOther options you can configure:\n\n```js /quasar.config file\nreturn {\n framework: {\n config: {\n cordova: {\n // add the dynamic top padding on iOS mobile devices\n iosStatusBarPadding: true / false,\n\n // Quasar handles app exit on mobile phone back button.\n backButtonExit: true / false / '*' / ['/login', '/home', '/my-page'],\n\n // On the other hand, the following completely\n // disables Quasar's back button management.\n backButton: true / false\n }\n }\n }\n}\n```\n\nShould you want to tamper with the Vite config for UI in /src:\n\n```js /quasar.config file\nexport default defineConfig(ctx => {\n return {\n build: {\n extendViteConf(viteConf) {\n if (ctx.mode.cordova) {\n // do something with viteConf\n // or return an object to deeply merge with current viteConf\n }\n }\n }\n }\n})\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5019,"content_sha256":"1041e1a1449067939684e8a8debc1c8e6b7eb960062df90274182a8eb32634ef"},{"filename":"references/docs/quasar-cli-vite/developing-cordova-apps/cordova-plugins.md","content":"---\ntitle: Cordova Plugins\ndesc: (@quasar/app-vite) How to use the Cordova plugins in a Quasar app.\n---\n\nYou can hook into the native device APIs by using Cordova Plugins.\n\n## Cordova Plugins\n\nA few examples of such plugins:\n\n- Battery Status\n- Camera\n- Contacts\n- Device\n- Device Motion\n- Geolocation\n- Media\n- Media Capture\n- Network Information\n- Splashscreen\n- Vibration\n- Statusbar\n\n## Deviceready Event\n\nYou'll notice that some Cordova plugins are usable only after the `deviceready` event has been triggered. We don't need to worry about it too much. Quasar listens to this event and takes care of our root Vue component to be mounted **after** this event has been triggered. But if you need some plugin's own variable and that is initialized after `deviceready` you can follow the example of using the plugin device below\n\n### Caveat\n\nLet's take a vue file for example:\n\n```html\n\u003ctemplate> ... we are sure 'deviceready' has been triggered here ... \u003c/template>\n\n\u003cscript>\n // outside of the default export,\n // we need to listen to the event for ourselves:\n document.addEventListener(\n 'deviceready',\n () => {\n // it's only now that we are sure\n // the event has triggered\n },\n false\n )\n\n export default {\n // we are sure 'deviceready' has been triggered here\n }\n\u003c/script>\n```\n\nThe reason is simple. Quasar listens for the event then mounts the root Vue component. But before this, the Vue files are imported into the `/src/router/routes.js` file, so the code outside of the default export gets executed.\n\n## Using a Cordova Plugin\n\nLet's learn by taking some examples, assuming you've added Cordova mode to your Quasar project and installed a platform (android, ios, ...) already.\n\n### Example: Battery Status\n\nFirst step is to read the documentation of the Cordova plugin that we want to use. We look at Cordova Plugins list and click on Battery Status doc page.\n\nWe see instructions on how to install this plugin. It's always a Cordova command. **So we \"cd\" into `/src-cordova`** (which is a Cordova generated folder) **and issue the install command form there**:\n\n```bash\n# from /src-cordova:\n$ cordova plugin add cordova-plugin-battery-status\n```\n\nNow let's put this plugin to some good use. In one of your Quasar project's pages/layouts/components Vue file, we write:\n\n```html\n// some Vue file // remember this is simply an example; // only look at how we\nuse the API described in the plugin's page; // the rest of things here are of no\nimportance\n\n\u003ctemplate>\n \u003cdiv> Battery status is: \u003cstrong>{{ batteryStatus }}\u003c/strong> \u003c/div>\n\u003c/template>\n\n\u003cscript>\n import { ref, onBeforeUnmount } from 'vue'\n\n export default {\n setup() {\n const batteryStatus = ref('determining...')\n\n function updateBatteryStatus(status) {\n batteryStatus.value = `Level: ${status.level}, plugged: ${status.isPlugged}`\n }\n\n // we register the event like on plugin's doc page\n window.addEventListener('batterystatus', updateBatteryStatus, false)\n\n onBeforeUnmount(() => {\n // we do some cleanup;\n // we need to remove the event listener\n window.removeEventListener('batterystatus', updateBatteryStatus, false)\n })\n\n return {\n batteryStatus\n }\n }\n }\n\u003c/script>\n```\n\n### Example: Camera\n\nFirst step is to read the documentation of the Cordova plugin that we want to use. We look at Cordova Plugins list and click on Camera doc page.\n\nThere's a mention of the `deviceready` event. But we already know how to handle it from the previous sections.\n\nWe read the instructions on how to install this plugin. It's always a Cordova command. **So we \"cd\" into `/src-cordova`** (which is a Cordova generated folder) **and issue the install command form there**:\n\n```bash\n# from /src-cordova:\n$ cordova plugin add cordova-plugin-camera\n```\n\nNow let's put this plugin to some good use. In one of your Quasar project's pages/layouts/components Vue file, we write:\n\n```html\n// some Vue file // remember this is simply an example; // only look at how we\nuse the API described in the plugin's page; // the rest of things here are of no\nimportance\n\n\u003ctemplate>\n \u003cdiv>\n \u003cq-btn color=\"primary\" label=\"Get Picture\" @click=\"captureImage\" />\n\n \u003cimg :src=\"imageSrc\" />\n \u003c/div>\n\u003c/template>\n\n\u003cscript>\n import { useQuasar } from 'quasar'\n import { ref } from 'vue'\n\n export default {\n setup() {\n const $q = useQuasar()\n const imageSrc = ref('')\n\n function captureImage() {\n navigator.camera.getPicture(\n data => {\n // on success\n imageSrc.value = `data:image/jpeg;base64,${data}`\n },\n () => {\n // on fail\n $q.notify('Could not access device camera.')\n },\n {\n // camera options\n }\n )\n }\n\n return {\n imageSrc,\n captureImage\n }\n }\n }\n\u003c/script>\n```\n\n### Example: Device\n\nFirst step is to read the documentation of the Cordova plugin that we want to use. Look at the Cordova Plugins list and click on Device doc page.\n\nThis plugin initializes a global variable called `device` which describes the device's hardware and software. So it can be accessed with `window.device`.\n\nRead the instructions on how to install this plugin on its cordova doc page. It's always a Cordova command. **So we \"cd\" into `/src-cordova`** (which is a Cordova generated folder) and **issue the install command from there**:\n\n```bash\n# from /src-cordova:\n$ cordova plugin add cordova-plugin-device\n```\n\nNow let's put this plugin to some good use. If you need the information of your device when starting the application, you will have to capture the created event. In one of your Quasar project's pages/layouts/components Vue file, we write:\n\n```html\n// some Vue file // remember this is simply an example; // only look at how we\nuse the API described in the plugin's page; // the rest of things here are of no\nimportance\n\n\u003ctemplate>\n \u003cdiv>\n \u003cq-page class=\"flex flex-center\">\n \u003cdiv>IMEI: {{ imei }}\u003c/div>\n \u003c/q-page>\n \u003c/div>\n\u003c/template>\n\n\u003cscript>\n import { ref } from 'vue'\n\n export default {\n setup() {\n const imei = ref(\n window.device === void 0\n ? 'Run this on a mobile/tablet device'\n : window.device\n )\n\n return {\n imei\n }\n }\n }\n\u003c/script>\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":6351,"content_sha256":"7eb346646c6bf906598de211329b57ae5c50f435a4ee601f1b9a742863da6401"},{"filename":"references/docs/quasar-cli-vite/developing-cordova-apps/introduction.md","content":"---\ntitle: What is Cordova\ndesc: (@quasar/app-vite) Introduction on one of the technologies behind Quasar hybrid mobile apps.\n---\n\nApache Cordova is a mobile application development framework originally created by Nitobi. Adobe Systems purchased Nitobi in 2011, rebranded it as PhoneGap, and later released an open source version of the software called Apache Cordova.\n\nApache Cordova enables software programmers to build applications for mobile devices using CSS3, HTML5, and JavaScript instead of relying on platform-specific APIs like those in Android, iOS, or Windows Phone. It enables wrapping up of CSS, HTML, and JavaScript code depending upon the platform of the device. It extends the features of HTML and JavaScript to work with the device. The resulting applications are hybrid, meaning that they are neither truly native mobile application (because all layout rendering is done via Web views instead of the platform's native UI framework) nor purely Web-based (because they are not just Web apps, but are packaged as apps for distribution and have access to native device APIs).\n\nYou can hook into the native device APIs by using [Cordova Plugins](/quasar-cli-vite/developing-cordova-apps/cordova-plugins).\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1220,"content_sha256":"7338f2f08459f71b3356121ea1563b6fd9c7db1d8208fb004095264ef19e42dc"},{"filename":"references/docs/quasar-cli-vite/developing-cordova-apps/managing-google-analytics.md","content":"---\ntitle: Managing Google Analytics\ndesc: (@quasar/app-vite) How to use analytics in a Quasar hybrid mobile app with Cordova.\n---\n\nGetting to know your users and measuring user behavior is an important step in App Development. Unfortunately, it takes a bit of non-standard work to get Google Analytics to work after wrapping your mobile app with Cordova. Setting up Google Analytics in a pure web application is quite easy, but Cordova somehow prevents pageviews and events from being sent to Google Analytics.\n\nFollow this guide to implement Google Analytics into your Cordova powered Quasar App.\n\nYou may also want to read this tutorial: Google Analytics Setup for a Cordova App.\n\n::: warning\nYou'll need to include a `\u003cscript>` tag provided by Google in `/index.html`, which will make your App depend on an Internet connection!\n:::\n\n## Prerequisites\n\n- Make sure all your routes have a name and path parameter specified. Otherwise, they cannot be posted to the `ga.logPage` function. Please refer to [Routing](/quasar-cli-vite/routing) for more info on routing.\n- Have Basic knowledge of Google Analytics\n\n## Preparation\n\nBefore we can start implementing Google Analytics into your application, you'll need an account for Google Analytics and Google Tagmanager. So let's do that first. When you have these accounts, it's time to configure Tag manager. Follow the steps in this Multiminds article to do so.\n\n## Implementing this into application\n\n> For this guide, we'll assume you have a fixed sessionId that you send to Google Analytics. Google Analytics uses a sessionId to distinguish different users from each other. If you want to create an anonymous sessionId, see Analytics Documentation on user id.\n\nPlace the Tag Manager snippet into head of your `index.html` file (if you've followed the Multiminds article, you already have this.) Create a new file in your codebase called `analytics.js` with the following contents:\n\n```javascript\nexport default {\n logEvent(category, action, label, sessionId = null) {\n window.dataLayer.push({\n appEventCategory: category,\n appEventAction: action,\n appEventLabel: label,\n sessionId: sessionId\n })\n window.dataLayer.push({ event: 'appEvent' })\n },\n\n logPage(path, name, sessionId = null) {\n window.dataLayer.push({\n screenPath: path,\n screenName: name,\n sessionId: sessionId\n })\n window.dataLayer.push({ event: 'appScreenView' })\n }\n}\n```\n\nTo make sure all the pages in your application are automatically posted to Google Analytics, we create an app boot file:\n\n```bash\n$ quasar new boot google-analytics [--format ts]\n```\n\nThen we edit the newly created file: `/src/boot/google-analytics.js`:\n\n```js\nimport { defineRouter } from '#q-app/wrappers'\nimport ga from 'analytics.js'\n\nexport default defineRouter(({ router }) => {\n router.afterEach((to, from) => {\n ga.logPage(to.path, to.name, sessionId)\n })\n})\n```\n\nFinally we register the app boot file in the `/quasar.config` file. We can do so only for Cordova wrapped apps if we want:\n\n```js\nboot: [ctx.mode.cordova ? 'google-analytics' : '']\n```\n\nMore information about events can be found in the Analytics documentation on events.\n\nYou'll see the events and pageviews coming in when you run your app. It usually takes around 5 to 10 seconds for a pageview to be registered in the realtime view.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3358,"content_sha256":"ec38453726c69b1fcee4449a7eeadcc41549791af4dc66ef79a207737e2ad479"},{"filename":"references/docs/quasar-cli-vite/developing-cordova-apps/preparation.md","content":"---\ntitle: Preparation for Cordova App\ndesc: (@quasar/app-vite) What you need to do before developing a Quasar hybrid mobile app with Cordova.\n---\n\nBefore we dive into the actual development, we need to do some preparation work.\n\n## Step 1: Installation\n\nThe first step is to make sure you got the Cordova CLI installed and the necessary SDKs.\n\n```bash\n$ npm install -g cordova\n```\n\n::: warning\nDepending on your version of Android Studio, you might need to re-enable the \"Android SDK Tools\". You can do this by going\nto \"Tools > SDK Manager > SDK Tools\" then un-ticking \"Hide Obsolete Packages\" and ticking \"Android SDK Tools (Obsolete)\".\n**The instructions below assume this has been done.**\n:::\n\n::: warning\nThe environmental variable `ANDROID_HOME` has been deprecated and replaced with `ANDROID_SDK_ROOT`. Depending on your version of Android Studio you may need one or the other. It doesn't hurt to have both set.\n:::\n\n### Android Setup\n\n- After this step you will need to install the Android platform SDK on your machine. You can download the Android Studio here and follow these installation steps afterward.\n\n- Make sure that after you install the Android SDK you then accept its licenses. Open the terminal and go to the folder where the SDK was installed, in tools/bin, and call `sdkmanager --licenses`.\n\n- Add Android installation to your path:\n\n#### Unix (macOS, Linux)\n\n```bash\nexport ANDROID_HOME=\"$HOME/Android/Sdk\"\nexport ANDROID_SDK_ROOT=\"$HOME/Android/Sdk\"\nexport PATH=$PATH:$ANDROID_SDK_ROOT/tools; PATH=$PATH:$ANDROID_SDK_ROOT/platform-tools\n```\n\n> Please note that sometimes the `/Android/Sdk` folder is added inside `/Library/` inside your user folder. Check your user folder and if the `/Android/` folder is only inside `/Library/` do: `export ANDROID_SDK_ROOT=\"$HOME/Library/Android/Sdk\"` or `export ANDROID_HOME=\"$HOME/Library/Android/Sdk\"` instead.\n\n#### Windows\n\nAfter installing Android Studio, you need to install two more pieces of software:\n\n- JDK from Oracle. It can be found here\n- Gradle. It used to be usable from Android Studio but now you have to install it separately. There is a particular version that Cordova requires. You can download it here\n\nThen you will have to set environment variables. You will need to set the following variables. Cordova has a good guide for it already. It can be found here. You need to:\n\n- add `ANDROID_SDK_ROOT`. It can safely be set to: \"%USERPROFILE%\\AppData\\Local\\Android\\Sdk\"\n- add two `ANDROID_SDK_ROOT` directories to your path: %ANDROID_SDK_ROOT%\\tools;%ANDROID_SDK_ROOT%\\platform-tools\n- add Gradle to your path. Note that Gradle does not have an installer. You just put the binary files where you want them, then add the bin directory to your path.\n- add `JAVA_HOME`. Its value depends on where you installed it. You can download the JDK here\n\n> You can check the value of an environment variable by typing in console `echo %ENVIRONMENT_VARIABLE%`.\n\nIf you have an init script for your command prompt or powershell, you can try this:\n\n```bash\nsetx ANDROID_HOME \"%USERPROFILE%\\AppData\\Local\\Android\\Sdk\"\nsetx ANDROID_SDK_ROOT \"%USERPROFILE%\\AppData\\Local\\Android\\Sdk\"\nsetx path \"%path%;%ANDROID_SDK_ROOT%\\tools;%ANDROID_SDK_ROOT%\\platform-tools;\u003cgradle_path>\\bin;\"\n```\n\nAfter the tools are installed, set up Android Studio with the correct SDK and create a virtual machine.\n\n- Start Android Studio (check the executable in the folder that you installed it in). The next step is to install the individual SDKs:\n\n- Open the \"Configure\" menu at the bottom of the window:\n\n \n\n- Select the desired SDKs. As of December 2019, Cordova requires android-28 (Android 9.0 - Pie) so be sure to include it. Click on \"Apply\" to install the SDKs.\n\n \n\n### iOS Setup\n\nYou will need a macOS with Xcode installed. After you've installed it, open Xcode in order to get the license prompt. Accept the license, then you can close it.\n\n## Step 2: Add Cordova Quasar Mode\n\nIn order to develop/build a Mobile app, we need to add the Cordova mode to our Quasar project. What this does is that it uses Cordova CLI to generate a Cordova project in the `/src-cordova` folder. The `/src-cordova/www` folder will be overwritten each time you build.\n\n```bash\n$ quasar mode add cordova\n```\n\n## Step 3: Add Platform\n\nTo switch to the Cordova project, type:\n\n```bash\n$ cd src-cordova\n```\n\nTarget platforms get installed on demand by Quasar CLI. However, if you want to add a platform manually, type:\n\n```bash\n$ cordova platform add [android|ios]\n```\n\nTo verify that everything is in order, type:\n\n```bash\n$ cordova requirements\n```\n\n> On some newer Debian-based operating systems you might face a very persistent problem when running `cordova requirements`. Please see the [\"Android SDK not found\" after installation](/quasar-cli-vite/developing-cordova-apps/troubleshooting-and-tips#Android-SDK-not-found-after-installation-of-the-SDK) section for assistance.\n\n### Switching to iOS WkWebView\n\nSwitching to WKWebView is highly recommended (but optional!) as UIWebView has been deprecated in iOS 12.0 as described in this Cordova blog post: https://cordova.apache.org/news/2018/08/01/future-cordova-ios-webview.html.\n\n**However, choose wisely if you want to replace the default Web View. Each comes with its own caveats.** Make sure that you visit the link above.\n\n#### Option 1: Ionic Webview Plugin\n\n1. Install Ionic Webview Plugin\n\n```bash\n# from /src-cordova\n$ cordova plugin add cordova-plugin-ionic-webview\n```\n\n2. Add `ScrollEnabled` preference to `Config.xml`\n\n```xml\n\u003cplatform name=\"ios\">\n \u003cpreference name=\"ScrollEnabled\" value=\"true\" />\n\u003c/platform>\n```\n\n3. Consult Ionic Docs for caveats on WkWebViewPlugin\n\n- https://beta.ionicframework.com/docs/building/webview\n- https://github.com/ionic-team/cordova-plugin-ionic-webview\n\n#### Option 2: Cordova WkWebviewEngine Plugin\n\n1. Install Cordova WkWebviewEngine Plugin\n\n```bash\n# from /src-cordova\n$ cordova plugin add cordova-plugin-wkwebview-engine\n```\n\n2. For caveats and more info, visit: https://github.com/apache/cordova-plugin-wkwebview-engine\n\n## Step 4: Start Developing\n\nYou can start the development server with the command below:\n\n```bash\n$ quasar dev -m cordova -T [android|ios]\n\n# passing extra parameters and/or options to\n# underlying \"cordova\" executable:\n$ quasar dev -m ios -- some params --and options --here\n# when on Windows and using PowerShell:\n$ quasar dev -m ios '--' some params --and options --here\n```\n\nThis will also add Cordova mode and install the related Cordova platform automatically if it is missing.\n\nYou will be able to run the app on your mobile device if you have one, or through the emulator. See [Mobile App Build Commands > Developing](/quasar-cli-vite/developing-cordova-apps/build-commands#developing) for more information.\n\n::: warning\nIn Android Studio, you will be greeted with a message recommending to upgrade the Gradle version. **DO NOT UPGRADE GRADLE** as it will break the Cordova project. The same goes for any other requested upgrades.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-upgrade-notice.png\" alt=\"Gradle upgrade\" class=\"q-my-md rounded-borders\" style=\"max-width: 350px\">\n\nIf you encounter any IDE errors then click on File > Invalidate caches and restart.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-invalidate-cache.png\" alt=\"Gradle upgrade\" class=\"q-mt-md rounded-borders\" style=\"max-width: 350px\">\n\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":7376,"content_sha256":"13123b911d01dc91184e3f9470e36d4ca1703c383ee8b561cf4a09787fb3b53d"},{"filename":"references/docs/quasar-cli-vite/developing-cordova-apps/publishing-to-store.md","content":"---\ntitle: Publishing to Store\ndesc: (@quasar/app-vite) How to publish a Quasar hybrid mobile app with Cordova to Google Play Store and to Apple App Store.\n---\n\nSo, you've finished working on your Mobile App. Now it's time to deploy it. Let's learn how.\n\n## Android Publishing\n\nTo generate a release build for Android, we can use the following Quasar CLI command:\n\n```bash\n$ quasar build -m cordova -T android\n# or the short form:\n$ quasar build -m android\n```\n\nThis will generate a release build based on the settings in your `/src-cordova/config.xml`.\n\nNext, we can find our unsigned APK file in \"/src-cordova/platforms/android/app/build/outputs/apk/release\" or equivalent path (written in the output of terminal). Filename usually ends with \"-release-unsigned.apk\". Now, we need to sign the unsigned APK and run an alignment utility on it to optimize it and prepare it for the app store. If you already have a signing key, skip these steps and use that one instead.\n\nLet’s generate our private key using the keytool command that comes with the JDK. If this tool isn’t found, refer to the installation guide:\n\n```bash\n$ keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 20000\n```\n\nYou’ll first be prompted to create a password for the keystore. Then, answer the rest of the nice tool’s questions and when it’s all done, you should have a file called my-release-key.keystore created in the current directory.\n\n::: danger\nMake sure to save this file somewhere safe, if you lose it you won’t be able to submit updates to your app!\n:::\n\nNext, we need to _zip align_ and to sign the APK. For this we use a couple of applications that can be found in the Android SDK `build-tools` folder, something like `/path/to/Android/Sdk/build-tools/VERSION/`. For example, on OS X with Android Studio installed, `zipalign` is in `~/Library/Android/Sdk/build-tools/VERSION/`.\n\nTo zip align the APK:\n\n```bash\n$ zipalign -v 4 \u003cpath-to-same-apk-file> HelloWorld.apk\n```\n\nTo sign the APK:\n\n```bash\napksigner sign --ks my-release-key.keystore --ks-key-alias alias_name \u003cpath-to-unsigned-apk-file>\n```\n\nNow we have our final release binary called HelloWorld.apk and we can release this on the Google Play Store for all the world to enjoy!\n\n(There are a few other ways to sign APKs. Refer to the official Android App Signing documentation for more information.)\n\n### Google Play Store\n\nNow that we have our release APK ready for the Google Play Store, we can create a Play Store listing and upload our APK.\n\nTo start, you’ll need to visit the Google Play Store Developer Console and create a new developer account. Unfortunately, this is not free. However, the cost is only $25 compared to Apple’s $99.\n\nOnce you have a developer account, you can go ahead and click “Publish an Android App on Google Play”.\n\nThen, you can go ahead and click the button to edit the store listing (We will upload an APK later). You’ll want to fill out the description for the app.\n\nWhen you are ready, upload the APK for the release build and publish the listing. Be patient and your hard work should be live in the wild!\n\n### Updating your App\n\nAs you develop your app, you’ll want to update it periodically.\n\nIn order for the Google Play Store to accept updated APKs, you’ll need to bump the app version (from `/package.json` or from `/quasar.config file > cordova > version`, then rebuild the app for release.\n\n## iOS Publishing\n\nFirst, you need to enroll in Apple Developer Program. As with Google, if you have a personal account with Apple, you can create an additional one for your applications.\n\n### Connecting Xcode with your developer account\n\nAfter you receive your developer status, open Xcode on your Mac and go to Preferences > Accounts. Add your account to Xcode by clicking the `+` button on the lower left-hand side and follow the instructions.\n\n### Signing\n\nNow that you linked Xcode with your developer account, go to Preferences > Accounts, select your Apple Id on the left-hand side and then click the View Details button shown on the previous image.\n\nClick the Create button next to the iOS Distribution option.\n\nYou can learn more about maintaining your signing identities and certificates from the official documentation.\n\n### Setting up the app identifier\n\nNext, through the Apple Developer Member Center we’ll set up the app ID identifier details. Identifiers are used to allow an app to have access to certain app services like for example Apple Pay. You can login to Apple Developer Member Center with your Apple ID and password.\n\nOnce you’re logged in you should choose Certificates, Identifiers, and Profiles option. Also select the Identifiers option under the iOS Apps. Then select the `+` button in order to add a new iOS App ID.\n\nThen you’ll have to set the name of your app, use the Explicit App ID option and set the Bundle ID to the value of the id in your Cordova config.xml tag.\n\nAdditionally, you’ll have to choose any of the services that need to be enabled. For example, if you use Apple Pay or Wallet in your app, you need to choose those option.\n\nYou can learn more about registering app identifiers from the official documentation.\n\n### Creating the app listing\n\nApple uses iTunes Connect to manage app submissions. After your login, you should select the My Apps button, and on the next screen select the `+` button, just below the iTunes Connect My Apps header.\n\nThis will show three options in a dropdown, and you should select the New App. After this the popup appears where you have to choose the name of the application, platform, primary language, bundle ID and SKU.\n\nOnce you’re done, click on the Create button and you’ll be presented with a screen where you’ll have to set some basic options like Privacy Policy URL, category and sub category.\n\nNow, before we fill out everything in the listing, we’ll build our app and get it uploaded with Xcode. Then you’ll come back to finish the listing.\n\nYou can learn more about managing your app in iTunes Connect from the official documentation.\n\n### Building the app for production\n\n```bash\n$ quasar build -m cordova -T ios\n# or the short form:\n$ quasar build -m ios\n\n# passing extra parameters and/or options to\n# underlying \"cordova\" executable:\n$ quasar build -m ios -- some params --and options --here\n```\n\nIf everything went well you’ll see the `BUILD SUCCEEDED` output in the console.\n\n### Opening the project in Xcode\n\nNow, open the `/src-cordova/platforms/ios/\u003cname>.xcodeproj` file in Xcode. You may need to instead use `\u003cname>.xcworkspace` if the next step doesn't work.\n\nOnce the Xcode opens up the project, you should see the details about your app in the general view.\n\nYou should just check that the bundle identifier is set up correctly, so that it’s the same as the value you specified earlier in the app ID. Also, make sure that the version and build numbers are correct. Team option should be set to your Apple developer account. Under the deployment target you can choose which devices your application will support.\n\n### Creating an archive of the application\n\nIn Xcode, select Product > Scheme > Edit Scheme to open the scheme editor. Next, select the Archive from the list on the left-hand side. Make sure that the Build configuration is set to Release.\n\nTo create an archive, choose a Generic iOS Device, or your device if it’s connected to your Mac (you can’t create an archive if simulator is selected), from the Scheme toolbar menu in the project editor.\n\nNext, select Product > Archive, and the Archive organizer appears and displays the new archive. (If it produces an error instead, go back to the last step and open `\u003cname>.xcworkspace`.)\n\nAt this point you can click the `Upload to App Store...` button, and if everything goes fine you’ll have an uploaded app, and the only thing that’s left to do is to complete the iTunes Connect listing and submit it for review!\n\nAt this point you should get an email from iTunes Connect shortly after you uploaded the archive with the content.\n\n### Finishing the app list process\n\nNow you should head back to the iTunes Connect portal and login. Next, click on the Pricing and Availability on the left-hand side under APP STORE INFORMATION.\n\nYou don’t have to worry about forgetting to insert any crucial and required information about your application, since you’ll be notified about what’s missing and what needs to be added/changed if you try to submit the app for review before all details are filled in.\n\nNext, click on the 1.0 Prepare for Submission button on the left-hand side, as shown on the image below. When we uploaded our archive, iTunes Connect automatically determined which device sizes are supported. You’ll need to upload at least one screenshot image for each of the various app sizes that were detected by iTunes Connect.\n\nNext, you’ll have to insert Description, Keywords, Support URL and Marketing URL (optionally).\n\nIn the Build section you have to click on the `+` button and select the build that was uploaded through Xcode in the previous steps.\n\nNext, you’ll have to upload the icon, edit the rating, and set some additional info like copyright and your information. Note that the size of the icon that you’ll have to upload here will have to be 1024 by 1024 pixels. Thankfully, you can use the splash.png from the second tutorial. If you’re the sole developer then the data in the App Review Information should be your own. Finally, as the last option, you can leave the default checked option that once your app is approved that it is automatically released to the App Store.\n\nNow that we’re finished with adding all of the details to the app listing, we can press Save and then Submit for Review. Finally, you’ll be presented with the last form that you’ll have to fill out.\n\nAfter you submit your app for review you’ll see the status of it in the My Apps as Waiting for review, as shown on the image below. Also, shortly after you submit your app for review you’ll get a confirmation email from iTunes Connect that your app is in review.\n\nApple prides itself with a manual review process, which basically means it can take several days for your app to be reviewed. You’ll be notified of any issues or updates to your app status.\n\n### Updating the app\n\nSince you’ll probably want to update your app at some point you’ll first need to bump the app version (from `/package.json` or from `/quasar.config file > cordova > version`, then rebuild the app for release. Finally, you'll have to open it up from the Xcode and follow the same steps all over again.\n\nOnce you submit for the review, you’ll have to wait for the review process again.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":10739,"content_sha256":"fddf445e7b22e7a3cdb531f3597bbc765a857dc8c4cd887723512e55829f508d"},{"filename":"references/docs/quasar-cli-vite/developing-cordova-apps/troubleshooting-and-tips.md","content":"---\ntitle: Cordova Troubleshooting and Tips\ndesc: (@quasar/app-vite) Tips and tricks for a Quasar hybrid mobile app with Cordova.\n---\n\n## $q.cordova\n\nWhile you are developing a Mobile App with Cordova Mode, you can access `$q.cordova` in your Vue files. This is an alias to the global `cordova` Object.\n\n## Android Tips\n\n### Android remote debugging\n\nIf you are debugging Android Apps, you can use Google Chrome Remote Debugging through a USB cable attached to your Android phone/tablet. It can be used for emulator too.\n\nThis way you have Chrome Dev Tools directly for your App running on the emulator/phone/table. Inspect elements, check console output, and so on and so forth.\n\n\n\n\n### Accept Licenses\n\nIf you are having problems getting Android builds to finish and you see a message like:\n\n```\n> Failed to install the following Android SDK packages as some licenses have not been accepted.\n```\n\nIf this is the case you need to accept ALL the licenses. Thankfully there is a tool for this:\n\n- Linux: `sdkmanager --licenses`\n- macOS: `~/Library/Android/sdk/tools/bin/sdkmanager --licenses`\n- Windows: `%ANDROID_SDK_ROOT%/tools/bin/sdkmanager --licenses`\n\n### Android SDK not found after installation of the SDK\n\n::: warning\nThe environmental variable `ANDROID_HOME` has been deprecated and replaced with `ANDROID_SDK_ROOT`. Depending on your version of Android Studio you may need one or the other. It doesn't hurt to have both set.\n:::\n\nSome newer Debian-based OS (e.g. ubuntu, elementary OS) might leave you with a `Android SDK not found.` after you installed and (correctly) configured the environment. The output might look similar to this:\n\n```bash\n$ cordova requirements\n\nRequirements check results for android:\nJava JDK: installed 1.8.0\nAndroid SDK: installed true\nAndroid target: not installed\nAndroid SDK not found. Make sure that it is installed. If it is not at the default location, set the ANDROID_HOME (or ANDROID_SDK_ROOT) environment variable.\nGradle: not installed\nCould not find gradle wrapper within Android SDK. Might need to update your Android SDK.\nLooked here: /home/your_user/Android/Sdk/tools/templates/gradle/wrapper\nError: Some of requirements check failed\n```\n\nThis could have two different reasons: Usually the paths aren't configured correctly. The first step is to verify if your paths are set correctly. This can be done by running the following commands:\n\n```bash\n$ echo $ANDROID_HOME\n\n# or\n\n$ echo $ANDROID_SDK_ROOT\n```\n\nThe expected output should be a path similar to this `$HOME/Android/Sdk`. After this run:\n\n```bash\n$ ls -la $ANDROID_HOME\n\n# or\n\n$ ls -la $ANDROID_SDK_ROOT\n```\n\nTo ensure the folder contains the SDK. The expected output should contain folders like 'tools', 'sources', 'platform-tools', etc.\n\n```bash\n$ echo $PATH\n```\n\nThe output should contain each one entry for the Android SDK 'tools'-folder and 'platform-tools'-tools. This could look like this:\n\n```bash\n/home/your_user/bin:/home/your_user/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/your_user/Android/Sdk/tools:/home/your_user/Android/Sdk/platform-tools\n```\n\n> If you ensured your paths are set correctly and still get the error on `cordova requirements` you can try the following fix: Replacing the Android Studio 'tools' folder manually\n\n### Android Studio\n\nIn Android Studio (if you open it on `/src-cordova/platforms/android`), you will be greeted with a message recommending to upgrade the Gradle version. **DO NOT UPGRADE GRADLE** as it will break the Cordova project. Same goes for any other requested upgrades.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-upgrade-notice.png\" alt=\"Gradle upgrade\" class=\"q-mb-md rounded-borders\" style=\"max-width: 350px\">\n\nIf you encounter any IDE errors then click on File > Invalidate caches and restart.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-invalidate-cache.png\" alt=\"Gradle upgrade\" class=\"rounded-borders\" style=\"max-width: 350px\">\n\n### Setting up device on Linux\n\nYou may bump into `?????? no permissions` problem when trying to run your App directly on an Android phone/tablet.\n\nHere's how you fix this:\n\n```bash\n# create the .rules file and insert the content\n# from below this example\nsudo vim /etc/udev/rules.d/51-android.rules\nsudo chmod 644 /etc/udev/rules.d/51-android.rules\nsudo chown root. /etc/udev/rules.d/51-android.rules\nsudo service udev restart\nsudo killall adb\n```\n\nThe content for `51-android.rules`:\n\n```\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0bb4\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0e79\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0502\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0b05\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"413c\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0489\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"091e\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"18d1\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0bb4\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"12d1\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"24e3\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"2116\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0482\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"17ef\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"1004\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"22b8\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0409\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"2080\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0955\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"2257\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"10a9\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"1d4d\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0471\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"04da\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"05c6\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"1f53\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"04e8\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"04dd\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0fce\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0930\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"19d2\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"1bbb\", MODE=\"0666\"\n```\n\nNow running `adb devices` should discover your device.\n\n### Post-build debugging\n\nThere are intermediate states to help with debugging, between `quasar dev` and distributing a completed app. If your app works fine on `quasar dev` but is not running properly after `quasar build`, you have two options:\n\n- go to your `src-cordova` directory and `cordova run [platform]`.\n - You will be running the final build, but you can still use Chrome DevTools Remote Debugging with a wired connection (see above), to inspect the internal web internals. You cannot do this while running the .apk file.\n - For more detail, read the Cordova platform guide and the CLI reference\n- open Android Studio and watch the Logcat\n - Here you can watch everything related to the app and its interaction with the underlying Android OS. After opening your Cordova project in Android Studio, go to `Run`...`Debug` from the top menu. Android Studio will ask you to confirm the device or emulator, then will deploy the app. In the bottom window, choose `Logcat` You may want to use the filters to reduce the volume of messages. You should see `[your app id].MainActivity.onCreate()` signifying the app launch, then various messages related to your app functionality.\n - Note: this should be for experienced Android developers only. If your app is not functioning properly, it is much more likely that `quasar dev` or `cordova run` can reveal the issue.\n\n::: danger Important!\nIf you find a bug using one of the above methods, do not edit the output files (probably the `www` folder) directly, as they will soon be overwritten. Go back to your quasar source, fix the bug, then re-run `quasar build`.\n:::\n\n## iOS Tips\n\n### Device type not found\n\nIf you get this error while running `$ quasar dev -m cordova -T ios`:\n\n```\nNo target specified for emulator. Deploying to undefined simulator\nDevice type \"com.apple.CoreSimulator.SimDeviceType.undefined\" could not be found.\n```\n\nThen it means you need to specify an emulator. Depending on your Cordova CLI version, here are some examples:\n\n```bash\n$ quasar dev -m cordova -T ios -e iPhone-X,12.2\n# or with older versions of Cordova CLI installed on your machine:\n$ quasar dev -m cordova -T ios -e iPhone-X,com.apple.CoreSimulator.SimRuntime.iOS-12-2\n```\n\n### Enabling modern build\n\nBy default, Xcode modern build for iOS is disabled due to Cordova issues. However, if you know what you are doing and you want to enable it, do so from the `/quasar.config` file:\n\n```js\ncordova: {\n noIosLegacyBuildFlag: true\n}\n```\n\nThe above applies also if you want to specify the build type in your \"build.json\".\n\n### iOS remote debugging\n\nIf you are debugging iOS Apps, you can use the Safari developer tools to remotely debug through a USB cable attached to your iOS phone/tablet. It can be used for emulator too.\n\nThis way you have Safari developer tools directly for your App running on the emulator/phone/table. Inspect elements, check console output, and so on and so forth.\n\nFirst enable the \"developer\" menu option in the Settings of Safari. Then if you navigate to the \"developer\" menu option you will see your emulator or connected device listed near the top. From here you can open the developer tools.\n\n### Status bar and notch safe-areas\n\nSince mobile phones have a status bar and/or notches, your app's styling might need some tweaking when building on Cordova. In order to prevent parts of your app from going behind the status bar, there is a global CSS variable that can be used for creating a \"safe-area\". This variable can then be applied in your app's top and bottom padding or margin.\n\nQuasar has support for these CSS safe-areas by default in QHeader/QFooter and Notify. However it's important to always check your Cordova build on several models to see if all cases of your app are dealing with the safe areas correctly.\n\nIn cases you need to manually tweak your CSS you can do so with:\n\n```css\n/* for your app's header */\npadding-top: constant(safe-area-inset-top); // for iOS 11.0\npadding-top: env(safe-area-inset-top); // for iOS 11.2 +\n/* for your app's footer */\npadding-bottom: constant(safe-area-inset-bottom);\npadding-bottom: env(safe-area-inset-bottom);\n```\n\nOf course you can also use the above example with `margin` instead of `padding` depending on your app.\n\nIn order to make sure these are only added when opened on mobile via the Cordova build, you can check for the CSS class `.cordova` which is automatically added to the body by Quasar. Example:\n\n```css\nbody.cordova .my-selector {\n padding-top: constant(safe-area-inset-top);\n padding-top: env(safe-area-inset-top);\n}\n```\n\n### Disabling iOS rubber band effect\n\nWhen building an iOS app with Cordova and you want to disable the rubber band effect, add this to your `/src-cordova/config.xml`:\n\n```xml\n\u003cpreference name=\"DisallowOverscroll\" value=\"true\" />\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":11073,"content_sha256":"48b30913c89431630e6b1fee1c88c1c035d8733f7e444f5a11a3871050fe4284"},{"filename":"references/docs/quasar-cli-vite/developing-electron-apps/app-icons-electron.md","content":"---\ntitle: App Icons for Electron\ndesc: (@quasar/app-vite) How to manage the app icons for a Desktop Quasar app.\nscope:\n tree:\n l: src-electron\n c:\n - l: icons\n c:\n - l: icon.ico\n - l: icon.icns\n - l: icon.png\n---\n\nThese images are used to display the icon of the application in the desktop operating system in the tray, on the desktop, in the file-browser and in relevant stores. The `icon.ico` file is for Windows and `icon.icns` is for MacOS. If you discover any that are missing, please open an issue.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/iconfactory.png\" style=\"float:right;max-width:15%;min-width:240px;padding-top:40px\">\n\n## Icon Genie CLI\n\n::: tip\nWe highly recommend using the [Icon Genie CLI](/icongenie/introduction), because it consumes a source icon and automatically clones, scales, minifies and places the icons in the appropriate directories for you. When needed, it also tells you what tags you'll need to add to your /index.html file.\n:::\n\nQuickly bootstrap the necessary images with Icon Genie CLI. For a complete list of options, please visit the [Icon Genie CLI](/icongenie/command-list) command list page.\n\n```bash\n$ icongenie generate -m electron -i /path/to/source/icon.png\n```\n\n## Manual instructions\n\n\u003cDocTree :def=\"scope.tree\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1304,"content_sha256":"04891e6e6f783a2eb9348b25a28a724faf6f8cb7fcc85aa92473e6bf58b55093"},{"filename":"references/docs/quasar-cli-vite/developing-electron-apps/build-commands.md","content":"---\ntitle: Electron Build Commands\ndesc: (@quasar/app-vite) The Quasar CLI list of commands when developing or building a desktop app.\n---\n\n## Developing\n\n```bash\n$ quasar dev -m electron\n\n# ..or the longer form:\n$ quasar dev --mode electron\n\n# passing extra parameters and/or options to\n# underlying \"electron\" executable:\n$ quasar dev -m electron -- --no-sandbox --disable-setuid-sandbox\n# when on Windows and using Powershell:\n$ quasar dev -m electron '--' --no-sandbox --disable-setuid-sandbox\n```\n\nIt opens up an Electron window with dev-tools included. You have HMR for the renderer process and changes to main process are also picked up (but the latter restarts the Electron window on each change).\n\nCheck how you can tweak Esbuild config Object for the Main Process and the Preload script on the [Configuring Electron](/quasar-cli-vite/developing-electron-apps/configuring-electron) page.\n\n### Chrome DevTools\n\nWhile in dev mode, hit the following combination (while your app window has focus):\n\n- macOS: \u003ckbd>Cmd\u003c/kbd> \u003ckbd>Alt\u003c/kbd> \u003ckbd>I\u003c/kbd> or \u003ckbd>F12\u003c/kbd>\n- Linux: \u003ckbd>Ctrl\u003c/kbd> \u003ckbd>Shift\u003c/kbd> \u003ckbd>I\u003c/kbd> or \u003ckbd>F12\u003c/kbd>\n- Windows: \u003ckbd>Ctrl\u003c/kbd> \u003ckbd>Shift\u003c/kbd> \u003ckbd>I\u003c/kbd> or \u003ckbd>F12\u003c/kbd>\n\n### Vuejs Devtools\n\nShould you want to also access Vue Devtools for the renderer thread:\n\n```bash\n$ quasar dev -m electron --devtools\n```\n\n## Building for Production\n\n```bash\n$ quasar build -m electron\n\n# ..or the longer form:\n$ quasar build --mode electron\n```\n\nIt builds your app for production and then uses @electron/packager to pack it into an executable. Check how to configure this on [Configuring Electron](/quasar-cli-vite/developing-electron-apps/configuring-electron) page.\n\nIf you want a production build with debugging enabled for the UI code:\n\n```bash\n$ quasar build -m electron -d\n\n# ..or the longer form\n$ quasar build -m electron --debug\n```\n\n### A note for non-Windows users\n\nIf you want to build for Windows with a custom icon using a non-Windows platform, you must have wine installed. More Info.\n\n## Publishing (electron-builder only)\n\n```bash\n$ quasar build -m electron -P always\n\n# ..or the longer form:\n$ quasar build --mode electron --publish always\n```\n\nYou can specify using `electron-builder` to build your app either directly on the command line (`--bundler builder`) or by setting it explicitly within the `quasar.config` file at `electron.bundler`. This flag has no effect when using `@electron/packager`.\n\nCurrently (June 2019) supported publishing destinations include GitHub, Bintray, S3, Digital Ocean Spaces, or a generic HTTPS server. More information, including how to create valid publishing instructions, can be found here.\n\nValid options for `-P` are \"onTag\", \"onTagOrDraft\", \"always\" and \"never\" which are explained at the above link. In addition, you must have valid `publish` configuration instructions in your `quasar.config` file at `electron.builder`.\n\nA very basic configuration to publish a Windows EXE setup file to Amazon S3 might look like this:\n\n```js /quasar.config file\nelectron: {\n bundler: 'builder', // set here instead of using command line flag --bundler\n builder: {\n appId: 'com.electron.myelectronapp',\n win: {\n target: 'nsis'\n },\n publish: {\n 'provider': 's3',\n 'bucket': 'myS3bucket'\n }\n }\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3314,"content_sha256":"90e366bba1f16a721a085768b5016fadaa8b7bf3f9f45a41b478dca77889a0c4"},{"filename":"references/docs/quasar-cli-vite/developing-electron-apps/configuring-electron.md","content":"---\ntitle: Configuring Electron\ndesc: (@quasar/app-vite) How to manage your Electron apps with Quasar CLI.\nrelated:\n - /quasar-cli-vite/quasar-config-file\n---\n\nWe'll be using Quasar CLI to develop and build an Electron App. The difference between building a SPA, PWA, Mobile App or an Electron App is simply determined by the \"mode\" parameter in \"quasar dev\" and \"quasar build\" commands.\n\nBut first, let's learn how we can configure the Electron build.\n\n## quasar.config file\n\n```js /quasar.config file > sourceFiles\n// should you wish to change default files\n// (notice no extension, so it resolves to both .js and .ts)\nsourceFiles: {\n electronMain?: 'src-electron/electron-main',\n}\n```\n\n```js /quasar.config file > electron\nelectron: {\n /**\n * The list of content scripts (js/ts) that you want embedded.\n * Each entry in the list should be a filename (WITHOUT its extension) from /src-electron/\n *\n * @default [ 'electron-preload' ]\n * @example [ 'my-other-preload-script' ]\n */\n preloadScripts?: string[];\n\n /**\n * Add/remove/change properties of production generated package.json\n */\n extendPackageJson?: (pkg: { [index in string]: any }) => void;\n\n /**\n * Extend the Esbuild config that is used for the electron-main thread\n */\n extendElectronMainConf?: (config: EsbuildConfiguration) => void;\n\n /**\n * Extend the Esbuild config that is used for the electron-preload thread\n */\n extendElectronPreloadConf?: (config: EsbuildConfiguration) => void;\n\n /**\n * You have to choose to use either packager or builder.\n * They are both excellent open-source projects,\n * however they serve slightly different needs.\n * With packager you will be able to build unsigned projects\n * for all major platforms from one machine.\n * Although this is great, if you just want something quick and dirty,\n * there is more platform granularity (and general polish) in builder.\n * Cross-compiling your binaries from one computer doesn’t really work with builder,\n * or we haven’t found the recipe yet.\n */\n // This property definition is here merely to avoid duplicating the TSDoc\n // It should not be optional, as TS cannot infer the discriminated union based on the absence of a field\n // Futhermore, making it optional here won't change the exported interface which is the union\n // of the two derivate interfaces where `bundler` is set without optionality\n bundler?: \"packager\" | \"builder\";\n packager?: ElectronPackager.Options;\n builder?: ElectronBuilder.Configuration;\n\n /**\n * Specify additional parameters when installing dependencies in\n * the UnPackaged folder, right before bundling with either\n * electron packager or electron builder;\n * Example: [ 'install', '--production', '--ignore-optional', '--some-other-param' ]\n */\n unPackagedInstallParams?: string[];\n\n /**\n * Specify the debugging port to use for the Electron app when running in development mode\n * @default 5858\n */\n inspectPort?: number;\n}\n```\n\nThe \"packager\" prop refers to @electron/packager options. The `dir` and `out` properties are overwritten by Quasar CLI to ensure the best results.\n\nThe \"builder\" prop refers to electron-builder options.\n\nShould you want to tamper with the \"Renderer\" thread (UI in /src) Vite config:\n\n```js /quasar.config file\nexport default defineConfig(ctx => {\n return {\n build: {\n extendViteConf(viteConf) {\n if (ctx.mode.electron) {\n // do something with viteConf\n // or return an object to deeply merge with current viteConf\n }\n }\n }\n }\n})\n```\n\n## Packager vs. Builder\n\nYou have to choose to use either packager or builder. They are both excellent open-source projects, however they serve slightly different needs. With packager you will be able to build unsigned projects for all major platforms from one machine (with restrictions). Although this is great, if you just want something quick and dirty, there is more platform granularity (and general polish) in builder. Cross-compiling your binaries from one computer doesn't really work with builder (or we haven't found the recipe yet...)\n\n## Dependencies optimization\n\nBy default, all `dependencies` from your root `package.json` file get installed and embedded into the production executable.\n\nThis means that it will also include your UI-only deps, which are already bundled in the UI files (so it will duplicate them). From our CLI perspective, we don't have any generic way of telling whether a dependency is UI only or if it's used by the main/preload scripts, so we cannot reliably auto-remove them.\n\nHowever, you can do this by using quasar.conf > electron > extendPackageJson(pkg) and overwriting or tampering with the `dependencies` key from your `package.json` file. If you leave only the main & preload threads depdendencies then this will lead to a smaller production executable file.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4884,"content_sha256":"468f20149bd236798bd4ec490257b653125736dbac0ab3b3a03ac300620abab1"},{"filename":"references/docs/quasar-cli-vite/developing-electron-apps/electron-accessing-files.md","content":"---\ntitle: Electron Accessing Files\ndesc: (@quasar/app-vite) How to access files in a Quasar desktop app.\nscope:\n tree:\n l: app.asar\n c:\n - l: dist\n c:\n - l: electron-*\n c:\n - l: js/...\n - l: icons/\n - l: node_modules/\n - l: index.html\n - l: package.json\n - l: electron-main.js\n e: (or .ts)\n - l: electron-preload.js\n e: (or .ts)\n - l: '...contents of /public'\n---\n\n## Using **dirname & **filename\n\nSince the main process is bundled using Esbuild, the use of `__dirname` and `__filename` will not provide an expected value in production. Referring to the File Tree, you'll notice that in production the electron-main.js and electron-preload.js files are placed inside the `dist/electron-*` folder. Based on this knowledge, use `__dirname` & `__filename` accordingly.\n\n\u003cDocTree :def=\"scope.tree\" />\n\n## Read & Write Local Files\n\nOne great benefit of using Electron is the ability to access the user's file system. This enables you to read and write files on the local system. To help avoid Chromium restrictions and writing to your application's internal files, make sure to make use of electron's APIs, specifically the app.getPath(name) function. This helper method can get you file paths to system directories such as the user's desktop, system temporary files, etc.\n\nWe can use the userData directory, which is reserved specifically for our application, so we can have confidence other programs or other user interactions should not tamper with this file space.\n\n### Prepping\n\nYou will need the `@electron/remote` dependency installed into your app:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add @electron/remote\n\u003c\u003c| bash NPM |>>\n$ npm install --save @electron/remote\n\u003c\u003c| bash PNPM |>>\n$ pnpm add @electron/remote\n\u003c\u003c| bash Bun |>>\n$ bun add @electron/remote\n```\n\nThen, in your `src-electron/electron-main.js` file, make some edits to these lines:\n\n```js /electron-main.js\nimport { app, BrowserWindow, nativeTheme } from 'electron'\nimport { initialize, enable } from '@electron/remote/main' // \u003c-- add this\nimport path from 'path'\n\ninitialize() // \u003c-- add this\n\n// ...\n\nmainWindow = new BrowserWindow({\n // ...\n webPreferences: {\n sandbox: false // \u003c-- to be able to import @electron/remote in preload script\n // ...\n }\n})\n\nenable(mainWindow.webContents) // \u003c-- add this\n\nmainWindow.loadURL(process.env.APP_URL)\n\n// ...\n```\n\n### Usage\n\nFinally, here's an example of how to access files:\n\n```js /electron-main or /electron-preload\nimport path from 'path'\nimport { app } from '@electron/remote'\n\nconst filePath = path.join(app.getPath('userData'), '/some.file')\n```\n\nIf you import `@electron/remote` in your preload script, please remember that you need to set the following in your `electron-main.js` where you instantiate BrowserWindow:\n\n```js /electron-main\nmainWindow = new BrowserWindow({\n // ...\n webPreferences: {\n // ...\n sandbox: false // \u003c-- to be able to import @electron/remote in preload script\n }\n}\n```\n\n## Accessing the Public Folder\n\nIf for some reason, you have important files that you are storing in the /public folder, you can access those too by following the code below. To understand why you need to access them this way, please read the \"Using **dirname & **filename\" section above.\n\n```js /electron-main or /electron-preload\nimport path from 'path'\nimport { fileURLToPath } from 'url'\n\nconst currentDir = fileURLToPath(new URL('.', import.meta.url))\n\nconst publicFolder = path.resolve(currentDir, process.env.QUASAR_PUBLIC_FOLDER)\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3643,"content_sha256":"4b311d06f792b735ac6f1101d26ccdc6c07b959d6c75ddc7205d3356d3631839"},{"filename":"references/docs/quasar-cli-vite/developing-electron-apps/electron-packages.md","content":"---\ntitle: Electron Packages\ndesc: (@quasar/app-vite) The list of Electron packages available in a Quasar app.\n---\n\nYou can yarn/npm/pnpm/bun install and use Electron specific packages in your main thread and preload script. Take a look at the link and choose wisely if you need to. Make sure these are installed into `dependencies` and NOT `devDependencies` in your `package.json` file.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":388,"content_sha256":"7501ea165472540b1de80be1359f5ce8759425af167ce3606170b2ca4da73608"},{"filename":"references/docs/quasar-cli-vite/developing-electron-apps/electron-preload-script.md","content":"---\ntitle: Electron Preload Script\ndesc: (@quasar/app-vite) How to handle Electron Node Integration with an Electron Preload script with Quasar CLI.\n---\n\nFor security reasons, the renderer thread (your UI code from `/src`) does not have access to the Node.js stuff. However, you can run Node.js code and bridge it to the renderer thread through an Electron Preload script located at `/src-electron/electron-preload.js`. Use `contextBridge` (from the `electron` package) to expose the stuff that you need for your UI.\n\nSince the preload script runs from Node.js, be careful what you do with it and what you expose to the renderer thread!\n\n## How to use it\n\nIn `/src-electron/` folder, there is a file named `electron-preload.js`. Fill it with your preload code.\n\nMake sure that your `/src-electron/electron-main.js` has the following (near the \"webPreferences\" section):\n\n```js /src-electron/electron-main\n// Add this at the top:\nimport path from 'path'\nimport { fileURLToPath } from 'url'\n\nconst currentDir = fileURLToPath(new URL('.', import.meta.url))\n// ...\n\nfunction createWindow () {\n // ...\n mainWindow = new BrowserWindow({\n // ...\n webPreferences: {\n // HERE IS THE MAGIC:\n preload: path.resolve(\n currentDir,\n path.join(process.env.QUASAR_ELECTRON_PRELOAD_FOLDER, 'electron-preload' + process.env.QUASAR_ELECTRON_PRELOAD_EXTENSION)\n )\n }\n })\n```\n\nExample of `/src-electron/electron-preload.js` content:\n\n```js\n// example which injects window.myAPI.doAThing() into the renderer\n// thread (/src/*)\n\nconst { contextBridge } = require('electron')\n\ncontextBridge.exposeInMainWorld('myAPI', {\n doAThing: () => {}\n})\n```\n\n::: warning\n\n1. Be aware that this file runs in a Node.js context.\n2. If you import anything from node_modules, then make sure that the package is specified in /package.json > \"dependencies\" and NOT in \"devDependencies\".\n :::\n\n## Security considerations\n\nJust by using `contextBridge` does not automatically mean that everything you do is safe. For instance the code below is unsafe:\n\n```js\n// BAD code; DON'T!!\ncontextBridge.exposeInMainWorld('myAPI', {\n send: ipcRenderer.send\n})\n```\n\nIt directly exposes a powerful API without any kind of argument filtering. This would allow any website to send arbitrary IPC messages which you do not want to be possible. The correct way to expose IPC-based APIs would instead be to provide one method per IPC message.\n\n```js\n// Good code\ncontextBridge.exposeInMainWorld('myAPI', {\n loadPreferences: () => ipcRenderer.invoke('myAPI:load-prefs')\n})\n```\n\nNow, `loadPreferences` is available globally in your javascript code (ie: `window.myAPI.loadPreferences`).\n\n::: warning\nMake sure to pick names which do not colide with existing `Window` keys.\n:::\n\nUsing the above code with an `invoke` to `load-prefs` in the main thread would have code like this:\n\n```js\nipcMain.handle('myAPI:load-prefs', () => {\n return {\n // object that contains preferences\n }\n})\n```\n\n## Custom path to the preload script\n\nShould you wish to change the location of the preload script (and/or even the main thread file) then edit the `/quasar.config` file:\n\n```js /quasar.config file\n// should you wish to change default files\nsourceFiles: {\n electronMain: 'src-electron/electron-main.js'\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3282,"content_sha256":"392e37cfb8ea44e5b158ee5a3b60b22ed89f14d7d64f0f081a01786bff5e496d"},{"filename":"references/docs/quasar-cli-vite/developing-electron-apps/electron-security-concerns.md","content":"---\ntitle: Electron Security Concerns\ndesc: (@quasar/app-vite) The things you should know about security in a Quasar desktop app.\n---\n\nIf you are not vigilant when building Electron apps, you will probably be placing the users of your app in tangible digital danger. Things like XSS (Cross Site Scripting) and remote code execution can literally enable attackers to get deep access to the data in your app - and potentially even the underlying operating system.\n\nEspecially when working \"in the open\", i.e. as an open-source project, you will definitely want to consider hardening your application with code-signing and integrity checking. (See \"Tips\" section)\n\n::: danger\nUnder no circumstances should you load and execute remote code. Instead, use only local files (packaged together with your application) to execute Node.js code in your main thread and/or preload script.\n:::\n\n## Checklist: Security Recommendations\n\nThe Electron team itself makes the following recommendations:\n\n1. Make sure that you leave `webPreferences` > `contextIsolation` set to `true`. Use the [preload script](/quasar-cli-vite/developing-electron-apps/electron-preload-script) to inject only must-have APIs to the renderer thread.\n2. If you must load remote content and cannot work around that, then only load secure content\n3. Use `ses.setPermissionRequestHandler()` in all sessions that load remote content\n4. Do not disable `webSecurity`\n5. Do not set `allowRunningInsecureContent` to `true`\n6. Do not enable experimental features\n7. Do not use `enableBlinkFeatures`\n8. `\u003cwebview>`: Do not use `allowpopups`\n9. `\u003cwebview>`: Verify options and params\n10. Disable or limit navigation\n11. Disable or limit creation of new windows\n\nExcept for items 3 and 4 above, Electron will put a warning in the dev console if one of the these issues have been detected.\n\n## Tips and Tricks\n\n#### Communication Protocols\n\nYou should know this by now, but if you are not using **https** / **sftp** / **wss** then the app's communications with the outside world can be very easily tampered with. Whatever you are building, please use a secure protocol everywhere.\n\n#### Filesystem Access\n\nHaving read & write permissions to the filesystem is the holy grail for penetration testers, and if your app enables this type of interaction, consider using IPC and multiple windows (with varying permissions) in order to minimize the attack surface.\n\n#### Encryption\n\nIf the user of your application has secrets like wallet addresses, personal information or some other kind of trade secrets, keep that information encrypted when at rest, un-encrypt it in-memory only when it is needed and make sure to overwrite / destroy the object in memory when you are done with it. But no matter how you approach this, follow these four rules:\n\n1. use strong crypto (i.e. collision resistant and not md5)\n2. do not invent a novel type of encryption\n3. follow the implementation instructions explicitly\n4. think about the user-experience\n\n#### Disable developer tools in production\n\nYou probably don't want rogue hoody-wearing menaces to be executing something like this in the console of your app:\n\n```js\nwindow.location = 'https://evilsite.com/looks-just-like-your-app'\n```\n\nThe key-combination \u003ckbd>CTRL\u003c/kbd>+\u003ckbd>SHIFT\u003c/kbd>+\u003ckbd>I\u003c/kbd> (or \u003ckbd>ALT\u003c/kbd>+\u003ckbd>CMD\u003c/kbd>+\u003ckbd>I\u003c/kbd> on Mac) will open the dev tools and enable inspection of the application. It will even enable some degree of modification. Prevent the simple `evil maid` attack by catching these keypresses and `return false`.\n\n#### Publish checksums\n\nWhen you have built your binary blobs and want to publish them e.g. on GitHub, use `shasum` and post these results somewhere prominent (like on the GitHub release page for your project) and potentially on a public blockchain, such as Steem.\n\n```bash\n$ shasum -a 256 myApp-v1.0.0_darwin-x64.dmg\n40ed03e0fb3c422e554c7e75d41ba71405a4a49d560b1bf92a00ea6f5cbd8daa myApp-v1.0.0_darwin-x64.dmg\n```\n\n#### Sign the builds\n\nAlthough not a hard requirement for sharing your app, signing code is a best practice - and it is required by both the MacOS and Windows stores. Read more about it at this official Electron tutorial.\n\n#### Use SNYK\n\nSnyk.io is a service, CLI and even GitHub integration bot that tracks vulnerabilities in node modules by comparing the dependencies in your package.json with its list of compromised modules. In many cases their service can recommend minimum update versions or even provide modules that they themselves have patched. They also undertake research and vulnerability disclosure. For an example of something that should scare the socks off of you if you are doing anything with compressed files (zip, tar, etc.) check out their writeup and list of affected software.\n\n#### For the truly paranoid\n\nUse a dedicated physical desktop machine for each platform target. If you have to keep this device online, make sure the OS is always updated, permits zero inbound connections from the internet / bluetooth (especially for shell / ssh) and run constant virus and rootkit checks.\n\nPermit only GPG-signed commits to be merged and require at least two team members (who did not make the PR) to review and approve the commit.\n\nReconsider your node package management system:\n\n- use a private npm registry (like JFrog)\n- fix your packages to specific versions known to work\n- use pnpm\n- audit each and every single module and its dependencies\n\n#### Pay to get hacked\n\nSomebody smart might have hacked your project (or an underlying library). If you are making money with this app, consider getting a Hacker One account and running a constant bounty award. At least you'll be able to convince the hacker to be ethical and NOT sell the exploit to your competitor.\n\n#### Get help\n\nYou may feel overwhelmed, because the awesomeness of Electron brings with it a great many headaches that you never wanted to think about. If this is the case, consider [reaching out](mailto:[email protected]) and getting expert support for the review, audit and hardening of your app by the team of seasoned devs that brought you the Quasar Framework.\n\n\u003cq-separator class=\"q-mt-xl\" />\n\n> Parts of this page have been taken from the official Electron Security Guide.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":6245,"content_sha256":"5d8f5921eb9303cb55ecdd8f6e5235200afe264a852c048ddc56f2abac6750cd"},{"filename":"references/docs/quasar-cli-vite/developing-electron-apps/electron-upgrade-guide.md","content":"---\ntitle: Upgrade guide on Electron\ndesc: (@quasar/app-vite) Upgrading instructions when dealing with Electron in Quasar.\n---\n\n## Upgrading Electron\n\nWhen you add the Electron mode in a Quasar project for the first time you will get the latest version of the Electron package. At some point in time, you will want to upgrade the Electron version.\n\nBefore upgrading Electron, please consult its release notes. Are there breaking changes?\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n# from the root of your Quasar project\n$ yarn upgrade electron@latest\n\u003c\u003c| bash NPM |>>\n# from the root of your Quasar project\n$ npm install electron@latest\n\u003c\u003c| bash PNPM |>>\n# from the root of your Quasar project\n$ pnpm add electron@latest\n\u003c\u003c| bash Bun |>>\n# from the root of your Quasar project\n$ bun add electron@latest\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":791,"content_sha256":"8dd26ac39976fbde67dde32eead03ab4f09dd6a5071fca92aaa80e9e663bf00f"},{"filename":"references/docs/quasar-cli-vite/developing-electron-apps/electron-with-typescript.md","content":"---\ntitle: Electron with Typescript\ndesc: (@quasar/app-vite) How to use Typescript with Electron in Quasar\n---\n\nIn order to support Electron with Typescript, you will need to rename the extension for your files in /src-electron from `.js` to `.ts` and make the necessary TS code changes.\n\n::: tip\n`@electron/packager` and `electron-builder` export their configuration types from their own packages.\nSince autocomplete into the `quasar.config` file relies on those types, properties `electron.packager` and `electron.builder` will be fully typed only after the respective package is installed.\nYou can force the installation of the selected bundler (depending on your `electron.bundler` option) by running a build command in Electron mode: `quasar build -m electron`\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":770,"content_sha256":"fe7f6f3962ffba856a26a7e38601ed36052b0aa52be7331a793fc5efef2a9f1b"},{"filename":"references/docs/quasar-cli-vite/developing-electron-apps/frameless-electron-window.md","content":"---\ntitle: Frameless Electron Window\ndesc: (@quasar/app-vite) How to hide the window frame in a Quasar desktop app.\nexamples: frameless-electron-window\nrelated:\n - /vue-components/bar\n---\n\nA nice combo is to use frameless Electron window along with [QBar](/vue-components/bar) component. Here's why.\n\n## Main thread\n\n### Setting frameless window\n\nFirstly, install the `@electron/remote` dependency into your app.\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add @electron/remote\n\u003c\u003c| bash NPM |>>\n$ npm install --save @electron/remote\n\u003c\u003c| bash PNPM |>>\n$ pnpm add @electron/remote\n\u003c\u003c| bash Bun |>>\n$ bun add @electron/remote\n```\n\nThen, in your `src-electron/main-process/electron-main.js` file, make some edits to these lines:\n\n```js /src-electron/main-process/electron-main\nimport { app, BrowserWindow, nativeTheme } from 'electron'\nimport { initialize, enable } from '@electron/remote/main' // \u003c-- add this\nimport path from 'path'\n\ninitialize() // \u003c-- add this\n\n// ...\n\nmainWindow = new BrowserWindow({\n width: 1000,\n height: 600,\n useContentSize: true,\n frame: false // \u003c-- add this\n webPreferences: {\n sandbox: false // \u003c-- to be able to import @electron/remote in preload script\n // ...\n }\n})\n\nenable(mainWindow.webContents) // \u003c-- add this\n\nmainWindow.loadURL(process.env.APP_URL)\n\n// ...\n```\n\nNotice that we need to explicitly enable the remote module too. We'll be using it in the preload script to provide the renderer thread with the window minimize/maximize/close functionality.\n\n### The preload script\n\nSince we can't directly access Electron from within the renderer thread, we'll need to provide the necessary functionality through the electron preload script (`src-electron/main-process/electron-preload.js`). So we edit it to:\n\n```js /src-electron/main-process/electron-preload\nimport { contextBridge } from 'electron'\nimport { BrowserWindow } from '@electron/remote'\n\ncontextBridge.exposeInMainWorld('myWindowAPI', {\n minimize() {\n BrowserWindow.getFocusedWindow().minimize()\n },\n\n toggleMaximize() {\n const win = BrowserWindow.getFocusedWindow()\n\n if (win.isMaximized()) {\n win.unmaximize()\n } else {\n win.maximize()\n }\n },\n\n close() {\n BrowserWindow.getFocusedWindow().close()\n }\n})\n```\n\n## Renderer thread\n\n### Handling window dragging\n\nWhen we use a frameless window (only frameless!) we also need a way for the user to be able to move the app window around the screen. You can use `q-electron-drag` and `q-electron-drag--exception` Quasar CSS helper classes for this.\n\n```html\n\u003cq-bar class=\"q-electron-drag\"> ... \u003c/q-bar>\n```\n\nWhat this does is that it allows the user to drag the app window when clicking, holding and simultaneously dragging the mouse on the screen.\n\nWhile this is a good feature, you must also take into account that you'll need to specify some exceptions. There may be elements in your custom statusbar that you do not want to trigger the window dragging. By default, [QBtn](/vue-components/button) is **excepted from this behavior** (no need to do anything for this). Should you want to add exceptions to any children of the element having `q-electron-drag` class, you can attach the `q-electron-drag--exception` CSS class to them.\n\nExample of adding an exception to an icon:\n\n```html\n\u003cq-bar class=\"q-electron-drag\">\n \u003cq-icon name=\"map\" class=\"q-electron-drag--exception\" />\n\n \u003cdiv>My title\u003c/div>\n\u003c/q-bar>\n```\n\n### Minimize, maximize and close app\n\n\u003cDocExample title=\"Full example\" file=\"StatusBar\" />\n\nIn the example above, notice that we add `q-electron-drag` to our QBar and we also add handlers for the minimize, maximize and close app buttons by using the injected `window.myWindowAPI` Object (from the Electron preload script).\n\n```js Some .vue file\n// We guard the Electron API calls, but this\n// is only needed if we build same app with other\n// Quasar Modes as well (SPA/PWA/Cordova/SSR...)\n\nexport default {\n setup() {\n // we rely upon\n function minimize() {\n if (process.env.MODE === 'electron') {\n window.myWindowAPI.minimize()\n }\n }\n\n function toggleMaximize() {\n if (process.env.MODE === 'electron') {\n window.myWindowAPI.toggleMaximize()\n }\n }\n\n function closeApp() {\n if (process.env.MODE === 'electron') {\n window.myWindowAPI.close()\n }\n }\n\n return { minimize, toggleMaximize, closeApp }\n }\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4371,"content_sha256":"a719f690b742bde25e41c4c29ab523d3bc758536fb244c20d5d49c36408d3720"},{"filename":"references/docs/quasar-cli-vite/developing-electron-apps/introduction.md","content":"---\ntitle: What is Electron\ndesc: (@quasar/app-vite) Introduction about the technology behind Quasar desktop apps.\n---\n\nElectron (formerly known as Atom Shell) is an open-source framework created by Cheng Zhao, and now developed by GitHub. **It allows for the development of desktop GUI applications** using front and back end components originally developed for web applications: Node.js runtime for the backend and Chromium for the frontend. Electron is the main GUI framework behind several notable open-source projects including GitHub's Atom and Microsoft's Visual Studio Code source code editors, the Tidal music streaming service desktop application and the Light Table IDE, in addition to the freeware desktop client for the Discord chat service.\n\nEach Electron app has two threads: one is the main thread (dealing with the App window and bootup), and one is the renderer thread (which is basically your UI web code). There is also a preload script to bridge the two \"worlds\".\n\n## Renderer Thread\n\nElectron uses Chromium for displaying web pages in a separate process called the render process. This thread deals with your UI code in `/src` folder. You won't be able to use the Node.js power here, but the preload script will allow you to bridge the UI with Node.js.\n\n## Main Thread\n\nIn Electron, the process that runs package.json’s main script is called the main process. This is the script that runs in the main process and can display a GUI by initializing the renderer thread. This thread deals with your code in `/src-electron/electron-main.js`.\n\n## Preload Script\n\nThe [preload script](/quasar-cli-vite/developing-electron-apps/electron-preload-script) (`/src-electron/electron-preload.js`) is a way for you to inject Node.js stuff into the renderer thread by using a bridge between it and the UI. You can expose APIs that you can then call from your UI.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1872,"content_sha256":"0dead261353aecdff7b4853b2b217fd268532ef8fae6a36da982cffa00be59f4"},{"filename":"references/docs/quasar-cli-vite/developing-electron-apps/preparation.md","content":"---\ntitle: Preparation for Electron\ndesc: (@quasar/app-vite) How to add Electron mode into a Quasar app.\nscope:\n tree:\n l: src-electron\n c:\n - l: icons\n e: Icons of your app for all platforms\n c:\n - l: icon.icns\n e: Icon file for Darwin (MacOS) platform\n - l: icon.ico\n e: Icon file for win32 (Windows) platform\n - l: icon.png\n e: Tray icon file for all platforms\n - l: electron-preload.js\n e: '(or .ts) Electron preload script (injects Node.js stuff into renderer thread)'\n - l: electron-main.js\n e: '(or .ts) Main thread code'\n - l: electron-env.d.ts\n e: 'TypeScript only'\n---\n\nBefore we dive in to the actual development, we need to do some preparation work.\n\n## Step 1: Add Quasar Electron Mode\n\nIn order to develop/build a Quasar Electron app, we need to add the Electron mode to our Quasar project. What this does is that it yarn/npm/pnpm/bun installs some Electron packages and creates `/src-electron` folder.\n\n```bash\n$ quasar mode add electron\n```\n\nEvery Electron app has two threads: the main thread (deals with the window and initialization code -- from the newly created folder `/src-electron`) and the renderer thread (which deals with the actual content of your app from `/src`).\n\nThe new folder has the following structure:\n\n\u003cDocTree :def=\"scope.tree\" />\n\n### A note for Windows Users\n\nIf you run into errors during npm install about node-gyp, then you most likely do not have the proper build tools installed on your system. Build tools include items like Python and Visual Studio. Fortunately, there are a few packages to help simplify this process.\n\nThe first item we need to check is our npm version and ensure that it is not outdated. This is accomplished using npm-windows-upgrade. If you are using yarn, then you can skip this check.\n\nOnce that is complete, we can then continue to setup the needed build tools. Using windows-build-tools, most of the dirty work is done for us. Installing this globally will in turn setup Visual C++ packages, Python, and more.\n\n::: warning Note: April 2019\nIn Powershell.exe (Run as Admin) `npm install --global windows-build-tools` seems to fail at the moment with errors pointing to python2 and vctools. You can get around this with Chocolatey. One-liner install:\n\n**Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))**\n\nand then run `choco upgrade python2 visualstudio2017-workload-vctools`.\n:::\n\nAt this point things should successfully install, but if not then you will need a clean installation of Visual Studio. Please note that these are not problems with Quasar, but they are related to NPM and Windows.\n\n## Step 2: Start Developing\n\nIf you want to jump right in and start developing, you can skip the previous step with \"quasar mode\" command and issue:\n\n```bash\n$ quasar dev -m electron\n\n# passing extra parameters and/or options to\n# underlying \"electron\" executable:\n$ quasar dev -m electron -- --no-sandbox --disable-setuid-sandbox\n# when on Windows and using Powershell:\n$ quasar dev -m electron '--' --no-sandbox --disable-setuid-sandbox\n```\n\nThis will add Electron mode automatically, if it is missing.\nIt will open up an Electron window which will render your app along with Developer Tools opened side by side.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3399,"content_sha256":"dd8357f8f4b4c4a8a0f151bf323e45b65e4966707942c8e9ea5a505982423e17"},{"filename":"references/docs/quasar-cli-vite/developing-electron-apps/troubleshooting-and-tips.md","content":"---\ntitle: Troubleshooting and Tips\ndesc: (@quasar/app-vite) Tips and tricks for a Quasar desktop app with Electron.\n---\n\n## Browser Devtools\n\nYou probably want your app to only give access to the browser devtools on dev mode only. On the production version (without debugging enabled) you'll want to disable this behavior.\n\nWhile we're at it, why not also open devtools by default when we're on dev mode.\n\n```js /src-electron/electron-main\nfunction createWindow () {\n mainWindow = new BrowserWindow({ ... })\n\n if (process.env.DEBUGGING) {\n // if on DEV or Production with debug enabled\n mainWindow.webContents.openDevTools()\n }\n else {\n // we're on production; no access to devtools pls\n mainWindow.webContents.on('devtools-opened', () => {\n mainWindow.webContents.closeDevTools()\n })\n }\n}\n```\n\n## Debugging Main Process\n\nWhen running your application in development you may have noticed a message from the main process mentioning a remote debugger. Ever since the release of electron@^1.7.2, remote debugging over the Inspect API was introduced and can be easily accessed by opening the provided link with Google Chrome or through another debugger that can remotely attach to the process using the default port of 5858, such as Visual Studio Code.\n\n```bash\nDebugger listening on ws://127.0.0.1:5858/b285586a-6091-4c41-b6ea-0d389e6f9c93\nFor help, see: https://nodejs.org/en/docs/inspector\n```\n\nThe port can vary, based on the quasar.config > electron > inspectPort setting. If the specified port is already occupied, the next closest available port will be used.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1589,"content_sha256":"92b93b964bc22d8d6c9e7199673a0ebf615285b0b93f1b0a8c5139901439d69d"},{"filename":"references/docs/quasar-cli-vite/developing-mobile-apps.md","content":"---\ntitle: Developing Mobile Apps\ndesc: (@quasar/app-vite) Developing hybrid mobile apps with Quasar CLI.\nrelated:\n - /quasar-cli-vite/developing-capacitor-apps/introduction\n - /quasar-cli-vite/developing-cordova-apps/introduction\n---\n\nQuasar offers two solutions for creating mobile apps:\n\n- **Capacitor** was created by Ionic Framework as a more modern replacement for Cordova. It supports most, but not all, Cordova plugins as well as Capacitor-specific plugins.\n- **Cordova** is a mobile application development framework originally created by Nitobi. Adobe Systems purchased Nitobi in 2011, rebranded it as PhoneGap, and later released an open source version of the software called Apache Cordova.\n\n## More info\n\nBoth tools enable you to run your website as a native app through a WebView. They both expose native device APIs to your JavaScript code, and allow you to write native code in the form of plugins, which can be called through JS. While Cordova supports a wide range of targets, Capacitor only supports iOS and Android.\n\nCheck the related links below to get started.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1085,"content_sha256":"1b6d2889aacf0bf8d8d14d0f317fd4a6d29e86d1a7029565c84293c64d183b4b"},{"filename":"references/docs/quasar-cli-vite/developing-pwa/app-icons-pwa.md","content":"---\ntitle: App Icons for PWA\ndesc: (@quasar/app-vite) How to manage the app icons for a Quasar Progressive Web App.\nscope:\n pwaTree:\n l: public\n c:\n - l: favicon.ico\n - l: icons\n c:\n - l: favicon-128x128.png\n - l: favicon-96x96.png\n - l: favicon-32x32.png\n - l: favicon-16x16.png\n - l: icon-128x128.png\n e: for the PWA manifest\n - l: icon-192x192.png\n e: for the PWA manifest\n - l: icon-256x256.png\n e: for the PWA manifest\n - l: icon-384x384.png\n e: for the PWA manifest\n - l: icon-512x512.png\n e: for the PWA manifest\n - l: ms-icon-144x144.png\n - l: safari-pinned-tab.svg\n - l: apple-icon-120x120.png\n - l: apple-icon-152x152.png\n - l: apple-icon-167x167.png\n - l: apple-icon-180x180.png\n - l: apple-launch-828x1792.png\n - l: apple-launch-1125x2436.png\n - l: apple-launch-1242x2688.png\n - l: apple-launch-750x1334.png\n - l: apple-launch-1242x2208.png\n - l: apple-launch-640x1136.png\n - l: apple-launch-1536x2048.png\n - l: apple-launch-1668x2224.png\n - l: apple-launch-1668x2388.png\n - l: apple-launch-2048x2732.png\n---\n\nThis build target includes a variety of special icons for individual browsers and operating systems. You need all of them - and if you discover one that is new or missing, please open an issue.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/iconfactory.png\" style=\"float:right;max-width:15%;min-width:240px;padding-top:40px\">\n\n## Icon Genie CLI\n\n::: tip\nWe highly recommend using the [Icon Genie CLI](/icongenie/introduction), because it consumes a source icon and automatically clones, scales, minifies and places the icons in the appropriate directories for you. When needed, it also tells you what tags you'll need to add to your /index.html file.\n:::\n\nQuickly bootstrap the necessary images with Icon Genie CLI. For a complete list of options, please visit the [Icon Genie CLI](/icongenie/command-list) command list page.\n\n```bash\n$ icongenie generate -m pwa -i /path/to/source/icon.png [-b /path/to/background.png]\n```\n\n## Manual instructions\n\n\u003cDocTree :def=\"scope.pwaTree\" />\n\nThe required HTML code that goes into `/index.html` to reference the above files (notice not all files need to be manually referenced as Quasar CLI automatically injects the other PWA ones):\n\n```html\n\u003clink rel=\"icon\" type=\"image/ico\" href=\"icons/favicon.ico\" />\n\u003clink\n rel=\"icon\"\n type=\"image/png\"\n sizes=\"128x128\"\n href=\"icons/favicon-128x128.png\"\n/>\n\u003clink\n rel=\"icon\"\n type=\"image/png\"\n sizes=\"96x96\"\n href=\"icons/favicon-96x96.png\"\n/>\n\u003clink\n rel=\"icon\"\n type=\"image/png\"\n sizes=\"32x32\"\n href=\"icons/favicon-32x32.png\"\n/>\n\u003clink\n rel=\"icon\"\n type=\"image/png\"\n sizes=\"16x16\"\n href=\"icons/favicon-16x16.png\"\n/>\n\u003c!-- iPhone XR -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2)\"\n href=\"icons/apple-launch-828x1792.png\"\n/>\n\u003c!-- iPhone X, XS -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3)\"\n href=\"icons/apple-launch-1125x2436.png\"\n/>\n\u003c!-- iPhone XS Max -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3)\"\n href=\"icons/apple-launch-1242x2688.png\"\n/>\n\u003c!-- iPhone 8, 7, 6s, 6 -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2)\"\n href=\"icons/apple-launch-750x1334.png\"\n/>\n\u003c!-- iPhone 8 Plus, 7 Plus, 6s Plus, 6 Plus -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3)\"\n href=\"icons/apple-launch-1242x2208.png\"\n/>\n\u003c!-- iPhone 5 -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)\"\n href=\"icons/apple-launch-640x1136.png\"\n/>\n\u003c!-- iPad Mini, Air, 9.7\" -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2)\"\n href=\"icons/apple-launch-1536x2048.png\"\n/>\n\u003c!-- iPad Pro 10.5\" -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2)\"\n href=\"icons/apple-launch-1668x2224.png\"\n/>\n\u003c!-- iPad Pro 11\" -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2)\"\n href=\"icons/apple-launch-1668x2388.png\"\n/>\n\u003c!-- iPad Pro 12.9\" -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2)\"\n href=\"icons/apple-launch-2048x2732.png\"\n/>\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4990,"content_sha256":"3c1423baf346550f830a00f59661418e30fa23c9a50e404de6c1bd3bb5488fee"},{"filename":"references/docs/quasar-cli-vite/developing-pwa/build-commands.md","content":"---\ntitle: PWA Build Commands\ndesc: (@quasar/app-vite) The Quasar CLI list of commands when developing or building a Progressive Web App.\n---\n\n## Developing\n\n```bash\n$ quasar dev -m pwa\n\n# ..or the longer form:\n$ quasar dev --mode pwa\n```\n\n::: warning\nThe development server uses a bare minimum Service Worker precaching only the public folder. Working offline will not be available.\n:::\n\n::: danger\nDo not run Lighthouse on your development build because at this stage the code is intentionally not optimized and contains embedded source maps (among many other things).\n:::\n\n## Building for Production\n\n```bash\n$ quasar build -m pwa\n\n# ..or the longer form:\n$ quasar build --mode pwa\n```\n\nIf you want a production build with debugging enabled:\n\n```bash\n$ quasar build -m pwa -d\n\n# ..or the longer form\n$ quasar build -m pwa --debug\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":837,"content_sha256":"5c166f507c983be11b34d646f75f42b848e08e6962988cd3baddcc493f534b74"},{"filename":"references/docs/quasar-cli-vite/developing-pwa/configuring-pwa.md","content":"---\ntitle: Configuring PWA\ndesc: (@quasar/app-vite) How to manage your Progressive Web Apps with Quasar CLI.\nrelated:\n - /quasar-cli-vite/quasar-config-file\nscope:\n tree:\n l: src-pwa\n c:\n - l: register-service-worker.js\n e: '(or .ts) UI code *managing* service worker'\n - l: manifest.json\n e: Your PWA manifest file\n - l: custom-service-worker.js\n e: '(or .ts) Optional custom service worker file (injectManifest mode ONLY)'\n---\n\n## Service Worker\n\nAdding PWA mode to a Quasar project means a new folder will be created: `/src-pwa`, which contains PWA specific files:\n\n\u003cDocTree :def=\"scope.tree\" />\n\nYou can freely edit these files. Notice a few things:\n\n1. `register-service-worker.js` is automatically imported into your app (like any other /src file). It registers the service worker (created by Workbox or your custom one, depending on workbox plugin mode -- quasar.config file > pwa > workboxPluginMode) and you can listen for Service Worker's events. You can use ES6 code.\n2. `custom-service-worker.js` will be your service worker file ONLY if workbox plugin mode is set to \"injectManifest\" (quasar.config file > pwa > workboxMode: 'injectManifest'). Otherwise, Quasar and Workbox will create a service-worker file for you.\n3. It makes sense to run Lighthouse tests on production builds only.\n\n::: tip\nRead more on `register-service-worker.js` and how to interact with the Service Worker on [Handling Service Worker](/quasar-cli-vite/developing-pwa/handling-service-worker) documentation page.\n:::\n\n## quasar.config file\n\nThis is the place where you can configure Workbox behavior and also tweak your manifest.json.\n\n```js\npwa: {\n workboxMode?: \"GenerateSW\" | \"InjectManifest\";\n\n /**\n * Generated service worker filename to use (needs to end with .js)\n * @default sw.js\n */\n swFilename?: string;\n\n /**\n * PWA manifest filename to use on your browser\n * @default manifest.json\n */\n manifestFilename?: string;\n\n /**\n * Should you need some dynamic changes to the /src-pwa/manifest.json,\n * use this method to do it.\n */\n extendManifestJson?: (json: PwaManifestOptions) => void;\n\n /**\n * Does the PWA manifest tag requires crossorigin auth?\n * @default false\n */\n useCredentialsForManifestTag?: boolean;\n\n /**\n * Auto inject the PWA meta tags?\n * If using the function form, return HTML tags as one single string.\n * @default true\n */\n injectPwaMetaTags?: boolean | ((injectParam: InjectPwaMetaTagsParams) => string);\n\n /**\n * Extend the Esbuild config that is used for the custom service worker\n * (if using it through workboxMode: 'InjectManifest')\n */\n extendPWACustomSWConf?: (config: EsbuildConfiguration) => void;\n\n /**\n * Extend/configure the Workbox GenerateSW options\n */\n extendGenerateSWOptions?: (config: GenerateSWOptions) => void;\n\n /**\n * Extend/configure the Workbox InjectManifest options\n */\n extendInjectManifestOptions?: (config: InjectManifestOptions) => void;\n}\n\nsourceFiles: {\n pwaRegisterServiceWorker: 'src-pwa/register-service-worker',\n pwaServiceWorker: 'src-pwa/custom-service-worker',\n pwaManifestFile: 'src-pwa/manifest.json',\n}\n```\n\nShould you want to tamper with the Vite config for UI in /src:\n\n```js /quasar.config file\nexport default defineConfig(ctx => {\n return {\n build: {\n extendViteConf(viteConf) {\n if (ctx.mode.pwa) {\n // do something with viteConf\n // or return an object to deeply merge with current viteConf\n }\n }\n }\n }\n})\n```\n\nMore information: Workbox.\n\n## Adding your own meta tags in index.html\n\nQuasar CLI adds (dynamically) some PWA oriented meta tags into your index.html. Should you wish to customize the tags, first disable this behavior in the `/quasar.config` file:\n\n```js /quasar.config file\npwa: {\n injectPwaMetaTags: false\n}\n```\n\nThen, edit your `/index.html` file. The following are the actual meta tags that Quasar CLI injects dynamically:\n\n```html\n\u003chead>\n \u003c% if (ctx.mode.pwa) { %>\n \u003cmeta name=\"theme-color\" content=\"\u003c%= pwaManifest.theme_color %>\" />\n \u003clink\n rel=\"mask-icon\"\n href=\"icons/safari-pinned-tab.svg\"\n color=\"\u003c%= pwaManifest.theme_color %>\"\n />\n \u003cmeta name=\"mobile-web-app-capable\" content=\"yes\" />\n \u003cmeta name=\"apple-mobile-web-app-status-bar-style\" content=\"default\" />\n \u003cmeta name=\"msapplication-TileImage\" content=\"icons/ms-icon-144x144.png\" />\n \u003cmeta name=\"msapplication-TileColor\" content=\"#000000\" />\n \u003cmeta name=\"apple-mobile-web-app-title\" content=\"\u003c%= pwaManifest.name %>\" />\n \u003clink rel=\"apple-touch-icon\" href=\"icons/apple-icon-120x120.png\" />\n \u003clink\n rel=\"apple-touch-icon\"\n sizes=\"152x152\"\n href=\"icons/apple-icon-152x152.png\"\n />\n \u003clink\n rel=\"apple-touch-icon\"\n sizes=\"167x167\"\n href=\"icons/apple-icon-167x167.png\"\n />\n \u003clink\n rel=\"apple-touch-icon\"\n sizes=\"180x180\"\n href=\"icons/apple-icon-180x180.png\"\n />\n \u003c% } %>\n\u003c/head>\n```\n\nNotice that you have access to your PWA manifest through `pwaManifest` above.\n\nAlternatively, you can assign a function to injectPwaMetaTags like below:\n\n```js /quasar.config file\npwa: {\n injectPwaMetaTags ({ pwaManifest, publicPath }) {\n return `\u003cmeta name=\"mobile-web-app-capable\" content=\"yes\">`\n + `\u003cmeta name=\"apple-mobile-web-app-status-bar-style\" content=\"default\">`\n }\n}\n```\n\n## Picking Workbox mode\n\nThere are two Workbox operating modes: **generateSW** (default) and **injectManifest**.\n\nSetting the mode that you want to use is done through the `/quasar.config` file:\n\n```js /quasar.config file\npwa: {\n workboxMode: 'generateSW',\n extendGenerateSWOptions (cfg) {\n // configure workbox on generateSW\n }\n}\n\npwa: {\n workboxMode: 'injectManifest',\n extendInjectManifestOptions (cfg) {\n // configure workbox on injectManifest\n }\n}\n```\n\n### generateSW\n\nWhen to use generateSW:\n\n- You want to precache files.\n- You have simple runtime configuration needs (e.g. the configuration allows you to define routes and strategies).\n\nWhen NOT to use generateSW:\n\n- You want to use other Service Worker features (i.e. Web Push).\n- You want to import additional scripts or add additional logic.\n\n::: tip\nPlease check the available workboxOptions for this mode on Workbox website.\n:::\n\n### InjectManifest\n\nWhen to use InjectManifest:\n\n- You want more control over your service worker.\n- You want to precache files.\n- You have more complex needs in terms of routing.\n- You would like to use your service worker with other APIs (e.g. Web Push).\n\nWhen NOT to use InjectManifest:\n\n- You want the easiest path to adding a service worker to your site.\n\n::: tip TIPS\n\n- If you want to use this mode, you will have to write the service worker (`/src-pwa/custom-service-worker.js`) file by yourself.\n- Please check the available workboxOptions for this mode on Workbox website.\n :::\n\nThe following snippet is the default code for a custom service worker (`/src-pwa/custom-service-worker.js`) which mimics the behavior of `generateSW` mode:\n\n```js\n/*\n * This file (which will be your service worker)\n * is picked up by the build system ONLY if\n * quasar.config file > pwa > workboxMode is set to \"injectManifest\"\n */\n\nimport { clientsClaim } from 'workbox-core'\nimport {\n precacheAndRoute,\n cleanupOutdatedCaches,\n createHandlerBoundToURL\n} from 'workbox-precaching'\nimport { registerRoute, NavigationRoute } from 'workbox-routing'\n\nself.skipWaiting()\nclientsClaim()\n\n// Use with precache injection\nprecacheAndRoute(self.__WB_MANIFEST)\n\ncleanupOutdatedCaches()\n\n// Non-SSR fallbacks to index.html\n// Production SSR fallbacks to offline.html (except for dev)\nif (process.env.PROD) {\n registerRoute(\n new NavigationRoute(\n createHandlerBoundToURL(process.env.PWA_FALLBACK_HTML),\n {\n denylist: [\n new RegExp(process.env.PWA_SERVICE_WORKER_REGEX),\n /workbox-(.)*\\.js$/\n ]\n }\n )\n )\n}\n```\n\n## Configuring Manifest File\n\nThe Manifest file is located at `/src-pwa/manifest.json`. You can freely edit it.\n\nShould you need to change it dynamically at build time, you can do so by editing the `/quasar.config` file:\n\n```js /quasar.config file\npwa: {\n extendManifestJson (json) {\n // tamper with the json inline\n }\n}\n```\n\nPlease read about the manifest config before diving in.\n\n::: warning\nNote that you don't need to edit your index.html file (generated from `/index.html`) to link to the manifest file. Quasar CLI takes care of embedding the right things for you.\n::::\n\n::: tip\nIf your PWA is behind basic auth or requires an Authorization header, set quasar.config file > pwa > useCredentialsForManifestTag to `true` to include `crossorigin=\"use-credentials\"` on the manifest.json meta tag.\n::::\n\n## PWA Checklist\n\nMore info: PWA Checklist\n\n::: danger\nDo not run Lighthouse on your development build because at this stage the code is intentionally not optimized and contains embedded source maps (among many other things). See the [Testing and Auditing](/quasar-cli-vite/testing-and-auditing) section of these docs for more information.\n:::\n\n## Reload & Update Automatically\n\nFor those who don't want to manually reload the page when the service worker is updated **and are using the default generateSW workbox mode**, Quasar CLI has configured Workbox to activate it at once. Should you need to disable this behavior:\n\n```js /quasar.config file\npwa: {\n extendGenerateSWOptions (cfg) {\n cfg.skipWaiting = false\n cfg.clientsClaim = false\n }\n}\n```\n\n## Filename hashes quirk\n\nDue to how Rolldown builds the assets (through Vite), when you change any of your script source files (.js) this will also change the hash part of (almost) ALL .js files (ex: `454d87bd` in `assets/index.454d87bd.js`). The revision number of all assets will get changed in your service worker file and this means that when PWA updates it will re-download ALL your assets again. What a waste of bandwidth and such a longer time to get the PWA updated!\n\nBy default, Vite builds all filenames **with the hash part**. However, should you want your filenames to NOT contain the hash part, you need to edit the `/quasar.config` file:\n\n```js /quasar.config file\nbuild: {\n useFilenameHashes: false // true by default\n}\n```\n\nWhen filename hashes are disabled it would be wise to also make sure that your webserver has cache set accordingly (as low as possible) to ensure consistent resource delivery to your clients that can't use the PWA functionality.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":10420,"content_sha256":"f0da12eac27dbd6cd5ff606c9b140d463a85801a428a6708c72ddb38c4513773"},{"filename":"references/docs/quasar-cli-vite/developing-pwa/handling-service-worker.md","content":"---\ntitle: Handling Service Worker\ndesc: (@quasar/app-vite) How to configure the service worker in a Quasar Progressive Web App.\n---\n\nHere you'll learn how to interact with the Service Worker from within your website/app space. Remember, **service workers MUST be served over HTTPS**.\n\nIt's important to note that the Service Worker (which gets automatically generated by Workbox -- or you've configured Quasar CLI to use your custom one) runs in a separate thread. You can however interact with it from app-space from within `/src-pwa/register-service-worker.js` file.\n\n## Interacting with Service Worker\n\nAdd the register-service-worker npm package in your package.json file as a dependency (if it's not already there).\n\n```js /src-pwa/register-service-worker.js\nimport { register } from 'register-service-worker'\n\nregister(process.env.SERVICE_WORKER_FILE, {\n ready(registration) {\n console.log('Service worker is active.')\n },\n\n registered(registration) {\n console.log('Service worker has been registered.')\n },\n\n cached(registration) {\n console.log('Content has been cached for offline use.')\n },\n\n updatefound(registration) {\n console.log('New content is downloading.')\n },\n\n updated(registration) {\n console.log('New content is available; please refresh.')\n },\n\n offline() {\n console.log('No internet connection found. App is running in offline mode.')\n },\n\n error(error) {\n console.error('Error during service worker registration:', error)\n }\n})\n```\n\n::: tip\nThis file is automatically bundled into your website/app by Quasar CLI because it is considered as part of app-space `/src`. What this means is that you can use ES6, import other files etc.\n:::\n\n## SSL certificate\n\nYou may notice in some dev environments, that Workbox will not load your service workers during `quasar dev` if you are not using HTTPS to serve - even on localhost. You may see that there are two scripts that can't load. The Chrome browser console is relatively tight-lipped about this, but Firefox tells you what is going on. The three options you have are:\n\n- set quasar.config file > devServer > `https: true`\n- setup a loopback from localhost to 127.0.0.1 (but this is not without security implications)\n- serve your localhost over tunnelmole, localhost.run or ngrok and use the https address provided by them.\n\nHere is a tunnelmole example (install it first with `yarn global add tunnelmole` or `npm i -g tunnelmole`):\n\n```bash\n$ tmole 80\nhttp://b8ootd-ip-157-211-195-182.tunnelmole.com is forwarding to localhost:80\nhttps://b8ootd-ip-157-211-195-182.tunnelmole.com is forwarding to localhost:80\n\n# ...and use the HTTPS url shown in the output\n```\n\nWhen you set `devServer > https: true` in your quasar.config file, Quasar will instruct Vite to auto-generate a SSL certificate for you. However, if you want to create one yourself for your localhost, then check out this blog post by Filippo. Then your `quasar.config file > devServer > https` should look like this:\n\n```js /quasar.config file\ndevServer: {\n https: {\n // Use ABSOLUTE paths or fileURLToPath(new URL('./root/relative/path', import.meta.url))\n // https://nodejs.org/api/https.html#https_https_createserver_options_requestlistener\n key: \"/path/to/server.key\",\n pfx: \"/path/to/server.pfx\",\n cert: \"/path/to/server.crt\",\n ca: \"/path/to/ca.pem\",\n passphrase: 'vite-dev-server' // do you need it?\n }\n}\n```\n\nMore info on Vite and HTTPS here.\n\n## Important Hosting Configuration\n\nIt's important that you do not allow browsers to cache the Service Worker file (by default: `sw.js`). Because otherwise updates to this file or to your app might slip through the cracks for browsers that load the service-worker from cache.\n\nThis is why you must always make sure to add `\"Cache-Control\": \"no-cache\"` to the headers of `sw.js` file via your hosting service.\n\nAs an example how this is done for Google Firebase, you would add the following to the `firebase.json` configuration:\n\n```json\n{\n \"hosting\": {\n \"headers\": [\n {\n \"source\": \"/sw.js\",\n \"headers\": [{ \"key\": \"Cache-Control\", \"value\": \"no-cache\" }]\n }\n ]\n }\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4145,"content_sha256":"91de19b626b876ada4b9f7a6bd6484d3135f0b0a3ffe72b3bedecd6e3d7177db"},{"filename":"references/docs/quasar-cli-vite/developing-pwa/hmr-for-dev.md","content":"---\ntitle: Hot Module Reload for PWA\ndesc: (@quasar/app-vite) How to manage HMR (Hot Module Reload) with Quasar PWA.\n---\n\n**When in develop mode** (not production), having a Service Worker installed and running will mess with the HMR (Hot Module Reload). However, the browser can be configured to bypass for network instead of using the Service Worker's cache.\n\n\n\nWhen your development activity does not include configuring the Service Worker (like when editing the \"/src-pwa/register-service-worker.js\" file), then you can safely trigger the `$ quasar dev -m spa` (instead of `$ quasar dev -m pwa`) command to avoid the extra hassle of paying attention to the effects of the Service Worker -- which sometimes may get in the way.\n\n::: warning\nThe development server by default uses a bare minimum Service Worker precaching only the public folder. Working offline will not be available.\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":890,"content_sha256":"691db15a2b173001d837ec29525376eea6ebf906264c0d83417af6ac9566381f"},{"filename":"references/docs/quasar-cli-vite/developing-pwa/introduction.md","content":"---\ntitle: What is a PWA\ndesc: (@quasar/app-vite) Introduction on what a Progressive Web App is and how it can be configured in a Quasar app.\n---\n\nA Progressive Web App (PWA) is a web app that uses modern web capabilities to deliver an app-like experience to users. These apps meet certain requirements (see below), are deployed to web servers and accessible through URLs (on HTTPS protocol).\n\nThis can work in conjunction with Cordova to provide a multiple deploy targets for all your users. Quasar CLI allows you to deploy your app as a PWA as well as a Mobile app and take advantage of both channels.\n\n## What is Required\n\nTo be considered a Progressive Web App, your app must be:\n\n- Progressive - Work for every user, regardless of browser choice, because they are built with progressive enhancement as a core tenet.\n- Responsive - Fit any form factor, desktop, mobile, tablet, or whatever is next.\n- Connectivity independent - Enhanced with service workers to work offline or on low quality networks.\n- App-like - Use the app-shell model to provide app-style navigation and interactions.\n- Fresh - Always up-to-date thanks to the service worker update process.\n- Safe - Served via HTTPS to prevent snooping and ensure content has not been tampered with.\n- Discoverable - Are identifiable as “applications” thanks to W3C manifests and service worker registration scope allowing search engines to find them.\n- Re-engageable - Make re-engagement easy through features like push notifications.\n- Installable - Allow users to “keep” apps they find most useful on their home screen without the hassle of an app store.\n- Linkable - Easily share via URL and not require complex installation.\n\nMore information available on Addy Osmani's article about PWA.\n\n## Manifest File\n\nAn app manifest file describes the resources your app will need. This includes your app’s displayed name, icons, as well as splash screen. You will see this as `/src-pwa/manifest.json`.\nMore information: Manifest file.\n\n## Service Worker\n\nThe Service worker provides a programmatic way to cache app resources (files). The programmatic API allows developers to decide how to handle caching and provides a much more flexible experience than other options.\n\nMore information: Service Worker API.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2275,"content_sha256":"dcee5b5e92f6ab9a35e0cb8c1427cf17f94671f2c72700657b20837bfc26bde2"},{"filename":"references/docs/quasar-cli-vite/developing-pwa/preparation.md","content":"---\ntitle: Preparation for PWA\ndesc: (@quasar/app-vite) How to add PWA mode with Quasar CLI.\nrelated:\n - /quasar-cli-vite/quasar-config-file\nscope:\n tree:\n l: src-pwa\n c:\n - l: register-service-worker.js\n e: '(or .ts) UI code *managing* service worker'\n - l: manifest.json\n e: Your PWA manifest file\n - l: custom-service-worker.js\n e: '(or .ts) Optional custom service worker file (injectManifest mode ONLY)'\n - l: pwa-end.d.ts\n e: 'TypeScript only'\n - l: tsconfig.json\n e: 'TypeScript only'\n---\n\nWe'll be using Quasar CLI to develop and build a PWA. The difference between building a SPA, Mobile App, Electron App, PWA or SSR is simply determined by the \"mode\" parameter in \"quasar dev\" and \"quasar build\" commands.\n\nIn order to build a PWA, we first need to add the PWA mode to our Quasar project:\n\n```bash\n$ quasar mode add pwa\n```\n\nIf you want to jump right in and start developing, you can skip the \"quasar mode\" command and issue:\n\n```bash\n$ quasar dev -m pwa\n```\n\nThis will add PWA mode automatically, if it is missing.\n\nA new folder will appear in your project folder (which is explained in detail on the [Configuring PWA](/quasar-cli-vite/developing-pwa/configuring-pwa) page):\n\n\u003cDocTree :def=\"scope.tree\" />\n\nAll the files above are going to be detailed in the next pages, but the high overview is:\n\n- The `register-service-worker.js` file is part of the UI code and communicates with the service worker.\n- The `manifest.json` is the PWA manifest file.\n- When using InjectManifest, you can write your own custom service worker (`custom-service-worker.js`).\n\nShould you want to use different filenames, you can do so by editing the `/quasar.config` file:\n\n```js /quasar.config file\nsourceFiles: {\n pwaRegisterServiceWorker: 'src-pwa/register-service-worker',\n pwaServiceWorker: 'src-pwa/custom-service-worker',\n pwaManifestFile: 'src-pwa/manifest.json',\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1940,"content_sha256":"c60b5672bd9d7b5e397d660b1784e329997a91188e7ecafc87e15e872736bcf3"},{"filename":"references/docs/quasar-cli-vite/developing-pwa/pwa-with-typescript.md","content":"---\ntitle: PWA with Typescript\ndesc: (@quasar/app-vite) How to use Typescript with Quasar PWA\n---\n\nIn order to support PWA with Typescript, you will need to rename the extension for your files in /src-pwa from `.js` to `.ts` and make the necessary TS code changes.\n\nAlso create these files:\n\n```js /src-pwa/pwa-env.d.ts\n/* eslint-disable */\n\ndeclare namespace NodeJS {\n interface ProcessEnv {\n SERVICE_WORKER_FILE: string;\n PWA_FALLBACK_HTML: string;\n PWA_SERVICE_WORKER_REGEX: string;\n // ...and your own\n }\n}\n```\n\n```js /src-pwa/tsconfig.json\n{\n \"extends\": \"../tsconfig.json\",\n \"compilerOptions\": {\n \"lib\": [\"WebWorker\", \"ESNext\"]\n },\n \"include\": [\"*.ts\", \"*.d.ts\"]\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":695,"content_sha256":"0aac53c26732fac8577d7ffafecc5393e6d798fcce1ca5d4d027295e0a47c5d5"},{"filename":"references/docs/quasar-cli-vite/developing-spa/app-icons-spa.md","content":"---\ntitle: App Icons for SPA\ndesc: (@quasar/app-vite) How to manage the app icons for a Quasar Single Page Application.\nscope:\n spaTree:\n l: public\n c:\n - l: favicon.ico\n - l: icons\n c:\n - l: favicon-128x128.png\n - l: favicon-96x96.png\n - l: favicon-32x32.png\n - l: favicon-16x16.png\n---\n\nThis build target includes a variety of special icons for individual browsers and operating systems. You need all of them - and if you discover one that is new or missing, please open an issue.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/iconfactory.png\" style=\"float:right;max-width:15%;min-width:240px;padding-top:40px\">\n\n## Icon Genie CLI\n\n::: tip\nWe highly recommend using the [Icon Genie CLI](/icongenie/introduction), because it consumes a source icon and automatically clones, scales, minifies and places the icons in the appropriate directories for you. When needed, it also tells you what tags you'll need to add to your /index.html file.\n:::\n\nQuickly bootstrap the necessary images with Icon Genie CLI. For a complete list of options, please visit the [Icon Genie CLI](/icongenie/command-list) command list page.\n\n```bash\n$ icongenie generate -m spa -i /path/to/source/icon.png\n```\n\n## Manual instructions\n\n\u003cDocTree :def=\"scope.spaTree\" />\n\nThe required HTML code that goes into `/index.html` to reference the above files:\n\n```html\n\u003clink rel=\"icon\" type=\"image/ico\" href=\"favicon.ico\" />\n\u003clink\n rel=\"icon\"\n type=\"image/png\"\n sizes=\"128x128\"\n href=\"icons/favicon-128x128.png\"\n/>\n\u003clink\n rel=\"icon\"\n type=\"image/png\"\n sizes=\"96x96\"\n href=\"icons/favicon-96x96.png\"\n/>\n\u003clink\n rel=\"icon\"\n type=\"image/png\"\n sizes=\"32x32\"\n href=\"icons/favicon-32x32.png\"\n/>\n\u003clink\n rel=\"icon\"\n type=\"image/png\"\n sizes=\"16x16\"\n href=\"icons/favicon-16x16.png\"\n/>\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1809,"content_sha256":"aefbb9eeabbbed21d92c3bfd8ab1abe9ced0fa51d1080a75b9b6b860483f8d0b"},{"filename":"references/docs/quasar-cli-vite/developing-spa/build-commands.md","content":"---\ntitle: SPA Build Commands\ndesc: (@quasar/app-vite) The Quasar CLI list of commands when developing or building a single page application.\n---\n\nDeveloping:\n\n```bash\n$ quasar dev\n```\n\nBuilding for Production:\n\n```bash\n$ quasar build\n```\n\nIf you want a production build with debugging enabled:\n\n```bash\n$ quasar build -d\n\n# ..or the longer form\n$ quasar build --debug\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":373,"content_sha256":"e75c5ee2f3856e27db426181b6969b47a6170951b92d2d8d393631abfe392fc0"},{"filename":"references/docs/quasar-cli-vite/developing-spa/deploying.md","content":"---\ntitle: Deploying a SPA\ndesc: (@quasar/app-vite) How to publish a Single Page App built by Quasar CLI.\n---\n\nThere exist many services that allow deploying applications with ease.\nTo list all of them would not be possible so we will focus on the general deployment process and some specifics for common services.\n\nIf your favorite deployment tool is missing feel free to create a pull request on GitHub to add it to the list.\n\n## General deployment\n\nThe first step in deploying your Quasar SPA is always to build a production-ready bundle of your files, which gets rid of development statements and minifies your source.\n\nTo produce such a build use Quasar CLI with the following command:\n\n```bash\n$ quasar build\n```\n\nThis command will build your project in SPA mode and output your production ready bundle to a newly created folder `/dist/spa`.\n\nTo serve your production files it is _required_ to use a web server, so to serve over http(s):// protocol. Simply opening the `index.html` file from within your browser will not work, since this uses the file:// protocol instead.\n\nCommon choices for web servers are nginx, Caddy, Apache, Express; but you should be able to use whatever web server you want.\n\nThe web server requires no special setup (unless you built with Vue Router in \"history\" mode in the `/quasar.config` file). The main requirement is to be able to serve static files from a directory, so consult the documentation of your web server on how to set up static file serving.\n\nAn example config for nginx may look like this:\n\n```nginx\nserver {\n listen 80 http2;\n server_name quasar.myapp.com;\n\n root /home/user/quasar.myapp.com/public;\n\n add_header X-Frame-Options \"SAMEORIGIN\";\n add_header X-XSS-Protection \"1; mode=block\";\n add_header X-Content-Type-Options \"nosniff\";\n\n index index.html;\n\n charset utf-8;\n\n location / {\n try_files $uri $uri/ /index.html;\n }\n\n location = /robots.txt { access_log off; log_not_found off; }\n\n access_log off;\n error_log /var/log/nginx/quasar.myapp.com-error.log error;\n\n location ~ /\\.(?!well-known).* {\n deny all;\n }\n}\n```\n\n## Important Hosting Configuration\n\nIt's important that you do not allow browsers to cache the `index.html` file. Because otherwise updates to this file or to your app might slip through the cracks for browsers that load the index.html from cache.\n\nThis is why you must always make sure to add `\"Cache-Control\": \"no-cache\"` to the headers of the `index.html` file via your hosting service.\n\nAs an example how this is done for Google Firebase, you would add the following to the `firebase.json` configuration:\n\n```json firebase.json\n{\n \"hosting\": {\n \"headers\": [\n {\n \"source\": \"/**\",\n \"headers\": [\n {\n \"key\": \"Cache-Control\",\n \"value\": \"no-cache, no-store, must-revalidate\"\n }\n ]\n },\n {\n \"source\": \"**/*.@(jpg|jpeg|gif|png|svg|webp|js|css|eot|otf|ttf|ttc|woff|woff2|font.css)\",\n \"headers\": [\n {\n \"key\": \"Cache-Control\",\n \"value\": \"max-age=604800\"\n }\n ]\n }\n ]\n }\n}\n```\n\n## Deploying with Cloudflare Pages\n\nCloudflare Pages offers a powerful platform for deploying Quasar SPAs with built-in performance, security, and scalability features. Let's set up your Quasar application for deployment.\n\nFirst, install the required dependencies:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add -D @cloudflare/vite-plugin wrangler\n\u003c\u003c| bash NPM |>>\n$ npm install -D @cloudflare/vite-plugin wrangler\n\u003c\u003c| bash PNPM |>>\n$ pnpm add -D @cloudflare/vite-plugin wrangler\n\u003c\u003c| bash Bun |>>\n$ bun add -D @cloudflare/vite-plugin wrangler\n```\n\nNext, modify your `/quasar.config` file to include the Cloudflare Vite plugin:\n\n```js /quasar.config file\nimport { cloudflare } from '@cloudflare/vite-plugin'\n\nexport default defineConfig(() => {\n return {\n build: {\n vitePlugins: [cloudflare()]\n }\n // ... rest of your config\n }\n})\n```\n\nCreate a `wrangler.jsonc` file in your project root:\n\n```json wrangler.jsonc\n{\n \"$schema\": \"node_modules/wrangler/config-schema.json\",\n \"name\": \"your-project-name\",\n \"compatibility_date\": \"2025-04-12\",\n \"pages_build_output_dir\": \"./dist/spa\"\n}\n```\n\nAdd the deploy script to your `package.json`:\n\n```json /package.json\n\"scripts\": {\n \"build\": \"quasar build\",\n \"deploy\": \"wrangler pages deploy\"\n}\n```\n\nNow you can build and deploy your application using:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn build\n$ yarn deploy\n\u003c\u003c| bash NPM |>>\n$ npm run build\n$ npm run deploy\n\u003c\u003c| bash PNPM |>>\n$ pnpm run build\n$ pnpm run deploy\n\u003c\u003c| bash Bun |>>\n$ bun run build\n$ bun run deploy\n```\n\nFor existing Git repositories, you can set up continuous deployment by connecting your repository to Cloudflare Pages:\n\n```bash\n$ wrangler pages project create my-quasar-app\n$ git remote add cloudflare https://github.com/your-username/your-repo.git\n$ git push cloudflare main\n```\n\nConfigure your build settings in the Cloudflare Pages dashboard:\n\n- Build command: `quasar build`\n- Build output directory: `dist/spa`\n- Environment variables (if needed)\n\nFor more information about Cloudflare Pages features and configuration options, visit the Cloudflare Pages documentation.\n\n## Deploying with Vercel\n\nDeploying your Quasar application with Vercel is really easy.\nAll you have to do is to download the vercel-cli and log in by running:\n\n```bash\n$ vercel login\n```\n\nThen proceed to build your Quasar application using the steps described in \"General deployment\" section.\n\nAfter the build is finished, change directory into your deploy root (example: `/dist/spa`) and run:\n\n```bash\n# from /dist/spa (or your distDir)\n$ vercel\n```\n\nThe Vercel CLI should now display information regarding your deployment, like the URL. That's it. You're done.\n\n### Vercel configuration tips\n\nYou should consider adding some additional configurations to your project.\n\n- Important: Vercel expects the build results to be in `/public` directory, and _Quasar_ has it in `/dist/spa` by default, so you will need to override the `Output Directory` in your Vercel project. Set it to `dist/spa` through the Vercel web ui under your project's settings > Build & Development Settings.\n\n- Since Vercel expects the _build_ script to be defined, you may add in `package.json` the following scripts:\n\n```json /package.json\n\"scripts\": {\n \"build\": \"quasar build\",\n \"deploy\": \"vercel\"\n}\n```\n\n- In order to support SPA routing in the deployed app, consider adding `vercel.json` file in your root folder:\n\n```json vercel.json\n{\n \"routes\": [{ \"handle\": \"filesystem\" }, { \"src\": \"/.*\", \"dest\": \"/\" }]\n}\n```\n\n## Deploying with Heroku\n\nUnfortunately, Heroku does not support static sites out of the box. But don't worry, we just need to add an HTTP server to our project so Heroku can serve our Quasar application.\n\nIn this example, we will use Express to create a minimal server which Heroku can use.\n\nFirst, we need to install the required dependencies to our project:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add express serve-static connect-history-api-fallback\n\u003c\u003c| bash NPM |>>\n$ npm install --save express serve-static connect-history-api-fallback\n\u003c\u003c| bash PNPM |>>\n$ pnpm add express serve-static connect-history-api-fallback\n\u003c\u003c| bash Bun |>>\n$ bun add express serve-static connect-history-api-fallback\n```\n\nNow that we have installed the required dependencies, we can add our server. Create a file called `server.js` in the root directory of your project.\n\n```js\nimport express from 'express'\nimport serveStatic from 'serve-static'\nimport history from 'connect-history-api-fallback'\n\nconst port = process.env.PORT || 5000\nconst app = express()\n\napp.use(history())\napp.use(serveStatic(__dirname + '/dist/spa'))\napp.listen(port)\n```\n\nHeroku assumes a set of npm scripts to be available, so we have to alter our `package.json` and add the following under the `script` section:\n\n```js /package.json\n\"scripts\": {\n \"build\": \"quasar build\",\n \"start\": \"node server.js\",\n \"heroku-postbuild\": \"yarn && yarn build\"\n}\n```\n\nNow it is time to create an app on Heroku by running:\n\n```bash\n$ heroku create\n```\n\nand deploy to Heroku using:\n\n```bash\n$ git init\n$ heroku git:remote -a \u003cheroku app name>\n\n$ git add .\n$ git commit -am \"make it better\"\n$ git push heroku master\n```\n\nFor existing Git repositories, simply add the heroku remote:\n\n```bash\n$ heroku git:remote -a \u003cheroku app name>\n```\n\n## Deploying with Surge\n\nSurge is a popular tool to host and deploy static sites.\n\nIf you want to deploy your application with Surge you first need to install the Surge CLI tool:\n\n```bash\n$ npm install -g surge\n```\n\nNext, we will use Quasar CLI to build our app:\n\n```bash\n$ quasar build\n```\n\nNow we can deploy our application using Surge by calling:\n\n```bash\n$ surge dist/spa\n```\n\nNow your application should be successfully deployed using Surge. You should be able to adapt this guide to any other static site deployment tool.\n\n## Deploying on GitHub Pages\n\nTo deploy your Quasar application to GitHub pages the first step is to create a special repository on GitHub which is named `\u003cusername>.github.io`. Clone this repository to your local machine.\n\nNext, you need to build your Quasar application like it is described in the \"General deployment section\". This will result in a `/dist/spa` directory. Copy the content of this folder to your cloned repository.\n\nThe last step is to add a commit in your repository and push to GitHub. After a short time, you should be able to visit your Quasar application at `https://\u003cusername>.github.io/`.\n\n### Adding a custom domain to GitHub pages\n\nPlease see the GitHub pages guides for an in-depth explanation on how to set up a custom domain.\n\n### Automated deployment to GitHub pages with push-dir\n\nManual copying all your files to your GitHub Pages repository can be a cumbersome task to do. This step can be automated by using the push-dir package.\n\nFirst, install the package with:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add --dev push-dir\n\u003c\u003c| bash NPM |>>\n$ npm install --save-dev push-dir\n\u003c\u003c| bash PNPM |>>\n$ pnpm add -D push-dir\n\u003c\u003c| bash Bun |>>\n$ bun add --dev push-dir\n```\n\nThen add a `deploy` script command to your `package.json`:\n\n```json /package.json\n\"scripts\": {\n \"deploy\": \"push-dir --dir=dist/spa --remote=gh-pages --branch=master\"\n}\n```\n\nAdd your GitHub Pages repository as a remote named `gh-pages`:\n\n```bash\n$ git remote add gh-pages [email protected]:\u003cusername>/\u003cusername>.github.io.git\n```\n\nNow you can build and deploy your application using:\n\n```bash\n$ quasar build\n$ yarn deploy # or npm/pnpm/bun equivalents\n```\n\nwhich will push the content of your build directory to your master branch on your GitHub Pages repository.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":10690,"content_sha256":"b9f344939e520e8867e2cffd8e16a9b08098f11feb2a628a029bf043ba2f62ae"},{"filename":"references/docs/quasar-cli-vite/developing-spa/introduction.md","content":"---\ntitle: What is SPA\ndesc: (@quasar/app-vite) Introduction on what a Single Page App is.\n---\n\nA Single-Page Application (SPA) is a web application or web site that interacts with the user by dynamically rewriting the current page rather than loading entire new pages from a server. This approach avoids interruption of the user experience between successive pages, making the application behave more like a desktop application.\n\nIn a SPA the appropriate resources are dynamically loaded and added to the page as necessary, usually in response to user actions. The page does not reload at any point in the process, nor does control transfer to another page, although the location hash or the HTML5 History API (using one or the other based on your Vue Router mode in the `/quasar.config` file) can be used to provide the perception and navigability of separate logical pages in the application.\n\nInteraction with the single page application often involves dynamic communication with the web server behind the scenes.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1018,"content_sha256":"14f61601731543ad673c1cc5f2154ef1d3e6410c69787058bb82f48fedaa8e35"},{"filename":"references/docs/quasar-cli-vite/developing-ssr/app-icons-ssr.md","content":"---\ntitle: App Icons for SSR\ndesc: (@quasar/app-vite) How to manage the app icons for a Quasar server-side rendered app.\nscope:\n spaTree:\n l: public\n c:\n - l: favicon.ico\n - l: icons\n c:\n - l: favicon-128x128.png\n - l: favicon-96x96.png\n - l: favicon-32x32.png\n - l: favicon-16x16.png\n ssrTree:\n l: public\n c:\n - l: icons\n c:\n - l: icon-128x128.png\n e: for the PWA manifest\n - l: icon-192x192.png\n e: for the PWA manifest\n - l: icon-256x256.png\n e: for the PWA manifest\n - l: icon-384x384.png\n e: for the PWA manifest\n - l: icon-512x512.png\n e: for the PWA manifest\n - l: ms-icon-144x144.png\n - l: safari-pinned-tab.svg\n - l: apple-icon-120x120.png\n - l: apple-icon-152x152.png\n - l: apple-icon-167x167.png\n - l: apple-icon-180x180.png\n - l: apple-icon-828x1792.png\n - l: apple-icon-1125x2436.png\n - l: apple-icon-1242x2688.png\n - l: apple-icon-750x1334.png\n - l: apple-icon-1242x2208.png\n - l: apple-icon-640x1136.png\n - l: apple-icon-1536x2048.png\n - l: apple-icon-1668x2224.png\n - l: apple-icon-1668x2388.png\n - l: apple-icon-2048x2732.png\n---\n\nThis build target includes a variety of special icons for individual browsers and operating systems. You need all of them - and if you discover one that is new or missing, please open an issue.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/iconfactory.png\" style=\"float:right;max-width:15%;min-width:240px;padding-top:40px\">\n\n## Icon Genie CLI\n\n::: tip\nWe highly recommend using the [Icon Genie CLI](/icongenie/introduction), because it consumes a source icon and automatically clones, scales, minifies and places the icons in the appropriate directories for you. When needed, it also tells you what tags you'll need to add to your /index.html file.\n:::\n\nQuickly bootstrap the necessary images with Icon Genie CLI. For a complete list of options, please visit the [Icon Genie CLI](/icongenie/command-list) command list page.\n\n```bash\n# SSR only:\n$ icongenie generate -m ssr -i /path/to/source/icon.png\n\n# SSR + PWA:\n$ icongenie generate -m ssr,pwa -i /path/to/source/icon.png [-b /path/to/background.png]\n```\n\n## Manual instructions\n\n\u003cDocTree :def=\"scope.spaTree\" />\n\nThe required HTML code that goes into `/index.html` to reference the above files:\n\n```html\n\u003clink rel=\"icon\" type=\"image/ico\" href=\"favicon.ico\" />\n\u003clink\n rel=\"icon\"\n type=\"image/png\"\n sizes=\"128x128\"\n href=\"icons/favicon-128x128.png\"\n/>\n\u003clink\n rel=\"icon\"\n type=\"image/png\"\n sizes=\"96x96\"\n href=\"icons/favicon-96x96.png\"\n/>\n\u003clink\n rel=\"icon\"\n type=\"image/png\"\n sizes=\"32x32\"\n href=\"icons/favicon-32x32.png\"\n/>\n\u003clink\n rel=\"icon\"\n type=\"image/png\"\n sizes=\"16x16\"\n href=\"icons/favicon-16x16.png\"\n/>\n```\n\nHowever, if you are developing with SSR + PWA mode, then you'll also need the PWA assets:\n\n\u003cDocTree :def=\"scope.ssrTree\" />\n\nAnd the corresponding HTML code to go into `/index.html` file (notice not all files need to be manually referenced as Quasar CLI automatically injects the other ones):\n\n```html\n\u003c!-- iPhone XR -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2)\"\n href=\"icons/apple-launch-828x1792.png\"\n/>\n\u003c!-- iPhone X, XS -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3)\"\n href=\"icons/apple-launch-1125x2436.png\"\n/>\n\u003c!-- iPhone XS Max -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3)\"\n href=\"icons/apple-launch-1242x2688.png\"\n/>\n\u003c!-- iPhone 8, 7, 6s, 6 -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2)\"\n href=\"icons/apple-launch-750x1334.png\"\n/>\n\u003c!-- iPhone 8 Plus, 7 Plus, 6s Plus, 6 Plus -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3)\"\n href=\"icons/apple-launch-1242x2208.png\"\n/>\n\u003c!-- iPhone 5 -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)\"\n href=\"icons/apple-launch-640x1136.png\"\n/>\n\u003c!-- iPad Mini, Air, 9.7\" -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2)\"\n href=\"icons/apple-launch-1536x2048.png\"\n/>\n\u003c!-- iPad Pro 10.5\" -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2)\"\n href=\"icons/apple-launch-1668x2224.png\"\n/>\n\u003c!-- iPad Pro 11\" -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2)\"\n href=\"icons/apple-launch-1668x2388.png\"\n/>\n\u003c!-- iPad Pro 12.9\" -->\n\u003clink\n rel=\"apple-touch-startup-image\"\n media=\"(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2)\"\n href=\"icons/apple-launch-2048x2732.png\"\n/>\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5313,"content_sha256":"a26189a0c37e62d5e7123eb5c12f4fb42e37d6aa258576685d4fd6de215388bd"},{"filename":"references/docs/quasar-cli-vite/developing-ssr/build-commands.md","content":"---\ntitle: SSR Build Commands\ndesc: (@quasar/app-vite) The Quasar CLI list of commands when developing or building a server-side rendered app.\n---\n\n## Developing\n\n```bash\n$ quasar dev -m ssr\n\n# ..or the longer form:\n$ quasar dev --mode ssr\n```\n\n## Building for Production\n\n```bash\n$ quasar build -m ssr\n\n# ..or the longer form:\n$ quasar build --mode ssr\n```\n\nIf you want a production build with debugging enabled:\n\n```bash\n$ quasar build -m ssr -d\n\n# ..or the longer form\n$ quasar build -m ssr --debug\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":506,"content_sha256":"a7cd8f5133a3ccb79293e1b54108c832fe025359fb62c41304459e459e7d3549"},{"filename":"references/docs/quasar-cli-vite/developing-ssr/client-side-hydration.md","content":"---\ntitle: Client Side Hydration\ndesc: (@quasar/app-vite) What hydration is and its caveats in a Quasar server-side rendered app.\n---\n\nHydration refers to the client-side process during which Vue takes over the static HTML sent by the server and turns it into dynamic DOM that can react to client-side data changes.\n\nSince the server has already rendered the markup, we obviously do not want to throw that away and re-create all the DOM elements. Instead, we want to \"hydrate\" the static markup and make it interactive.\n\n::: warning\nIn development mode, Vue will assert the client-side generated virtual DOM tree matches the DOM structure rendered from the server. If there is a mismatch, it will bail hydration, discard existing DOM and render from scratch. **In production mode, this assertion is disabled for maximum performance.**\n:::\n\n## Hydration Caveats\n\nOne thing to be aware of when using SSR + client hydration is some special HTML structures that may be altered by the browser. For example, when you write this in a Vue template:\n\n```html\n\u003ctable>\n \u003ctr>\u003ctd>hi\u003c/td>\u003c/tr>\n\u003c/table>\n```\n\nThe browser will automatically inject `\u003ctbody>` inside `\u003ctable>`, however, the virtual DOM generated by Vue does not contain `\u003ctbody>`, so it will cause a mismatch. To ensure correct matching, make sure to write valid HTML in your templates.\n\n## Handling Hydration Errors\n\nIf you do receive hydration errors (as seen in console: \"Vuejs Error - The client-side rendered virtual DOM tree is not matching server-rendered content\"), you can try following these steps:\n\n1. Show DevTools in Chrome (F12)\n2. Load the page that causes \"the client-side rendered virtual DOM tree...\" warning.\n3. Scroll to the warning in DevTools console.\n4. Click at the source location hyperlink of the warning in vue.runtime.esm.js.\n5. Set a breakpoint there (left-clicking at line number in the source code browser).\n6. Make the same warning appear again. Usually by reloading the page. If there are many warnings, you can check the message by moving a mouse over `msg` variable.\n7. When you have found your message and stopped on a breakpoint, look at the _call stack_. Click one frame down to call to \"patch\" to open its source. Hover mouse over hydrate function call 4 lines above the execution line in patch. Hyperlink to the source of hydrate would open.\n8. In the hydrate function, move about 15 lines from the start and set a breakpoint where false is returned after `assertNodeMatch` returned `false`. Set the breakpoint there and remove all other breakpoints.\n9. Make the same warning happen again. Now, when breakpoint is hit, execution should stop in the hydrate function. Switch to DevTools console and evaluate `elm` and then `vnode`. Here `elm` seems to be a _server-rendered DOM element_ while `vnode` is a _virtual DOM node_. `Elm` is printed as HTML so you can figure out where the error happened.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2887,"content_sha256":"35d81abaeec8fa2e402e89075ef8c804f03fae22d1ed8aabf056dff9c2b4305c"},{"filename":"references/docs/quasar-cli-vite/developing-ssr/configuring-ssr.md","content":"---\ntitle: Configuring SSR\ndesc: (@quasar/app-vite) How to manage your server-side rendered apps with Quasar CLI.\nrelated:\n - /quasar-cli-vite/quasar-config-file\nscope:\n nodeJsTree:\n l: src-ssr\n c:\n - l: middlewares/\n e: SSR middleware files\n - l: server.js\n e: (or .ts) SSR webserver\n---\n\n## quasar.config file\n\nThis is the place where you can configure some SSR options. Like if you want the client side to takeover as a SPA (Single Page Application -- the default behaviour), or as a PWA (Progressive Web App).\n\n```js /quasar.config file\nreturn {\n // ...\n ssr: {\n /**\n * If a PWA should take over or just a SPA.\n * @default false\n */\n pwa?: boolean;\n\n /**\n * When using SSR+PWA, this is the name of the\n * PWA index html file that the client-side fallbacks to.\n * For production only.\n *\n * Do NOT use index.html as name as it will mess SSR up!\n *\n * @default 'offline.html'\n */\n pwaOfflineHtmlFilename?: string;\n\n /**\n * Extend/configure the Workbox GenerateSW options\n * Specify Workbox options which will be applied on top of\n * `pwa > extendGenerateSWOptions()`.\n * More info: https://developer.chrome.com/docs/workbox/the-ways-of-workbox/\n */\n pwaExtendGenerateSWOptions?: (config: object) => void;\n\n /**\n * Extend/configure the Workbox InjectManifest options\n * Specify Workbox options which will be applied on top of\n * `pwa > extendInjectManifestOptions()`.\n * More info: https://developer.chrome.com/docs/workbox/the-ways-of-workbox/\n */\n pwaExtendInjectManifestOptions?: (config: object) => void;\n\n /**\n * Manually serialize the store state and provide it yourself\n * as window.__INITIAL_STATE__ to the client-side (through a \u003cscript> tag)\n * @default false\n */\n manualStoreSerialization?: boolean;\n\n /**\n * Manually inject the store state into ssrContext.state\n * @default false\n */\n manualStoreSsrContextInjection?: boolean;\n\n /**\n * Manually handle the store hydration instead of letting Quasar CLI do it.\n *\n * For Pinia: store.state.value = window.__INITIAL_STATE__\n *\n * @default false\n */\n manualStoreHydration?: boolean;\n\n /**\n * Manually call $q.onSSRHydrated() instead of letting Quasar CLI do it.\n * This announces that client-side code should takeover.\n * @default false\n */\n manualPostHydrationTrigger?: boolean;\n\n /**\n * The default port (3000) that the production server should use\n * (gets superseded if process.env.PORT is specified at runtime)\n * @default 3000\n */\n prodPort?: number;\n\n /**\n * List of middleware files in src-ssr/middlewares\n * Order is important.\n */\n middlewares?: string[];\n\n /**\n * Add/remove/change properties of production generated package.json\n */\n extendPackageJson?: (pkg: { [index in string]: any }) => void;\n\n /**\n * Extend the Esbuild config that is used for the SSR webserver\n * (which includes the SSR middlewares)\n */\n extendSSRWebserverConf?: (config: EsbuildConfiguration) => void;\n }\n}\n```\n\n> If you decide to go with a PWA client takeover (**which is a killer combo**), the Quasar CLI PWA mode will be installed too. You may want to check out the [Quasar PWA](/quasar-cli-vite/developing-pwa/introduction) guide too. But most importantly, make sure you read [SSR with PWA](/quasar-cli-vite/developing-ssr/ssr-with-pwa) page.\n\nShould you want to tamper with the Vite config for UI in /src:\n\n```js /quasar.config file\nexport default defineConfig(ctx => {\n return {\n build: {\n extendViteConf(viteConf, { isClient, isServer }) {\n if (ctx.mode.ssr) {\n // do something with viteConf\n // or return an object to deeply merge with current viteConf\n }\n }\n }\n }\n})\n```\n\n### Manually triggering store hydration\n\nBy default, Quasar CLI takes care of hydrating the Pinia stores (if you use it) on client-side.\n\nHowever, should you wish to manually hydrate it yourself, you need to set quasar.config file > ssr > manualStoreHydration: true. One good example is doing it from [a boot file](/quasar-cli-vite/boot-files):\n\n```js Some boot file\n// MAKE SURE TO CONFIGURE THIS BOOT FILE\n// TO RUN ONLY ON CLIENT-SIDE\nimport { defineBoot } from '#q-app/wrappers'\n\nexport default defineBoot(({ store }) => {\n // For Pinia\n store.state.value = window.__INITIAL_STATE__\n})\n```\n\n### Manually triggering post-hydration\n\nBy default, Quasar CLI wraps your App component and calls `$q.onSSRHydrated()` on the client-side when this wrapper component gets mounted. This is the moment that the client-side takes over. You don't need to configure anything for this to happen.\n\nHowever should you wish to override the moment when this happens, you need to set quasar.config file > ssr > manualPostHydrationTrigger: true. For whatever your reason is (very custom use-case), this is an example of manually triggering the post hydration:\n\n```tabs\n\u003c\u003c| js Composition API |>>\n// App.vue\n\nimport { onMounted } from 'vue'\nimport { useQuasar } from 'quasar'\n\nexport default {\n // ....\n setup () {\n // ...\n const $q = useQuasar()\n onMounted(() => {\n $q.onSSRHydrated()\n })\n }\n}\n\u003c\u003c| js Options API |>>\n// App.vue\n\nexport default {\n mounted () {\n this.$q.onSSRHydrated()\n }\n}\n```\n\n## Nodejs Server\n\nAdding SSR mode to a Quasar project means a new folder will be created: `/src-ssr`, which contains SSR specific files:\n\n\u003cDocTree :def=\"scope.nodeJsTree\" />\n\nYou can freely edit these files. Each of the two folders are detailed in their own doc pages (check left-side menu).\n\nNotice a few things:\n\n1. If you import anything from node_modules, then make sure that the package is specified in package.json > \"dependencies\" and NOT in \"devDependencies\".\n\n2. The `/src-ssr/middlewares` is built through a separate Esbuild config. You can extend the Esbuild configuration of these files through the `/quasar.config` file:\n\n```js /quasar.config file\nreturn {\n // ...\n ssr: {\n // ...\n extendSSRWebserverConf(esbuildConf) {\n // tamper with esbuildConf here\n }\n }\n}\n```\n\n4. The `/src-ssr/server.js` file is detailed in [SSR Webserver](/quasar-cli-vite/developing-ssr/ssr-webserver) page. Read it especially if you need to support serverless functions.\n\n## Helping SEO\n\nOne of the main reasons when you develop a SSR instead of a SPA is for taking care of the SEO. And SEO can be greatly improved by using the [Quasar Meta Plugin](/quasar-plugins/meta) to manage dynamic html markup required by the search engines.\n\n## Boot Files\n\nWhen running on SSR mode, your application code needs to be isomorphic or \"universal\", which means that it must run both on a Node.js context and in the browser. This applies to your [Boot Files](/quasar-cli-vite/boot-files) too.\n\nHowever, there are cases where you only want some boot files to run only on the server or only on the client-side. You can achieve that by specifying:\n\n```js /quasar.config file\nreturn {\n // ...\n boot: [\n 'some-boot-file', // runs on both server and client\n { path: 'some-other', server: false }, // this boot file gets embedded only on client-side\n { path: 'third', client: false } // this boot file gets embedded only on server-side\n ]\n}\n```\n\nJust make sure that your app is consistent, though.\n\nWhen a boot file runs on the server, you will have access to one more parameter (called [ssrContext](/quasar-cli-vite/developing-ssr/ssr-context)) on the default exported function:\n\n```js Some boot file\nexport default ({ app, ..., ssrContext }) => {\n // You can add props to the ssrContext then use them in the /index.html.\n // Example - let's say we ssrContext.someProp = 'some value', then in index template we can reference it:\n // {{ ssrContext.someProp }}\n}\n```\n\nWhen you add such references into your `/index.html`, make sure you tell Quasar it's only valid for SSR builds:\n\n```html /index.html\n\u003c% if (ctx.mode.ssr) { %>{{ ssrContext.someProp }} \u003c% } %>\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":8053,"content_sha256":"d4e4e54ce54884c817969b194a4d4f3bb8948c660047d8cd2c67b773d6371d25"},{"filename":"references/docs/quasar-cli-vite/developing-ssr/deploying.md","content":"---\ntitle: Deploying SSR\ndesc: (@quasar/app-vite) How to publish a Quasar server-side rendered app.\n---\n\nWhen deploying as a SPA or PWA, the distributables folder that gets generated by Quasar CLI can be served by a static webserver. However, this not the case with a SSR (Server-side Render) build. Your distributables, in this case, contain your production webserver too -- which can be tweaked from `/src-ssr`.\n\nBy default, the SSR distributables use Express, but you can replace it with your webserver of choice.\n\n## Serverless\n\nIf you are deploying to a Serverless service, then please read about [SSR Webserver](/quasar-cli-vite/developing-ssr/ssr-webserver) on how to prepare for it.\n\n## The Distributables Folder\n\nAfter building your app on SSR mode (`$ quasar build -m ssr`) the folder that gets generated contains a standalone webserver tweaked for serving with SSR.\n\nYou'll notice that it contains a `package.json` file of its own. It has an npm script defined, called \"start\":\n\n```js\n\"scripts\": {\n \"start\": \"node index.js\"\n}\n```\n\nSo what you need to do when deploying is to copy this distributables folder on your server, yarn/npm install the dependencies inside it, then run `$ yarn start`. This boots up the webserver and starts listening for connections.\n\n::: tip\nThe distributables folder generated after building your app is standalone. It does NOT require the rest of your project folder to work and it does NOT depend on `@quasar/cli` being installed.\n:::\n\n## Enhancing Performance\n\nBy default, the webserver runs on only one of the available server's cores. What you could do is make it use all cores. There is a solution for this: PM2.\n\nAfter installing PM2 on your server, your npm start script can look like this instead:\n\n```js\n\"scripts\": {\n \"start\": \"pm2 start index.js\"\n}\n```\n\n## Deploying with Cleavr\n\nYou can use Cleavr to deploy Quasar SSR apps to several popular VPS providers. Cleavr will automatically set up PM2 with cluster mode enabled for your app.\n\nAdd a new **NodeJS SSR** site to Cleavr and then configure the web app settings with the following:\n\n- **Entry point:** index.js\n- **Build command:** npx quasar build --mode ssr\n- **Artifact path:** dist/ssr\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2196,"content_sha256":"0654d4703c933cf409f1ba37f352a2bafb06a81f894616e3ac43a70318ddd6e4"},{"filename":"references/docs/quasar-cli-vite/developing-ssr/handling-404-and-500-errors.md","content":"---\ntitle: SSR Handling of 404 and 500 Errors\ndesc: (@quasar/app-vite) Managing the common 404 and 500 HTTP errors in a Quasar server-side rendered app.\n---\n\nThe handling of the 404 & 500 errors on SSR is a bit different than on the other modes (like SPA). If you check out `/src-ssr/middlewares/render.js`, you will notice the following section:\n\n```js /src-ssr/middlewares/render.js\nimport { defineSsrMiddleware } from '#q-app/wrappers'\n\n// This middleware should execute as last one\n// since it captures everything and tries to\n// render the page with Vue\n\nexport default defineSsrMiddleware(({ app, resolve, render, serve }) => {\n // we capture any other Express route and hand it\n // over to Vue and Vue Router to render our page\n app.get(resolve.urlPath('*'), (req, res) => {\n res.setHeader('Content-Type', 'text/html')\n\n render(/* the ssrContext: */ { req, res })\n .then(html => {\n // now let's send the rendered html to the client\n res.send(html)\n })\n .catch(err => {\n // oops, we had an error while rendering the page\n\n // we were told to redirect to another URL\n if (err.url) {\n if (err.code) {\n res.redirect(err.code, err.url)\n } else {\n res.redirect(err.url)\n }\n } else if (err.code === 404) {\n // hmm, Vue Router could not find the requested route\n\n // Should reach here only if no \"catch-all\" route\n // is defined in /src/routes\n res.status(404).send('404 | Page Not Found')\n } else if (process.env.DEV) {\n // well, we treat any other code as error;\n // if we're in dev mode, then we can use Quasar CLI\n // to display a nice error page that contains the stack\n // and other useful information\n\n // serve.error is available on dev only\n serve.error({ err, req, res })\n } else {\n // we're in production, so we should have another method\n // to display something to the client when we encounter an error\n // (for security reasons, it's not ok to display the same wealth\n // of information as we do in development)\n\n // Render Error Page on production or\n // create a route (/src/routes) for an error page and redirect to it\n res.status(500).send('500 | Internal Server Error')\n\n if (process.env.DEBUGGING) {\n console.error(err.stack)\n }\n }\n })\n })\n})\n```\n\nThe section above is written after catching the other possible requests (like for /public folder, the manifest.json and service worker, etc). This is where we render the page with Vue and Vue Router.\n\n## Things to be aware of\n\nWe'll discuss some architectural decisions that you need to be aware of. Choose whatever fits your app best.\n\n### Error 404\n\nIf you define an equivalent 404 route on your Vue Router `/src/router/routes.js` file (like below), then `if (err.code === 404) {` part from the example above will NEVER be `true` since Vue Router already handled it.\n\n```js\n// Example of route for catching 404 with Vue Router\n{ path: '/:catchAll(.*)*', component: () => import('pages/Error404.vue') }\n```\n\n### Error 500\n\nOn the `/src-ssr/middlewares/render.js` example at the top of the page, notice that if the webserver encounters any rendering error, we send a simple string back to the client ('500 | Internal Server Error'). If you want to show a nice page instead, you could:\n\n1. Add a specific route in `/src/router/routes.js`, like:\n\n```js\n{ path: 'error500', component: () => import('pages/Error500.vue') }\n```\n\n2. Write the Vue component to handle this page. In this example, we create `/src/pages/Error500.vue`\n3. Then in `/src-ssr/middlewares/render.js`:\n\n```js\nif (err.url) { ... }\nelse if (err.code === 404) { ... }\nelse {\n // We got a 500 error here;\n // We redirect to our \"error500\" route newly defined at step #1.\n res.redirect(resolve.urlPath('error500')) // keep account of publicPath though!\n}\n```\n\n::: danger\nThe only caveat is that you need to be sure that while rendering '/error500' route you don't get another 500 error, which would put your app into an infinite loop!\n:::\n\nA perfect approach to avoid this would simply be to directly return the HTML (as String) of the error 500 page from `/src-ssr/middlewares/render.js`:\n\n```js\nres.status(500).send(`\u003chtml>....\u003c/html>`)\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4400,"content_sha256":"deb4b3fd3ae7d000db58c80a082e54c2ff2c9d53c7e6813d1a68f8e92a1987c9"},{"filename":"references/docs/quasar-cli-vite/developing-ssr/introduction.md","content":"---\ntitle: What is SSR\ndesc: (@quasar/app-vite) Introduction on server-side rendered apps with Quasar CLI.\n---\n\nQuasar and Vue.js are frameworks for building client-side applications. By default, Quasar Vue components produce and manipulate DOM in the browser as output. However, it is also possible to render the same components into HTML strings on the server, send them directly to the browser, and finally \"hydrate\" the static markup into a fully interactive app on the client.\n\nA server-rendered Quasar app can also be considered `isomorphic` or `universal`, in the sense that the majority of your app's code runs on both the server and the client.\n\n## Why SSR?\n\nCompared to a traditional SPA (Single-Page Application), the advantage of SSR primarily lies in:\n\n- **Better SEO**, as the search engine crawlers will directly see the fully rendered page.\n- **Faster time-to-content**, especially on slow internet or slow devices. Server-rendered markup doesn't need to wait until all JavaScript has been downloaded and executed to be displayed, so your user will see a fully-rendered page sooner. This generally results in better user experience, and can be critical for applications where time-to-content is directly associated with conversion rate.\n\nThere are also some trade-offs to consider when using SSR:\n\n- **Development constraints**. Browser-specific code can only be used inside certain lifecycle hooks; some external libraries may need special treatment to be able to run in a server-rendered app.\n- **More server-side load**. Rendering a full app in Node.js is obviously going to be more CPU-intensive than just serving static files, so if you expect high traffic, be prepared for corresponding server load and wisely employ caching strategies.\n\nBefore using SSR for your app, the first question you should ask is whether you actually need it. It mostly depends on how important time-to-content is for your app. For example, if you are building an internal dashboard where an extra few hundred milliseconds on initial load doesn't matter that much, SSR would be an overkill. However, in cases where time-to-content is absolutely critical, SSR can help you achieve the best possible initial load performance.\n\n\u003cq-separator class=\"q-mt-xl\" />\n\n> Parts of this page are taken from the official Vue.js SSR guide.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2323,"content_sha256":"cebebb90af2774e74adaca4b985e11b2bc2b392a51765986d2b03776e779759d"},{"filename":"references/docs/quasar-cli-vite/developing-ssr/preparation.md","content":"---\ntitle: Preparation for SSR\ndesc: (@quasar/app-vite) How to add SSR mode with Quasar CLI.\nrelated:\n - /quasar-cli-vite/quasar-config-file\nscope:\n nodeJsTree:\n l: src-ssr\n c:\n - l: middlewares/\n e: SSR middleware files\n - l: server.js\n e: (or .ts) SSR webserver\n---\n\nWe’ll be using Quasar CLI to develop and build a SSR website. The difference between building a SPA, Mobile App, Electron App, PWA or SSR is simply determined by the “mode” parameter in “quasar dev” and “quasar build” commands.\n\nIn order to develop or build a SSR website, we first need to add the SSR mode to our Quasar project:\n\n```bash\n$ quasar mode add ssr\n```\n\nIf you want to jump right in and start developing, you can skip the \"quasar mode\" command and issue:\n\n```bash\n$ quasar dev -m ssr\n```\n\nThis will add SSR mode automatically, if it is missing.\n\nA new folder will appear in your project folder (which is explained in detail on the [Configuring SSR](/quasar-cli-vite/developing-ssr/configuring-ssr) page):\n\n\u003cDocTree :def=\"scope.nodeJsTree\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1069,"content_sha256":"a3a3030d8f26d13563975e5d9a26f078635bab0d7e8120b3eaf23b5b9466c80e"},{"filename":"references/docs/quasar-cli-vite/developing-ssr/seo-for-ssr.md","content":"---\ntitle: SEO for SSR\ndesc: (@quasar/app-vite) Managing the search engine optimizations in a Quasar server-side rendered app.\n---\n\nThe term SEO refers to Search Engine Optimization. And Quasar covers this aspect too through the [Quasar Meta Plugin](/quasar-plugins/meta).\n\n## Quasar Meta Plugin\n\nThe [Quasar Meta Plugin](/quasar-plugins/meta) can dynamically change page title, manage `\u003cmeta>` tags, manage `\u003chtml>` and `\u003cbody>` DOM element attributes, add/remove/change `\u003cstyle>` and `\u003cscript>` tags in the head of your document (useful for CDN stylesheets or for json-ld markup, for example), or manage `\u003cnoscript>` tags.\n\n::: tip\nThis Quasar plugin has the most tight integration with Quasar and so it has the best performance against any other similar solution.\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":771,"content_sha256":"a6ac6fd10d4f7540d1c3ec2ca315eeab85436af39a2b95ca7463f4121c68fccd"},{"filename":"references/docs/quasar-cli-vite/developing-ssr/ssr-context.md","content":"---\ntitle: The ssrContext Object\ndesc: (@quasar/app-vite) The ssrContext Object in Quasar SSR\n---\n\nThe `ssrContext` Object is the SSR context with which all the app's Vue components are rendered with.\n\n## Usage\n\n::: warning\nThe `ssrContext` Object is available only on SSR builds, on the server-side compilation (when `process∙env∙SERVER === true`).\n:::\n\nAmong other places, it is supplied as parameter to [boot files](/quasar-cli-vite/boot-files), to the [Pinia instance](/quasar-cli-vite/state-management-with-pinia) and [Vue Router](/quasar-cli-vite/routing) initialization functions, and to the [preFetch](/quasar-cli-vite/prefetch-feature) method:\n\n```js\n// a boot file\nexport default defineBoot(({ ..., ssrContext }) => { /* ... */ })\n\n// src/router/index.js\nexport default defineRouter(({ ..., ssrContext }) { /* ... */ })\n\n// src/store/index.js\nexport default defineStore(({ ..., ssrContext }) { /* ... */ })\n\n// with preFetch:\npreFetch: definePreFetch(({ ..., ssrContext }) { /* ... */ })\n```\n\nYou can also access the ssrContext in your Vue components. Below are two examples, one with Composition API and one with Options API:\n\n```tabs\n\u003c\u003c| js Composition API |>>\nimport { useSSRContext } from 'vue'\n\nexport default {\n // ...\n setup () {\n // we need to guard it and call it only on SSR server-side:\n const ssrContext = process.env.SERVER ? useSSRContext() : null\n // ...do something with it\n }\n}\n\u003c\u003c| js Options API |>>\nexport default {\n // ...\n created () { // can be any other Vue component lifecycle hook\n this.ssrContext\n }\n}\n```\n\n## Anatomy of ssrContext\n\n```js\nssrContext: {\n ;(req, // Express.js object\n res, // Express.js object\n $q, // The Quasar's $q Object\n nonce, // (optional to set it yourself)\n // The global \"nonce\" attribute to use\n\n onRendered, // Registers a function to be executed server-side after\n // app has been rendered with Vue. You might need this\n // to access ssrContext again after it has been fully processed.\n // Example: ssrContext.onRendered(() => { /* ... */ })\n\n rendered) // (optional to set it yourself)\n // Set this to a function which will be executed server-side\n // after the app has been rendered with Vue.\n // We recommend using the \"onRendered\" instead.\n //\n // Purpose: backward compatibility with Vue ecosystem packages\n // (like @vue/apollo-ssr)\n // Example: ssrContext.rendered = () => { /* ... */ }\n}\n```\n\nMore information on the purpose of the \"nonce\" property is available on MDN.\n\nThe `req` and `res` are Express.js's objects for the current server client. One use-case for `req` is accessing `req.url` to get the URL that the client is requesting.\n\n::: tip\nFeel free to inject your own stuff into ssrContext too, but do NOT tamper with any of the private props (props that start with an underscore, eg. `_someProp`).\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2841,"content_sha256":"be1d0523f7fd6049342774cfdb32c5d8732690b6ceeeb77180048c9e4d990587"},{"filename":"references/docs/quasar-cli-vite/developing-ssr/ssr-frequently-asked-questions.md","content":"---\ntitle: SSR FAQ\ndesc: (@quasar/app-vite) Tips and tricks for a Quasar server-side rendered app.\n---\n\n## Why am I getting hydration errors?\n\nTake a look at our [Client Side Hydration](/quasar-cli-vite/developing-ssr/client-side-hydration) page. When you get hydration errors, it means the HTML rendered on the server does not match the equivalent HTML rendered on client-side. This error will appear only when developing (and NOT on production) and it definitely needs to be addressed, before you release your website. Is there some content that you can only generate on client-side? Then use [QNoSsr](/vue-components/no-ssr).\n\n## Why doesn't importing Platform and Cookies work?\n\nWhen building for SSR, use only the `$q.platform` / `$q.cookies` form. Alternatively, when on server-side, this is one more example of how you can use it:\n\n```js\n// example with Platform; same thing for Cookies\nimport { Platform } from 'quasar'\n\n// you need access to `ssrContext`\nfunction (ssrContext) {\n const platform = process.env.SERVER\n ? Platform.parseSSR(ssrContext)\n : Platform // otherwise we're on client\n\n // platform is equivalent to the global import as in non-SSR builds\n}\n```\n\nThe `ssrContext` is available in the [Boot Files](/quasar-cli-vite/boot-files) or the [PreFetch Feature](/quasar-cli-vite/prefetch-feature), where it is supplied as a parameter.\n\nThere is a good reason for this. In a client-only app, every user will be using a fresh instance of the app in their browser. For server-side rendering we want the same thing. Each request should have a fresh, isolated app instance so that there is no cross-request state pollution. So [Platform](/options/platform-detection) and [Cookies](/quasar-plugins/cookies) need to be bound to each request separately.\n\nAlso a good idea is to read the [Writing Universal Code](/quasar-cli-vite/developing-ssr/writing-universal-code) documentation page.\n\n## Why isn't LocalStorage and SessionStorage working?\n\nWhen running the code on server-side, the storage facilities can't work. Web Storage is a browser only API.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2071,"content_sha256":"e619ca1d3d83acc070b2781406bb8554860a77ca021d2f8d4db3ed4eee14d18a"},{"filename":"references/docs/quasar-cli-vite/developing-ssr/ssr-middleware.md","content":"---\ntitle: SSR Middleware\ndesc: (@quasar/app-vite) Managing the SSR middleware in a Quasar app.\nrelated:\n - /quasar-cli-vite/quasar-config-file\n---\n\nThe SSR middleware files fulfill one special purpose: they prepare the Nodejs server that runs your SSR app with additional functionality (Express compatible middleware).\n\nWith SSR middleware files, it is possible to split the middleware logic into self-contained, easy to maintain files. It is also trivial to disable any of the SSR middleware files or even contextually determine which of the SSR middleware files get into the build through the `/quasar.config` file configuration.\n\n::: tip\nFor more advanced usage, you will need to get acquainted to the Express API.\n:::\n\n::: warning\nYou will need at least one SSR middleware file which handles the rendering of the page with Vue (which should be positioned as last in the middlewares list). When SSR mode is added to your Quasar CLI project, this will be scaffolded into `src-ssr/middlewares/render.js`.\n:::\n\n## Anatomy of a middleware file\n\nA SSR middleware file is a simple JavaScript file which exports a function. Quasar will then call the exported function when it prepares the Nodejs server (Express) app and additionally pass an Object as param (which will be detailed in the next section).\n\n```js\nimport { defineSsrMiddleware } from '#q-app/wrappers'\n\nexport default defineSsrMiddleware(\n ({ app, port, resolve, publicPath, folders, render, serve }) => {\n // something to do with the server \"app\"\n }\n)\n```\n\nThe SSR middleware files can also be async:\n\n```js\n// import something here\n\nexport default defineSsrMiddleware(\n async ({ app, port, resolve, publicPath, folders, render, serve }) => {\n // something to do with the server \"app\"\n await something()\n }\n)\n```\n\nNotice the `defineSsrMiddleware` import. It is essentially a no-op function, but it helps with the IDE autocomplete.\n\nNotice we are using the ES6 destructuring assignment. Only assign what you actually need/use.\n\n## Middleware object parameter\n\nWe are referring here to the Object received as parameter by the default exported function of the SSR middleware file.\n\n```js\nexport default defineSsrMiddleware(({ app, port, resolve, publicPath, folders, render, serve }) => {\n```\n\nDetailing the Object:\n\n```js\n{\n app, // Express app or whatever is returned from src-ssr/server -> create()\n port, // on dev: devServer port; on prod: process.env.PORT or quasar.config > ssr > prodPort\n resolve: {\n urlPath, // (url) => path string with publicPath ensured to be included,\n root, // (pathPart1, ...pathPartN) => path string (joins to the root folder),\n public // (pathPart1, ...pathPartN) => path string (joins to the public folder)\n },\n publicPath, // string\n folders: {\n root, // path string of the root folder\n public // path string of the public folder\n },\n render, // (ssrContext) => html string\n serve: {\n static, // ({ urlPath = '/', pathToServe = '.', opts = {} }) => void (OR whatever returned by src-ssr/server -> serveStaticContent())\n error // DEV only; ({ err, req, res }) => void\n }\n}\n```\n\n#### app\n\nThis is the Node.js app instance. The \"bread and butter\" of any middleware since you'll be using it to configure the webserver.\n\n#### port\n\nThe configured port for the Node.js webserver.\n\n#### resolve\n\n| Prop name | Description |\n| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `urlPath(path)` | Whenever you define a route (with app.use(), app.get(), app.post() etc), you should use the `resolve.urlPath()` method so that you'll also keep into account the configured publicPath (quasar.config file > build > publicPath). |\n| `root(path1[, path2, ...pathN])` | Resolve folder path to the root (of the project in dev and of the distributables in production). Under the hood, it does a `path.join()`. |\n| `public(path1[, path2, ...pathN])` | Resolve folder path to the \"public\" folder. Under the hood, it does a `path.join()`. |\n\n#### publicPath\n\nThe configured quasar.config file > build > publicPath\n\n#### folders\n\nThe `folders` is sometimes needed because the exact path to root folder and to the public folder differs in a production build than in a development build. So by using `folders` you won't need to mind about this.\n\n| Prop name | Description |\n| --------- | -------------------------------------------------------------------------------------- |\n| `root` | Full path to the root (of the project in dev and of the distributables in production). |\n| `public` | Full path to the \"public\" folder. |\n\n#### render\n\n- Syntax: `\u003cPromise(String)> render(ssrContext)`.\n- Description: Uses Vue and Vue Router to render the requested URL path. Returns the rendered HTML string to return to the client.\n\n#### serve\n\nserve.static():\n\n- Syntax: `\u003cmiddlewareFn> serve.static(pathFromPublicFolder, opts)`\n- Description: It's essentially a wrapper over `express.static()` with a few convenient tweaks:\n - the `pathFromPublicFolder` is a path resolved to the \"public\" folder out of the box\n - the `opts` are the same as for `express.static()`\n - `opts.maxAge` is used by default, taking into account the quasar.config file > ssr > maxAge configuration; this sets how long the respective file(s) can live in browser's cache\n\n ```js\n serve.static({ urlPath: '/my-file.json', pathToServe: '.', opts = {} })\n\n // is equivalent to:\n\n express.static(resolve.public('my-file.json'), {})\n ```\n\nserve.error():\n\n- Syntax: `\u003cvoid> serve.error({ err, req, res })`\n- Description: Displays a wealth of useful debug information (including the stack trace).\n- It's available only in development and **NOT in production**.\n\n## Usage of SSR middleware\n\nThe first step is always to generate a new SSR middleware file using Quasar CLI:\n\n```bash\n$ quasar new ssrmiddleware \u003cname>\n```\n\nWhere `\u003cname>` should be exchanged by a suitable name for your SSR middleware file.\n\nThis command creates a new file: `/src-ssr/middlewares/\u003cname>.js` with the following content:\n\n```js\n// import something here\n\n// \"async\" is optional!\n// remove it if you don't need it\nexport default async ({\n app,\n port,\n resolveUrlPath,\n publicPath,\n folders,\n render,\n serve\n}) => {\n // something to do with the server \"app\"\n}\n```\n\nYou can also return a Promise:\n\n```js\n// import something here\n\nexport default defineSsrMiddleware(\n ({ app, port, resolve, publicPath, folders, render, serve }) => {\n return new Promise((resolve, reject) => {\n // something to do with the server \"app\"\n })\n }\n)\n```\n\nYou can now add content to that file depending on the intended use of your SSR middleware file.\n\nThe last step is to tell Quasar to use your new SSR middleware file. For this to happen you need to add the file in the `/quasar.config` file:\n\n```js /quasar.config file\nssr: {\n middlewares: [\n // references /src-ssr/middlewares/\u003cname>.js\n '\u003cname>'\n ]\n}\n```\n\nWhen building a SSR app, you may want some boot files to run only on production or only on development, in which case you can do so like below:\n\n```js /quasar.config file\nssr: {\n middlewares: [\n ctx.prod ? '\u003cname>' : '', // I run only on production!\n ctx.dev ? '\u003cname>' : '' // I run only on development\n ]\n}\n```\n\nIn case you want to specify SSR middleware file from node_modules, you can do so by prepending the path with `~` (tilde) character:\n\n```js /quasar.config file\nssr: {\n middlewares: [\n // boot file from an npm package\n '~my-npm-package/some/file'\n ]\n}\n```\n\n::: warning\nThe order in which you specify the SSR middlewares matters because it determines the way in which the middlewares are applied to the Nodejs server. So they influence how it responds to the client.\n:::\n\n## The SSR render middleware\n\n::: danger Important!\nOut of all the possible SSR middlewares in your app, **this one is absolutely required**, because it handles the actual SSR rendering with Vue.\n:::\n\nIn the example below we highlight that this middleware needs to be the last in the list. This is because it also responds to the client (as we'll see in the second code sample below) with the HTML of the page. So any subsequent middleware cannot set headers.\n\n```js /quasar.config file\nssr: {\n middlewares: [\n // ..... all other middlewares\n\n 'render' // references /src-ssr/middlewares/render.js;\n // you can name the file however you want,\n // just make sure that it runs as last middleware\n ]\n}\n```\n\nNow let's see what it contains:\n\n```js src-ssr/middlewares/render.js\n// This middleware should execute as last one\n// since it captures everything and tries to\n// render the page with Vue\n\nexport default ({ app, resolve, render, serve }) => {\n // we capture any other Express route and hand it\n // over to Vue and Vue Router to render our page\n app.get(resolve.urlPath('*'), (req, res) => {\n res.setHeader('Content-Type', 'text/html')\n\n render({ req, res })\n .then(html => {\n // now let's send the rendered html to the client\n res.send(html)\n })\n .catch(err => {\n // oops, we had an error while rendering the page\n\n // we were told to redirect to another URL\n if (err.url) {\n if (err.code) {\n res.redirect(err.code, err.url)\n } else {\n res.redirect(err.url)\n }\n }\n // hmm, Vue Router could not find the requested route\n else if (err.code === 404) {\n // Should reach here only if no \"catch-all\" route\n // is defined in /src/routes\n res.status(404).send('404 | Page Not Found')\n }\n // well, we treat any other code as error;\n // if we're in dev mode, then we can use Quasar CLI\n // to display a nice error page that contains the stack\n // and other useful information\n else if (process.env.DEV) {\n // serve.error is available on dev only\n serve.error({ err, req, res })\n }\n // we're in production, so we should have another method\n // to display something to the client when we encounter an error\n // (for security reasons, it's not ok to display the same wealth\n // of information as we do in development)\n else {\n // Render Error Page on production or\n // create a route (/src/routes) for an error page and redirect to it\n res.status(500).send('500 | Internal Server Error')\n\n if (process.env.DEBUGGING) {\n console.error(err.stack)\n }\n }\n })\n })\n}\n```\n\nNotice the `render` parameter (from the above code sample) that the exported function of the middleware gets called with. That's where the SSR rendering happens.\n\n## Hot Module Reload\n\nWhile developing, whenever you change anything in the SSR middlewares, Quasar App CLI will automatically trigger a recompilation of client-side resources and apply the middleware changes to the Nodejs server (Express).\n\n## Examples of SSR middleware\n\n::: tip\nYou can use any connect API compatible middleware.\n:::\n\n### Logger / Interceptor\n\nThe order in which the SSR middlewares are applied matters. So it might be wise to set the following one as the first (in quasar.config file > ssr > middlewares) so that it will be able to intercept all client requests.\n\n```js\nexport default defineSsrMiddleware(({ app, resolve }) => {\n app.all(resolve.urlPath('*'), (req, _, next) => {\n console.log('someone requested:', req.url)\n next()\n })\n})\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":12237,"content_sha256":"e2c8ff8d5189be0fe26697050a0461bcfde07227c753fa89b35416a90745224f"},{"filename":"references/docs/quasar-cli-vite/developing-ssr/ssr-webserver.md","content":"---\ntitle: SSR Webserver\ndesc: (@quasar/app-vite) Configuring the Quasar SSR webserver for different platforms, including a serverless architecture.\n---\n\nNotice that your generated `/src-ssr` contains a file named `server.js`. This file defines how your SSR webserver is created, managed and served. You can start listening to a port or provide a handler for your serverless infrastructure to use. It's up to you.\n\n## Anatomy\n\nThe `/src-ssr/server.js` file is a simple JavaScript/Typescript file which boots up your SSR webserver and defines what how your webserver starts & handles requests and what it exports (if exporting anything).\n\n::: danger\nThe `/src-ssr/server.js` file is used for both DEV and PROD, so please be careful on how you configure it. To differentiate between the two states you can use `process∙env∙DEV` and `process∙env∙PROD`.\n:::\n\n```js\n/**\n * Runs in Node.js context.\n */\n\n/**\n * Make sure to yarn/npm/pnpm/bun install (in your project root)\n * anything you import here (except for express and compression).\n */\nimport express from 'express'\nimport compression from 'compression'\nimport {\n defineSsrCreate,\n defineSsrListen,\n defineSsrClose,\n defineSsrServeStaticContent,\n defineSsrRenderPreloadTag\n} from '#q-app/wrappers'\n\n/**\n * Create your webserver and return its instance.\n *\n * Can be async: defineSsrCreate(async ({ ... }) => { ... })\n *\n * Param: ({\n * port, // on dev: devServer port; on prod: process.env.PORT or quasar.config > ssr > prodPort\n * devHttpsOptions, // DEV only, if using HTTPS; if using a custom server, you can use this to handle HTTPS on your own instead of using the devHttpsApp in listen()\n * resolve: {\n * urlPath, // (url) => path string with publicPath ensured to be included,\n * root, // (pathPart1, ...pathPartN) => path string (joins to the root folder),\n * public // (pathPart1, ...pathPartN) => path string (joins to the public folder)\n * },\n * publicPath, // string\n * folders: {\n * root, // path string of the root folder\n * public // path string of the public folder\n * },\n * render // (ssrContext) => html string\n * })\n */\nexport const create = defineSsrCreate((/* { ... } */) => {\n const app = express()\n\n // attackers can use this header to detect apps running Express\n // and then launch specifically-targeted attacks\n app.disable('x-powered-by')\n\n // place here any middlewares that\n // absolutely need to run before anything else\n if (process.env.PROD) {\n app.use(compression())\n }\n\n return app\n})\n\n/**\n * Used by Quasar SSR dev server to inject middleware into the webserver.\n * It uses it to handle Vite dev server, handle public paths, etc.\n * The given middleware is compatible with `node:http`'s Server, Express, Connect, etc.\n *\n * Can be async: defineSsrInjectDevMiddleware(async ({ app }) => { ... })\n */\nexport const injectDevMiddleware = defineSsrInjectDevMiddleware(({ app }) => {\n return middleware => {\n app.use(middleware)\n }\n})\n\n/**\n * You need to make the server listen to the indicated port\n * and return the listening instance or whatever you need to\n * close the server with.\n *\n * The \"listenResult\" param for the \"close()\" definition below\n * is what you return here.\n *\n * For production, you can instead export your\n * handler for serverless use or whatever else fits your needs.\n *\n * Can be async: defineSsrListen(async ({ app, devHttpsApp, port }) => { ... })\n *\n * Param: ({\n * app, // Express app or whatever is returned from create()\n * devHttpsApp, // DEV only, if using HTTPS; Node.js HTTPS server instance\n * devHttpsOptions, // DEV only, if using HTTPS; if using a custom server, you can use this to handle HTTPS on your own\n * port, // on dev: devServer port; on prod: process.env.PORT or quasar.config > ssr > prodPort\n * resolve: {\n * urlPath, // (url) => path string with publicPath ensured to be included,\n * root, // (pathPart1, ...pathPartN) => path string (joins to the root folder),\n * public // (pathPart1, ...pathPartN) => path string (joins to the public folder)\n * },\n * publicPath, // string\n * folders: {\n * root, // path string of the root folder\n * public // path string of the public folder\n * },\n * render, // (ssrContext) => html string\n * serve: {\n * static, // ({ urlPath = '/', pathToServe = '.', opts = {} }) => void (OR whatever returned by serveStaticContent())\n * error // DEV only; ({ err, req, res }) => void\n * },\n * })\n */\nexport const listen = defineSsrListen(({ app, devHttpsApp, port }) => {\n const server = devHttpsApp || app\n return server.listen(port, () => {\n if (process.env.PROD) {\n console.log('Server listening at port ' + port)\n }\n })\n})\n\n/**\n * Should close the server and free up any resources.\n * Will be used on development only when the server needs\n * to be rebooted.\n *\n * Should you need the result of the \"listen()\" call above,\n * you can use the \"listenResult\" param.\n *\n * Can be async: defineSsrClose(async ({ listenResult }) => { ... })\n *\n * Param: ({\n * app, // Express app or whatever is returned from create()\n * devHttpsApp, // DEV only, if using HTTPS\n * port, // on dev: devServer port; on prod: process.env.PORT or quasar.config > ssr > prodPort\n * resolve: {\n * urlPath, // (url) => path string with publicPath ensured to be included,\n * root, // (pathPart1, ...pathPartN) => path string (joins to the root folder),\n * public // (pathPart1, ...pathPartN) => path string (joins to the public folder)\n * },\n * publicPath, // string\n * folders: {\n * root, // path string of the root folder\n * public // path string of the public folder\n * },\n * serve: {\n * static, // ({ urlPath = '/', pathToServe = '.', opts = {} }) => void (OR whatever returned by serveStaticContent())\n * error // DEV only; ({ err, req, res }) => void\n * },\n * render, // (ssrContext) => html string\n * listenResult // whatever returned from listen()\n * })\n */\nexport const close = defineSsrClose(({ listenResult }) => {\n return listenResult.close()\n})\n\nconst maxAge = process.env.DEV ? 0 : 1000 * 60 * 60 * 24 * 30\n\n/**\n * Should return a function that will be used to configure the webserver\n * to serve static content at \"urlPath\" from \"pathToServe\" folder/file.\n *\n * Notice resolve.urlPath(urlPath) and resolve.public(pathToServe) usages.\n *\n * Can be async: defineSsrServeStaticContent(async ({ app, resolve }) => {\n * Can return an async function: return async ({ urlPath = '/', pathToServe = '.', opts = {} }) => {\n *\n * Param: ({\n * app, // Express app or whatever is returned from create()\n * port, // on dev: devServer port; on prod: process.env.PORT or quasar.config > ssr > prodPort\n * resolve: {\n * urlPath: (url) => path string with publicPath ensured to be included,\n * root: (pathPart1, ...pathPartN) => path string (joins to the root folder),\n * public: (pathPart1, ...pathPartN) => path string (joins to the public folder)\n * },\n * publicPath, // string\n * folders: {\n * root, // path string of the root folder\n * public // path string of the public folder\n * },\n * render: (ssrContext) => html string\n * })\n */\nexport const serveStaticContent = defineSsrServeStaticContent(\n ({ app, resolve }) => {\n return ({ urlPath = '/', pathToServe = '.', opts = {} }) => {\n const serveFn = express.static(resolve.public(pathToServe), {\n maxAge,\n ...opts\n })\n app.use(resolve.urlPath(urlPath), serveFn)\n }\n }\n)\n\nconst jsRE = /\\.js$/\nconst cssRE = /\\.css$/\nconst woffRE = /\\.woff$/\nconst woff2RE = /\\.woff2$/\nconst gifRE = /\\.gif$/\nconst jpgRE = /\\.jpe?g$/\nconst pngRE = /\\.png$/\n\n/**\n * Should return a String with HTML output\n * (if any) for preloading indicated file\n */\nexport const renderPreloadTag = defineSsrRenderPreloadTag(\n (file /* , { ssrContext } */) => {\n if (jsRE.test(file) === true) {\n return `\u003clink rel=\"modulepreload\" href=\"${file}\" crossorigin>`\n }\n\n if (cssRE.test(file) === true) {\n return `\u003clink rel=\"stylesheet\" href=\"${file}\" crossorigin>`\n }\n\n if (woffRE.test(file) === true) {\n return `\u003clink rel=\"preload\" href=\"${file}\" as=\"font\" type=\"font/woff\" crossorigin>`\n }\n\n if (woff2RE.test(file) === true) {\n return `\u003clink rel=\"preload\" href=\"${file}\" as=\"font\" type=\"font/woff2\" crossorigin>`\n }\n\n if (gifRE.test(file) === true) {\n return `\u003clink rel=\"preload\" href=\"${file}\" as=\"image\" type=\"image/gif\" crossorigin>`\n }\n\n if (jpgRE.test(file) === true) {\n return `\u003clink rel=\"preload\" href=\"${file}\" as=\"image\" type=\"image/jpeg\" crossorigin>`\n }\n\n if (pngRE.test(file) === true) {\n return `\u003clink rel=\"preload\" href=\"${file}\" as=\"image\" type=\"image/png\" crossorigin>`\n }\n\n return ''\n }\n)\n```\n\n::: tip\nRemember that whatever the `listen()` function returns (if anything) will be exported from your built `dist/ssr/index.js`. You can return your ssrHandler for a serverless architecture should you need it.\n:::\n\n## Usage\n\n::: warning\n\n- If you import anything from node_modules, then make sure that the package is specified in package.json > \"dependencies\" and NOT in \"devDependencies\".\n- This is usually not the place to add middlewares (but you can do it). Add middlewares by using the [SSR Middlewares](/quasar-cli-vite/developing-ssr/ssr-middleware) instead. You can configure SSR Middlewares to run only for dev or only for production too.\n :::\n\n### Replacing Express\n\nYou can replace the default Express server with any other one such as Connect, Fastify, h3, etc. You need to install the relevant packages, then adapt `create`, `listen`, `close`, etc. accordingly.\n\n#### Example: Connect\n\nSince Express is a Connect-based server, you can use Connect as a simple drop-in replacement:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add connect\n\u003c\u003c| bash NPM |>>\n$ npm install --save connect\n\u003c\u003c| bash PNPM |>>\n$ pnpm add connect\n\u003c\u003c| bash Bun |>>\n$ bun add connect\n```\n\n```js src-ssr/server.js\nimport { defineSsrCreate } from '#q-app/wrappers'\nimport connect from 'connect'\nimport compression from 'compression'\n\nexport const create = defineSsrCreate((/* { ... } */) => {\n const app = connect()\n\n // Place any middleware that needs to run before anything else\n if (process.env.PROD) {\n app.use(compression())\n }\n\n return app\n})\n```\n\n#### Example: Fastify\n\nFastify is considerably different from Express, so it requires a more thorough adaptation:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add fastify @fastify/middie @fastify/compress @fastify/static\n\u003c\u003c| bash NPM |>>\n$ npm install --save fastify @fastify/middie @fastify/compress @fastify/static\n\u003c\u003c| bash PNPM |>>\n$ pnpm add fastify @fastify/middie @fastify/compress @fastify/static\n\u003c\u003c| bash Bun |>>\n$ bun add fastify @fastify/middie @fastify/compress @fastify/static\n```\n\n```js src-ssr/server.js\nimport {\n defineSsrCreate,\n defineSsrInjectDevMiddleware,\n defineSsrListen,\n defineSsrClose,\n defineSsrServeStaticContent\n} from '#q-app/wrappers'\nimport Fastify from 'fastify'\n\n// If using TypeScript, also enable the following:\n/*\nimport type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'\n\nimport type { Server } from 'node:http'\ndeclare module '#q-app' {\n interface SsrDriver {\n app: FastifyInstance;\n listenResult: Server;\n request: FastifyRequest;\n response: FastifyReply;\n }\n}\n*/\n\nexport const create = defineSsrCreate(async ({ devHttpsOptions }) => {\n const app = Fastify({\n https: devHttpsOptions ?? null\n })\n\n // Place any middleware that needs to run before anything else\n if (process.env.PROD) {\n await app.register(import('@fastify/compress'))\n }\n\n return app\n})\n\nexport const injectDevMiddleware = defineSsrInjectDevMiddleware(\n async ({ app }) => {\n await app.register(import('@fastify/middie'))\n\n return middleware => {\n app.use(middleware)\n }\n }\n)\n\nexport const listen = defineSsrListen(async ({ app, port }) => {\n await app.listen({ port })\n return app.server\n})\n\nexport const close = defineSsrClose(({ listenResult }) => {\n return listenResult.close()\n})\n\nconst maxAge = process.env.DEV ? 0 : 1000 * 60 * 60 * 24 * 30\n\nexport const serveStaticContent = defineSsrServeStaticContent(\n ({ app, resolve }) => {\n return async ({ urlPath = '/', pathToServe = '.', opts = {} }) => {\n await app.register(import('@fastify/static'), {\n root: resolve.public(pathToServe),\n prefix: resolve.urlPath(urlPath),\n maxAge: opts.maxAge ?? maxAge,\n // To avoid conflicts with ./middlewares/render\n wildcard: false,\n index: false\n })\n }\n }\n)\n\n// renderPreloadTag logic is the same\n```\n\n```js src-ssr/middlewares/render.js\nimport { defineSsrMiddleware } from '#q-app/wrappers'\n\nexport default defineSsrMiddleware(({ app, resolve, render, serve }) => {\n app.get(resolve.urlPath('*'), async (req, res) => {\n res.type('text/html')\n\n try {\n return await render({ req, res })\n } catch (err) {\n if (err.url) {\n return res.redirect(err.url, err.code)\n }\n\n if (err.code === 404) {\n return res.status(404).send('404 | Page Not Found')\n }\n\n if (process.env.DEV) {\n serve.error({ err, req, res })\n } else {\n res.status(500).send('500 | Internal Server Error')\n\n if (process.env.DEBUGGING) {\n console.error(err.stack)\n }\n }\n }\n })\n})\n```\n\n### Listen on a port\n\nThis is the default option that you get when adding SSR support in a Quasar CLI project. It starts listening on the configured port (process∙env∙PORT or quasar.config file > ssr > prodPort).\n\n```js src-ssr/server.js\nexport const listen = defineSsrListen(({ app, devHttpsApp, port }) => {\n const server = devHttpsApp || app\n return server.listen(port, () => {\n if (process.env.PROD) {\n console.log('Server listening at port ' + port)\n }\n })\n})\n```\n\n### Serverless\n\nIf you have a serverless infrastructure, then you generally need to export a handler instead of starting to listen to a port.\n\nSay that your serverless service requires you to name export a variable called `handler`. Then what you'd need to do is:\n\n```js src-ssr/server.js\nimport { defineSsrListen } from '#q-app/wrappers'\nexport const listen = defineSsrListen(({ app, devHttpsApp, port }) => {\n if (process.env.DEV) {\n // for dev, start listening on the created server\n const server = devHttpsApp || app\n return server.listen(port, () => {\n // we're ready to serve clients\n })\n } else {\n // in production\n // return an object with a \"handler\" property\n // that the server script will be named-export\n return { handler: app }\n }\n})\n```\n\nPlease note that the provided `app` is a Function of form: `(req, res, next) => void`.\nShould you require to export a handler of form `(event, context, callback) => void` then you will most likely want to use the `serverless-http` package (see below).\n\n#### Example: serverless-http\n\nYou will need to manually yarn/npm install the `serverless-http` package.\n\n```js src-ssr/server.js\nimport { defineSsrListen } from '#q-app/wrappers'\nimport serverless from 'serverless-http'\n\nexport const listen = defineSsrListen(({ app, devHttpsApp, port }) => {\n if (process.env.DEV) {\n // for dev, start listening on the created server\n const server = devHttpsApp || app\n return server.listen(port, () => {\n // we're ready to serve clients\n })\n } else {\n // in production\n return { handler: serverless(app) }\n }\n})\n```\n\n#### Example: Firebase function\n\n```js src-ssr/server.js\nimport { defineSsrListen } from '#q-app/wrappers'\nimport * as functions from 'firebase-functions'\n\nexport const listen = defineSsrListen(({ app, devHttpsApp, port }) => {\n if (process.env.DEV) {\n // for dev, start listening on the created server\n const server = devHttpsApp || app\n return server.listen(port, () => {\n // we're ready to serve clients\n })\n } else {\n // in production\n return {\n handler: functions.https.onRequest(app)\n }\n }\n})\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":16051,"content_sha256":"a7870022164d344087ba1309e59541e2a2f3ffba933b2d408c45885be229204b"},{"filename":"references/docs/quasar-cli-vite/developing-ssr/ssr-with-pwa.md","content":"---\ntitle: SSR with PWA Client Takeover\ndesc: (@quasar/app-vite) How to configure your Quasar server-side rendered app to become a Progressive Web App on the client side.\n---\n\nWith Quasar CLI you can build your app with the killer combo of SSR + PWA. In order to enable PWA for SSR builds, you need to edit your `/quasar.config` file first:\n\n```js /quasar.config file\nreturn {\n // ...\n ssr: {\n pwa: true\n }\n}\n```\n\nThe first request of a **new** client will be served from the webserver (so SSR supplies the initial page content). The PWA gets installed then it takes over on client side. All further requests will be served from cache (unless you have some custom configuration to change that).\n\n> For more information on PWA, head on to [PWA Introduction](/quasar-cli-vite/developing-pwa/introduction) and read the whole PWA Guide section.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":847,"content_sha256":"e253a7f8bb2a4523abca1d54c9d4a8e8bcad9115e324c6de46c9ac12db61c896"},{"filename":"references/docs/quasar-cli-vite/developing-ssr/ssr-with-typescript.md","content":"---\ntitle: SSR with Typescript\ndesc: (@quasar/app-vite) How to use Typescript with SSR in Quasar\n---\n\nIn order to support SSR with Typescript, you will need to rename all your files in /src-ssr from `.js` to `.ts` and make the necessary TS code changes.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":254,"content_sha256":"ebbf2eb76a77c440f07403027c8f5ce486a3759bd40f4149296cfb272b0750d3"},{"filename":"references/docs/quasar-cli-vite/developing-ssr/vue-ssr-directives.md","content":"---\ntitle: Vue SSR Directives\ndesc: (@quasar/app-vite) Managing the Vue directives for SSR in a Quasar app.\n---\n\n::: warning\nThis guide refers to usage with Quasar v2.6+\n:::\n\nA SSR app has the same code running on server and on client. Declaring a Vue directive (or directly importing it) in a .vue SFC file is usually enough for making it to work on non-SSR builds. But on SSR builds and due to the architecture of Vue 3 it requires some extra leg work.\n\nServer-side builds require all Vue directives to also specify a getSSRProps() method in their definition.\n\n::: tip\n\n- You will NOT need to do anything for the Quasar supplied Vue directives to work.\n- However, if you are using a third-party supplied Vue directive and the CLI errors out on it then you will need to contact the owner of that package in order for them to make it compliant with Vue 3 SSR specs (which is to add the getSSRProps() method in the directive's definition).\n :::\n\n## How to declare a directive\n\nThe following is taken from Vue.js docs:\n\n> Since most custom directives involve direct DOM manipulation, they are ignored during SSR. However, if you want to specify how a custom directive should be rendered (i.e. what attributes it should add to the rendered element), you can use the getSSRProps directive hook:\n\n```js\nconst myDirective = {\n mounted(el, binding) {\n // client-side implementation:\n // directly update the DOM\n el.id = binding.value\n },\n\n getSSRProps(binding) {\n // server-side implementation:\n // return the props to be rendered.\n // getSSRProps only receives the directive binding.\n return {\n id: binding.value\n }\n }\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1653,"content_sha256":"4f98138395cca988ce10d23dd09c9e6f09776dd9744f5698e9e74e775c591c1a"},{"filename":"references/docs/quasar-cli-vite/developing-ssr/writing-universal-code.md","content":"---\ntitle: Writing Universal Code\ndesc: (@quasar/app-vite) Guide on how to write code for a Quasar server-side rendered app.\n---\n\nWriting `universal` code (also called `isomorphic`) means writing code that runs on both the server and the client. Due to use-case and platform API differences, the behavior of our code will not be exactly the same when running in different environments. Here we will go over the key things you need to be aware of.\n\n\n\n## Data Reactivity on the Server\n\nIn a client-only app, every user will be using a fresh instance of the app in their browser. For server-side rendering we want the same: each request should have a fresh, isolated app instance so that there is no cross-request state pollution.\n\nBecause the actual rendering process needs to be deterministic, we will also be \"pre-fetching\" data on the server - this means our application state will be already resolved when we start rendering. This means data reactivity is unnecessary on the server, so it is disabled by default. Disabling data reactivity also avoids the performance cost of converting data into reactive objects.\n\n## Component Lifecycle Hooks\n\nSince there are no dynamic updates, of all the Vue lifecycle hooks, only `beforeCreate` and `created` will be called during SSR. This means any code inside other lifecycle hooks such as `beforeMount` or `mounted` will only be executed on the client.\n\nAnother thing to note is that you should avoid code that produces global side effects in `beforeCreate` and `created`, for example setting up timers with `setInterval`. In client-side only code we may setup a timer and then tear it down in `beforeUnmount` or `destroyed`. However, because the destroy hooks will not be called during SSR, the timers will stay around forever. To avoid this, move your side-effect code into `beforeMount` or `mounted` instead.\n\n## Avoid Stateful Singletons\n\nWhen writing client-only code, we are used to the fact that our code will be evaluated in a fresh context every time. However, a Node.js server is a long-running process. When our code is required into the process, it will be evaluated once and then it stays in memory. This means if you create a singleton object, it will be shared between every incoming request.\n\nSo, Quasar CLI creates a new root Vue instance with a new Router and Pinia instance for each request. This is similar to how each user will be using a fresh instance of the app in their own browser. If we would have used a shared instance across multiple requests, it will easily lead to cross-request state pollution.\n\nInstead of directly creating a Router and Pinia instance, you'll be exposing a factory function that can be repeatedly executed to create fresh app instances for each request:\n\n```js src/router/index.js\nimport { defineRouter } from '#q-app/wrappers'\nexport default defineRouter((/* { store, ssrContext } */) => {\n const Router = new VueRouter({...})\n return Router\n})\n```\n\n```js src/stores/index.js\nimport { defineStore } from '#q-app/wrappers'\nimport { createPinia } from 'pinia'\n\n/*\n * If not building with SSR mode, you can\n * directly export the Store instantiation;\n *\n * The function below can be async too; either use\n * async/await or return a Promise which resolves\n * with the Store instance.\n */\n\nexport default defineStore((/* { ssrContext } */) => {\n const pinia = createPinia()\n\n // You can add Pinia plugins here\n // pinia.use(SomePiniaPlugin)\n\n return pinia\n})\n```\n\n## Access to Platform-Specific APIs\n\nUniversal code cannot assume access to platform-specific APIs, so if your code directly uses browser-only globals like `window` or `document`, they will throw errors when executed in Node.js, and vice-versa.\n\nFor tasks shared between server and client but use different platform APIs, it's recommended to wrap the platform-specific implementations inside a universal API, or use libraries that do this for you. For example, Axios is an HTTP client that exposes the same API for both server and client.\n\nFor browser-only APIs, the common approach is to lazily access them inside client-only lifecycle hooks.\n\n## Boot Files\n\nNote that if a 3rd party library is not written with universal usage in mind, it could be tricky to integrate it into a server-rendered app. You _might_ be able to get it working by mocking some of the globals, but it would be hacky and may interfere with the environment detection code of other libraries.\n\nWhen you add a 3rd party library to your project (through a [Boot File](/quasar-cli-vite/boot-files)), take into consideration whether it can run on server and on client. If it needs to run only on server or only on client, then specify this in the `/quasar.config` file:\n\n```js /quasar.config file\nreturn {\n // ...\n boot: [\n 'some-boot-file', // runs on both server & client\n { path: 'some-other', server: false } // this boot file gets embedded only on client-side\n { path: 'third', client: false } // this boot file gets embedded only on server-side\n ]\n}\n```\n\n## Data Pre-Fetching and State\n\nDuring SSR, we are essentially rendering a \"snapshot\" of our app, so if the app relies on some asynchronous data, this data need to be pre-fetched and resolved before we start the rendering process.\n\nThe Quasar CLI [PreFetch Feature](/quasar-cli-vite/prefetch-feature) has been created to solve this problem. Take a few moments to read about it.\n\n\u003cq-separator class=\"q-mt-xl\" />\n\n> Parts of this page are taken from the official Vue.js SSR guide.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5483,"content_sha256":"cae434002bcfbcaaf40226bdbaf5fca591a17e46e1c21b6a7fa4b976097e666b"},{"filename":"references/docs/quasar-cli-vite/directory-structure.md","content":"---\ntitle: Directory Structure\ndese: (@quasar/app-vite) The structure of a Quasar app with explanations for each folder and file.\nscope:\n tree:\n l: '.'\n c:\n - l: public\n e: Pure static assets (directly copied)\n url: '/quasar-cli-vite/handling-assets#static-assets-public'\n - l: src\n c:\n - l: assets/\n e: Dynamic assets (processed by Vite)\n url: '/quasar-cli-vite/handling-assets#regular-assets-src-assets'\n - l: components/\n e: '.vue components used in pages & layouts'\n url: '/start/how-to-use-vue#vue-single-file-components-sfc-'\n - l: css\n e: CSS/Sass/... files for your app\n c:\n - l: app.sass\n - l: quasar.variables.sass\n e: Quasar Sass variables for you to tweak\n url: '/style/sass-scss-variables'\n - l: layouts/\n e: Layout .vue files\n url: '/layout/layout'\n - l: pages/\n e: Page .vue files\n - l: boot/\n e: Boot files (app initialization code)\n url: '/quasar-cli-vite/boot-files'\n - l: router\n e: Vue Router\n url: '/quasar-cli-vite/routing'\n c:\n - l: index.js\n e: (or .ts) Vue Router definition\n - l: routes.js\n e: (or .ts) App Routes definitions\n - l: stores\n e: Pinia Stores\n url: '/quasar-cli-vite/state-management-with-pinia'\n c:\n - l: index.js\n e: (or .ts) Pinia initialization\n - l: '\u003cstore>'\n e: Pinia stores...\n - l: '\u003cstore>...'\n - l: App.vue\n e: Root Vue component of your App\n - l: src-ssr/\n e: SSR specific code (like production Node.js webserver)\n url: '/quasar-cli-vite/developing-ssr/introduction'\n - l: src-pwa/\n e: PWA specific code (like Service Worker)\n url: '/quasar-cli-vite/developing-pwa/introduction'\n - l: src-capacitor/\n e: Capacitor generated folder used to create Mobile Apps\n url: '/quasar-cli-vite/developing-capacitor-apps/introduction'\n - l: src-cordova/\n e: Cordova generated folder used to create Mobile Apps\n url: '/quasar-cli-vite/developing-cordova-apps/introduction'\n - l: src-electron/\n e: Electron specific code (like \"main\" thread)\n url: '/quasar-cli-vite/developing-electron-apps/introduction'\n - l: src-bex/\n e: BEX (browser extension) specific code (like \"main\" thread)\n url: '/quasar-cli-vite/developing-browser-extensions/introduction'\n - l: dist\n e: Where production builds go\n c:\n - l: spa\n e: Example when building SPA\n - l: ssr\n e: Example when building SSR\n - l: electron\n e: Example when building Electron\n - l: '...'\n - l: quasar.config.js\n e: (or .ts) Quasar App Config file\n url: '/quasar-cli-vite/quasar-config-file'\n - l: index.html\n e: Template for index.html\n - l: '.gitignore'\n e: GIT ignore paths\n url: https://git-scm.com/docs/gitignore\n - l: '.editorconfig'\n e: EditorConfig file\n url: https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig\n - l: 'eslint.config.js'\n e: ESLint config\n url: https://eslint.org/docs/latest/user-guide/configuring/configuration-files#using-configuration-files\n - l: postcss.config.js\n e: PostCSS config\n url: https://github.com/postcss/postcss\n - l: jsconfig.json\n e: Editor config (if not using TypeScript)\n url: https://code.visualstudio.com/docs/languages/jsconfig\n - l: tsconfig.json\n e: TypeScript config\n url: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html\n - l: package.json\n e: npm scripts and dependencies\n url: https://docs.npmjs.com/cli/v9/configuring-npm/package-json\n - l: README.md\n e: Readme for your website/App\n url: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-readmes\n---\n\nThis is the structure of a project with all modes installed. There's no reason to be intimidated though!\n\n::: tip\nIf you are a beginner, all you'll need to care about is the `/quasar.config` file (Quasar App Config file), `/src/router`, `/src/layouts`, `/src/pages` and optionally `/src/assets`.\n:::\n\n\u003cDocTree :def=\"scope.tree\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4621,"content_sha256":"ba4bcadd1da1ecf8bd79742b12d2ce3f0298b7b5c0f2a50c280954268ee2ae89"},{"filename":"references/docs/quasar-cli-vite/handling-assets.md","content":"---\ntitle: App Handling Assets\ndesc: (@quasar/app-vite) How to use regular app assets and static assets in a Quasar app.\n---\n\nYou will notice in the project structure we have two directories for assets: `/public/` and `/src/assets/`. What is the difference between them? Some are static assets while the others are processed and embedded by the build system.\n\nSo let's try to answer the question above. We'll first talk about using regular assets then we'll see what the difference is for static assets.\n\n## Regular assets - /src/assets\n\nIn `*.vue` components, all your templates and CSS are parsed by Vite to look for asset URLs. For example, in `\u003cimg src=\"./logo.png\">` and `background: url(./logo.png)`, `\"./logo.png\"` is a relative asset path and will be resolved by Vite as a module dependency.\n\nSince these assets may be inlined/copied/renamed during build, they are essentially part of your source code. This is why it is recommended to place Vite-processed assets inside `/src/assets`, along side other source files. In fact, you don't even have to put them all in `/src/assets`: you can organize them based on the module/component using them. For example, you can put each component in its own directory, with its static assets right next to it.\n\n### Asset Resolving Rules\n\nRelative URLs, e.g. `./assets/logo.png` will be interpreted as a module dependency. They will be replaced with an auto-generated URL based on your Vite output configuration.\n\nURLs prefixed with `~` are treated as a module request, similar to `import 'some-module/image.png'`. You need to use this prefix if you want to leverage Vite's module resolving configurations. Quasar provides the `assets` alias out of the box, so it is recommended that you use it like this: `\u003cimg src=\"~assets/logo.png\">`. Notice `~` in front of 'assets'.\n\n## Static Assets - /public\n\nRoot-relative URLs (e.g. `/logo.png` -- where '/' is your publicPath) or `logo.png` are not processed at all. This should be placed in `public/`. These won't be processed at all. The content of the public folder is simply copied over to the distributable folder as-is.\n\n::: tip Assets vs Statics\nFiles in the \"assets\" folder are only included in your build if they have a literal reference in one of your Vue files.\nEvery file and folder from the \"public\" folder are copied into your production build as-is, no matter what.\n:::\n\n::: danger\nWhen not building a SPA/PWA/SSR, then `/public/icons/*` and `/public/favicon.ico` will NOT be embedded into your app because they would not serve any purpose. For example, Electron or Cordova apps do not require those files.\n:::\n\n## More info with Vite\n\nPlease read Vite's guide here.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2669,"content_sha256":"8ae3393a80cabcacf827807ad2bdb37c24acdc64f3e4ced127752dc088f2e2b6"},{"filename":"references/docs/quasar-cli-vite/handling-process-env.md","content":"---\ntitle: Handling process.env\ndesc: (@quasar/app-vite) How to differentiate the runtime procedure based on process.env in a Quasar app.\n---\n\nUsing `process.env` can help you in many ways:\n\n- differentiating runtime procedure depending on Quasar Mode (SPA/PWA/Cordova/Electron)\n- differentiating runtime procedure depending if running a dev or production build\n- adding flags to it based on terminal environment variables at build time\n\n## Values provided by Quasar CLI\n\n| `process∙env∙\u003cname>` | Type | Meaning |\n| -------------------- | ------- | -------------------------------------------------------------------------------------------- |\n| `DEV` | Boolean | Code runs in development mode |\n| `PROD` | Boolean | Code runs in production mode |\n| `DEBUGGING` | Boolean | Code runs in development mode or `--debug` flag was set for production mode |\n| `CLIENT` | Boolean | Code runs on client (not on server) |\n| `SERVER` | Boolean | Code runs on server (not on client) |\n| `MODE` | String | Quasar CLI mode (`spa`, `pwa`, ...) |\n| `NODE_ENV` | String | Has two possible values: `production` or `development` |\n| `TARGET` | String | Can be `ios` or `android` for Cordova/Capacitor modes and `chrome` or `firefox` for BEX mode |\n\n## Example\n\n```js\nif (process.env.DEV) {\n console.log(`I'm on a development build`)\n}\n\n// process∙env∙MODE is the \u003cmode> in\n// \"quasar dev/build -m \u003cmode>\"\n// (defaults to 'spa' if -m parameter is not specified)\n\nif (process.env.MODE === 'electron') {\n import('@electron/remote').then(({ BrowserWindow }) => {\n const win = BrowserWindow.getFocusedWindow()\n\n if (win.isMaximized()) {\n win.unmaximize()\n } else {\n win.maximize()\n }\n })\n}\n```\n\n## Stripping out code\n\nWhen compiling your website/app, `if ()` branches depending on process.env are evaluated, and if the expression is `false`, they get stripped out of the file. Example:\n\n```js\nif (process.env.DEV) {\n console.log('dev')\n} else {\n console.log('build')\n}\n\n// running with \"quasar dev\" will result in:\nconsole.log('dev')\n// while running with \"quasar build\" will result in:\nconsole.log('build')\n```\n\nNotice above that the `if`s are evaluated and also completely stripped out at compile-time, resulting in a smaller bundle.\n\n## Import based on process.env\n\nYou can combine what you learned in the section above with dynamic imports:\n\n```js\nif (process.env.MODE === 'electron') {\n import('my-fancy-npm-package').then(package => {\n // notice \"default\" below, which is the prop with which\n // you can access what your npm imported package exports\n package.default.doSomething()\n })\n}\n```\n\n## Adding to process.env\n\nYou can add your own definitions to `process.env` through the `/quasar.config` file.\n\nIt's important to understand the different types of environment variables.\n\n- The env variables from the terminal that are defined in the `/quasar.config` file\n- The environment variables that you pass to your UI code\n\n```js /quasar.config file\n// Accessing terminal variables\nconsole.log(process.env)\n\nexport default defineConfig(ctx => {\n return {\n // ...\n\n build: {\n // passing down to UI code from the quasar.config file\n env: {\n API: ctx.dev ? 'https://dev.api.com' : 'https://prod.api.com'\n }\n }\n }\n})\n```\n\nThen, in your website/app, you can access `process∙env∙API`, and it will point to one of those two links above, depending on dev or production build type.\n\nYou can even combine it with values from the `quasar dev/build` env variables:\n\n```bash\n# we set an env variable in terminal\n$ MY_API=api.com quasar build\n```\n\n```js /quasar.config file\n// then we pick it up in the /quasar.config file\nbuild: {\n env: {\n API: ctx.dev\n ? 'https://dev.' + process.env.MY_API\n : 'https://prod.' + process.env.MY_API\n }\n}\n```\n\n#### The env dotfiles support\n\nExpanding a bit on the env dotfiles support. These files will be detected and used (the order matters):\n\n```\n.env # loaded in all cases\n.env.local # loaded in all cases, ignored by git\n.env.[dev|prod] # loaded for dev or prod only\n.env.local.[dev|prod] # loaded for dev or prod only, ignored by git\n.env.[quasarMode] # loaded for specific Quasar CLI mode only\n.env.local.[quasarMode] # loaded for specific Quasar CLI mode only, ignored by git\n.env.[dev|prod].[quasarMode] # loaded for specific Quasar CLI mode and dev|prod only\n.env.local.[dev|prod].[quasarMode] # loaded for specific Quasar CLI mode and dev|prod only, ignored by git\n```\n\n...where \"ignored by git\" assumes a default project folder created after releasing this package, otherwise add `.env.local*` to your `/.gitignore` file.\n\nYou can also configure the files above to be picked up from a different folder or even add more files to the list:\n\n```js /quasar.config file\nbuild: {\n /**\n * Folder where Quasar CLI should look for .env* files.\n * Can be an absolute path or a relative path to project root directory.\n *\n * @default project root directory\n */\n envFolder?: string;\n\n /**\n * Additional .env* files to be loaded.\n * Each entry can be an absolute path or a relative path to quasar.config > build > envFolder.\n *\n * @example ['.env.somefile', '../.env.someotherfile']\n */\n envFiles?: string[];\n\n /**\n * Filter the env variables that are exposed to the client\n * through the env files. This does not account also for the definitions\n * assigned directly to quasar.config > build > env prop.\n *\n * Requires @quasar/app-vite v2.0.3+\n */\n envFilter?:\n (env: { [index: string]: string | boolean | undefined | null })\n => { [index: string]: string | boolean | undefined | null };\n}\n```\n\nRemember that you can filter out unwanted keys, or even change values for keys by using `build > envFilter`:\n\n```js /quasar.config file\nbuild: {\n // @quasar/app-vite v2.0.3+\n envFilter (originalEnv) {\n const newEnv = {}\n for (const key in originalEnv) {\n if (/* ...decide if it goes in or not... */) {\n newEnv[ key ] = originalEnv[ key ]\n }\n }\n\n // remember to return your processed env\n return newEnv\n }\n}\n```\n\n## Troubleshooting\n\nYou might be getting `process is not defined` errors in the browser console if you are accessing the variables wrong or if you have a misconfiguration.\n\n### Wrong usage\n\n```js /quasar.config file\nbuild: {\n env: {\n FOO: 'hello',\n }\n}\n```\n\n```js\nconst { FOO } = process.env // ❌ It doesn't allow destructuring or similar\nprocess.env.FOO // ✅ It can only replace direct usage like this\n\nfunction getEnv(name) {\n return process.env[name] // ❌ It can't analyze dynamic usage\n}\n\nconsole.log(process) // ❌\nconsole.log(process.env) // ❌\n// If you want to see a list of available env variables,\n// you can log the object you are passing to `build > env` inside the `quasar.config` file\n\nconsole.log(process.env.FOO) // ✅\nconsole.log(process.env.foo) // ❌ Case sensitive\nconsole.log(process.env.F0O) // ❌ Typo in the variable name (middle o is 0(zero))\n```\n\n### Misconfiguration\n\n#### Manual definition\n\n```js /quasar.config file\nbuild: {\n env: {\n FOO: 'hello',\n }\n}\n```\n\n```js\nconsole.log(process.env.FOO) // ✅\nconsole.log(process.env.BAR) // ❌ It's not defined in `build > env`\n```\n\n#### The env dotfiles\n\n```\n# order matters!\n.env # loaded in all cases\n.env.local # loaded in all cases, ignored by git\n.env.[dev|prod] # loaded for dev or prod only\n.env.local.[dev|prod] # loaded for dev or prod only, ignored by git\n.env.[quasarMode] # loaded for specific Quasar CLI mode only\n.env.local.[quasarMode] # loaded for specific Quasar CLI mode only, ignored by git\n.env.[dev|prod].[quasarMode] # loaded for specific Quasar CLI mode and dev|prod only\n.env.local.[dev|prod].[quasarMode] # loaded for specific Quasar CLI mode and dev|prod only, ignored by git\n```\n\nIf the `/.env` doesn't exist or there is a typo in the file name:\n\n```js\nconsole.log(process.env.FOO) // ❌ The .env file is not loaded, this will fail\n```\n\nIf the `/.env` file exists with the correct name, and has the following content:\n\n```bash /.env\nFOO=hello\n```\n\n```js\nconsole.log(process.env.FOO) // ✅ It's loaded correctly from the `.env` file\nconsole.log(process.env.BAR) // ❌ It's not defined in the `.env` file\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9016,"content_sha256":"3b81cbb51f08eace905ab670f0a900ec19e97bcc8b1f7e71a3fbb1bba112fe0e"},{"filename":"references/docs/quasar-cli-vite/handling-vite.md","content":"---\ntitle: Handling Vite\ndesc: (@quasar/app-vite) How to manage Vite in a Quasar app.\nrelated:\n - /quasar-cli-vite/quasar-config-file\n---\n\nThe build system uses Vite to create the UI of your website/app (`/src` folder). Don't worry if you aren't acquainted with Vite. Out of the box, you won't need to configure it because it already has everything set up.\n\n## Updating Vite config\n\nYou may have noticed that the `vite.config.js` / `vite.config.ts` file does not exist in your Quasar CLI with Vite project. This is because Quasar CLI generates the Vite configuration for you so that you don't have to worry about it.\n\nIn case you need to tweak it, you can do so through quasar.config file > build > extendViteConf like so:\n\n```js /quasar.config file\nbuild: {\n extendViteConf (viteConf, { isServer, isClient }) {\n // We return an Object which will get deeply merged into\n // the config, instead of directly tampering with viteConf\n return {\n build: {\n chunkSizeWarningLimit: 750\n }\n }\n // equivalent of following vite.config.js/vite.config.ts:\n // export default defineConfig({\n // build: {\n // chunkSizeWarningLimit: 750\n // }\n // })\n }\n}\n```\n\nNotice that you don't need to return anything. The parameter of extendViteConf(viteConf) is the Vite configuration Object generated by Quasar for you. You can add/remove/replace almost anything in it, assuming you really know what you are doing. Do not tamper with the input and output files though or any other option that is already configured by `quasar.config file > build`.\n\nIf you want to add some Vite plugins, see the [Adding Vite plugins](#adding-vite-plugins) section below.\n\n## Inspecting Vite Config\n\nQuasar CLI offers a useful command for this:\n\n```bash\n$ quasar inspect -h\n\n Description\n Inspect Quasar generated Vite config\n\n Usage\n $ quasar inspect\n $ quasar inspect -c build\n $ quasar inspect -m electron -p 'build.outDir'\n\n Options\n --cmd, -c Quasar command [dev|build] (default: dev)\n --mode, -m App mode [spa|ssr|pwa|bex|cordova|capacitor|electron] (default: spa)\n --depth, -d Number of levels deep (default: 2)\n --path, -p Path of config in dot notation\n Examples:\n -p module.rules\n -p plugins\n --thread, -t Display only one specific app mode config thread\n --help, -h Displays this message\n```\n\n## Adding Vite plugins\n\nMake sure to yarn/npm install the vite plugin package that you want to use, then edit the `/quasar.config` file:\n\n```js /quasar.config file\nbuild: {\n vitePlugins: [\n // both are perfectly equivalent:\n [\n '\u003cplugin-name>',\n {\n /* plugin options */\n }\n ],\n [\n '\u003cplugin-name>',\n {\n /* plugin options */\n },\n { server: true, client: true }\n ]\n ]\n}\n```\n\nYou can disable a plugin on the client-side or the server-side, which is especially useful when developing a SSR app:\n\n```js /quasar.config file\nbuild: {\n vitePlugins: [\n // disable on the server-side:\n [\n '\u003cplugin-name>',\n {\n /* plugin options */\n },\n { server: false }\n ],\n\n // disable on the client-side:\n [\n '\u003cplugin-name>',\n {\n /* plugin options */\n },\n { client: false }\n ]\n ]\n}\n```\n\nThere are multiple syntaxes supported:\n\n```js /quasar.config file\nvitePlugins: [\n [\n '\u003cplugin1-name>',\n {\n /* plugin1 options */\n },\n { server: true, client: true }\n ],\n [\n '\u003cplugin2-name>',\n {\n /* plugin2 options */\n },\n { server: true, client: true }\n ]\n // ...\n]\n\n// or:\nimport plugin1 from 'plugin1'\nimport plugin2 from 'plugin2'\n\nvitePlugins: [\n [\n plugin1,\n {\n /* plugin1 options */\n },\n { server: true, client: true }\n ],\n [\n plugin2,\n {\n /* plugin2 options */\n },\n { server: true, client: true }\n ]\n // ...\n]\n\n// finally, you can specify using the form below,\n// but this one has a drawback in that Quasar CLI cannot pick up\n// when you change the options param so you'll have to manually\n// restart the dev server\nimport plugin1 from 'plugin1'\nimport plugin2 from 'plugin2'\n\nvitePlugins: [\n plugin1({\n /* plugin1 options */\n }),\n plugin2({\n /* plugin2 options */\n })\n // ...\n]\n```\n\nAnd, should you want, you can also add Vite plugins through `extendViteConf()` in the `/quasar.config` file. This is especially useful for (but not limited to) SSR mode where you'd want a Vite plugin to be applied only on the server-side or the client-side:\n\n```js\nimport plugin1 from 'plugin1'\nimport plugin2 from 'plugin2'\n\nbuild: {\n extendViteConf (viteConf, { isClient, isServer }) {\n viteConf.plugins.push(\n plugin1({ /* plugin1 options */ }),\n plugin2({ /* plugin2 options */ })\n // ...\n )\n }\n}\n```\n\nMoreover, don't forget that your `/quasar.config` file exports a function that receives `ctx` as parameter. You can use it throughout the whole config file to apply settings only to certain Quasar modes or only to dev or prod:\n\n```js\nexport default defineConfig(ctx => {\n return {\n build: {\n extendViteConf(viteConf, { isClient, isServer }) {\n if (ctx.mode.pwa) {\n viteConf.plugins.push(/* ... */)\n }\n\n if (ctx.dev) {\n viteConf.plugins.push(/* ... */)\n }\n }\n }\n }\n})\n```\n\n### Example: rollup-plugin-copy\n\nIt is likely that you will need to copy static or external files to your Quasar project during the build to production process, rollup-plugin-copy allows you to copy files and folders when building your app.\n\n```js /quasar.config file\n// ...\nbuild: {\n // ...\n vitePlugins: [\n [\n 'rollup-plugin-copy',\n {\n targets: [\n {\n // Syntax code, check doc in https://www.npmjs.com/package/rollup-plugin-copy\n src: '[ORIGIN_PATH]',\n dest: '[DEST_PATH]'\n },\n {\n // Copying firebase-messaging-sw.js to SPA/PWA/SSR dest build folder\n src: 'config/firebase/firebase-messaging-sw.js',\n dest: 'dest/spa' // example when building SPA\n }\n ]\n }\n ]\n // other vite/rollup plugins\n ]\n}\n// ...\n```\n\n## Vite Vue Plugin options\n\nIf you need to tweak the Vite Vue Plugin(`@vitejs/plugin-vue`) options, you can do so through `quasar.config file > build > viteVuePluginOptions` like so:\n\n```js /quasar.config file\nbuild: {\n viteVuePluginOptions: {\n script: {\n // example: enable experimental props destructuring\n propsDestructure: true\n },\n\n template: {\n compilerOptions: {\n // example: enable custom/web element tag detection\n isCustomElement: (tag) => tag.startsWith('my-')\n }\n }\n }\n}\n```\n\n## Folder aliases\n\nQuasar comes with a bunch of useful folder aliases pre-configured. You can use them anywhere in your project and Vite will resolve the correct path.\n\n| Alias | Resolves to |\n| ------------ | -------------------------- |\n| `src` | /src |\n| `app` | / |\n| `components` | /src/components |\n| `layouts` | /src/layouts |\n| `pages` | /src/pages |\n| `assets` | /src/assets |\n| `boot` | /src/boot |\n| `stores` | /src/stores (Pinia stores) |\n\n#### Adding folder aliases\n\nWe will use `utils` as an example, which may be used as `import { formatTime } from 'utils/time.js'`. There are two ways to add a folder alias:\n\n1. Through `/quasar.config file > build > alias` property. This is the simplest way to add a folder alias. Use an absolute path to your alias. Example:\n\n```js /quasar.config file\nimport { fileURLToPath } from 'node:url'\n\nexport default ctx => {\n return {\n build: {\n alias: {\n utils: fileURLToPath(new URL('./src/utils', import.meta.url))\n }\n }\n }\n}\n```\n\n2. By extending the Vite config directly. Do not assign to `viteConf.resolve.alias` directly to preserve the built-in aliases, use `Object.assign` instead or return an Object with your extra aliases. Always use absolute paths.\n\n```js /quasar.config file\nimport { fileURLToPath } from 'node:url'\n\nexport default ctx => {\n return {\n build: {\n extendViteConf(viteConf, { isServer, isClient }) {\n Object.assign(viteConf.resolve.alias, {\n utils: fileURLToPath(new URL('./src/utils', import.meta.url))\n })\n }\n }\n }\n}\n```\n\n##### Using with TypeScript\n\nIf you are using TypeScript, you DON'T have to also add the aliases to your `tsconfig.json` file (nor use packages like vite-tsconfig-paths). These are taken care of by the Quasar CLI by default.\n\n## PostCSS\n\nStyles in `*.vue` files (and all other style files) are piped through PostCSS by default, so you don't need to use a specific loader for it.\n\nBy default, PostCSS is configured to use Autoprefixer. Take a look at `/postcss.config.js` where you can tweak it if you need to.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9042,"content_sha256":"9737d001b4d57e6fa590428110d41465b1f32dd17905db842e8f6cebba1f8864"},{"filename":"references/docs/quasar-cli-vite/lazy-loading.md","content":"---\ntitle: Lazy Loading / Code Splitting\ndesc: (@quasar/app-vite) How to create async chunks in a Quasar CLI with Vite app.\n---\n\nWhen your website/app is small, you can load all layouts/pages/components into the initial bundle and serve everything at startup. But when your code gets complex and has many layouts/pages/components, it won't be optimal to do this as it will massively impact loading time. Fortunately, there is a way to solve this.\n\nWe'll cover how you can lazy load / code split parts of your app so that they are automatically requested only on demand. This is done through dynamic imports. Let's start with an example and then convert it so that we use lazy loading -- we'll focus this example on loading a page, but the same principle can be applied to load anything (assets, JSONs, ...).\n\n## Lazy-load router pages\n\nIt's normal to use the Vue Router calling static components as below.\n\n::: warning\nQuasar documentation assumes you are already familiar with Vue Router. Below it's described only the basics of how to make use of it in a Quasar CLI project. For the full list of its features please visit the Vue Router documentation.\n:::\n\n```js\nimport SomePage from 'pages/SomePage.vue'\n\nconst routes = [\n {\n path: '/some-page',\n component: SomePage\n }\n]\n```\n\nNow let's change this and make the page be loaded on demand only, using dynamic imports:\n\n```js\nconst routes = [\n {\n path: '/some-page',\n component: () => import('pages/SomePage.vue')\n }\n]\n```\n\nEasy, right? What this does is that it creates a separate chunk for `/src/pages/SomePage.vue` which is then loaded only when it is needed. In this case, when a user visits the '/some-page' route.\n\n## Lazy-load components\n\nNormally you would import a component and then register it to the Page, Layout or Component.\n\n```html\n\u003cscript>\n import SomeComponent from 'components/SomeComponent.vue'\n\n export default {\n components: {\n SomeComponent\n }\n }\n\u003c/script>\n```\n\nNow let's change this and make the component be loaded on demand only, using dynamic imports:\n\n```html\n\u003cscript>\n import { defineAsyncComponent } from 'vue'\n export default {\n components: {\n SomeComponent: defineAsyncComponent(\n () => import('components/SomeComponent.vue')\n )\n }\n }\n\u003c/script>\n```\n\n## Lazy-load on the fly\n\nAs you noticed above, we're using dynamic imports (`import('..resource..')`) instead of regular imports (`import Resource from './path/to/resource'`). Dynamic imports are essentially returning a Promise that you can use:\n\n```js\nimport('./categories.json')\n .then(categories => {\n // hey, we have lazy loaded the file\n // and we have its content in \"categories\"\n })\n .catch(() => {\n // oops, something went wrong...\n // couldn't load the resource\n })\n```\n\nOne advantage of using dynamic imports as opposed to regular imports is that the import path can be determined at runtime:\n\n```js\nimport('pages/' + pageName + '/' + idWithExtension)\n```\n\n## Importing with Vite\n\n### Dynamic import statements\n\n```js\nconst importList = import.meta.glob('./pages/*.vue')\nconst startIndex = '/pages/'.length\n\nconst routes = Object.keys(importList).map(key => {\n return {\n path: key.substring(startIndex, key.length - 4),\n component: importList[key]\n }\n})\n```\n\n### Other import options\n\nMore info on importing assets with Vite here.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3353,"content_sha256":"b3cb2be6723cdaacb3e7502fecfdf79c2e26b2acd283bb21c185b349059ac88a"},{"filename":"references/docs/quasar-cli-vite/linter.md","content":"---\ntitle: Linter\ndesc: (@quasar/app-vite) How to configure a code linter in a Quasar app.\n---\n\nHaving a code linter (like ESLint v9+) in place is highly recommended and ensures your code looks legible. It also helps you capture some errors before even running the code.\n\nWhen you scaffold a Quasar project folder it will ask you if you want ESLint (also prettier as a code formatter).\n\n## Javascript projects\n\n### Needed dependencies\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add --dev @eslint/js eslint@9 eslint-plugin-vue vue-eslint-parser globals vite-plugin-checker\n\u003c\u003c| bash NPM |>>\n$ npm install --save-dev @eslint/js eslint@9 eslint-plugin-vue vue-eslint-parser globals vite-plugin-checker\n\u003c\u003c| bash PNPM |>>\n$ pnpm add -D @eslint/js eslint@9 eslint-plugin-vue vue-eslint-parser globals vite-plugin-checker\n\u003c\u003c| bash Bun |>>\n$ bun add --dev @eslint/js eslint@9 eslint-plugin-vue vue-eslint-parser globals vite-plugin-checker\n```\n\nIf you want `prettier` as a code formatter, then install these too:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add --dev prettier@3 @vue/eslint-config-prettier\n\u003c\u003c| bash NPM |>>\n$ npm install --save-dev prettier@3 @vue/eslint-config-prettier\n\u003c\u003c| bash PNPM |>>\n$ pnpm add -D prettier@3 @vue/eslint-config-prettier\n\u003c\u003c| bash Bun |>>\n$ bun add --dev prettier@3 @vue/eslint-config-prettier\n```\n\n### The quasar.config file settings\n\n```diff [highlight=3-8] /quasar.config file\nbuild: {\n vitePlugins: [\n ['vite-plugin-checker', {\n eslint: {\n lintCommand: 'eslint -c ./eslint.config.js \"./src*/**/*.{js,mjs,cjs,vue}\"',\n useFlatConfig: true\n }\n }, { server: false }]\n ]\n}\n```\n\n### The ESLint configuration\n\n```js /eslint.config.js\nimport js from '@eslint/js'\nimport globals from 'globals'\nimport pluginVue from 'eslint-plugin-vue'\nimport pluginQuasar from '@quasar/app-vite/eslint'\n\n// the following is optional, if you want prettier too:\nimport prettierSkipFormatting from '@vue/eslint-config-prettier/skip-formatting'\n\nexport default [\n {\n /**\n * Ignore the following files.\n * Please note that pluginQuasar.configs.recommended() already ignores\n * the \"node_modules\" folder for you (and all other Quasar project\n * relevant folders and files).\n *\n * ESLint requires \"ignores\" key to be the only one in this object\n */\n // ignores: []\n },\n\n ...pluginQuasar.configs.recommended(),\n js.configs.recommended,\n\n /**\n * https://eslint.vuejs.org\n *\n * pluginVue.configs.base\n * -> Settings and rules to enable correct ESLint parsing.\n * pluginVue.configs[ 'flat/essential']\n * -> base, plus rules to prevent errors or unintended behavior.\n * pluginVue.configs[\"flat/strongly-recommended\"]\n * -> Above, plus rules to considerably improve code readability and/or dev experience.\n * pluginVue.configs[\"flat/recommended\"]\n * -> Above, plus rules to enforce subjective community defaults to ensure consistency.\n */\n ...pluginVue.configs['flat/essential'],\n\n {\n languageOptions: {\n ecmaVersion: 'latest',\n sourceType: 'module',\n\n globals: {\n ...globals.browser,\n ...globals.node, // SSR, Electron, config files\n process: 'readonly', // process.env.*\n ga: 'readonly', // Google Analytics\n cordova: 'readonly',\n Capacitor: 'readonly',\n chrome: 'readonly', // BEX related\n browser: 'readonly' // BEX related\n }\n },\n\n // add your custom rules here\n rules: {\n 'prefer-promise-reject-errors': 'off',\n\n // allow debugger during development only\n 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'\n }\n },\n\n {\n files: ['src-pwa/custom-service-worker.js'],\n languageOptions: {\n globals: {\n ...globals.serviceworker\n }\n }\n },\n\n prettierSkipFormatting // optional, if you want prettier\n]\n```\n\n## TypeScript projects\n\n### Dependencies\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add --dev vue-tsc @vue/eslint-config-typescript @eslint/js eslint@9 eslint-plugin-vue globals vite-plugin-checker\n\u003c\u003c| bash NPM |>>\n$ npm install --save-dev vue-tsc @vue/eslint-config-typescript @eslint/js eslint@9 eslint-plugin-vue globals vite-plugin-checker\n\u003c\u003c| bash PNPM |>>\n$ pnpm add -D vue-tsc @vue/eslint-config-typescript @eslint/js eslint@9 eslint-plugin-vue globals vite-plugin-checker\n\u003c\u003c| bash Bun |>>\n$ bun add --dev vue-tsc @vue/eslint-config-typescript @eslint/js eslint@9 eslint-plugin-vue globals vite-plugin-checker\n```\n\nIf you want `prettier` as a code formatter, then install these too:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add --dev prettier@3 @vue/eslint-config-prettier\n\u003c\u003c| bash NPM |>>\n$ npm install --save-dev prettier@3 @vue/eslint-config-prettier\n\u003c\u003c| bash PNPM |>>\n$ pnpm add -D prettier@3 @vue/eslint-config-prettier\n\u003c\u003c| bash Bun |>>\n$ bun add --dev prettier@3 @vue/eslint-config-prettier\n```\n\n### The quasar.config settings\n\n```diff [highlight=3-9] /quasar.config file\nbuild: {\n vitePlugins: [\n ['vite-plugin-checker', {\n vueTsc: true,\n eslint: {\n lintCommand: 'eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,mjs,cjs,vue}\"',\n useFlatConfig: true\n }\n }, { server: false }]\n ]\n}\n```\n\n### ESLint configuration file\n\n```js /eslint.config.js\nimport js from '@eslint/js'\nimport globals from 'globals'\nimport pluginVue from 'eslint-plugin-vue'\nimport pluginQuasar from '@quasar/app-vite/eslint'\nimport {\n defineConfigWithVueTs,\n vueTsConfigs\n} from '@vue/eslint-config-typescript'\n\n// the following is optional, if you want prettier too:\nimport prettierSkipFormatting from '@vue/eslint-config-prettier/skip-formatting'\n\nexport default defineConfigWithVueTs(\n {\n /**\n * Ignore the following files.\n * Please note that pluginQuasar.configs.recommended() already ignores\n * the \"node_modules\" folder for you (and all other Quasar project\n * relevant folders and files).\n *\n * ESLint requires \"ignores\" key to be the only one in this object\n */\n // ignores: []\n },\n\n pluginQuasar.configs.recommended(),\n js.configs.recommended,\n\n /**\n * https://eslint.vuejs.org\n *\n * pluginVue.configs.base\n * -> Settings and rules to enable correct ESLint parsing.\n * pluginVue.configs[ 'flat/essential']\n * -> base, plus rules to prevent errors or unintended behavior.\n * pluginVue.configs[\"flat/strongly-recommended\"]\n * -> Above, plus rules to considerably improve code readability and/or dev experience.\n * pluginVue.configs[\"flat/recommended\"]\n * -> Above, plus rules to enforce subjective community defaults to ensure consistency.\n */\n pluginVue.configs['flat/essential'],\n\n {\n files: ['**/*.ts', '**/*.vue'],\n rules: {\n '@typescript-eslint/consistent-type-imports': [\n 'error',\n { prefer: 'type-imports' }\n ]\n }\n },\n vueTsConfigs.recommendedTypeChecked,\n\n {\n languageOptions: {\n ecmaVersion: 'latest',\n sourceType: 'module',\n\n globals: {\n ...globals.browser,\n ...globals.node, // SSR, Electron, config files\n process: 'readonly', // process.env.*\n ga: 'readonly', // Google Analytics\n cordova: 'readonly',\n Capacitor: 'readonly',\n chrome: 'readonly', // BEX related\n browser: 'readonly' // BEX related\n }\n },\n\n // add your custom rules here\n rules: {\n 'prefer-promise-reject-errors': 'off',\n\n // allow debugger during development only\n 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'\n }\n },\n\n {\n files: ['src-pwa/custom-service-worker.ts'],\n languageOptions: {\n globals: {\n ...globals.serviceworker\n }\n }\n },\n\n prettierSkipFormatting // optional, if you want prettier\n)\n```\n\n## Performance and ignoring files\n\n::: warning\nPlease be sure to ignore unused files to increase performance. If you lint unused files/folders the UX will degrade significantly.\n:::\n\nYou can ignore files by editing your `/eslint.config.js` file:\n\n```js /eslint.config.js\nexport default [\n {\n /**\n * Ignore the following files.\n * Please note that pluginQuasar.configs.recommended() already ignores\n * the \"node_modules\" folder for you (and all other Quasar project\n * relevant folders and files).\n *\n * ESLint requires \"ignores\" key to be the only one in this object\n */\n ignores: [] // \u003c\u003c\u003c---- here!\n },\n```\n\nNotice that `pluginQuasar.configs.recommended()` from a few sections above will add the following to your ESLint `ignores` setting (no need to add them yourself too!):\n\n```js\n// not an exhaustive list auto-added to \"ignores\"\n;[\n 'dist/*',\n 'src-capacitor/*',\n 'src-cordova/*',\n '.quasar/*',\n 'quasar.config.*.temporary.compiled*'\n]\n```\n\n## Lint Rules\n\nThe linting rules can be removed, changed, or added. Notice some things:\n\n- Some rules are standard ESLint ones. Example: 'brace-style'.\n- Some rules are for eslint-plugin-vue. Example: 'vue/max-attributes-per-line'.\n\nYou can add/remove/change rules by first visiting https://eslint.org/docs/rules/ or https://eslint.vuejs.org/rules.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9037,"content_sha256":"61a23a0622b5fac36923dcf9b08a7d5ba59baac2f8b0507bda8caaa22a936c0e"},{"filename":"references/docs/quasar-cli-vite/opening-dev-server-to-public.md","content":"---\ntitle: Opening Your Dev Server to the Public\ndesc: (@quasar/app-vite) How to offer temporary access to your development server to anyone on the Internet.\n---\n\nAt some point you may want to show someone else the project you've been working on. Fortunately, there are a couple of good tools to accomplish this, localhost.run and Ngrok. Both create a tunnel to your dev server and (by default) auto-generate an internet address on their respective servers to offer to your clients or anyone special you'd like to show your work to.\n\n::: warning\nOpening your dev server to the public poses security risks. Be absolutely cautious when using tools like this.\n\nWhen you've finished with your demonstration or testing, make sure to stop localhost.run or ngrok. This will prevent any unwanted access of your computer through them.\n:::\n\n## Using Tunnelmole\n\nTunnelmole will work on any machine with NodeJS 16+ installed and has no non-JavaScript dependencies.\n\nFirst, install `tunnelmole` package globally:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn global add tunnelmole\n\u003c\u003c| bash NPM |>>\n$ npm install -g tunnelmole\n\u003c\u003c| bash PNPM |>>\n$ pnpm add -g tunnelmole\n\u003c\u003c| bash Bun |>>\n$ bun add -g tunnelmole\n```\n\nThen, assuming you are running quasar on port `80`, run the following:\n\n```bash\n$ tmole 80\n```\n\nIf your port is different to `80`, change `80` to your port.\n\nHere's the full command with output:\n\n```bash\n$ tmole 80\nhttp://b8ootd-ip-157-211-195-182.tunnelmole.com is forwarding to localhost:80\nhttps://b8ootd-ip-157-211-195-182.tunnelmole.com is forwarding to localhost:80\n```\n\nIf you are self hosting your own Tunnelmole service or you have a set an API key for the official service, you can run the following to use a custom subdomain (again, replace `80` with your port if it is different).\n\n```bash\n$ tmole 80 as mysubdomain.tunnelmole.com\n```\n\nIts also possible to launch tunnelmole from code if you add it as a dependency to your project (`yarn add --dev tunnelmole` or `npm i --save-dev tunnelmole` or pnpm/bun equivalents)\n\nFirst import tunnelmole. Both ES and CommonJS modules are supported.\n\nImporting tunnelmole as an ES module\n\n```js\n// import as ESM:\nimport { tunnelmole } from 'tunnelmole'\n\n// or import as CommonJS module:\nconst tunnelmole = require('tunnelmole/cjs')\n```\n\nOnce the module is imported you can start tunnelmole with the code below, changing port `80` to the port your application listens on if it is different.\n\n```js\nconst url = await tunnelmole({\n port: 80\n // Optionally, add \"domain: 'mysubdomain.tunnelmole.com'\" if using a custom subdomain\n})\n// url = https://idsq6j-ip-157-211-195-169.tunnelmole.com\n```\n\n## Using localhost.run\n\n1. Assuming you have an SSH shell, you only need issue the following command (substituting your details)\n\n```bash\n$ ssh -R 80:localhost:8080 ssh.localhost.run\n# In case your development server doesn't run on port 8080 you need to change the number to the correct port\n```\n\n2. That's it, and you will now have a random subdomain based on your current system username assigned to you like so:\n\n```bash\n$ ssh -R 80:localhost:8080 ssh.localhost.run\n# Connect to http://fakeusername-random4chars.localhost.run or https://fakeusername-random4chars.localhost.run\n# Press ctrl-c to quit.\n```\n\nIt's not currently possible to request your own subdomain.\n\n## Using Ngrok\n\n1. Download and install ngrok here.\n (Please note that the ngrok executable file does not need to be placed in or run from inside your cordova folder. When on a mac it's best to place the ngrok executable file inside `/usr/local/bin` to be able to run it globally.)\n\n2. Start your Dev server\n\n```bash\n$ quasar dev\n```\n\n3. Create your ngrok connection\n\n```bash\n$ ngrok http 8080\n# In case your development server doesn't run on port 8080 you need to change the number to the correct port\n```\n\n4. ngrok shows the url in the command line when it started.\n\n```bash\nTunnel Status online\nVersion 2.0/2.0\nWeb Interface http://127.0.0.1:4040\nForwarding http://92832de0.ngrok.io -> localhost:8080\nForwarding https://92832de0.ngrok.io -> localhost:8080\n\nConnections ttl opn rt1 rt5 p50 p90\n 0 0 0.00 0.00 0.00 0.00\n```\n\nPlease be careful as the 'Forwarding' URL will be accessible to anyone until this connection is closed again.\n\n### Inspecting traffic\n\nWhen running ngrok, visit `http://localhost:4040` to inspect the traffic.\n\nThis tool allows for custom domains, password protection and a lot more. If you require further assistance, please refer to the ngrok docs for more information.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4681,"content_sha256":"b2307f5b8d61f70c687c5388d128aab5edc74bcd8c51f20614559726b9ede72e"},{"filename":"references/docs/quasar-cli-vite/prefetch-feature.md","content":"---\ntitle: PreFetch Feature\ndesc: (@quasar/app-vite) How to prefetch data and initialize Pinia, validate the route and redirect to another page in a Quasar app.\nrelated:\n - /quasar-cli-vite/quasar-config-file\n---\n\nThe PreFetch is a feature (**only available when using Quasar CLI**) which allows the components picked up by Vue Router (defined in `/src/router/routes.js`) to:\n\n- pre-fetch data\n- validate the route\n- redirect to another route, when some conditions aren't met (like user isn't logged in)\n- can help in initializing the Store state\n\nAll the above will run before the actual route component is rendered.\n\n**It is designed to work with all Quasar modes** (SPA, PWA, SSR, Cordova, Electron), but it is especially useful for SSR builds.\n\n## Installation\n\n```js /quasar.config file\nreturn {\n preFetch: true\n}\n```\n\n::: warning\nWhen you use it to pre-fetch data, you may want to use Pinia, so make sure that your project folder has the `/src/stores` (for Pinia) folders when you create your project, otherwise generate a new project and copy the store folder contents to your current project (or use `quasar new store` command).\n:::\n\n## How PreFetch Helps SSR Mode\n\nThis feature is especially useful for the SSR mode (but not limited to it only). During SSR, we are essentially rendering a \"snapshot\" of our app, so if the app relies on some asynchronous data, **then this data needs to be pre-fetched and resolved before we start the rendering process**.\n\nAnother concern is that on the client, the same data needs to be available before we mount the client side app - otherwise the client app would render using a different state and the hydration would fail.\n\nTo address this, the fetched data needs to live outside the view components, in a dedicated data store, or a \"state container\". On the server, we can pre-fetch and fill data into the store before rendering. The client-side store will directly pick up the server state before we mount the app.\n\n## When PreFetch Gets Activated\n\nThe `preFetch` hook (described in next sections) is determined by the route visited - which also determines what components are rendered. In fact, the data needed for a given route is also the data needed by the components rendered at that route. **So it is natural (and also required) to place the hook logic ONLY inside route components.** This includes `/src/App.vue`, which in this case will run only once at the app bootup.\n\nLet's take an example in order to understand when the hook is being called. Let's say we have these routes and we've written `preFetch` hooks for all these components:\n\n```js Routes\n;[\n {\n path: '/',\n component: LandingPage\n },\n {\n path: '/shop',\n component: ShopLayout,\n children: [\n {\n path: 'all',\n component: ShopAll\n },\n {\n path: 'new',\n component: ShopNew\n },\n {\n path: 'product/:name',\n component: ShopProduct,\n children: [\n {\n path: 'overview',\n component: ShopProductOverview\n }\n ]\n }\n ]\n }\n]\n```\n\nNow, let's see how the hooks are called when the user visits these routes in the order specified below, one after another.\n\n| Route being visited | Hooks called from | Observations |\n| ------------------------------ | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |\n| `/` | App.vue then LandingPage | App.vue hook is called since our app boots up. |\n| `/shop/all` | ShopLayout then ShopAll | - |\n| `/shop/new` | ShopNew | ShopNew is a child of ShopLayout, and ShopLayout is already rendered, so ShopLayout isn't called again. |\n| `/shop/product/pyjamas` | ShopProduct | - |\n| `/shop/product/shoes` | ShopProduct | Quasar notices the same component is already rendered, but the route has been updated and it has route params, so it calls the hook again. |\n| `/shop/product/shoes/overview` | ShopProduct then ShopProductOverview | ShopProduct has route params so it is called even though it's already rendered. |\n| `/` | LandingPage | - |\n\n## Usage\n\nThe hook is defined as a custom static function called `preFetch` on our route components. Note that because this function will be called before the components are instantiated, it doesn't have access to `this`.\n\nExample below is when using Pinia:\n\n```html Some .vue component used as route\n\u003ctemplate>\n \u003cdiv>{{ item.title }}\u003c/div>\n\u003c/template>\n\n\u003cscript>\n import { useRoute } from 'vue-router'\n import { useMyStore } from 'stores/myStore.js'\n\n export default {\n // our hook here\n preFetch({\n store,\n currentRoute,\n previousRoute,\n redirect,\n ssrContext,\n urlPath,\n publicPath\n }) {\n // fetch data, validate route and optionally redirect to some other route...\n\n // ssrContext is available only server-side in SSR mode\n\n // No access to \"this\" here\n\n // Return a Promise if you are running an async job\n // Example:\n const myStore = useMyStore() // useMyStore(store) for SSR\n return myStore.fetchItem(currentRoute.params.id) // assumes it is async\n },\n\n setup() {\n const myStore = useMyStore()\n const $route = useRoute()\n\n // display the item from store state.\n const item = computed(() => myStore.items[$route.params.id])\n\n return { item }\n }\n }\n\u003c/script>\n```\n\nIf you are using `\u003cscript setup>` (and Vue 3.3+):\n\n```html\n\u003cscript setup>\n /**\n * The defineOptions is a macro.\n * The options will be hoisted to module scope and cannot access local\n * variables in \u003cscript setup> that are not literal constants.\n */\n defineOptions({\n preFetch() {\n console.log('running preFetch')\n }\n })\n\u003c/script>\n```\n\n::: tip\nIf you are developing a SSR app, then you can check out the [ssrContext](/quasar-cli-vite/developing-ssr/ssr-context) Object that gets supplied server-side.\n:::\n\n```js\n// related action for Promise example\n// ...\n\nactions: {\n fetchItem ({ commit }, id) {\n return axiosInstance.get(url, id).then(({ data }) => {\n this.items = data\n })\n }\n}\n\n// ...\n```\n\n### Redirecting Example\n\nBelow is an example of redirecting the user under some circumstances, like when they try to access a page that only an authenticated user should see.\n\n```js\n// We assume here we already wrote the authentication logic\n// in one Pinia Store, so take as a high-level example only.\nimport { useMyStore } from 'stores/myStore'\n\npreFetch ({ store, redirect }) {\n const myStore = useMyStore() // useMyStore(store) for SSR\n if (!myStore.isAuthenticated) {\n redirect({ path: '/login' })\n }\n}\n```\n\nBy default, redirect occurs with a status response code of 302, but we can pass this status code as the second optional parameter when calling the function, like this:\n\n```js\nredirect({ path: '/moved-permanently' }, 301)\n```\n\nIf `redirect(false)` is called (supported only on client-side!), it aborts the current route navigation. Note that if you use it like this in `src/App.vue` it will halt the app bootup, which is undesirable.\n\nThe `redirect()` method requires a Vue Router location Object.\n\n### Using preFetch to Initialize Pinia\n\nThe `preFetch` hook runs only once, when the app boots up, so you can use this opportunity to initialize the Pinia store(s) here.\n\n```tabs\n\u003c\u003c| js Pinia on Non SSR |>>\n// App.vue - handling Pinia stores\n// example with a store named \"myStore\"\n// placed in /src/stores/myStore.js|ts\n\nimport { useMyStore } from 'stores/myStore.js'\n\nexport default {\n // ...\n preFetch () {\n const myStore = useMyStore()\n // do something with myStore\n }\n}\n\u003c\u003c| js Pinia on SSR |>>\n// App.vue - handling Pinia stores\n// example with a store named \"myStore\"\n// placed in /src/stores/myStore.js|ts\n\nimport { useMyStore } from 'stores/myStore.js'\n\nexport default {\n // ...\n preFetch ({ store }) {\n const myStore = useMyStore(store)\n // do something with myStore\n }\n}\n```\n\n## Loading State\n\nA good UX includes notifying the user that something is being worked on in the background while he/she waits for the page to be ready. Quasar CLI offers two options for this out of the box.\n\n### LoadingBar\n\nWhen you add Quasar [LoadingBar](/quasar-plugins/loading-bar) plugin to your app, Quasar CLI will use it while it runs the preFetch hooks by default.\n\n### Loading\n\nThere's also the possibility to use Quasar [Loading](/quasar-plugins/loading) plugin. Here's an example:\n\n```js A route .vue component\nimport { Loading } from 'quasar'\n\nexport default {\n // ...\n preFetch(\n {\n /* ... */\n }\n ) {\n Loading.show()\n\n return new Promise(resolve => {\n // do something async here\n // then call \"resolve()\"\n }).then(() => {\n Loading.hide()\n })\n }\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9792,"content_sha256":"f3c3554df73948d9816db8632027c4d1cda9aba50b14b7a2e808fb055604d50d"},{"filename":"references/docs/quasar-cli-vite/quasar-config-file.md","content":"---\ntitle: Configuring quasar.config file\ndesc: (@quasar/app-vite) Where, how and what you can configure in a Quasar CLI with Vite app.\n---\n\nNotice that your scaffolded project folder contains a `/quasar.config` file. So what can you configure through it? Basically anything that Quasar CLI does for you.\n\n- Quasar components, directives and plugins that you'll be using in your website/app\n- Default [Quasar Language Pack](/options/quasar-language-packs)\n- [Icon libraries](/options/installing-icon-libraries) that you wish to use\n- Default [Quasar Icon Set](/options/quasar-icon-sets) for Quasar components\n- Development server port, HTTPS mode, hostname and so on\n- [CSS animations](/options/animations) that you wish to use\n- [Boot Files](/quasar-cli-vite/boot-files) list (that determines order of execution too) -- which are files in `/src/boot` that tell how your app is initialized before mounting the root Vue component\n- Global CSS/Sass/... files to be included in the bundle\n- SPA, PWA, Electron, Capacitor, Cordova, SSR, BEX (browser extensions) configuration\n- Extend the under the hood tools, like the generated Vite config\n- ...and many many more that you'll discover along the way\n\n::: tip\nYou'll notice that changing any of these settings does not require you to manually reload the dev server. Quasar detects and reloads the necessary processes. You won't lose your development flow, because you can just sit back while Quasar CLI quickly reloads the changed code, even keeping the current state. This saves tons of your time!\n:::\n\n::: warning\nThe `/quasar.config` file is run by the Quasar CLI build system, so this code runs under Node.js directly, not in the context of your app. This means you can require modules like `node:fs`, `node:path`, Vite plugins, and so on.\n:::\n\n## Structure\n\n### The basics\n\nYou'll notice that the `/quasar.config` file exports a function that takes a `ctx` (context) parameter and returns an Object. This allows you to dynamically change your website/app config based on this context:\n\n```js /quasar.config file\nimport { defineConfig } from '#q-app/wrappers'\n\nexport default defineConfig(ctx => {\n // can be async too\n console.log(ctx)\n\n // Example output on console:\n /*\n {\n dev: true,\n prod: false,\n mode: { spa: true },\n modeName: 'spa',\n target: {},\n targetName: undefined,\n arch: {},\n archName: undefined,\n debug: undefined\n }\n */\n\n // context gets generated based on the parameters\n // with which you run \"quasar dev\" or \"quasar build\"\n\n return {\n // ... your config\n }\n})\n```\n\nWhat this means is that, as an example, you can load a font when building for a certain mode (like PWA), and pick another one for the others:\n\n```js /quasar.config file\n{\n extras: [\n ctx.mode.pwa // we're adding only if working on a PWA\n ? 'roboto-font'\n : null\n ]\n}\n```\n\nOr you can use a global CSS file for SPA mode and another one for Cordova mode while avoiding loading any such file for the other modes.\n\n```js /quasar.config file\n{\n css: [\n ctx.mode.spa ? 'app-spa.sass' : null, // looks for /src/css/app-spa.sass\n ctx.mode.cordova ? 'app-cordova.sass' : null // looks for /src/css/app-cordova.sass\n ]\n}\n```\n\nOr you can configure the dev server to run on port 8000 for SPA mode, on port 9000 for PWA mode or on port 9090 for the other modes:\n\n```js /quasar.config file\n{\n devServer: {\n port: ctx.mode.spa ? 8000 : ctx.mode.pwa ? 9000 : 9090\n }\n}\n```\n\nYou can also do async work before returning the quasar configuration:\n\n```js /quasar.config file\nimport { defineConfig } from '#q-app/wrappers'\n\nexport default async defineConfig((ctx) => {\n const data = await someAsyncFunction()\n return {\n // ... use \"data\"\n }\n})\n\n// or:\nexport default defineConfig((ctx) => {\n return new Promise(resolve => {\n // some async work then:\n // resolve() with the quasar config\n resolve({\n //\n })\n })\n})\n```\n\nThe possibilities are endless.\n\n### IDE autocompletion\n\nNotice the `defineConfig` import from `#q-app/wrappers`. This is essentially a no-op function but what it does is it helps with the IDE autocomplete experience.\n\n```js /quasar.config file\nimport { defineConfig } from '#q-app/wrappers'\n\nexport default defineConfig(ctx => {\n /* configuration options */\n})\n```\n\n## Options to Configure\n\n### css\n\n```js\n/**\n * Global CSS/Stylus/SCSS/SASS/... files from `/src/css/`,\n * except for theme files, which are included by default.\n */\ncss?: string[];\n```\n\nExample:\n\n```js /quasar.config file\n{\n css: [\n 'app.sass', // referring to /src/css/app.sass\n '~some-library/style.css' // referring to node_modules/some-library/style.css\n ]\n}\n```\n\n### boot\n\nMore on [Boot Files](/quasar-cli-vite/boot-files).\n\n```js\n/** Boot files to load. Order is important. */\nboot?: QuasarBootConfiguration;\n\ninterface BootConfigurationItem {\n path: string;\n server?: false;\n client?: false;\n}\n\ntype QuasarBootConfiguration = (string | BootConfigurationItem)[];\n```\n\n### preFetch\n\nMore on the [PreFetch Feature](/quasar-cli-vite/prefetch-feature) page.\n\n```js\n/** Enable the preFetch feature. */\npreFetch?: boolean;\n```\n\n### extras\n\n```js\n/**\n * What to import from [@quasar/extras](https://github.com/quasarframework/quasar/tree/dev/extras) package.\n * @example ['material-icons', 'roboto-font', 'ionicons-v4']\n */\nextras?: (QuasarIconSets | QuasarFonts)[];\n```\n\n### framework\n\n```js\n/**\n * What Quasar language pack to use, what Quasar icon\n * set to use for Quasar components, etc.\n */\nframework?: {\n /**\n * @see - QuasarConfOptions tab in API cards throughout the docs\n */\n config?: SerializableConfiguration\u003cQuasarUIConfiguration>;\n /**\n * One of the Quasar IconSets\n *\n * @see https://v2.quasar.dev/options/quasar-icon-sets\n *\n * @example 'material-icons'\n */\n iconSet?: QuasarIconSets;\n /**\n * One of the Quasar language packs\n *\n * @see https://v2.quasar.dev/options/quasar-language-packs\n *\n * @example 'en-US'\n * @example 'es'\n */\n lang?: QuasarLanguageCodes;\n /**\n * Quasar CSS addons have breakpoint aware versions of flex and spacing classes\n *\n * @see https://v2.quasar.dev/layout/grid/introduction-to-flexbox#flex-addons\n * @see https://v2.quasar.dev/style/spacing#flex-addons\n */\n cssAddon?: boolean;\n\n /**\n * Auto import - how to detect components in your vue files\n * \"kebab\": q-carousel q-page\n * \"pascal\": QCarousel QPage\n * \"combined\": q-carousel QPage\n *\n * @default 'kebab'\n */\n autoImportComponentCase?: \"kebab\" | \"pascal\" | \"combined\";\n /**\n * Auto import - which file extensions should be interpreted as referring to Vue SFC?\n *\n * @default ['vue']\n */\n autoImportVueExtensions?: string[];\n /**\n * Auto import - which file extensions should be interpreted as referring to script files?\n *\n * @default ['js', 'jsx', 'ts', 'tsx']\n */\n autoImportScriptExtensions?: string[];\n /**\n * Treeshake Quasar's UI on dev too?\n * Recommended to leave this as false for performance reasons.\n *\n * @default false\n */\n devTreeshaking?: boolean;\n\n /**\n * Quasar will auto import components based on your usage.\n * But, in case you have a special case, you can manually specify Quasar components to be available everywhere.\n *\n * An example case would be having custom component definitions with plain string templates, inside .js or .ts files,\n * in which you are using Quasar components (e.g. q-avatar).\n *\n * Another example would be that dynamically rendering components depending on an API response or similar (e.g. in a CMS),\n * something like `\u003ccomponent :is=\"dynamicName\">` where `dynamicName` is a string that matches a Quasar component name.\n *\n * @example ['QAvatar', 'QChip']\n */\n components?: (keyof QuasarComponents)[];\n /**\n * Quasar will auto import directives based on your usage.\n * But, in case you have a special case, you can manually specify Quasar directives to be available everywhere.\n *\n * An example case would be having custom component definitions with plain string templates, inside .js or .ts files,\n * in which you are using Quasar directives (e.g. v-intersection).\n *\n * @example ['Intersection', 'Mutation']\n */\n directives?: (keyof QuasarDirectives)[];\n /**\n * Quasar plugins to be installed. Specify the ones you are using in your app.\n *\n * @example ['Notify', 'Loading', 'Meta', 'AppFullscreen']\n */\n plugins?: (keyof QuasarPlugins)[];\n}\n```\n\nSee these references for more info:\n\n- [Quasar Language Packs](/options/quasar-language-packs)\n- [Quasar Icon Sets](/options/quasar-icon-sets)\n- [Quasar CSS Addons - Flex](/layout/grid/introduction-to-flexbox#flex-addons)\n- [Quasar CSS Addons - Spacing](/style/spacing#flex-addons)\n\n### animations\n\nMore on [CSS animations](/options/animations).\n\n```js\n/**\n * What Quasar CSS animations to import.\n * @example [ 'bounceInLeft', 'bounceOutRight' ]\n * */\nanimations?: QuasarAnimationsConfiguration | 'all';\n```\n\n### devServer\n\nMore info: Vite server options\n\n```js\nimport { ServerOptions as ViteServerOptions } from \"vite\";\nimport { Options as OpenOptions } from \"open\";\ntype DevServerOptions = Omit\u003cViteServerOptions, \"open\" | \"https\"> & {\n open?: Omit\u003cOpenOptions, \"wait\"> | boolean;\n https?: ViteServerOptions[\"https\"] | boolean;\n};\n\n/**\n * Vite \"server\" options.\n * Some properties are overwritten based on the Quasar mode you're using in order\n * to ensure a correct config.\n * Note: if you're proxying the development server (i.e. using a cloud IDE),\n * set the `public` setting to your public application URL.\n */\ndevServer?: DevServerOptions;\n```\n\nApart from these options, Quasar CLI tampers with some and you will experience them differently than on a Vite app:\n\nUsing `open` prop to open with a specific browser and not with the default browser of your OS (check supported values). The `options` param described in previous link is what you should configure quasar.config file > devSever > open with. Some examples:\n\n```js /quasar.config file\n// opens Google Chrome\ndevServer: {\n open: {\n app: {\n name: 'google chrome'\n }\n }\n}\n\n// opens Firefox\ndevServer: {\n open: {\n app: {\n name: 'firefox'\n }\n }\n}\n\n// opens Google Chrome and automatically deals with cross-platform issues:\nimport open from 'open'\n\ndevServer: {\n open: {\n app: {\n name: open.apps.chrome\n }\n }\n}\n```\n\nYou can also configure automatically opening remote Vue Devtools:\n\n```js /quasar.config file\ndevServer: {\n vueDevtools: true\n}\n```\n\n### build\n\n````js\n/** Build configuration options. */\nbuild?: QuasarBuildConfiguration;\n\nimport { Plugin, UserConfig as ViteUserConfig } from \"vite\";\nimport { Options as VuePluginOptions } from \"@vitejs/plugin-vue\"\n\ninterface InvokeParams {\n isClient: boolean;\n isServer: boolean;\n}\n\ninterface BuildTargetOptions {\n /**\n * @default ['es2022', 'firefox115', 'chrome115', 'safari14']\n */\n browser?: string | string[];\n /**\n * @example 'node20'\n */\n node?: string;\n}\n\ninterface PluginEntryRunOptions {\n server?: boolean;\n client?: boolean;\n}\n\ntype PluginEntry =\n | [pluginName: string, options?: any, runOptions?: PluginEntryRunOptions]\n | [pluginFactory: (options?: any) => Plugin, options?: any, runOptions?: PluginEntryRunOptions]\n | Plugin\n | null\n | undefined\n | false;\n\ninterface QuasarBuildConfiguration {\n /**\n * @example\n * {\n * browser: ['es2022', 'firefox115', 'chrome115', 'safari14'],\n * node: 'node20'\n * }\n */\n target?: BuildTargetOptions;\n /**\n * Extend Vite config generated by Quasar CLI.\n *\n * You can either return overrides or directly modify the config object.\n *\n * @example\n * ```js\n * // return overrides\n * extendViteConf: (config) => ({\n * optimizeDeps: {\n * include: ['some-package']\n * }\n * })\n * ```\n *\n * @example\n * ```js\n * // directly modify the config object\n * import { mergeConfig } from 'vite'\n * // ...\n * extendViteConf(config) {\n * config.optimizeDeps = mergeConfig(config.optimizeDeps, {\n * include: ['some-package']\n * }, false)\n * }\n * ```\n */\n extendViteConf?: (\n config: ViteUserConfig,\n invokeParams: InvokeParams\n ) => ViteUserConfig | void;\n /**\n * Options to supply to @vitejs/plugin-vue\n *\n * @see https://v2.quasar.dev/quasar-cli-vite/handling-vite#vite-vue-plugin-options\n */\n viteVuePluginOptions?: VuePluginOptions;\n /**\n * Vite plugins\n *\n * @see https://v2.quasar.dev/quasar-cli-vite/handling-vite#adding-vite-plugins\n *\n * @example\n * // ESM\n * import { somePlugin } from 'some-plugin'\n * // ...\n * [\n * [ 'some-plugin', { ...pluginOptions... } ],\n *\n * // disable running on client or server threads (set server/client to false):\n * [ 'some-plugin', { ...pluginOptions... }, { server: true, client: true } ],\n *\n * [ somePlugin, { ...pluginOptions... } ],\n *\n * // disable running on client or server threads (set server/client to false):\n * [ somePlugin, { ...pluginOptions... }, { server: true, client: true } ],\n *\n * somePlugin({ ...pluginOptions... })\n * ]\n *\n * @example\n * // CJS\n * [\n * [ 'some-plugin', { ...pluginOptions... } ],\n *\n * // disable running on client or server threads (set server/client to false):\n * [ 'some-plugin', { ...pluginOptions... }, { server: true, client: true } ],\n *\n * [ require('some-plugin'), { ...pluginOptions... } ],\n *\n * // disable running on client or server threads (set server/client to false):\n * [ require('some-plugin'), { ...pluginOptions... }, { server: true, client: true } ],\n *\n * require('some-plugin')({ ...pluginOptions... })\n * ]\n */\n vitePlugins?: PluginEntry[];\n /**\n * @see https://v2.quasar.dev/quasar-cli-vite/handling-vite#folder-aliases\n *\n * @example\n * {\n * // import { ... } from 'locales/...'\n * locales: path.join(__dirname, 'src/locales')\n * }\n */\n alias?: { [key: string]: string };\n /**\n * Configuration for TypeScript integration.\n */\n typescript?: {\n /**\n * Once your codebase is fully using TypeScript and all team members are comfortable with it,\n * you can set this to `true` to enforce stricter type checking.\n * It is recommended to set this to `true` and use stricter typescript-eslint rules.\n *\n * It will set the following TypeScript options:\n * - \"strict\": true\n * - \"allowUnreachableCode\": false\n * - \"allowUnusedLabels\": false\n * - \"noImplicitOverride\": true\n * - \"exactOptionalPropertyTypes\": true\n * - \"noUncheckedIndexedAccess\": true\n *\n * @see https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html#getting-stricter-checks\n */\n strict?: boolean;\n\n /**\n * Extend the generated `.quasar/tsconfig.json` file.\n *\n * If you don't have dynamic logic, you can directly modify your `tsconfig.json` file instead.\n */\n extendTsConfig?: (tsConfig: TSConfig) => void;\n\n /**\n * Generate a shim file for `*.vue` files to process them as plain Vue component instances.\n *\n * Vue Language Tools VS Code extension can analyze `*.vue` files in a better way, without the shim file.\n * So, you can disable the shim file generation and let the extension handle the types.\n *\n * However, some tools like ESLint can't work with `*.vue` files without the shim file.\n * So, if your tooling is not properly working, enable this option.\n */\n vueShim?: boolean;\n };\n /**\n * Public path of your app.\n * Use it when your public path is something else,\n * like _“\u003cprotocol>://\u003cdomain>/some/nested/folder”_ – in this case,\n * it means the distributables are in _“some/nested/folder”_ on your webserver.\n *\n * @default '/'\n */\n publicPath?: string;\n /**\n * Sets [Vue Router mode](https://router.vuejs.org/guide/essentials/history-mode.html).\n * History mode requires configuration on your deployment web server too.\n * For Capacitor and Electron, it's always 'hash' for [compatibility reasons](https://github.com/quasarframework/quasar/issues/17322#issuecomment-2191987962).\n *\n * @default 'hash'\n */\n vueRouterMode?: \"hash\" | \"history\";\n /**\n * Sets Vue Router base.\n * Should not need to configure this, unless absolutely needed.\n */\n vueRouterBase?: string;\n /**\n * Automatically open remote Vue Devtools when running in development mode.\n */\n vueDevtools?: boolean;\n /**\n * Should the Vue Options API be available? If all your components only use Composition API\n * it would make sense performance-wise to disable Vue Options API for a compile speedup.\n *\n * @default true\n */\n vueOptionsAPI?: boolean;\n /**\n * Do you want to analyze the production bundles?\n * Generates and opens an HTML report.\n *\n * @default false\n */\n analyze?: boolean;\n /**\n * Folder where Quasar CLI should generate the distributables.\n * Relative path to project root directory.\n *\n * @default 'dist/{ctx.modeName}' For all modes except Cordova.\n * @default 'src-cordova/www' For Cordova mode.\n */\n distDir?: string;\n\n /**\n * Add properties to `process.env` that you can use in your website/app JS code.\n *\n * @see https://v2.quasar.dev/quasar-cli-vite/handling-process-env\n *\n * @example { SOMETHING: 'someValue' }\n */\n env?: { [index: string]: string | boolean | undefined | null };\n /**\n * Defines constants that get replaced in your app.\n * Unlike `env`, you will need to use JSON.stringify() on the values yourself except for booleans.\n * Also, these will not be prefixed with `process.env.`.\n *\n * @example { SOMETHING: JSON.stringify('someValue') } -> console.log(SOMETHING) // console.log('someValue')\n */\n rawDefine?: { [index: string]: string | boolean | undefined | null };\n /**\n * Folder where Quasar CLI should look for .env* files.\n * Can be an absolute path or a relative path to project root directory.\n *\n * @default project root directory\n */\n envFolder?: string;\n /**\n * Additional .env* files to be loaded.\n * Each entry can be an absolute path or a relative path to quasar.config > build > envFolder.\n *\n * @example ['.env.somefile', '../.env.someotherfile']\n */\n envFiles?: string[];\n\n /**\n * Build production assets with or without the hash part in filenames.\n * Example: \"454d87bd\" in \"assets/index.454d87bd.js\"\n *\n * When used, please be careful how you configure your web server cache strategy as\n * files will not change name so your client might get 304 (Not Modified) even when\n * it's not the case.\n *\n * Will not change anything if your Vite config already touches the\n * build.rolldownOptions.output.entryFileNames/chunkFileNames/assetFileNames props.\n *\n * Gets applied to production builds only.\n *\n * Useful especially for (but not restricted to) PWA. If set to false then updating the\n * PWA will force to re-download all assets again, regardless if they were changed or\n * not (due to how Rolldown works through Vite).\n *\n * @default true\n */\n useFilenameHashes?: boolean;\n\n /**\n * whether to inject module preload polyfill.\n * @default false\n */\n polyfillModulePreload?: boolean;\n /**\n * Ignores the public folder.\n * @default false\n */\n ignorePublicFolder?: boolean;\n\n /**\n * Prepare external services before `$ quasar dev` command runs\n * like starting some backend or any other service that the app relies on.\n * Can use async/await or directly return a Promise.\n */\n beforeDev?: (params: QuasarHookParams) => void;\n /**\n * Run hook after Quasar dev server is started (`$ quasar dev`).\n * At this point, the dev server has been started and is available should you wish to do something with it.\n * Can use async/await or directly return a Promise.\n */\n afterDev?: (params: QuasarHookParams) => void;\n /**\n * Run hook before Quasar builds app for production (`$ quasar build`).\n * At this point, the distributables folder hasn’t been created yet.\n * Can use async/await or directly return a Promise.\n */\n beforeBuild?: (params: QuasarHookParams) => void;\n /**\n * Run hook after Quasar built app for production (`$ quasar build`).\n * At this point, the distributables folder has been created and is available\n * should you wish to do something with it.\n * Can use async/await or directly return a Promise.\n */\n afterBuild?: (params: QuasarHookParams) => void;\n /**\n * Run hook if publishing was requested (`$ quasar build -P`),\n * after Quasar built app for production and the afterBuild hook (if specified) was executed.\n * Can use async/await or directly return a Promise.\n * `opts` is Object of form `{arg, distDir}`,\n * where “arg” is the argument supplied (if any) to -P parameter.\n */\n onPublish?: (ops: { arg: string; distDir: string }) => void;\n\n /**\n * Set to `false` to disable minification, or specify the minifier to use.\n * Available options are 'terser' or 'esbuild'.\n * If set to anything but boolean false then it also applies to CSS.\n * For production only.\n * @default 'esbuild'\n */\n minify?: boolean | 'terser' | 'esbuild';\n /**\n * Minification options for html-minifier-terser.\n *\n * @see https://github.com/terser/html-minifier-terser?tab=readme-ov-file#options-quick-reference for complete list of options\n *\n * @default\n * {\n * removeComments: true,\n * collapseWhitespace: true,\n * removeAttributeQuotes: true,\n * collapseBooleanAttributes: true,\n * removeScriptTypeAttributes: true\n * }\n */\n htmlMinifyOptions?: HtmlMinifierOptions;\n /**\n * If `true`, a separate sourcemap file will be created. If 'inline', the\n * sourcemap will be appended to the resulting output file as data URI.\n * 'hidden' works like `true` except that the corresponding sourcemap\n * comments in the bundled files are suppressed.\n * @default false\n */\n sourcemap?: boolean | 'inline' | 'hidden';\n}\n````\n\nSee these references for more info:\n\n- Vite server options\n- [Vite Vue Plugin options](/quasar-cli-vite/handling-vite#vite-vue-plugin-options)\n- [Adding Vite plugins](/quasar-cli-vite/handling-vite#adding-vite-plugins)\n- [Folder Aliases](/quasar-cli-vite/handling-vite#folder-aliases)\n- [Handling Process Env](/quasar-cli-vite/handling-process-env)\n- html-minifier-terser options\n\n### sourceFiles\n\n```js\n/**\n * Use this property to change the default names of some files of your website/app if you have to.\n * All paths must be relative to the root folder of your project.\n *\n * @default\n * {\n * rootComponent: 'src/App.vue',\n * router: 'src/router/index',\n * store: 'src/stores/index',\n * pwaRegisterServiceWorker: 'src-pwa/register-service-worker',\n * pwaServiceWorker: 'src-pwa/custom-service-worker',\n * pwaManifestFile: 'src-pwa/manifest.json',\n * electronMain: 'src-electron/electron-main',\n * bexManifestFile: 'src-bex/manifest.json'\n * }\n */\nsourceFiles?: {\n rootComponent?: string;\n router?: string;\n store?: string;\n pwaRegisterServiceWorker?: string;\n pwaServiceWorker?: string;\n pwaManifestFile?: string;\n electronMain?: string;\n bexManifestFile?: string;\n}\n```\n\n### htmlVariables\n\n```js\n/** Add variables that you can use in /index.html. */\nhtmlVariables?: Record\u003cstring, any>;\n```\n\nYou can define and then reference variables in `/index.html`, like this:\n\n```js /quasar.config file\nimport { defineConfig } from '#q-app/wrappers'\n\nexport default defineConfig(ctx => {\n return {\n htmlVariables: {\n myVar: 'some-content'\n }\n }\n})\n```\n\nThen, as an example:\n\n```html /index.html\n\u003c%= myVar %> \u003c% if (myVar) { %>something\u003c% } %>\n```\n\nOne more example:\n\n```js /quasar.config file\nhtmlVariables: {\n title: 'test name',\n some: {\n prop: 'my-prop'\n }\n}\n```\n\nThen, as an example:\n\n```html /index.html\n\u003c%= title %> \u003c%= some.prop %> \u003c% if (some.prop) { %>\u003c%= title %>\u003c% } %>\n```\n\n### Quasar Mode Specific\n\n| Property | Type | Description |\n| --------- | ------ | --------------------------------------------------------------------------------------------------------- |\n| cordova | Object | Cordova specific [config](/quasar-cli-vite/developing-cordova-apps/configuring-cordova). |\n| capacitor | Object | Quasar CLI Capacitor specific [config](/quasar-cli-vite/developing-capacitor-apps/configuring-capacitor). |\n| pwa | Object | PWA specific [config](/quasar-cli-vite/developing-pwa/configuring-pwa). |\n| ssr | Object | SSR specific [config](/quasar-cli-vite/developing-ssr/configuring-ssr). |\n| electron | Object | Electron specific [config](/quasar-cli-vite/developing-electron-apps/configuring-electron). |\n| bex | Object | BEX specific [config](/quasar-cli-vite/developing-browser-extensions/configuring-bex). |\n\n## Examples\n\n### Setting env for dev/build\n\nPlease refer to [Adding to process.env](/quasar-cli-vite/handling-process-env#adding-to-process-env) section in our docs.\n\n### Adding Vite plugins\n\nPlease refer to the [Handling Vite](/quasar-cli-vite/handling-vite#adding-vite-plugins) page.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":25252,"content_sha256":"76757414f929627b6b73c386fe0b6f5ba61f8bef7d85aee7f0621475a3aaae22"},{"filename":"references/docs/quasar-cli-vite/routing.md","content":"---\ntitle: App Routing\ndesc: (@quasar/app-vite) How to use the Vue Router in a Quasar app.\n---\n\nYou'll notice that your Quasar project contains a `/src/router` folder. This holds the routing configuration of your website/app:\n\n- \"/src/router/index.js\" holds the Vue Router initialization code\n- \"/src/router/routes.js\" holds the routes of your website/app\n\n::: warning\nQuasar documentation assumes you are already familiar with Vue Router. Below it's described only the basics of how to make use of it in a Quasar CLI project. For the full list of its features please visit the Vue Router documentation.\n:::\n\nThe `/src/router/routes.js` needs to import your website/app's Pages and Layouts. Read more on [Routing with Layouts and Pages](/layout/routing-with-layouts-and-pages) documentation page.\n\nWhen using Pinia, the store is not directly importable from other scripts, but it is passed to the exported function of `/src/router/index.js`, so it can be accessed from there. For example you can use the `Router.beforeEach` method to check authentication in the router:\n\n```js /src/router.js\nimport { defineRouter } from '#q-app/wrappers'\n\nexport default defineRouter(({ store /*, ssrContext */ }) => {\n // ...\n const userStore = useUserStore(store)\n\n Router.beforeEach((to, from) => {\n if (\n to.matched.some(record => record.meta.requiresAuth) &&\n !userStore.isSignedIn\n ) {\n return { name: 'account-signin', query: { next: to.fullPath } }\n }\n })\n // ...\n})\n```\n\n::: tip\nIf you are developing a SSR app, then you can check out the [ssrContext](/quasar-cli-vite/developing-ssr/ssr-context) Object that gets supplied server-side.\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1662,"content_sha256":"19011330d0ed69baa907a80d934f6a18ef830ba727576aa3672cf6eee9e71e4a"},{"filename":"references/docs/quasar-cli-vite/state-management-with-pinia.md","content":"---\ntitle: State management with Pinia\ndesc: (@quasar/app-vite) How to manage Pinia in a Quasar App.\nscope:\n tree:\n l: src\n c:\n - l: stores\n e: Pinia\n c:\n - l: index.js\n e: (or .ts) Pinia initialization\n - l: '\u003cstore>'\n e: Pinia store...\n - l: '\u003cstore>'\n e: Pinia store...\n newStore:\n l: src\n c:\n - l: stores\n c:\n - l: index.js\n e: (or .ts) Pinia initialization\n - l: counter.js\n e: (or .ts) Pinia store\n---\n\nIn large applications, state management often becomes complex due to multiple pieces of state scattered across many components and the interactions between them. It is often overlooked that the source of truth in Vue instances is the raw data object - a Vue instance simply proxies access to it. Therefore, if you have a piece of state that should be shared by multiple instances, you should avoid duplicating it and share it by identity.\n\nThe recommended way to go if you want components sharing state is Pinia. Take a look at its documentation before diving in. It has a great feature when used along the Vue dev-tools browser extension like Time Travel debugging.\n\nWe won't go into details on how to configure or use Pinia since it has great docs. Instead we'll just show you what the folder structure looks like when using it on a Quasar project.\n\n\u003cDocTree :def=\"scope.tree\" />\n\nWhen you scaffold a Quasar project folder you can choose to add Pinia. It will create all the necessary configuration for you. Like for example the creation of `/src/stores` which handles all the Pinia related code that you need.\n\nIf you don't choose the Pinia option during project creation but would like to add it later then all you need to do is to check the next section and create the `src/stores/index.js` file (it's automatically created when you run `quasar new store \u003cname>`):\n\n```js /src/stores/index.js\nimport { defineStore } from '#q-app/wrappers'\nimport { createPinia } from 'pinia'\n\n/*\n * If not building with SSR mode, you can\n * directly export the Store instantiation;\n *\n * The function below can be async too; either use\n * async/await or return a Promise which resolves\n * with the Store instance.\n */\n\nexport default defineStore((/* { ssrContext } */) => {\n const pinia = createPinia()\n\n // You can add Pinia plugins here\n // pinia.use(SomePiniaPlugin)\n\n return pinia\n})\n```\n\n## Adding a Pinia store\n\nAdding a Pinia store is easy with Quasar CLI through the `$ quasar new` command.\n\n```bash\n$ quasar new store \u003cstore_name> [--format ts]\n```\n\nIt will create a folder in `/src/stores` named by \"store_name\" from the command above. It will contain all the boilerplate that you need.\n\nLet's say that you want to create a \"counter\" Pinia store. You issue `$ quasar new store counter`. You then notice the newly created `/src/stores/counter.js` file:\n\n\u003cDocTree :def=\"scope.newStore\" />\n\nExample of Pinia store:\n\n```js\nimport { defineStore } from 'pinia'\n\nexport const useCounterStore = defineStore('counter', {\n state: () => ({\n counter: 0\n }),\n getters: {\n doubleCount: state => state.counter * 2\n },\n actions: {\n increment() {\n this.counter++\n }\n }\n})\n```\n\nWe've created the new Pinia store, but we haven't yet used it in our app. In a Vue file:\n\n```html\n\u003ctemplate>\n \u003cdiv>\n \u003c!-- Option 1 -->\n \u003cdiv>Direct store\u003c/div>\n \u003c!-- Read the state value directly -->\n \u003cdiv>{{ store.counter }}\u003c/div>\n \u003c!-- Use getter directly -->\n \u003cdiv>{{ store.doubleCount }}\u003c/div>\n\n \u003c!-- Manipulate state directly -->\n \u003cq-btn @click=\"store.counter--\">-\u003c/q-btn>\n \u003c!-- Use an action -->\n \u003cq-btn @click=\"store.increment()\">+\u003c/q-btn>\n \u003c/div>\n\n \u003cdiv>\n \u003c!-- Option 2 -->\n \u003cdiv>Indirect store\u003c/div>\n \u003c!-- Use the computed state -->\n \u003cdiv>{{ count }}\u003c/div>\n \u003c!-- Use the computed getter -->\n \u003cdiv>{{ doubleCountValue }}\u003c/div>\n\n \u003c!-- Use the exposed function -->\n \u003cq-btn @click=\"decrementCount()\">-\u003c/q-btn>\n \u003c!-- Use the exposed function -->\n \u003cq-btn @click=\"incrementCount()\">+\u003c/q-btn>\n \u003c/div>\n\n \u003cdiv>\n \u003c!-- Option 3 -->\n \u003cdiv>Destructured store\u003c/div>\n \u003c!-- Use the destructured state -->\n \u003cdiv>{{ counter }}\u003c/div>\n \u003c!-- Use the destructured getter -->\n \u003cdiv>{{ doubleCount }}\u003c/div>\n\n \u003c!-- Manipulate state directly-->\n \u003cq-btn @click=\"counter--\">-\u003c/q-btn>\n \u003c!-- Use an action -->\n \u003cq-btn @click=\"increment()\">+\u003c/q-btn>\n \u003c/div>\n\u003c/template>\n\n\u003cscript>\n import { computed } from 'vue'\n import { useCounterStore } from 'stores/counter'\n import { storeToRefs } from 'pinia'\n\n export default {\n setup() {\n const store = useCounterStore()\n\n // Option 2: use computed and functions to use the store\n const count = computed(() => store.counter)\n const doubleCountValue = computed(() => store.doubleCount)\n const incrementCount = () => store.increment() // use action\n const decrementCount = () => store.counter-- // manipulate directly\n\n // Option 3: use destructuring to use the store in the template\n const { counter, doubleCount } = storeToRefs(store) // state and getters need \"storeToRefs\"\n const { increment } = store // actions can be destructured directly\n\n return {\n // Option 1: return the store directly and couple it in the template\n store,\n\n // Option 2: use the store in functions and compute the state to use in the template\n count,\n doubleCountValue,\n incrementCount,\n decrementCount,\n\n // Option 3: pass the destructed state, getters and actions to the template\n counter,\n increment,\n doubleCount\n }\n }\n }\n\u003c/script>\n```\n\nMore info on defining a Pinia store.\n\n## Accessing the router in Pinia stores\n\nSimply use `this.router` in Pinia stores to get access to the router.\n\nHere is an example:\n\n```js\nimport { defineStore } from 'pinia'\n\nexport const useWhateverStore = defineStore('whatever', {\n // ...\n actions: {\n whateverAction () { // do NOT use arrow function\n this.router.push('...')\n }\n }\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":6107,"content_sha256":"73275aea403cab4281b32bcccec67aa4762aefcf1000b36c11cd9e8f0f41629e"},{"filename":"references/docs/quasar-cli-vite/supporting-ts.md","content":"---\ntitle: Supporting TypeScript\ndesc: (@quasar/app-vite) How to enable support for TypeScript in a Quasar app.\nrelated:\n - /quasar-cli-vite/quasar-config-file\n - /quasar-cli-vite/linter\n---\n\nIf you didn't select TypeScript support when creating your project, you can still add it later. This guide will show you how to add TypeScript support to your existing JavaScript-based Quasar project.\n\n::: tip\nIf you selected TypeScript support when creating your project, you can skip this guide.\n:::\n\n## Installation of TypeScript Support\n\nInstall the `typescript` package:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add --dev typescript@~5.5.3\n\u003c\u003c| bash NPM |>>\n$ npm install --save-dev typescript@~5.5.3\n\u003c\u003c| bash PNPM |>>\n$ pnpm add -D typescript@~5.5.3\n\u003c\u003c| bash Bun |>>\n$ bun add --dev typescript@~5.5.3\n```\n\nThen, create `/tsconfig.json` file at the root of you project with this content:\n\n```json /tsconfig.json\n{\n \"extends\": \"./.quasar/tsconfig.json\"\n}\n```\n\nRun `$ quasar prepare` in the root of your project folder.\n\nNow you can start using TypeScript into your project. Note that some IDEs might require a restart for the new setup to fully kick in.\n\n::: tip\nRemember that you must change the extension of your JavaScript files to `.ts` to be allowed to write TypeScript code inside them. To use TypeScript in Vue files, you must update the script tag to include the `lang=\"ts\"` attribute, like `\u003cscript lang=\"ts\">` or `\u003cscript setup lang=\"ts\">`\n:::\n\n::: warning\nIf you forget to add the `tsconfig.json` file, the application will break at compile time!\n:::\n\n## Linting setup\n\nYou might want to check the requirements for it [here](/quasar-cli-vite/linter).\n\n## TypeScript Declaration Files\n\nIf you chose TypeScript support when scaffolding the project, the following declaration file was automatically scaffolded for you. If TypeScript support wasn't enabled during project creation, create it:\n\n```ts /src/env.d.ts\ndeclare namespace NodeJS {\n interface ProcessEnv {\n NODE_ENV: string\n VUE_ROUTER_MODE: 'hash' | 'history' | 'abstract' | undefined\n VUE_ROUTER_BASE: string | undefined\n // Define any custom env variables you have here, if you wish\n }\n}\n```\n\nSee the following sections for the features and build modes you are using.\n\n### Pinia\n\nIf you are using Pinia, Quasar CLI augments the `router` property inside `.quasar/pinia.d.ts` automatically. So, don't manually add the `router` property from the `PiniaCustomProperties` interface in the `src/stores/index.ts` file.\n\n```diff /src/stores/index.ts\nimport { defineStore } from '#q-app/wrappers'\nimport { createPinia } from 'pinia'\n- import { type Router } from 'vue-router';\n\n/*\n * When adding new properties to stores, you should also\n * extend the `PiniaCustomProperties` interface.\n * @see https://pinia.vuejs.org/core-concepts/plugins.html#Typing-new-store-properties\n */\ndeclare module 'pinia' {\n export interface PiniaCustomProperties {\n- readonly router: Router;\n+ // add your custom properties here, if any\n }\n}\n```\n\n### PWA mode\n\nIf you are using [PWA mode](/quasar-cli-vite/developing-pwa/introduction), make the following modifications to your project, and create any files that do not exist:\n\n```ts /src-pwa/pwa-env.d.ts\ndeclare namespace NodeJS {\n interface ProcessEnv {\n SERVICE_WORKER_FILE: string\n PWA_FALLBACK_HTML: string\n PWA_SERVICE_WORKER_REGEX: string\n }\n}\n```\n\n```ts /src-pwa/custom-service-worker.ts\n// at the top of the file\ndeclare const self: ServiceWorkerGlobalScope &\n typeof globalThis & { skipWaiting: () => void }\n```\n\n```json /src-pwa/tsconfig.json\n{\n \"extends\": \"../tsconfig.json\",\n \"compilerOptions\": {\n \"lib\": [\"WebWorker\", \"ESNext\"]\n },\n \"include\": [\"*.ts\", \"*.d.ts\"]\n}\n```\n\n### Electron mode\n\nIf you are using [Electron mode](/quasar-cli-vite/developing-electron-apps/introduction), add the section below to your project.\n\n```ts /src-electron/electron-env.d.ts\ndeclare namespace NodeJS {\n interface ProcessEnv {\n QUASAR_PUBLIC_FOLDER: string\n QUASAR_ELECTRON_PRELOAD_FOLDER: string\n QUASAR_ELECTRON_PRELOAD_EXTENSION: string\n APP_URL: string\n }\n}\n```\n\n### BEX mode\n\nIf you are using [BEX mode](/quasar-cli-vite/developing-browser-extensions/introduction), add the section below to your project. You may need to adjust it to your needs depending on the events you are using. The key is the event name, the value is a tuple where the first element is the input and the second is the output type.\n\n```ts /src-bex/background.ts\ndeclare module '@quasar/app-vite' {\n interface BexEventMap {\n /* eslint-disable @typescript-eslint/no-explicit-any */\n log: [{ message: string; data?: any[] }, never]\n getTime: [never, number]\n\n 'storage.get': [{ key: string | null }, any]\n 'storage.set': [{ key: string; value: any }, any]\n 'storage.remove': [{ key: string }, any]\n /* eslint-enable @typescript-eslint/no-explicit-any */\n }\n}\n```\n\nYou'll also need this in every content script file:\n\n```ts /src-bex/my-content-script.ts\ndeclare module '@quasar/app-vite' {\n interface BexEventMap {\n /* eslint-disable @typescript-eslint/no-explicit-any */\n 'some.event': [{ someProp: string }, void]\n /* eslint-enable @typescript-eslint/no-explicit-any */\n }\n}\n```\n\n## Configuring TypeScript\n\n### tsconfig.json\n\nNotice the `/tsconfig.json` file in your project folder. This file is used by the Quasar CLI to detect if you want TypeScript support or not. Its content should look like this:\n\n```json /tsconfig.json\n{\n \"extends\": \"./.quasar/tsconfig.json\"\n}\n```\n\nFor reviewing purposes, here is an example of the generated tsconfig (non strict) that your `/tsconfig.json` is extending:\n\n```json /.quasar/tsconfig.json\n{\n \"compilerOptions\": {\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"target\": \"esnext\",\n \"allowJs\": true,\n \"resolveJsonModule\": true,\n \"moduleDetection\": \"force\",\n \"isolatedModules\": true,\n \"module\": \"preserve\",\n \"noEmit\": true,\n \"lib\": [\n \"esnext\",\n \"dom\",\n \"dom.iterable\"\n ],\n \"paths\": { ... }\n },\n \"exclude\": [ ... ]\n}\n```\n\nProperly running typechecking and linting requires the `.quasar/tsconfig.json` to be present. The file will be auto-generated when running `quasar dev` or `quasar build` commands. But, as a lightweight alternative, there is the CLI command `quasar prepare` that will generate the `.quasar/tsconfig.json` file and some types files. It is especially useful for CI/CD pipelines.\n\n```bash\n$ quasar prepare\n```\n\nYou can add it as a `postinstall` script to make sure it's run after installing the dependencies. This would be helpful when someone is pulling the project for the first time.\n\n```json /package.json\n{\n \"scripts\": {\n \"postinstall\": \"quasar prepare\"\n }\n}\n```\n\nThanks to this setup, Capacitor dependencies are properly linked to the project's TypeScript configuration. That means you won't have to install dependencies twice, once in `/src-capacitor` and once in the root folder.\n\nAnother benefit of this change is that folder aliases (`quasar.config file > build > alias`) are automatically recognized by TypeScript. So, you can remove `tsconfig.json > compilerOptions > paths`. If you are using a plugin like `vite-tsconfig-paths`, you can uninstall it and use `quasar.config file > build > alias` as the source of truth.\n\nIf you are using ESLint, we recommend enabling `@typescript-eslint/consistent-type-imports` rules in your ESLint configuration. If you don't have linting set up, we recommend using `verbatimModuleSyntax` in your `tsconfig.json` file as an alternative (_unlike ESLint rules, it's not auto-fixable_). These changes will help you unify your imports regarding regular and type-only imports. Please read typescript-eslint Blog - Consistent Type Imports and Exports: Why and How for more information about this and how to set it up. Here is an example:\n\n```js /eslint.config.js\nrules: {\n // ...\n '@typescript-eslint/consistent-type-imports': [\n 'error',\n { prefer: 'type-imports' },\n ],\n // ...\n}\n```\n\n### quasar.config.ts\n\nYou can use `quasar.config file > build > typescript` to control the TypeScript-related behavior. Add this section into your configuration:\n\n```diff /quasar.config.ts\n build: {\n+ typescript: {\n+ strict: true, // (recommended) enables strict settings for TypeScript\n+ vueShim: true, // required when using ESLint with type-checked rules, will generate a shim file for `*.vue` files\n+ extendTsConfig (tsConfig) {\n+ // You can use this hook to extend tsConfig dynamically\n+ // For basic use cases, you can still update the usual tsconfig.json file to override some settings\n+ },\n+ }\n}\n```\n\nShould you want, you should be able to set the `strict` option to `true` without facing much trouble. But, if you face any issues, you can either update your code to satisfy the stricter rules or set the \"problematic\" options to `false` in your `tsconfig.json` file, at least until you can fix them.\n\nIf you are using ESLint with type-check rules, enable the `vueShim` option to preserve the previous behavior with the shim file. If your project is working fine without that option, you don't need to enable it.\n\n```diff /quasar.config.ts\nbuild: {\n typescript: {\n+ vueShim: true // required when using ESLint with type-checked rules, will generate a shim file for `*.vue` files\n }\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9323,"content_sha256":"350b7733f7c5ebbd924407be18997d0113fd0643680b2219397f9c6933d16d05"},{"filename":"references/docs/quasar-cli-vite/testing-and-auditing.md","content":"---\ntitle: Testing & Auditing\ndesc: (@quasar/app-vite) How to unit and end to end test a Quasar app.\n---\n\nYour Quasar projects have the ability to add unit and e2e testing harnesses. This introduction will not go into details about how to write and use tests, for that please consult the specially prepared and maintained documentation at the testing repo at GitHub. If you are a beginner, consider reading one of the books in the \"Further Reading\" section.\n\n## High level overview\n\nYou can install multiple pre-rigged testing harnesses to your existing Quasar application by running a simple command. This command will pull and install a node module (with dependencies) into your project's `package.json`, place necessary configuration files as appropriate and add script commands that expose some of the functionality of the respective harness. You can add multiple harnesses and even use them for your continuous integration pipelines - as appropriate.\n\nTesting is not in and of itself hard. The most complicated part is setting up the testing harness. The trick lies in knowing what to test. If you are new to testing, it is absolutely imperative that you familiarize yourself with some of the concepts and patterns. There are some links for further reading at the end of this document page.\n\n## Testing documentation\n\nYou can find the documentation of testing AEs at https://testing.quasar.dev or into `dev` branch of quasar-testing repo.\n\n\u003cq-btn label=\"Testing AEs documentation\" icon-right=\"launch\" href=\"https://testing.quasar.dev\" target=\"_blank\" />\n\n## Installing\n\n```bash\n$ cd your-quasar-project\n\n$ quasar ext add @quasar/testing-e2e-cypress\n# or\n$ quasar ext add @quasar/testing-unit-jest\n# or\n$ quasar ext add @quasar/testing-unit-vitest\n```\n\nThese extension will install the respective harnesses, which you can configure as you like.\nIt is how multiple testing harnesses are ideally managed within a Quasar project.\nIf you ever need to review your installation choices you can take a look at `quasar.extensions.json`.\n\n> Note that we previously suggested to use `@quasar/testing` AE to manage all testing harnesses in a project. This is no longer the case, as it is now deprecated. Please use the above commands instead.\n\n## Further Reading\n\n### Books\n\n- Testing Vue.js Applications by Edd Yerburgh, the author of the `@vue/test-utils` repo\n- Free Vue Testing Handbook\n\n### Tutorials\n\n- Unit Testing Vue Router with Jest\n\n### Documentation\n\n- @vue/test-utils\n- jest 24\n- cypress\n- lighthouse\n- snyk\n- nlf\n- chai\n- istanbul\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2538,"content_sha256":"5f70f54d39f97118da552c5239426f6905d41d55c6bf492e3f2b0542e74db1a2"},{"filename":"references/docs/quasar-cli-vite/upgrade-guide.md","content":"---\ntitle: Upgrade Guide for Quasar CLI with Vite\ndesc: (@quasar/app-vite) How to upgrade Quasar CLI with Vite from older versions to the latest one.\n---\n\n## @quasar/app-vite v2\n\n### A note to App Extensions owners\n\nYou might want to release new versions of your Quasar App Extensions with support for the new @quasar/app-vite. If you are not touching the quasar.config configuration, then it will be as easy as just changing the following:\n\n```diff\napi.compatibleWith(\n '@quasar/app-vite',\n- '^1.0.0'\n+ '^1.0.0 || ^2.0.0'\n)\n```\n\n### Notable breaking changes\n\n- Minimum Node.js version is now 22 (mainly due to Vite 8)\n- We have shifted towards an ESM style for the whole Quasar project folder, so many default project files now require ESM code (although using `.cjs` as an extension for these files is supported, but you will most likely need to rename the extension should you not wish to change anything). One example is the `/quasar.config.js` file which now it's assumed to be ESM too (so change from `.js` to `.cjs` should you still want a CommonJs file).\n- The \"test\" cmd was removed due to latest updates for @quasar/testing-\\* packages. See here\n- The \"clean\" cmd has been re-designed. Type \"quasar clean -h\" in your upgraded Quasar project folder for more info.\n- TypeScript detection is based on the quasar.config file being in TS form (quasar.config.ts) and tsconfig.json file presence.\n- TypeScript `tsconfig.json` presets have been replaced by an auto-generated `.quasar/tsconfig.json` file. This is more flexible and brings new features, more on this below.\n- feat+refactor(app-vite): ability to run multiple modes + dev/build simultaneously (huge effort!)\n- SSR and Electron modes now build in ESM format.\n- New BEX mode with significant new capabilities and ease of use (includes HMR for Chrome now!).\n- Dropped support for our internal linting system (quasar.config file > eslint). Should use vite-plugin-checker instead.\n- Dropped support for Vuex. Pinia has been the official store for Vue 3 for a while now. Vuex was deprecated in app-vite v1 and it had problems with the new structure, so it's now removed. You can still use Vuex as any Vue plugin, but you will have to manage everything(installing the store, hydration, no `store` parameter in boot files, etc.) yourself and will not receive any support from Quasar CLI. You will likely have to patch Vuex in order to get it working with TypeScript. We recommend migrating to Pinia.\n- **We will detail more breaking changes for each of the Quasar modes below**.\n\n### Highlights on what's new\n\nSome of the work below has already been backported to the old @quasar/app-vite v1, but posting here for reader's awareness.\n\n- feat(app-vite): upgrade to Vite 8\n- feat(app-vite): ability to run multiple quasar dev/build commands simultaneously (example: can run \"quasar dev -m capacitor\" and \"quasar dev -m ssr\" and \"quasar dev -m capacitor -T ios\" simultaneously)\n- feat(app-vite): Better TS typings overall\n- refactor(app-vite): port CLI to ESM format (major effort! especially to support Vite 8 and SSR)\n- feat(app-vite): support for quasar.config file in multiple formats (.js, .mjs, .ts, .cjs)\n- feat(app-vite): Improve quasarConfOptions, generate types for it, improve docs (fix: #14069) (#15945)\n- feat(app-vite): reload app if one of the imports from quasar.config file changes\n- feat(app-vite): TS detection should keep account of quasar.config file format too (quasar.config.ts)\n- feat(app-vite): The shorthand CLI command \"quasar dev/build -m ios/android\" is now targeting Capacitor mode instead of Cordova (2.0.0-beta.12+)\n- feat(app-vite): support for SSR development with HTTPS\n- feat(app-vite): env dotfiles support #15303\n- feat(app-vite): New quasar.config file props: build > envFolder (string) and envFiles (string[])\n- feat(app-vite): reopen browser (if configured so) when changing app url through quasar.config file\n- feat&perf(app-vite): faster & more accurate algorithm for determining node package manager to use\n- feat(app-vite): upgrade deps\n- feat(app-vite): remove workaround for bug in Electron 6-8 in cli templates (#15845)\n- feat(app-vite): remove bundleWebRuntime config for Capacitor v5+\n- feat(app-vite): use workbox v7 by default\n- feat(app-vite): quasar.config > pwa > injectPwaMetaTags can now also be a function: (({ pwaManifest, publicPath }) => string);\n- feat(app-vite): quasar.config > build > htmlMinifyOptions\n- feat(app-vite): lookup open port for vue devtools when being used; ability to run multiple cli instances with vue devtools\n- perf(app-vite): SSR render-template in specific esm or cjs form, according to host project; interpolation by variable\n- perf(app-vite): only verify quasar.conf server address for \"dev\" cmd\n- feat(app-vite): pick new electron inspect port for each instance\n- feat(app-vite): Electron - can now load multiple preload scripts\n- refactor(app-vite): AE support - better and more efficient algorithms\n- feat(app-vite): AE support for ESM format\n- feat(app-vite): AE support for TS format (through a build step)\n- feat(app-vite): AE API new methods -> hasTypescript() / hasLint() / getStorePackageName() / getNodePackagerName()\n- feat(app-vite): AE -> Prompts API (and ability for prompts default exported fn to be async)\n- refactor(app-vite): the \"clean\" cmd now works different, since the CLI can be run in multiple instances on the same project folder (multiple modes on dev or build)\n- feat(app-vite): Support for Bun as package manager #16335\n- feat(app-vite): for default /src-ssr template -> prod ssr -> on error, print err stack if built with debugging enabled\n- feat(app-vite): extend build > vitePlugins form (additional { server?: boolean, client?: boolean } param\n- feat+refactor(app-vite): BEX -> Completely rewrote & redesigned the Quasar Bridge (with a ton of new features); Automatically infer the background script file & the content script files from the bex manifest itself; Ability to compile other js/ts files as well that you might need to dynamically load/inject; No more 3s delay when opening the popup; No more \"dom\" script (use content script directly); The bridge is available globally in App (/src) through the $q object or window.QBexBridge\n- feat(app-vite): BEX with HMR (hot module reload) for Chrome\n- feat(app-vite): support returning overrides from build > extendViteConf\n\n### Beginning of the upgrade process\n\n::: tip\nIf you are unsure that you won't skip by mistake any of the recommended changes, you can scaffold a new project folder with the @quasar/app-vite v2 at any time and then easily start porting your app from there. The bulk of the changes refer to the different project folder config files and mostly NOT to your /src files.\n\u003cbr>\u003cbr>\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn create quasar\n\u003c\u003c| bash NPM |>>\n$ npm init quasar@latest\n\u003c\u003c| bash PNPM |>>\n$ pnpm create quasar@latest\n\u003c\u003c| bash Bun |>>\n$ bun create quasar@latest\n```\n\n\u003cbr>\nWhen asked to \"Pick Quasar App CLI variant\", answer with: \"Quasar App CLI with Vite\".\n:::\n\nPreparations:\n\n- If using the global installation of Quasar CLI (`@quasar/cli`), make sure that you have the latest one. This is due to the support of quasar.config file in multiple formats.\n- Again, we highlight that the minimum supported version of Node.js is now v22 (always use the LTS versions of Node.js - the higher the version the better).\n\n- Edit your `/package.json` on the `@quasar/app-vite` entry and assign it `^2.0.0`:\n\n ```diff /package.json\n \"devDependencies\": {\n - \"@quasar/app-vite\": \"^1.0.0\",\n + \"@quasar/app-vite\": \"^2.0.0\"\n }\n ```\n\n \u003cbr>\n Then yarn/npm/pnpm/bun install.\n \u003cbr>\u003cbr>\n\n- Convert your `/quasar.config.js` file to the ESM format (which is recommended, otherwise rename the file extension to `.cjs` and use CommonJs format). Also notice the wrappers import change, more on that later.\n\n ```diff /quasar.config.js file\n - const { configure } = require('quasar/wrappers')\n + import { defineConfig } from '#q-app/wrappers'\n\n - module.export = configure((ctx) => {\n + export default defineConfig((ctx) => {\n return {\n // ...\n }\n })\n ```\n\n ::: tip Tip on TypeScript\n You can now write this file in TS too should you wish (rename `/quasar.config.js` to `/quasar.config.ts` -- notice the `.ts` file extension).\n :::\n\n- Set `type` to `module` in your `/package.json`. Do not overlook this step!\n\n ```diff /package.json\n {\n + \"type\": \"module\"\n }\n ```\n\n \u003cbr>\n\n Convert `postcss.config.js` to ESM, if it's not already in ESM format.\n\n ```js /postcss.config.js\n import autoprefixer from 'autoprefixer'\n // import rtlcss from 'postcss-rtlcss'\n\n export default {\n plugins: [\n // https://github.com/postcss/autoprefixer\n autoprefixer({\n overrideBrowserslist: [\n 'last 4 Chrome versions',\n 'last 4 Firefox versions',\n 'last 4 Edge versions',\n 'last 4 Safari versions',\n 'last 4 Android versions',\n 'last 4 ChromeAndroid versions',\n 'last 4 FirefoxAndroid versions',\n 'last 4 iOS versions'\n ]\n })\n\n // https://github.com/elchininet/postcss-rtlcss\n // If you want to support RTL css, then\n // 1. yarn/pnpm/bun/npm install postcss-rtlcss\n // 2. optionally set quasar.config.js > framework > lang to an RTL language\n // 3. uncomment the following line (and its import statement above):\n // rtlcss()\n ]\n }\n ```\n\n \u003cbr>\n\n- You might want to add the following to your `/.gitignore` file. The `/quasar.config.*.temporary.compiled*` entry refers to files that are left for inspection purposes when something fails with your `/quasar.config` file (and can be removed by the `quasar clean` command):\n\n ```bash [highlight=8,11] /.gitignore\n .DS_Store\n .thumbs.db\n node_modules\n\n # Quasar core related directories\n .quasar\n /dist\n /quasar.config.*.temporary.compiled*\n\n # local .env files\n .env.local*\n\n # Cordova related directories and files\n /src-cordova/node_modules\n /src-cordova/platforms\n /src-cordova/plugins\n /src-cordova/www\n\n # Capacitor related directories and files\n /src-capacitor/www\n /src-capacitor/node_modules\n\n # Log files\n npm-debug.log*\n yarn-debug.log*\n yarn-error.log*\n\n # Editor directories and files\n .idea\n *.suo\n *.ntvs*\n *.njsproj\n *.sln\n ```\n\n \u003cbr>\n\n- Make sure to update your `/quasar.config` file with the newest specs in order to satisfy the types. Check all following sections.\n\n- If you've installed the `dotenv` package and are using it in your quasar.config file then uninstall it and use our CLIs native [dotenv support](#the-env-dotfiles-support).\n\n ```diff /quasar.config file\n - build: {\n - env: require('dotenv').config().parsed\n - }\n ```\n\n \u003cbr>\n\n- If you have linting, please review your setup by going to [Linter page](/quasar-cli-vite/linter). You will need to:\n 1. Uninstall all your current linting packages\n 2. Rename `/.eslintrc.cjs` to `/eslint.config.js` (check link above on how the new file should look)\n 3. Port `/.eslintignore` to the new `/eslint.config.js`\n 4. Delete `/.eslintignore`\n 5. Install the new dependencies (check the link above).\n 6. Edit your `/package.json` > scripts > lint:\n \u003cbr>\u003cbr>\n\n ```diff /package.json\n \"scripts\": {\n - \"lint\": \"eslint --ext .js,.ts,.vue ./\"\n\n // for non-TS projects:\n + \"lint\": \"eslint -c ./eslint.config.js \\\"./src*/**/*.{js,cjs,mjs,vue}\\\"\"\n // for TS projects:\n + \"lint\": \"eslint -c ./eslint.config.js \\\"./src*/**/*.{ts,js,cjs,mjs,vue}\\\"\"\n }\n ```\n\n \u003cbr>\n\n- The types feature flag files will now be auto-generated in the `.quasar` folder. So, you must delete them:\n\n ```tabs\n \u003c\u003c| bash rimraf through npx (cross-platform) |>>\n # in project folder root:\n $ npx rimraf -g ./src*/*-flag.d.ts\n $ quasar prepare\n \u003c\u003c| bash Unix-like (Linux, macOS) |>>\n # in project folder root:\n $ rm ./src*/*-flag.d.ts\n $ quasar prepare\n ```\n\n \u003cbr>\n\n- We have deprecated all the imports coming from `quasar/wrappers`. You can still use them, but we highly recommend switching to the new `#q-app/wrappers`, as shown below:\n\n ```diff The wrapper functions\n - import { configure } from 'quasar/wrappers'\n + import { defineConfig } from '#q-app/wrappers'\n\n - import { boot } from 'quasar/wrappers'\n + import { defineBoot } from '#q-app/wrappers'\n\n - import { preFetch } from 'quasar/wrappers'\n + import { definePreFetch } from '#q-app/wrappers'\n\n - import { route } from 'quasar/wrappers'\n + import { defineRouter } from '#q-app/wrappers'\n\n - import { store } from 'quasar/wrappers'\n + import { defineStore } from '#q-app/wrappers'\n\n - import { ssrMiddleware } from 'quasar/wrappers'\n + import { defineSsrMiddleware } from '#q-app/wrappers'\n\n - import { ssrCreate } from 'quasar/wrappers'\n + import { defineSsrCreate } from '#q-app/wrappers'\n\n - import { ssrListen } from 'quasar/wrappers'\n + import { defineSsrListen } from '#q-app/wrappers'\n\n - import { ssrClose } from 'quasar/wrappers'\n + import { defineSsrClose } from '#q-app/wrappers'\n\n - import { ssrServeStaticContent } from 'quasar/wrappers'\n + import { defineSsrServeStaticContent } from '#q-app/wrappers'\n\n - import { ssrRenderPreloadTag } from 'quasar/wrappers'\n + import { defineSsrRenderPreloadTag } from '#q-app/wrappers'\n ```\n\n \u003cbr>\n\n- For **non-TS projects**, update your `/jsconfig.json` file. Yes, it contains `tsconfig` in it and it's correct.\n\n ```json /jsconfig.json\n {\n \"extends\": \"./.quasar/tsconfig.json\"\n }\n ```\n\n \u003cbr>\n\n- For **TypeScript projects**: `@quasar/app-vite/tsconfig-preset` has been dropped, so update your `/tsconfig.json` file to extend the new auto-generated `.quasar/tsconfig.json` file. Unless you really know what you are doing, drop any other configuration and just keep `extends` as the only option in the file.\n\n ```diff /tsconfig.json\n {\n + \"extends\": \"./.quasar/tsconfig.json\"\n - \"extends\": \"@quasar/app-vite/tsconfig-preset\",\n - \"compilerOptions\": {\n - \"baseUrl\": \".\"\n - },\n - \"include\": [ ... ],\n - \"exclude\": [ ... ]\n }\n ```\n\n \u003cbr>\n\n The underlying configuration is different now, so please review the new options in the generated file to see if you need further adjustments to your `tsconfig.json` file. Here is an example of the generated tsconfig (non strict) for reviewing purposes:\n \u003cbr>\n\n ```json /.quasar/tsconfig.json\n {\n \"compilerOptions\": {\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"target\": \"esnext\",\n \"allowJs\": true,\n \"resolveJsonModule\": true,\n \"moduleDetection\": \"force\",\n \"isolatedModules\": true,\n \"module\": \"preserve\",\n \"noEmit\": true,\n \"lib\": [\n \"esnext\",\n \"dom\",\n \"dom.iterable\"\n ],\n \"paths\": { ... }\n },\n \"exclude\": [ ... ]\n }\n ```\n\n \u003cbr>\n\n If you are using ESLint, we recommend enabling `@typescript-eslint/consistent-type-imports` rules in your ESLint configuration. If you don't have linting set up, we recommend using `verbatimModuleSyntax` in your `tsconfig.json` file as an alternative (_unlike ESLint rules, it's not auto-fixable_). These changes will help you unify your imports regarding regular and type-only imports. Please read typescript-eslint Blog - Consistent Type Imports and Exports: Why and How for more information about this and how to set it up. Here is an example:\n\n ```js /eslint.config.js\n rules: {\n // ...\n '@typescript-eslint/consistent-type-imports': [\n 'error',\n { prefer: 'type-imports' },\n ],\n // ...\n }\n ```\n\n \u003cbr>\n\n You can use `quasar.config file > build > typescript` to control the TypeScript-related behavior. Add this section into your configuration:\n \u003cbr>\n\n ```diff /quasar.config.ts\n build: {\n + typescript: {\n + strict: true, // (recommended) enables strict settings for TypeScript\n + vueShim: true, // required when using ESLint with type-checked rules, will generate a shim file for `*.vue` files\n + extendTsConfig (tsConfig) {\n + // You can use this hook to extend tsConfig dynamically\n + // For basic use cases, you can still update the usual tsconfig.json file to override some settings\n + },\n + }\n }\n ```\n\n \u003cbr>\n\n Most of the strict options were already enabled in the previous preset. So,\n you should be able to set the `strict` option to `true` without facing much trouble. But, if you face any issues, you can either update your code to satisfy the stricter rules or set the \"problematic\" options to `false` in your `tsconfig.json` file, at least until you can fix them.\n\n `src/quasar.d.ts` and `src/shims-vue.d.ts` files will now be auto-generated in the `.quasar` folder. So, you must delete those files:\n \u003cbr>\n\n ```tabs\n \u003c\u003c| bash rimraf through npx (cross-platform) |>>\n # in project folder root:\n $ npx rimraf src/quasar.d.ts src/shims-vue.d.ts\n \u003c\u003c| bash Unix-like (Linux, macOS) |>>\n # in project folder root:\n $ rm src/quasar.d.ts src/shims-vue.d.ts\n ```\n\n \u003cbr>\n\n If you are using ESLint with type-check rules, enable the `vueShim` option to preserve the previous behavior with the shim file. If your project is working fine without that option, you don't need to enable it.\n \u003cbr>\n\n ```diff /quasar.config.ts\n build: {\n typescript: {\n + vueShim: true // required when using ESLint with type-checked rules, will generate a shim file for `*.vue` files\n }\n }\n ```\n\n \u003cbr>\n\n Thanks to this change, Capacitor dependencies are now properly linked to the project's TypeScript configuration. That means you won't have to install dependencies twice, once in `/src-capacitor` and once in the root folder. So, you can remove the Capacitor dependencies from the root `package.json` file. From now on, installing Capacitor dependencies only in the `/src-capacitor` folder will be enough.\n\n Another benefit of this change is that folder aliases(`quasar.config file > build > alias`) are automatically recognized by TypeScript. So, you can remove `tsconfig.json > compilerOptions > paths`. If you were using a plugin like `vite-tsconfig-paths`, you can uninstall it and use `quasar.config file > build > alias` as the source of truth.\n\n Properly running typechecking and linting requires the `.quasar/tsconfig.json` to be present. The file will be auto-generated when running `quasar dev` or `quasar build` commands. But, as a lightweight alternative, there is a new CLI command `quasar prepare` that will generate the `.quasar/tsconfig.json` file and some types files. It is especially useful for CI/CD pipelines.\n \u003cbr>\n\n ```bash\n $ quasar prepare\n ```\n\n \u003cbr>\n\n You can add it as a `postinstall` script to make sure it's run after installing the dependencies. This would be helpful when someone is pulling the project for the first time.\n \u003cbr>\n\n ```json /package.json\n {\n \"scripts\": {\n \"postinstall\": \"quasar prepare\"\n }\n }\n ```\n\n \u003cbr>\n\n If you are using Pinia, we are now augmenting the `router` property inside `.quasar/pinia.d.ts` automatically. So, you can remove the `router` property from the `PiniaCustomProperties` interface in the `src/stores/index.ts` file. It will continue to work as before, but it's recommended to remove it to avoid confusion.\n\n ```diff /src/stores/index.ts\n import { defineStore } from '#q-app/wrappers'\n import { createPinia } from 'pinia'\n - import { type Router } from 'vue-router';\n\n /*\n * When adding new properties to stores, you should also\n * extend the `PiniaCustomProperties` interface.\n - * @see https://pinia.vuejs.org/core-concepts/plugins.html#typing-new-store-properties\n + * @see https://pinia.vuejs.org/core-concepts/plugins.html#Typing-new-store-properties\n */\n declare module 'pinia' {\n export interface PiniaCustomProperties {\n - readonly router: Router;\n + // add your custom properties here, if any\n }\n }\n ```\n\n### Capacitor / Cordova modes changes\n\nThe UI code (`/src`) can now use `process.env.TARGET` (which will be \"ios\" or \"android\").\n\n### PWA mode changes\n\nThe `register-service-worker` dependency is no longer supplied by the CLI. You will have to install it yourself in your project folder.\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add register-service-worker@^1.0.0\n\u003c\u003c| bash NPM |>>\n$ npm install --save register-service-worker@^1.0.0\n\u003c\u003c| bash PNPM |>>\n$ pnpm add register-service-worker@^1.0.0\n\u003c\u003c| bash Bun |>>\n$ bun add register-service-worker@^1.0.0\n```\n\nEdit your `/src-pwa/custom-service-worker.js` file:\n\n```diff /src-pwa/custom-service-worker.js\n- if (process.env.MODE !== 'ssr' || process.env.PROD) {\n+ if (process.env.PROD) {\n registerRoute(\n new NavigationRoute(\n createHandlerBoundToURL(process.env.PWA_FALLBACK_HTML),\n- { denylist: [/sw\\.js$/, /workbox-(.)*\\.js$/] }\n+ { denylist: [new RegExp(process.env.PWA_SERVICE_WORKER_REGEX), /workbox-(.)*\\.js$/] }\n )\n )\n}\n```\n\nThere are some subtle changes in `/quasar.config` file too:\n\n```diff /quasar.config file\nsourceFiles: {\n- registerServiceWorker: 'src-pwa/register-service-worker',\n- serviceWorker: 'src-pwa/custom-service-worker',\n+ pwaRegisterServiceWorker: 'src-pwa/register-service-worker',\n+ pwaServiceWorker: 'src-pwa/custom-service-worker',\n+ pwaManifestFile: 'src-pwa/manifest.json',\n // ...\n},\n\npwa: {\n- workboxMode?: \"generateSW\" | \"injectManifest\";\n+ workboxMode?: \"GenerateSW\" | \"InjectManifest\";\n\n- // useFilenameHashes: false,\n+ // Moved to quasar.config > build > useFilenameHashes\n\n /**\n * Auto inject the PWA meta tags?\n * If using the function form, return HTML tags as one single string.\n * @default true\n */\n- injectPwaMetaTags?: boolean;\n+ injectPwaMetaTags?: boolean | ((injectParam: InjectPwaMetaTagsParams) => string);\n+ // see below for the InjectPwaMetaTagsParams interface\n\n // ...\n}\n\n// additional types for injectPwaMetaTags\ninterface InjectPwaMetaTagsParams {\n pwaManifest: PwaManifestOptions;\n publicPath: string;\n}\ninterface PwaManifestOptions {\n id?: string;\n background_color?: string;\n categories?: string[];\n description?: string;\n // ...\n}\n```\n\n### Electron mode changes\n\n::: warning\nThe distributables (your production code) will be compiled to ESM form, thus also taking advantage of Electron in ESM form.\n:::\n\n::: tip\nYou might want to upgrade the `electron` package to the latest so it can handle the ESM format.\n:::\n\nMost changes refer to editing your `/src-electron/electron-main.js` file:\n\n```diff Icon path\n+import { fileURLToPath } from 'node:url'\n\n+const currentDir = fileURLToPath(new URL('.', import.meta.url))\n\nfunction createWindow () {\n mainWindow = new BrowserWindow({\n- icon: path.resolve(__dirname, 'icons/icon.png'), // tray icon\n+ icon: path.resolve(currentDir, 'icons/icon.png'), // tray icon\n // ...\n })\n```\n\n```diff Preload script\nimport { fileURLToPath } from 'node:url'\n\nconst currentDir = fileURLToPath(new URL('.', import.meta.url))\n\nfunction createWindow () {\n mainWindow = new BrowserWindow({\n // ...\n webPreferences: {\n- preload: path.resolve(__dirname, process.env.QUASAR_ELECTRON_PRELOAD)\n+ preload: path.resolve(\n+ currentDir,\n+ path.join(process.env.QUASAR_ELECTRON_PRELOAD_FOLDER, 'electron-preload' + process.env.QUASAR_ELECTRON_PRELOAD_EXTENSION)\n+ )\n }\n })\n```\n\n::: danger\nEdit `/quasar.config.js` to specify your preload script:\n\u003cbr>\u003cbr>\n\n```diff /quasar.config file\nsourceFiles: {\n- electronPreload?: string;\n},\n\nelectron: {\n+ // Electron preload scripts (if any) from /src-electron, WITHOUT file extension\n+ preloadScripts: [ 'electron-preload' ],\n}\n```\n\n\u003cbr>\nAs you can see, you can now specify multiple preload scripts should you need them.\n:::\n\n```diff\n- function createWindow () {\n+ async function createWindow () {\n // ...\n- mainWindow.loadURL(process.env.APP_URL)\n+ if (process.env.DEV) {\n+ await mainWindow.loadURL(process.env.APP_URL)\n+ } else {\n+ await mainWindow.loadFile('index.html')\n+ }\n```\n\nFinally, the new file should look like this:\n\n```js The new /src-electron/electron-main.js\nimport { app, BrowserWindow } from 'electron'\nimport path from 'node:path'\nimport os from 'node:os'\nimport { fileURLToPath } from 'node:url'\n\n// needed in case process is undefined under Linux\nconst platform = process.platform || os.platform()\n\nconst currentDir = fileURLToPath(new URL('.', import.meta.url))\n\nlet mainWindow\n\nasync function createWindow() {\n /**\n * Initial window options\n */\n mainWindow = new BrowserWindow({\n icon: path.resolve(currentDir, 'icons/icon.png'), // tray icon\n width: 1000,\n height: 600,\n useContentSize: true,\n webPreferences: {\n contextIsolation: true,\n // More info: https://v2.quasar.dev/quasar-cli-vite/developing-electron-apps/electron-preload-script\n preload: path.resolve(\n currentDir,\n path.join(\n process.env.QUASAR_ELECTRON_PRELOAD_FOLDER,\n 'electron-preload' + process.env.QUASAR_ELECTRON_PRELOAD_EXTENSION\n )\n )\n }\n })\n\n if (process.env.DEV) {\n await mainWindow.loadURL(process.env.APP_URL)\n } else {\n await mainWindow.loadFile('index.html')\n }\n\n if (process.env.DEBUGGING) {\n // if on DEV or Production with debug enabled\n mainWindow.webContents.openDevTools()\n } else {\n // we're on production; no access to devtools pls\n mainWindow.webContents.on('devtools-opened', () => {\n mainWindow.webContents.closeDevTools()\n })\n }\n\n mainWindow.on('closed', () => {\n mainWindow = null\n })\n}\n\napp.whenReady().then(createWindow)\n\napp.on('window-all-closed', () => {\n if (platform !== 'darwin') {\n app.quit()\n }\n})\n\napp.on('activate', () => {\n if (mainWindow === null) {\n createWindow()\n }\n})\n```\n\n### SSR mode changes\n\n::: warning\nThe distributables (your production code) will be compiled to ESM form.\n:::\n\n```diff /src-ssr/middlewares/*\n- import { ssrMiddleware } from 'quasar/wrappers'\n+ import { defineSsrMiddleware } from '#q-app/wrappers'\n\n- export default ssrMiddleware({\n+ export default defineSsrMiddleware(({\n app,\n port,\n resolve,\n publicPath,\n folders,\n render,\n serve\n}) => {\n // something to do with the server \"app\"\n})\n```\n\nThe other changes refer to editing your `/src-ssr/server.js` file. Since you can now use HTTPS while developing your app too, you need to make the following changes to the file:\n\n```diff /src-ssr/server.js > listen\n- import { ssrListen } from 'quasar/wrappers'\n+ import { defineSsrListen } from '#q-app/wrappers'\n\n- export const listen = ssrListen(async ({ app, port, isReady }) => {\n+ // notice: devHttpsApp param which will be a Node.js httpsServer (on DEV only) and if https is enabled\n+ // notice: no \"isReady\" param (starting with 2.0.0-beta.16+)\n+ // notice: defineSsrListen() param can still be async (below it isn't)\n+ export const listen = defineSsrListen(({ app, devHttpsApp, port }) => {\n- await isReady()\n- return app.listen(port, () => {\n+ const server = devHttpsApp || app\n+ return server.listen(port, () => {\n if (process.env.PROD) {\n console.log('Server listening at port ' + port)\n }\n })\n })\n```\n\nFinally, this is how it should look like now:\n\n```js /src-ssr/server.js > listen\nimport { defineSsrListen } from '#q-app/wrappers'\nexport const listen = defineSsrListen(({ app, devHttpsApp, port }) => {\n const server = devHttpsApp || app\n return server.listen(port, () => {\n if (process.env.PROD) {\n console.log('Server listening at port ' + port)\n }\n })\n})\n```\n\nFor a serverless approach, this is how the \"listen\" part should look like:\n\n```js /src-ssr/server.js > listen\nexport const listen = defineSsrListen(({ app, devHttpsApp, port }) => {\n if (process.env.DEV) {\n const server = devHttpsApp || app\n return server.listen(port, () => {\n console.log('Server listening at port ' + port)\n })\n } else {\n // in production\n // return an object with a \"handler\" property\n // that the server script will named-export\n return { handler: app }\n }\n})\n```\n\nNext, the `serveStaticContent` function has changed:\n\n```diff /src-ssr/server.js > serveStaticContent\n- import { serveStaticContent }\n+ import { defineSsrServeStaticContent } from '#q-app/wrappers'\n\n- export const serveStaticContent = ssrServeStaticContent((path, opts) => {\n- return express.static(path, { maxAge, ...opts })\n- })\n\n+ /**\n+ * Should return a function that will be used to configure the webserver\n+ * to serve static content at \"urlPath\" from \"pathToServe\" folder/file.\n+ *\n+ * Notice resolve.urlPath(urlPath) and resolve.public(pathToServe) usages.\n+ *\n+ * Can be async: defineSsrServeStaticContent(async ({ app, resolve }) => {\n+ * Can return an async function: return async ({ urlPath = '/', pathToServe = '.', opts = {} }) => {\n+ */\n+ export const serveStaticContent = defineSsrServeStaticContent(({ app, resolve }) => {\n+ return ({ urlPath = '/', pathToServe = '.', opts = {} }) => {\n+ const serveFn = express.static(resolve.public(pathToServe), { maxAge, ...opts })\n+ app.use(resolve.urlPath(urlPath), serveFn)\n+ }\n+ })\n```\n\nAlso, the `renderPreloadTag()` function can now take an additional parameter (`ssrContext`):\n\n```diff /src-ssr/server.js\n- import { ssrRenderPreloadTag } from 'quasar/wrappers'\n+ import { defineSsrRenderPreloadTag } from '#q-app/wrappers'\n\n+ export const renderPreloadTag = defineSsrRenderPreloadTag((file, { ssrContext }) => {\n+ // ...\n+ })\n```\n\nFor TS devs, you should also make a small change to your /src-ssr/middlewares files, like this:\n\n```diff For TS devs\n+ import { type Request, type Response } from 'express';\n// ...\n- app.get(resolve.urlPath('*'), (req, res) => {\n+ app.get(resolve.urlPath('*'), (req: Request, res: Response) => {\n```\n\nThere are some additions to the `/quasar.config` file too:\n\n```diff /quasar.config file\nssr: {\n // ...\n\n /**\n * When using SSR+PWA, this is the name of the\n * PWA index html file that the client-side fallbacks to.\n * For production only.\n *\n * Do NOT use index.html as name as it will mess SSR up!\n *\n * @default 'offline.html'\n */\n- ssrPwaHtmlFilename?: string;\n+ pwaOfflineHtmlFilename?: string;\n\n /**\n * Tell browser when a file from the server should expire from cache\n * (the default value, in ms)\n * Has effect only when server.static() is used\n */\n- maxAge?: number;\n\n /**\n * Extend/configure the Workbox GenerateSW options\n * Specify Workbox options which will be applied on top of\n * `pwa > extendGenerateSWOptions()`.\n * More info: https://developer.chrome.com/docs/workbox/the-ways-of-workbox/\n */\n+ pwaExtendGenerateSWOptions?: (config: object) => void;\n\n /**\n * Extend/configure the Workbox InjectManifest options\n * Specify Workbox options which will be applied on top of\n * `pwa > extendInjectManifestOptions()`.\n * More info: https://developer.chrome.com/docs/workbox/the-ways-of-workbox/\n */\n+ pwaExtendInjectManifestOptions?: (config: object) => void;\n}\n```\n\n### Bex mode changes\n\nThere are quite a few improvements:\n\n- **The BEX mode now has HMR (hot module reload)!!!** (Chrome only)\n- Completely rewrote & redesigned the Quasar Bridge to allow for:\n - Sending/receiving messages directly between any part of your bex (app, content scripts, background)\n - Ability to skip using the bridge altogether\n - Error handling for sending & receiving messages through the bridge\n - Better handling of internal resources to avoid memory leaks (there were some edge cases in the previous implementation)\n - Debug mode (where all the bridge communication will be outputted to the browser console)\n - Breaking changes highlights: background & content scripts initialization of the bridge; bride.on() calls when responding; bridge.send() calls\n - The bridge is now available throughout the App in `/src/` (regardless of the file used: boot files, router init, App.vue, any Vue component, ...) by accessing the `$q object` or `window.QBexBridge`\n- One single manifest file from which both chrome & firefox ones can be extracted.\n- Automatically infer the background script file & the content script files from the BEX manifest file.\n- Ability to compile other js/ts files as well that you might need to dynamically load/inject.\n- No more 3s delay when opening the popup.\n- The \"dom\" script support was removed. Simply move your logic from there into one of your content scripts.\n- New, easier API for the background/content scripts.\n\n#### Dependencies\n\nThe `events` dependency is no longer required. If you have it installed, uninstall it:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn remove events\n\u003c\u003c| bash NPM |>>\n$ npm uninstall --save events\n\u003c\u003c| bash PNPM |>>\n$ pnpm remove events\n\u003c\u003c| bash Bun |>>\n$ bun remove events\n```\n\n#### CLI commands\n\nThe `quasar dev` and `quasar build` commands now require an explicit target (chrome or firefox). Should you wish to develop for both simultaneously, then you can spawn two quasar dev commands.\n\n```bash\n$ quasar dev -m bex -T \u003cchrome|firefox>\n$ quasar dev -m bex --target \u003cchrome|firefox>\n\n$ quasar build -m bex -T \u003cchrome|firefox>\n$ quasar build -m bex --target \u003cchrome|firefox>\n```\n\nNote that the code in `/src` and `/src-bex` can now use `process.env.TARGET` (which will be \"chrome\" or \"firefox\").\n\n#### HMR for Chrome\n\nSignificant improvements to the DX:\n\n- Full HMR for devtools/options/popup page\n- When changing the background script, the extension will automatically reload.\n- When changing a content script, the extension will automatically reload & the tabs using those content scripts will auto-refresh.\n\n#### The quasar.config file\n\n```diff /quasar.config file\nsourceFiles: {\n+ bexManifestFile: 'src-bex/manifest.json',\n // ...\n},\nbex: {\n- contentScripts: [] // no longer needed as scripts are\n- // now extracted from the manifest file\n+ extraScripts: []\n}\n```\n\n#### The BEX manifest file\n\nWe are now supplying a way to differentiate the manifest for each target (chrome and firefox).\n\nNotice that the manifest file now contains three root props: `all`, `chrome` & `firefox`. The manifest for chrome is deeply merged from all+chrome, while the firefox one is generated from all+firefox. You could even have different manifest versions for each target.\n\n```json\n{\n \"all\": {\n \"manifest_version\": 3,\n\n \"icons\": {\n \"16\": \"icons/icon-16x16.png\",\n \"48\": \"icons/icon-48x48.png\",\n \"128\": \"icons/icon-128x128.png\"\n },\n\n \"permissions\": [\"storage\", \"tabs\", \"activeTab\"],\n\n \"host_permissions\": [\"*://*/*\"],\n \"content_security_policy\": {\n \"extension_pages\": \"script-src 'self'; object-src 'self';\"\n },\n \"web_accessible_resources\": [\n {\n \"resources\": [\"*\"],\n \"matches\": [\"*://*/*\"]\n }\n ],\n\n \"action\": {\n \"default_popup\": \"www/index.html\"\n },\n\n \"content_scripts\": [\n {\n \"matches\": [\"\u003call_urls>\"],\n \"css\": [\"assets/content.css\"],\n \"js\": [\"my-content-script.js\"]\n }\n ]\n },\n\n \"chrome\": {\n \"background\": {\n \"service_worker\": \"background.js\"\n }\n },\n\n \"firefox\": {\n \"background\": {\n \"scripts\": [\"background.js\"]\n }\n }\n}\n```\n\n::: warning For TS devs\nYour background and content scripts have the `.ts` extension. Use that extension in the manifest.json file as well! Examples: \"background.ts\", \"my-content-script.ts\". While the browser vendors do support only the `.js` extension, Quasar CLI will convert the file extensions automatically.\n:::\n\n#### The script files\n\n```tabs Background script\n\u003c\u003c| js New way |>>\n/**\n * Importing the file below initializes the extension background.\n *\n * Warnings:\n * 1. Do NOT remove the import statement below. It is required for the extension to work.\n * If you don't need createBridge(), leave it as \"import '#q-app/bex/background'\".\n * 2. Do NOT import this file in multiple background scripts. Only in one!\n * 3. Import it in your background service worker (if available for your target browser).\n */\nimport { createBridge } from '#q-app/bex/background'\n\n/**\n * Call createBridge() to enable communication with the app & content scripts\n * (and between the app & content scripts), otherwise skip calling\n * createBridge() and use no bridge.\n */\nconst bridge = createBridge({ debug: false })\n\u003c\u003c| js Old way |>>\nimport { bexBackground } from 'quasar/wrappers'\n\nexport default bexBackground((bridge /* , allActiveConnections */) => {\n // ...\n})\n```\n\n```tabs Content script\n\u003c\u003c| js New way |>>\n/**\n * Importing the file below initializes the content script.\n *\n * Warning:\n * Do not remove the import statement below. It is required for the extension to work.\n * If you don't need createBridge(), leave it as \"import '#q-app/bex/content'\".\n */\nimport { createBridge } from '#q-app/bex/content'\n\n// The use of the bridge is optional.\nconst bridge = createBridge({ debug: false })\n/**\n * bridge.portName is 'content@\u003cpath>-\u003cnumber>'\n * where \u003cpath> is the relative path of this content script\n * filename (without extension) from /src-bex\n * (eg. 'my-content-script', 'subdir/my-script')\n * and \u003cnumber> is a unique instance number (1-10000).\n */\n\n// Attach initial bridge listeners...\n\n/**\n * Leave this AFTER you attach your initial listeners\n * so that the bridge can properly handle them.\n *\n * You can also disconnect from the background script\n * later on by calling bridge.disconnectFromBackground().\n *\n * To check connection status, access bridge.isConnected\n */\nbridge.connectToBackground()\n .then(() => {\n console.log('Connected to background')\n })\n .catch(err => {\n console.error('Failed to connect to background:', err)\n })\n\u003c\u003c| js Old way |>>\nimport { bexContent } from 'quasar/wrappers'\n\nexport default bexContent((/* bridge */) => {\n // ...\n})\n```\n\n```tabs App (/src/...) vue components\n\u003c\u003c| html Composition API + script setup |>>\n\u003ctemplate>\n \u003cdiv />\n\u003c/template>\n\n\u003cscript setup>\nimport { useQuasar } from 'quasar'\nconst $q = useQuasar()\n\n// Use $q.bex (the bridge)\n// $q.bex.portName is \"app\"\n\u003c/script>\n\u003c\u003c| html Composition API + script |>>\n\u003ctemplate>\n \u003cdiv />\n\u003c/template>\n\n\u003cscript>\nimport { useQuasar } from 'quasar'\n\nexport default {\n setup () {\n const $q = useQuasar()\n // Use $q.bex (the bridge)\n // $q.bex.portName is \"app\"\n }\n}\n\u003c/script>\n\u003c\u003c| html Options API |>>\n\u003ctemplate>\n \u003cdiv />\n\u003c/template>\n\n\u003cscript>\nexport default {\n // Use this.$q.bex (the bridge)\n // this.$q.bex.portName is \"app\"\n}\n\u003c/script>\n```\n\nPlease note that the devtools/popup/options page portName will be `app`.\n\n#### The new BEX bridge\n\n```js Bex Bridge messaging\n// Listen to a message from the client\nbridge.on('test', message => {\n console.log(message)\n console.log(message.payload)\n console.log(message.from)\n})\n\n// Send a message and split payload into chunks\n// to avoid max size limit of BEX messages.\n// Warning! This happens automatically when the payload is an array.\n// If you actually want to send an Array, wrap it in an object.\nbridge.send({\n event: 'test',\n to: 'app',\n payload: [ 'chunk1', 'chunk2', 'chunk3', ... ]\n}).then(responsePayload => { ... }).catch(err => { ... })\n\n// Send a message and wait for a response\nbridge.send({\n event: 'test',\n to: 'background',\n payload: { banner: 'Hello from content-script' }\n}).then(responsePayload => { ... }).catch(err => { ... })\n\n// Listen to a message from the client and respond synchronously\nbridge.on('test', message => {\n console.log(message)\n return { banner: 'Hello from a content-script!' }\n})\n\n// Listen to a message from the client and respond asynchronously\nbridge.on('test', async message => {\n console.log(message)\n const result = await someAsyncFunction()\n return result\n})\nbridge.on('test', message => {\n console.log(message)\n return new Promise(resolve => {\n setTimeout(() => {\n resolve({ banner: 'Hello from a content-script!' })\n }, 1000)\n })\n})\n\n// Broadcast a message to app & content scripts\nbridge.portList.forEach(portName => {\n bridge.send({ event: 'test', to: portName, payload: 'Hello from background!' })\n})\n\n// Find any connected content script and send a message to it\nconst contentPort = bridge.portList.find(portName => portName.startsWith('content@'))\nif (contentPort) {\n bridge.send({ event: 'test', to: contentPort, payload: 'Hello from background!' })\n}\n\n// Send a message to a certain content script\nbridge\n .send({ event: 'test', to: 'content@my-content-script-2345', payload: 'Hello from a content-script!' })\n .then(responsePayload => { ... })\n .catch(err => { ... })\n\n// Listen for connection events\n// (the \"@quasar:ports\" is an internal event name registered automatically by the bridge)\n// --> ({ portList: string[], added?: string } | { portList: string[], removed?: string })\nbridge.on('@quasar:ports', ({ portList, added, removed }) => {\n console.log('Ports:', portList)\n if (added) {\n console.log('New connection:', added)\n } else if (removed) {\n console.log('Connection removed:', removed)\n }\n})\n\n// Current bridge port name (can be 'background', 'app', or 'content@\u003cname>-\u003cxxxxx>')\nconsole.log(bridge.portName)\n```\n\n::: warning Warning! Sending large amounts of data\nAll browser extensions have a hard limit on the amount of data that can be passed as communication messages (example: 50MB). If you exceed that amount on your payload, you can send chunks (**`payload` param should be an Array**).\n\n\u003cbr>\n\n```js\nbridge.send({\n event: 'some.event',\n to: 'app',\n payload: [chunk1, chunk2, ...chunkN]\n})\n```\n\n\u003cbr>\n\nWhen calculating the payload size, have in mind that the payload is wrapped in a message built by the Bridge that contains some other properties too. That takes a few bytes as well. So your chunks' size should be with a few bytes below the browser's threshold.\n:::\n\n::: warning Warning! Performance on sending an Array\nLike we've seen on the warning above, if `payload` is Array then the bridge will send a message for each of the Array's elements.\nWhen you actually want to send an Array (not split the payload into chunks), this will be **VERY** inefficient.\n\n\u003cbr>\n\nThe solution is to wrap your Array in an Object (so only one message will be sent):\n\n\u003cbr>\n\n```js\nbridge.send({\n event: 'some.event',\n to: 'background',\n payload: {\n myArray: [\n /*...*/\n ]\n }\n})\n```\n\n:::\n\nIf you encounter problems with sending messages between the BEX parts, you could enable the debug mode for the bridges that interest you. In doing so, the communication will also be outputted to the browser console:\n\n```js Bridge debug mode\n// Dynamically set debug mode\nbridge.setDebug(true) // boolean\n\n// Log a message on the console (if debug is enabled)\nbridge.log('Hello world!')\nbridge.log('Hello', 'world!')\nbridge.log('Hello world!', { some: 'data' })\nbridge.log('Hello', 'world', '!', { some: 'object' })\n// Log a warning on the console (regardless of the debug setting)\nbridge.warn('Hello world!')\nbridge.warn('Hello', 'world!')\nbridge.warn('Hello world!', { some: 'data' })\nbridge.warn('Hello', 'world', '!', { some: 'object' })\n```\n\n### Other /quasar.config file changes\n\nThe `ctx` from `/quasar.config` file has an additional prop (`appPaths`):\n\n```js\nimport { defineConfig } from '#q-app/wrappers'\nexport default defineConfig((ctx) => ({\n // ctx.appPaths is available\n```\n\nThe definition for `ctx.appPaths` is defined with QuasarAppPaths TS type as below:\n\n```diff\nexport interface IResolve {\n cli: (dir: string) => string;\n app: (dir: string) => string;\n src: (dir: string) => string;\n+ public: (dir: string) => string;\n pwa: (dir: string) => string;\n ssr: (dir: string) => string;\n cordova: (dir: string) => string;\n capacitor: (dir: string) => string;\n electron: (dir: string) => string;\n bex: (dir: string) => string;\n}\n\nexport interface QuasarAppPaths {\n cliDir: string;\n appDir: string;\n srcDir: string;\n+ publicDir: string;\n pwaDir: string;\n ssrDir: string;\n cordovaDir: string;\n capacitorDir: string;\n electronDir: string;\n bexDir: string;\n\n quasarConfigFilename: string;\n+ quasarConfigInputFormat: \"esm\" | \"cjs\" | \"ts\";\n+ quasarConfigOutputFormat: \"esm\" | \"cjs\";\n\n resolve: IResolve;\n}\n```\n\n```diff /quasar.config > sourceFiles\nsourceFiles: {\n+ bexManifestFile?: string;\n}\n```\n\n```diff /quasar.config > framework\nframework: {\n /**\n * Auto import - how to detect components in your vue files\n * \"kebab\": q-carousel q-page\n * \"pascal\": QCarousel QPage\n * \"combined\": q-carousel QPage\n * @default 'kebab'\n */\n autoImportComponentCase?: \"kebab\" | \"pascal\" | \"combined\";\n\n /**\n * Auto import - which file extensions should be interpreted as referring to Vue SFC?\n * @default [ 'vue' ]\n */\n+ autoImportVueExtensions?: string[];\n\n /**\n * Auto import - which file extensions should be interpreted as referring to script files?\n * @default [ 'js', 'jsx', 'ts', 'tsx' ]\n */\n+ autoImportScriptExtensions?: string[];\n\n /**\n * Treeshake Quasar's UI on dev too?\n * Recommended to leave this as false for performance reasons.\n * @default false\n */\n+ devTreeshaking?: boolean;\n+ // was previously under /quasar.conf > build\n}\n```\n\n```diff /quasar.config > build\nbuild: {\n /**\n * Treeshake Quasar's UI on dev too?\n * Recommended to leave this as false for performance reasons.\n * @default false\n */\n- devTreeshaking?: boolean;\n- // moved under /quasar.conf > framework\n\n /**\n * Should we invalidate the Vite and ESLint cache on startup?\n * @default false\n */\n- rebuildCache?: boolean;\n\n /**\n * Automatically open remote Vue Devtools when running in development mode.\n */\n+ vueDevtools?: boolean;\n\n /**\n * Folder where Quasar CLI should look for .env* files.\n * Can be an absolute path or a relative path to project root directory.\n *\n * @default project root directory\n */\n+ envFolder?: string;\n /**\n * Additional .env* files to be loaded.\n * Each entry can be an absolute path or a relative path to quasar.config > build > envFolder.\n *\n * @example ['.env.somefile', '../.env.someotherfile']\n */\n+ envFiles?: string[];\n}\n```\n\n### Other considerations\n\nYou might want to upgrade/switch from `@intlify/vite-plugin-vue-i18n` to the newer `@intlify/unplugin-vue-i18n`.\n\nAfter removing the old package and installing the new one then update your `/quasar.config` file as follows:\n\n```diff /quasar.config\n- import path from 'node:path'\n+ import { fileURLToPath } from 'node:url'\n\nexport default defineConfig((ctx) => {\n return {\n build: {\n vitePlugins: [\n- ['@intlify/vite-plugin-vue-i18n', {\n+ ['@intlify/unplugin-vue-i18n/vite', {\n- include: path.resolve(__dirname, './src/i18n/**')\n+ include: [ fileURLToPath(new URL('./src/i18n', import.meta.url)) ],\n+ ssr: ctx.modeName === 'ssr'\n }]\n ]\n }\n }\n})\n```\n\n### The env dotfiles support\n\nExpanding a bit on the env dotfiles support. These files will be detected and used (the order matters):\n\n```\n.env # loaded in all cases\n.env.local # loaded in all cases, ignored by git\n.env.[dev|prod] # loaded for dev or prod only\n.env.local.[dev|prod] # loaded for dev or prod only, ignored by git\n.env.[quasarMode] # loaded for specific Quasar CLI mode only\n.env.local.[quasarMode] # loaded for specific Quasar CLI mode only, ignored by git\n.env.[dev|prod].[quasarMode] # loaded for specific Quasar CLI mode and dev|prod only\n.env.local.[dev|prod].[quasarMode] # loaded for specific Quasar CLI mode and dev|prod only, ignored by git\n```\n\n...where \"ignored by git\" assumes a default project folder created after releasing this package, otherwise add `.env.local*` to your `/.gitignore` file.\n\nYou can also configure the files above to be picked up from a different folder or even add more files to the list:\n\n```js /quasar.config file\nbuild: {\n /**\n * Folder where Quasar CLI should look for .env* files.\n * Can be an absolute path or a relative path to project root directory.\n *\n * @default project root directory\n */\n envFolder?: string;\n\n /**\n * Additional .env* files to be loaded.\n * Each entry can be an absolute path or a relative path to quasar.config > build > envFolder.\n *\n * @example ['.env.somefile', '../.env.someotherfile']\n */\n envFiles?: string[];\n\n /**\n * Filter the env variables that are exposed to the client\n * through the env files. This does not account also for the definitions\n * assigned directly to quasar.config > build > env prop.\n *\n * Requires @quasar/app-vite v2.0.3+\n */\n envFilter?:\n (env: { [index: string]: string | boolean | undefined | null })\n => { [index: string]: string | boolean | undefined | null };\n}\n```\n\nRemember that you can filter out unwanted keys, or even change values for keys by using `build > envFilter`:\n\n```js /quasar.config file\nbuild: {\n // @quasar/app-vite v2.0.3+\n envFilter (originalEnv) {\n const newEnv = {}\n for (const key in originalEnv) {\n if (/* ...decide if it goes in or not... */) {\n newEnv[ key ] = originalEnv[ key ]\n }\n }\n\n // remember to return your processed env\n return newEnv\n }\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":48904,"content_sha256":"d95d4a9f7068f20cb26054b9d3c4d055bee81b2659f5fdff64faf11cc940254d"},{"filename":"references/docs/quasar-cli-webpack/ajax-requests.md","content":"---\ntitle: Ajax Requests\ndesc: (@quasar/app-webpack) Using Axios for fetching data in a Quasar app.\n---\n\n> We recommend selecting Axios during project initialization.\n\nIf you haven't selected Axios during the project initialization then you should create a new boot file `axios.js` that looks like this:\n(Here you can also specify additional settings for your axios instance)\n\n```js src/boot/axios.js\nimport { defineBoot } from '#q-app/wrappers'\nimport axios from 'axios'\n\nconst api = axios.create({ baseURL: 'https://api.example.com' })\n\nexport default defineBoot(({ app }) => {\n // for use inside Vue files (Options API) through this.$axios and this.$api\n\n app.config.globalProperties.$axios = axios\n // ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form)\n // so you won't necessarily have to import axios in each vue file\n\n app.config.globalProperties.$api = api\n // ^ ^ ^ this will allow you to use this.$api (for Vue Options API form)\n // so you can easily perform requests against your app's API\n})\n\nexport { axios, api }\n```\n\nAlso make sure to yarn/npm install the `axios` package.\n\n::: tip\nBe sure to check out [Prefetch Feature](/quasar-cli-webpack/prefetch-feature) if you are using Quasar CLI.\n:::\n\nUsage in your single file components methods will be like below. Notice that in the next example we're using the Quasar's [Notify plugin](/quasar-plugins/notify) (through `$q = useQuasar()` and `$q.notify`) which you'll need to install (follow the link earlier).\n\n```js\nimport { ref } from 'vue'\nimport { api } from 'boot/axios'\nimport { useQuasar } from 'quasar'\n\nsetup () {\n const $q = useQuasar()\n const data = ref(null)\n\n function loadData () {\n api.get('/api/backend')\n .then((response) => {\n data.value = response.data\n })\n .catch(() => {\n $q.notify({\n color: 'negative',\n position: 'top',\n message: 'Loading failed',\n icon: 'report_problem'\n })\n })\n }\n\n return { data, loadData }\n}\n```\n\nUsage in Pinia Actions for globally adding headers to axios (such as during authentication):\n\n```js\nimport { api } from 'boot/axios'\n\nexport const useAuthStore = defineStore('auth', {\n actions: {\n register (form) {\n return api.post('/auth/register', form)\n .then(response => {\n api.defaults.headers.common['Authorization'] = 'Bearer ' + response.data.token\n // do something with { token: response.data.token, user: response.data.user }\n })\n }\n})\n```\n\nAlso look at Axios docs for more information.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2567,"content_sha256":"16a1fa5f4f837006a3f0808000cccd521fa06b9e6ac484cf14458cdf0f1d306a"},{"filename":"references/docs/quasar-cli-webpack/api-proxying.md","content":"---\ntitle: API Proxying for Dev\ndesc: (@quasar/app-webpack) How to use an API proxy with the Quasar dev server.\nrelated:\n - /quasar-cli-webpack/quasar-config-file\n---\n\nWhen integrating a project folder (created by Quasar CLI) with an existing backend, a common need is to access the backend API when using the dev server. To achieve this, we can run the dev server and the API backend side-by-side (or remotely), and let the dev server proxy all API requests to the actual backend.\n\nThis is useful if you access relative paths in your API requests. Obviously, these relative paths will probably not work while you are developing. In order to create an environment similar to the one used by your deployed website/app, you can proxy your API requests.\n\nTo configure the proxy rules, edit the `/quasar.config` file in `devServer.proxy`. You should refer to Webpack Dev Server Proxy docs for detailed usage. But here's a simple example:\n\n```js /quasar.config file\ndevServer: {\n proxy: [\n // proxy all requests starting with /api to jsonplaceholder\n {\n context: ['/api'],\n target: 'http://some.api.target.com:7070',\n pathRewrite: { '^/api': '' },\n changeOrigin: true\n }\n ]\n}\n```\n\nThe above example will proxy the request `/api/posts/1` to `http://some.api.target.com:7070/posts/1`.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1310,"content_sha256":"f0f7d53f0ce6fb41e8eec562c3db5e77cc1b252d3da99414fdfb5643cef97d18"},{"filename":"references/docs/quasar-cli-webpack/boot-files.md","content":"---\ntitle: Boot files\ndesc: (@quasar/app-webpack) Managing your startup code in a Quasar app.\nrelated:\n - /quasar-cli-webpack/quasar-config-file\n---\n\nA common use case for Quasar applications is to **run code before the root Vue app instance is instantiated**, like injecting and initializing your own dependencies (examples: Vue components, libraries...) or simply configuring some startup code of your app.\n\nSince you won't have access to any `/main.js` file (so that Quasar CLI can seamlessly initialize and build same codebase for SPA/PWA/SSR/Cordova/Electron) Quasar provides an elegant solution to that problem by allowing users to define so-called boot files.\n\nIn earlier Quasar versions, to run code before the root Vue instance was instantiated, you could alter the `/src/main.js` file and add any code you needed to execute.\n\nThere is a major problem with this approach: with a growing project, your `main.js` file was very likely to get cluttered and challenging to maintain, which breaks with Quasar's concept of encouraging developers to write maintainable and elegant cross-platform applications.\n\nWith boot files, it is possible to split each of your dependencies into self-contained, easy to maintain files. It is also trivial to disable any of the boot files or even contextually determine which of the boot files get into the build through the `/quasar.config` file configuration.\n\n## Anatomy of a boot file\n\nA boot file is a simple JavaScript file which can optionally export a function. Quasar will then call the exported function when it boots the application and additionally pass **an object** with the following properties to the function:\n\n| Prop name | Description |\n| ------------ | ----------------------------------------------------------------------------------------------------------------- |\n| `app` | Vue app instance |\n| `router` | Instance of Vue Router from 'src/router/index.js' |\n| `store` | Instance of Pinia - **store only will be passed if your project uses Pinia (you have src/stores)** |\n| `ssrContext` | Available only on server-side, if building for SSR. [More info](/quasar-cli-webpack/developing-ssr/ssr-context) |\n| `urlPath` | The pathname (path + search) part of the URL. It also contains the hash on client-side. |\n| `publicPath` | The configured public path. |\n| `redirect` | Function to call to redirect to another URL. Accepts String (full URL) or a Vue Router location String or Object. |\n\n```js\nimport { defineBoot } from '#q-app/wrappers'\nexport default defineBoot(({ app, router, store }) => {\n // something to do\n})\n```\n\nBoot files can also be async:\n\n```js\nimport { defineBoot } from '#q-app/wrappers'\nexport default defineBoot(async ({ app, router, store }) => {\n // something to do\n await something()\n})\n```\n\nNotice the `defineBoot` import. This is essentially a no-op function, but its purpose is to help with a better IDE autocomplete experience:\n\n```js\nimport { defineBoot } from '#q-app/wrappers'\n\nexport default defineBoot(async ({ app, router, store }) => {\n // something to do\n await something()\n})\n```\n\nNotice we are using the ES6 destructuring assignment. Only assign what you actually need/use.\n\nYou may ask yourself why we need to export a function. This is actually optional, but before you decide to remove the default export, you need to understand when you need it:\n\n```js\n// Outside of default export:\n// - Code here gets executed immediately,\n// - Good place for import statements,\n// - No access to router, Pinia instance, ...\n\nexport default async ({ app, router, store }) => {\n // Code here has access to the Object param above, connecting\n // with other parts of your app;\n // Code here can be async (use async/await or directly return a Promise);\n // Code here gets executed by Quasar CLI at the correct time in app's lifecycle:\n // - we have a Router instantiated,\n // - we have the optional Pinia instance (store),\n // - we have the root app's component [\"app\" prop in Object param] Object with\n // which Quasar will instantiate the Vue app\n // (\"new Vue(app)\" -- do NOT call this by yourself),\n // - ...\n}\n```\n\n## When to use boot files\n\n::: warning\nPlease make sure you understand what problem boot files solve and when it is appropriate to use them, to avoid applying them in cases where they are not needed.\n:::\n\nBoot files fulfill one special purpose: they run code **before** the App's Vue root component is instantiated while giving you access to certain variables, which is required if you need to initialize a library, interfere with Vue Router, inject Vue prototype or inject the root instance of the Vue app.\n\n### Examples of appropriate usage of boot files\n\n- Your Vue plugin has installation instructions, like needing to call `app.use()` on it.\n- Your Vue plugin requires instantiation of data that is added to the root instance - An example would be vue-i18n.\n- You want to add a global mixin using `app.mixin()`.\n- You want to add something to the Vue app globalProperties for convenient access - An example would be to conveniently use `this.$axios` (for Options API) inside your Vue files instead of importing Axios in each such file.\n- You want to interfere with the router - An example would be to use `router.beforeEach` for authentication\n- You want to interfere with the Pinia instance\n- Configure aspects of libraries - An example would be to create an instance of Axios with a base URL; you can then inject it into Vue prototype and/or export it (so you can import the instance from anywhere else in your app)\n\n### Example of unneeded usage of boot files\n\n- For plain JavaScript libraries like Lodash, which don't need any initialization prior to their usage. Lodash, for example, might make sense to use as a boot file only if you want to inject Vue prototype with it, like being able to use `this.$_` inside your Vue files.\n\n## Usage of boot files\n\nThe first step is always to generate a new boot file using Quasar CLI:\n\n```bash\n$ quasar new boot \u003cname> [--format ts]\n```\n\nWhere `\u003cname>` should be exchanged by a suitable name for your boot file.\n\nThis command creates a new file: `/src/boot/\u003cname>.js` with the following content:\n\n```js\n// import something here\n\n// \"async\" is optional!\n// remove it if you don't need it\nexport default defineBoot(\n async (\n {\n /* app, router, store */\n }\n ) => {\n // something to do\n }\n)\n```\n\nYou can also return a Promise:\n\n```js\n// import something here\n\nexport default defineBoot(\n (\n {\n /* app, router, store */\n }\n ) => {\n return new Promise((resolve, reject) => {\n // do something\n })\n }\n)\n```\n\n::: tip\nThe default export can be left out of the boot file if you don't need it. These are the cases where you don't need to access the \"app\", \"router\", \"store\" and so on.\n:::\n\nYou can now add content to that file depending on the intended use of your boot file.\n\n> Do not forget that your default export needs to be a function.\n> However, you can have as many named exports as you want, should the boot file expose something for later usage. In this case, you can import any of these named exports anywhere in your app.\n\nThe last step is to tell Quasar to use your new boot file. For this to happen you need to add the file in the `/quasar.config` file:\n\n```js\nboot: [\n // references /src/boot/\u003cname>.js\n '\u003cname>'\n]\n```\n\nWhen building a SSR app, you may want some boot files to run only on the server or only on the client, in which case you can do so like below:\n\n```js\nboot: [\n {\n server: false, // run on client-side only!\n path: '\u003cname>' // references /src/boot/\u003cname>.js\n },\n {\n client: false, // run on server-side only!\n path: '\u003cname>' // references /src/boot/\u003cname>.js\n }\n]\n```\n\nIn case you want to specify boot files from node_modules, you can do so by prepending the path with `~` (tilde) character:\n\n```js\nboot: [\n // boot file from an npm package\n '~my-npm-package/some/file'\n]\n```\n\nIf you want a boot file to be injected into your app only for a specific build type:\n\n```js\nboot: [ctx.mode.electron ? 'some-file' : '']\n```\n\n### Redirecting to another page\n\n::: warning\nPlease be mindful when redirecting as you might configure the app to go into an infinite redirect loop.\n:::\n\n```js\nexport default defineBoot(({ urlPath, redirect }) => {\n // ...\n const isAuthorized = // ...\n if (!isAuthorized && !urlPath.startsWith('/login')) {\n redirect({ path: '/login' })\n return\n }\n // ...\n})\n```\n\nThe `redirect()` method accepts a String (full URL) or a Vue Router location String or Object. On SSR it can receive a second parameter which should be a Number for any of the HTTP STATUS codes that redirect the browser (3xx ones).\n\n```js\n// Examples for redirect() with a Vue Router location:\nredirect('/1') // Vue Router location as String\nredirect({ path: '/1' }) // Vue Router location as Object\n\n// Example for redirect() with a URL:\nredirect('https://quasar.dev')\n```\n\n::: warning IMPORTANT!\nThe Vue Router location (in String or Object form) does not refer to URL path (and hash), but to the actual Vue Router routes that you have defined.\nSo **don't add the publicPath** to it and if you're using the Vue Router hash mode then don't add the hash to it.\n\n\u003cbr>Let's say that we have this Vue Router route defined:\u003cbr>\u003cbr>\n\n```js\n{\n path: '/one',\n component: PageOne\n}\n```\n\n\u003cbr>Then **regardless of our publicPath** we can call `redirect()` like this:\u003cbr>\u003cbr>\n\n```js\n// publicPath: /wiki; vueRouterMode: history\nredirect('/one') // good way\nredirect({ path: '/one' }) // good way\nredirect('/wiki/one') // WRONG!\n\n// publicPath: /wiki; vueRouterMode: hash\nredirect('/one') // good way\nredirect({ path: '/one' }) // good way\nredirect('/wiki/#/one') // WRONG!\n\n// no publicPath; vueRouterMode: hash\nredirect('/one') // good way\nredirect({ path: '/one' }) // good way\nredirect('/#/one') // WRONG!\n```\n\n:::\n\nAs it was mentioned in the previous sections, the default export of a boot file can return a Promise. If this Promise gets rejected with an Object that contains a \"url\" property, then Quasar CLI will redirect the user to that URL:\n\n```js\nexport default defineBoot(({ urlPath }) => {\n return new Promise((resolve, reject) => {\n // ...\n const isAuthorized = // ...\n if (!isAuthorized && !urlPath.startsWith('/login')) {\n // the \"url\" param here is of the same type\n // as for \"redirect\" above\n reject({ url: '/login' })\n return\n }\n // ...\n })\n})\n```\n\nOr a simpler equivalent:\n\n```js\nexport default defineBoot(() => {\n // ...\n const isAuthorized = // ...\n if (!isAuthorized && !urlPath.startsWith('/login')) {\n return Promise.reject({ url: '/login' })\n }\n // ...\n})\n```\n\n### Quasar App Flow\n\nIn order to better understand how a boot file works and what it does, you need to understand how your website/app boots:\n\n1. Quasar is initialized (components, directives, plugins, Quasar i18n, Quasar icon sets)\n2. Quasar Extras get imported (Roboto font -- if used, icons, animations, ...)\n3. Quasar CSS & your app's global CSS are imported\n4. App.vue is loaded (not yet being used)\n5. Pinia (if using) is injected into the Vue app instance\n6. Router is imported (in src/router)\n7. Boot files are imported\n8. Router default export function executed\n9. Boot files get their default export function executed\n10. (if on Electron mode) Electron is imported and injected into Vue prototype\n11. (if on Cordova mode) Listening for \"deviceready\" event and only then continuing with following steps\n12. Instantiating Vue with root component and attaching to DOM\n\n## Examples of boot files\n\n### Axios\n\n```js\nimport { defineBoot } from '#q-app/wrappers'\nimport axios from 'axios'\n\nconst api = axios.create({ baseURL: 'https://api.example.com' })\n\nexport default defineBoot(({ app }) => {\n // for use inside Vue files (Options API) through this.$axios and this.$api\n\n app.config.globalProperties.$axios = axios\n // ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form)\n // so you won't necessarily have to import axios in each vue file\n\n app.config.globalProperties.$api = api\n // ^ ^ ^ this will allow you to use this.$api (for Vue Options API form)\n // so you can easily perform requests against your app's API\n})\n\nexport { axios, api }\n```\n\n### vue-i18n\n\n```js\nimport { defineBoot } from '#q-app/wrappers'\nimport { createI18n } from 'vue-i18n'\nimport messages from 'src/i18n'\n\nexport default defineBoot(({ app }) => {\n // Create I18n instance\n const i18n = createI18n({\n locale: 'en-US',\n messages\n })\n\n // Tell app to use the I18n instance\n app.use(i18n)\n})\n```\n\n### Router authentication\n\nSome boot files might need to interfere with Vue Router configuration:\n\n```js\nimport { defineBoot } from '#q-app/wrappers'\n\nexport default defineBoot(({ router, store }) => {\n router.beforeEach((to, from, next) => {\n // Now you need to add your authentication logic here, like calling an API endpoint\n })\n})\n```\n\n## Accessing data from boot files\n\nSometimes you want to access data that you configure in your boot file in files where you don't have access to the root Vue instance.\n\nFortunately, because boot files are just normal JavaScript files you can add as many named exports to your boot file as you want.\n\nLet's take the example of Axios. Sometimes you want to access your Axios instance inside your JavaScript files, but you cannot access the root Vue instance. To solve this you can export the Axios instance in your boot file and import it elsewhere.\n\nConsider the following boot file for axios:\n\n```js Axios boot file (src/boot/axios.js)\nimport axios from 'axios'\n\n// We create our own axios instance and set a custom base URL.\n// Note that if we wouldn't set any config here we do not need\n// a named export, as we could just `import axios from 'axios'`\nconst api = axios.create({\n baseURL: 'https://api.example.com'\n})\n\n// for use inside Vue files through this.$axios and this.$api\n// (only in Vue Options API form)\nexport default defineBoot(({ app }) => {\n app.config.globalProperties.$axios = axios\n app.config.globalProperties.$api = api\n})\n\n// Here we define a named export\n// that we can later use inside .js files:\nexport { axios, api }\n```\n\nIn any JavaScript file, you'll be able to import the axios instance like this.\n\n```js\n// we import one of the named exports from src/boot/axios.js\nimport { api } from 'boot/axios'\n```\n\nFurther reading on syntax: ES6 import, ES6 export.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":14857,"content_sha256":"7599def232bd79e8994265c8195354d0beaca90245ad1985149dd51635728357"},{"filename":"references/docs/quasar-cli-webpack/browser-compatibility.md","content":"---\ntitle: Browser compatibility\ndesc: (@quasar/app-webpack) How to handle the browser support with Quasar CLI.\nrelated:\n - /quasar-cli-webpack/quasar-config-file\n---\n\n## Configuring compatibility\n\nYour `/package.json` file should contain a `browserslist` field. This will tell Quasar App the range of browsers that the project is targeting. Babel and Autoprefixer will use this field to determine how to transpile JS code (if transpiling is left enabled) and what CSS vendor prefixes it needs to add your CSS code.\n\nBabel will look for exactly the JS features that need transpiling (based on the configured browsers) and apply them. Be mindful about it though, as it is sufficient to add one \"bad apple\" in the options list and that will dumb down your code back to ES5.\n\nThe following is the default \"browserslist\" when you create a Quasar project:\n\n```js package.json\n\"browserslist\": [\n \"last 10 Chrome versions\",\n \"last 10 Firefox versions\",\n \"last 4 Edge versions\",\n \"last 7 Safari versions\",\n \"last 8 Android versions\",\n \"last 8 ChromeAndroid versions\",\n \"last 8 FirefoxAndroid versions\",\n \"last 10 iOS versions\",\n \"last 5 Opera versions\"\n]\n```\n\nMore info on how to specify browser ranges: browserslist.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1220,"content_sha256":"c46559d46e2c534cfca6aa7f230bfdc9bc52cc1a8f55a59d55b3f260362a852c"},{"filename":"references/docs/quasar-cli-webpack/commands-list.md","content":"---\ntitle: Commands List\ndesc: (@quasar/app-webpack) The entire list of Quasar CLI commands.\n---\n\nFamiliarize yourself with the list of available commands inside a Quasar project:\n\n```bash\n$ quasar -h\n\n Example usage\n $ quasar \u003ccommand> \u003coptions>\n\n Help for a command\n $ quasar \u003ccommand> --help\n $ quasar \u003ccommand> -h\n\n Options\n --version, -v Print Quasar App CLI version\n\n Commands\n dev, d Start a dev server for your App\n build, b Build your app for production\n prepare, p Prepare the app for linting, type-checking, IDE integration, etc.\n clean, c Clean dev/build cache, /dist folder & entry points\n new, n Quickly scaffold page/layout/component/... vue file\n mode, m Add/remove Quasar Modes for your App\n inspect Inspect Webpack/Esbuild configs used under the hood\n - keeps into account your quasar.config file\n and your installed App Extensions\n ext, e Manage Quasar App Extensions\n run, r Run specific command provided by an installed\n Quasar App Extension\n describe Describe a Quasar API (component)\n info, i Display info about your machine and your App\n help, h Displays this message\n\n If the specified command is not found, then \"quasar run\"\n will be executed with the provided arguments.\n\n Commands supplied by @quasar/cli global installation:\n\n upgrade Check (and optionally) upgrade Quasar packages\n from a Quasar project folder\n serve Create an ad-hoc server on App's distributables\n```\n\nSee help for any command:\n\n```bash\n$ quasar [command name] --help\n```\n\n## Upgrade\n\nCheck (and optionally) upgrade Quasar packages from a Quasar project folder:\n\n```bash\n# view all options:\n$ quasar upgrade -h\n\n# checks for non-breaking change upgrades and displays them,\n# but will not carry out the install\n$ quasar upgrade\n\n# checks for pre-releases (alpha/beta):\n$ quasar upgrade -p\n\n# checks for major new releases (includes breaking changes):\n$ quasar upgrade -m\n\n# use another npm registry url than what your machine is configured with:\n# (added in @quasar/cli v2.4)\n$ quasar upgrade -r https://registry.npmjs.org/\n\n# to perform the actual upgrade,\n# combine any of the params above and add \"-i\" (or \"--install\"):\n$ quasar upgrade -i\n```\n\n::: warning Note for code editor terminals\nIf you're using a code editor terminal instead of the real one, you run `quasar upgrade` and get an error _Command not found_ or _@quasar/cli_ version appears to be _undefined_, you will need to go to the settings of your code editor terminal and untick the option (or its equivalent) _Add 'node_modules/.bin' from the project root to %PATH%_ then restart your code editor.\n:::\n\n## Info\n\nThe Quasar CLI is equipped with a stable combination of multiple NPM build packages (Webpack, Vue, etc) which gets updated frequently after heavy testing.\n\nIn order for you to see what versions of Node, Quasar CLI, Quasar, Vue (and many others) you are using, issue this command in a Quasar project folder:\n\n```bash\n$ quasar info\n```\n\n## Dev\n\n```bash\n$ quasar dev -h\n\n Description\n Starts the app in development mode (hot-code reloading, error\n reporting, etc)\n\n Usage\n $ quasar dev\n $ quasar dev -p \u003cport number>\n\n $ quasar dev -m ssr\n\n # alias for \"quasar dev -m capacitor -T ios\"\n $ quasar dev -m ios\n\n # alias for \"quasar dev -m capacitor -T android\"\n $ quasar dev -m android\n\n # passing extra parameters and/or options to\n # underlying \"cordova\" or \"electron\" executables:\n $ quasar dev -m cordova -T ios -- some params --and options --here\n $ quasar dev -m electron -- --no-sandbox --disable-setuid-sandbox\n # when on Windows and using Powershell:\n $ quasar dev -m cordova -T ios '--' some params --and options --here\n $ quasar dev -m electron '--' --no-sandbox --disable-setuid-sandbox\n\n Options\n --mode, -m App mode [spa|ssr|pwa|cordova|capacitor|electron|bex] (default: spa)\n --port, -p A port number on which to start the application\n --devtools, -d Open remote Vue Devtools\n --hostname, -H A hostname to use for serving the application\n --help, -h Displays this message\n\n Only for Cordova mode:\n --target, -T (required) App target [android|ios]\n --emulator, -e (optional) Emulator name\n Examples: iPhone-7, iPhone-X\n iPhone-X,com.apple.CoreSimulator.SimRuntime.iOS-12-2\n --ide, -i Open IDE (Android Studio / XCode) instead of letting Cordova\n boot up the emulator / building in terminal, in which case\n the \"--emulator\" param will have no effect\n\n Only for Capacitor mode:\n --target, -T (required) App target [android|ios]\n\n Only for BEX mode:\n --target, -T (required) Browser family target [chrome|firefox]\n```\n\nThe Quasar development server allows you to develop your App by compiling and maintaining code in-memory. A web server will serve your App while offering hot-reload out of the box. Running in-memory offers faster rebuilds when you change your code.\n\n> Hot Reload is much more than just refreshing your browser when code changes. It skips the refresh and updates your code on the fly, while maintaining your App's state (like your Vue's model data). Please note that there are cases when this is impossible, so the dev webserver will simply refresh your browser. (Always ensure you are running only one instance of Quasar CLI at a time, otherwise Hot-Reload and other stuff will break!)\n\nBased on what you want to develop, you can start the development server by using \"quasar dev\" command as follows:\n\n```bash\n# Developing a SPA\n$ quasar dev\n# ...or\n$ quasar dev -m spa\n\n# Developing for SSR\n$ quasar dev -m ssr\n\n# Developing a PWA\n$ quasar dev -m pwa\n\n# Developing a BEX for production\n$ quasar dev -m bex\n\n# Developing a Mobile App (through Cordova)\n$ quasar dev -m cordova -T [android|ios]\n# or the short form:\n$ quasar dev -m [android|ios]\n\n# Developing an Electron App\n$ quasar dev -m electron\n\n# Developing a Browser Extension (BEX)\n$ quasar dev -m bex -T [chrome|firefox]\n\n# passing extra parameters and/or options to\n# underlying \"cordova\" or \"electron\" executables:\n$ quasar dev -m ios -- some params --and options --here\n$ quasar dev -m electron -- --no-sandbox --disable-setuid-sandbox\n# when on Windows and using Powershell:\n$ quasar dev -m ios '--' some params --and options --here\n$ quasar dev -m electron '--' --no-sandbox --disable-setuid-sandbox\n```\n\nIf you wish to change the hostname or port serving your App you have 3 options:\n\n- Edit the `/quasar.config` file:\n ```js\n devServer: {\n host: '...',\n port: ...\n }\n ```\n- Through '-H' (hostname) and '-p' (port) command options.\n- If this is a one time thing, specify the hostname and/or port as an environment variable:\n ```bash\n $ PORT=3000 quasar dev\n $ HOSTNAME=1.1.1.14 quasar dev\n ```\n\nIf there appears to be an issue with hot reload, you can try two fixes:\n\n- Change the permissions for the project folder with\n\n ```bash\n sudo chown -R username: .\n ```\n\n- or run the dev server with root privileges\n\n ```bash\n sudo quasar dev\n ```\n\n## Build\n\n```bash\n$ quasar build -h\n\n Description\n Builds distributables of your app.\n\n Usage\n $ quasar build\n $ quasar build -p \u003cport number>\n\n $ quasar build -m ssr\n\n # alias for \"quasar build -m cordova -T ios\"\n $ quasar build -m ios\n\n # alias for \"quasar build -m cordova -T android\"\n $ quasar build -m android\n\n # passing extra parameters and/or options to\n # underlying \"cordova\" executable:\n $ quasar build -m ios -- some params --and options --here\n # when on Windows and using Powershell:\n $ quasar build -m ios '--' some params --and options --here\n\n Options\n --mode, -m App mode [spa|ssr|pwa|cordova|capacitor|electron|bex] (default: spa)\n --target, -T App target\n - Cordova (default: all installed)\n [android|ios]\n - Capacitor\n [android|ios]\n - Electron with default \"@electron/packager\" bundler (default: yours)\n [darwin|win32|linux|mas|all]\n - Electron with \"electron-builder\" bundler (default: yours)\n [darwin|mac|win32|win|linux|all]\n - Bex\n [chrome|firefox]\n --publish, -P Also trigger publishing hooks (if any are specified)\n - Has special meaning when building with Electron mode and using\n electron-builder as bundler\n --debug, -d Build for debugging purposes\n --skip-pkg, -s Build only UI (skips creating Cordova/Capacitor/Electron executables)\n - Cordova (it only fills in /src-cordova/www folder with the UI code)\n - Capacitor (it only fills in /src-capacitor/www folder with the UI code)\n - Electron (it only creates the /dist/electron/UnPackaged folder)\n --help, -h Displays this message\n\n ONLY for Cordova and Capacitor mode:\n --ide, -i Open IDE (Android Studio / XCode) instead of finalizing with a\n terminal/console-only build\n\n ONLY for Electron mode:\n --bundler, -b Bundler (@electron/packager or electron-builder)\n [packager|builder]\n --arch, -A App architecture (default: yours)\n - with default \"@electron/packager\" bundler:\n [ia32|x64|armv7l|arm64|mips64el|all]\n - with \"electron-builder\" bundler:\n [ia32|x64|armv7l|arm64|all]\n\n ONLY for electron-builder (when using \"publish\" parameter):\n --publish, -P Publish options [onTag|onTagOrDraft|always|never]\n - see https://www.electron.build/configuration/publish\n\n Only for BEX mode:\n --target, -T (required) Browser family target [chrome|firefox]\n```\n\nThe Quasar CLI can pack everything together and optimize your App for production. It minifies source code, extracts vendor components, leverages browser cache and much more.\n\n```bash\n# Build a SPA for production\n$ quasar build\n# ...or\n$ quasar build -m spa\n\n# Build a SSR for production\n$ quasar build -m ssr\n\n# Build a PWA for production\n$ quasar build -m pwa\n\n# Build a BEX for production\n$ quasar build -m bex -T [chrome|firefox]\n\n# Build a Mobile App (through Cordova)\n$ quasar build -m cordova -T [android|ios]\n# or the short form:\n$ quasar build -m [android|ios]\n\n# Build an Electron App for production\n$ quasar build -m electron\n\n# passing extra parameters and/or options to\n# underlying \"cordova\" executable:\n$ quasar build -m ios -- some params --and options --here\n# when on Windows and using Powershell:\n$ quasar build -m ios '--' some params --and options --here\n\n# Create a production build with ability to debug it\n# (has source-maps and code is NOT minified)\n$ quasar build -d [-m \u003cmode>]\n```\n\n## Prepare\n\nPrepares your project folder for the IDE, making autocompletion and other IDE features work correctly.\n\n```bash\n$ quasar prepare\n```\n\n## Clean\n\nCleans up all the build assets:\n\n```bash\n$ quasar clean\n# requires \"quasar prepare\" to be called again\n```\n\n## New\n\nGenerates Components, Pages, Layouts, Pinia Store.\n\n::: tip\nThis command is simply a helper in order to quickly scaffold a page/layout/component/pinia store module. You are not required to use it, but can help you when you don't know how to start.\n:::\n\n```bash\n$ quasar new -h\n\n Description\n Quickly scaffold files.\n\n Usage\n $ quasar new \u003cp|page> [-f \u003cjs|ts>] \u003cpage_file_name>\n $ quasar new \u003cl|layout> [-f \u003cjs|ts>] \u003clayout_file_name>\n $ quasar new \u003cc|component> [-f \u003cjs|ts>] \u003ccomponent_file_name>\n $ quasar new \u003cb|boot> [-f \u003cjs|ts>] \u003cboot_name>\n $ quasar new \u003cs|store> [-f \u003cjs|ts>] \u003cstore_module_name>\n $ quasar new ssrmiddleware [-f \u003cjs|ts>] \u003cmiddleware_name>\n\n Examples\n # Create src/pages/MyNewPage.vue:\n $ quasar new p MyNewPage\n\n # Create src/pages/MyNewPage.vue and src/pages/OtherPage.vue:\n $ quasar new p MyNewPage OtherPage\n\n # Create src/layouts/shop/Checkout.vue\n $ quasar new layout shop/Checkout.vue\n\n # Create src/layouts/shop/Checkout.vue (forcing TypeScript)\n $ quasar new layout -f ts shop/Checkout.vue\n\n # Create a store with TypeScript (-f ts is optional if tsconfig.json is present)\n $ quasar new store -f ts myStore\n\n Options\n --help, -h Displays this message\n\n --format -f \u003coption> (optional) Use a supported format for the template.\n This gets inferred automatically for your project.\n Possible overriding values:\n * js - JS template\n * ts - TS template\n```\n\n## Mode\n\n```bash\n$ quasar mode -h\n\n Description\n Add/Remove support for PWA / BEX / Cordova / Capacitor / Electron modes.\n\n Usage\n $ quasar mode [add|remove] [pwa|ssr|bex|cordova|capacitor|electron] [--yes]\n\n # determine what modes are currently installed:\n $ quasar mode\n\n Options\n --yes, -y Skips the \"Are you sure?\" question\n when removing a Quasar mode\n --help, -h Displays this message\n```\n\nWhen you initialize a project with the CLI, you can build SPA (Single Page Website/Application), SSR (Server-side Render Website/Application with optional PWA client takeover), PWA (Progressive Web App), Mobile App (through Cordova), and/or Electron Apps. When you develop for SSR, PWA, Cordova or Electron, you need these modes installed. If you issue \"quasar dev\" or \"quasar build\" they will automatically be installed.\n\nThese modes will add a \"src-\\*\" folder into your project with very specific code for it:\n\n| Folder | Mode | Description |\n| ------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| src-ssr | ssr | Contains the production Node.js server files. |\n| src-pwa | pwa | Contains the Service Worker file that you can tweak. |\n| src-cordova | cordova | Is a Cordova project folder that will be using your 'src' as content. Tweak Cordova config, add/remove platforms, splash screens, Cordova plugins and so on from this folder. Do NOT touch \"src-cordova/www\" folder though as it will get overwritten at every build. |\n| src-electron | electron | Has code for the main Electron thread. The renderer thread will be your app in 'src'. |\n| src-bex | bex | Contains the specific files for Browser Extensions mode. |\n\nIf for some reason you decide you don't need a mode, you can remove it. **This will permanently delete** the respective \"src-\\*\" folder.\n\n```bash\n$ quasar mode remove pwa\n```\n\n## Describe\n\nThis command is useful to describe the API of any Quasar components/directives/plugins that your project is using. **It is specific to your Quasar version installed in your project folder.**\n\nExamples: `$ quasar describe QIcon`, `$ quasar describe TouchPan`, `$ quasar describe Cookies`.\n\n```bash\n$ quasar describe -h\n\n Description\n Describes a component API for project's Quasar version being used\n\n Usage\n $ quasar describe \u003ccomponent/directive/Quasar plugin>\n\n # list all available API entries:\n $ quasar describe list\n # list available API entries that contain a String (ex \"storage\"):\n $ quasar describe list storage\n\n # display everything:\n $ quasar describe QIcon\n\n # displaying only props:\n $ quasar describe QIcon -p\n # displaying props and methods only:\n $ quasar describe QIcon -p -m\n # filtering by \"si\":\n $ quasar describe QIcon -f si\n # filtering only props by \"co\":\n $ quasar describe QIcon -p -f co\n\n # Open docs URL:\n $ quasar describe QIcon -d\n\n Options\n --filter, -f \u003cfilter> Filters the API\n --props, -p Displays the API props\n --slots, -s Displays the API slots\n --events, -e Displays the API events\n --methods, -m Displays the API methods\n --computedProps, -c Displays the API computed props\n --value, -v Displays the API value\n --arg, -a Displays the API arg\n --modifiers, -M Displays the API modifiers\n --injection, -i Displays the API injection\n --quasar, -q Displays the API quasar conf options\n --docs, -d Opens the docs API URL\n --help, -h Displays this message\n```\n\n```bash\n$ quasar describe QIcon\n\n Describing QIcon component API\n Description is based on your project's Quasar version\n\n Properties\n\n name (String)\n Description: Name of the icon, following Quasar convention\n Examples:\n map\n ion-add\n\n color (String)\n Description: Color name for component from the Quasar Color Palette\n Examples:\n primary\n teal-10\n\n size (String)\n Description: Size in CSS units, including unit name\n Examples:\n 16px\n 2rem\n\n left (Boolean)\n Description: Apply a standard margin on the left side. Useful if icon is on the right side of something.\n\n right (Boolean)\n Description: Apply a standard margin on the right side. Useful if icon is on the left side of something.\n\n Slots\n\n default\n Suggestions: QTooltip or QMenu\n\n Scoped Slots\n\n *No scoped slots*\n\n Events\n\n *No events*\n\n Methods\n\n *No methods*\n```\n\n## Inspect\n\nThis command can be used to inspect the Webpack config generated by Quasar CLI.\n\n```bash\n$ quasar inspect -h\n\n Description\n Inspect Quasar generated Webpack/Esbuild config\n\n Usage\n $ quasar inspect\n $ quasar inspect -c build\n $ quasar inspect -m electron -p 'build.outDir'\n\n Options\n --cmd, -c Quasar command [dev|build] (default: dev)\n --mode, -m App mode [spa|ssr|pwa|bex|cordova|capacitor|electron] (default: spa)\n --depth, -d Number of levels deep (default: 2)\n --path, -p Path of config in dot notation\n Examples:\n -p module.rules\n -p plugins\n --thread, -t Display only one specific app mode config thread\n --help, -h Displays this message\n```\n\n## Ext\n\nThis command is used to manage [App Extensions](/app-extensions/introduction).\n\n```bash\n$ quasar ext -h\n\n Description\n Manage Quasar App Extensions\n\n Usage\n # display list of installed extensions\n $ quasar ext\n\n # Add Quasar App Extension\n $ quasar ext add \u003cext-id>\n\n # Remove Quasar App Extension\n $ quasar ext remove \u003cext-id>\n\n # Add Quasar App Extension, but\n # skip installing the npm package\n # (assumes it's already installed)\n $ quasar ext invoke \u003cext-id>\n\n # Remove Quasar App Extension, but\n # skip uninstalling the npm package\n $ quasar ext uninvoke \u003cext-id>\n\n Options\n --help, -h Displays this message\n```\n\n## Run\n\nThis command is used to run commands supplied by the [App Extensions](/app-extensions/introduction) that you've installed into your project folder.\n\n```bash\n$ quasar run -h\n\n Description\n Run app extension provided commands\n\n Usage\n $ quasar run \u003cextension-id> \u003ccmd> [args, params]\n $ quasar \u003cextension-id> \u003ccmd> [args, params]\n\n $ quasar run iconify create pic -s --mark some_file\n $ quasar iconify create pic -s --mark some_file\n # Note: \"iconify\" is an example and not a real extension.\n # Looks for installed extension called \"iconify\"\n # (quasar-app-extension-iconify extension package)\n # and runs its custom defined \"create\" command\n # with \"pic\" argument and \"-s --mark some_file\" params\n\n Options\n --help, -h Displays this message\n```\n\n## Serve\n\nThis command can be used in production too and it is being supplied by the global installation of `@quasar/cli` package.\n\n```bash\n$ quasar serve -h\n\n Description\n Start a HTTP(S) server on a folder.\n\n Usage\n $ quasar serve [path]\n $ quasar serve . # serve current folder\n\n If you serve a SSR folder built with the CLI then\n control is yielded to /index.js and params have no effect.\n\n Options\n --port, -p Port to use (default: 4000)\n --hostname, -H Address to use (default: 0.0.0.0)\n --gzip, -g Compress content (default: true)\n --silent, -s Suppress log message\n --colors Log messages with colors (default: true)\n --open, -o Open browser window after starting\n --cache, -c \u003cnumber> Cache time (max-age) in seconds;\n Does not apply to /service-worker.js\n (default: 86400 - 24 hours)\n --micro, -m \u003cseconds> Use micro-cache (default: 1 second)\n\n --history Use history api fallback;\n All requests fallback to /index.html,\n unless using \"--index\" parameter\n --index, -i \u003cfile> History mode (only!) index url path\n (default: index.html)\n\n --https Enable HTTPS\n --cert, -C [path] Path to SSL cert file (Optional)\n --key, -K [path] Path to SSL key file (Optional)\n --proxy \u003cfile.mjs> Proxy specific requests defined in file;\n File must export Array ({ path, rule })\n See example below. \"rule\" is defined at:\n https://github.com/chimurai/http-proxy-middleware\n --cors Enable CORS for all requests\n --help, -h Displays this message\n\n Proxy file example\n export default [\n {\n path: '/api',\n rule: { target: 'http://www.example.org' }\n }\n ]\n --> will be transformed into app.use(path, httpProxyMiddleware(rule))\n```\n\n### Custom Node server\n\nWhen building a SPA or PWA, the distributable folder can be served by any static webserver. To test it out (assuming you don't have a specific publicPath or not using Vue Router \"history\" mode), you can use the \"http-server\" npm package.\n\nOr you can build your own server. Here are some examples:\n\n```js\n// when using default Vue Router \"hash\" mode\nimport express from 'express'\nimport serveStatic from 'serve-static'\n\nconst port = process.env.PORT || 5000\nconst app = express()\n\napp.use(serveStatic(...path-to-dist...))\napp.listen(port)\n```\n\n```js\n// when using Vue Router \"history\" mode\nimport express from 'express'\nimport serveStatic from 'serve-static'\nimport history from 'connect-history-api-fallback'\n\nconst port = process.env.PORT || 5000\nconst app = express()\n\napp.use(history())\napp.use(serveStatic(...path-to-dist...))\napp.listen(port)\n```\n\nIf you need URL rewrites of API, or simply put you want to proxy your API requests, then you can use \"http-proxy-middleware\" package:\n\n```js\n// add this to one of the two previous examples:\nimport { createProxyMiddleware } from 'http-proxy-middleware'\n\n// ...\napp.use(\n '/api',\n createProxyMiddleware({\n target: `http://my-api.com:5050`,\n pathRewrite: { '^/api': '' }\n })\n)\n\n// then app.listen(...)\n```\n\nFinally, run one of these files:\n\n```bash\n$ node my-server.js\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":24506,"content_sha256":"d6d6d95b2fc9a862262b323cd0048413e949d9e8ba8ff2611f6be8779e888a68"},{"filename":"references/docs/quasar-cli-webpack/convert-to-quasar-cli-with-webpack.md","content":"---\ntitle: Convert project to Quasar CLI with Webpack\ndesc: (@quasar/app-webpack) How to convert a Quasar CLI with Vite project to a Quasar CLI with Webpack one.\n---\n\nThis page will guide you on how to convert a Quasar CLI with Vite (`@quasar/app-vite v2`) project into a Quasar CLI with Webpack one (`@quasar/app-webpack v4`).\n\n### Step 1: Edit package.json\n\n```diff /package.json\ndependencies: {\n+ \"core-js\": \"^3.6.5\",\n},\n\ndevDependencies: {\n- \"@quasar/app-vite\": \"^2.0.0\"\n+ \"@quasar/app-webpack\": \"^4.0.0\"\n\n+ \"eslint-webpack-plugin\": \"^4.0.1\",\n+ \"ts-loader\": \"^9.4.2\", // if using TS\n\n- \"postcss\"\n- \"postcss-rtlcss\"\n\n// if you have PWA mode:\n+ \"workbox-webpack-plugin\": \"^7.0.0\"\n- \"workbox-build\": \"^7.0.0\",\n- \"workbox-cacheable-response\": \"^7.0.0\",\n- \"workbox-core\": \"^7.0.0\",\n- \"workbox-expiration\": \"^7.0.0\",\n- \"workbox-precaching\": \"^7.0.0\",\n- \"workbox-routing\": \"^7.0.0\",\n- \"workbox-strategies\": \"^7.0.0\"\n}\n\n+ \"browserslist\": [\n+ \"last 10 Chrome versions\",\n+ \"last 10 Firefox versions\",\n+ \"last 4 Edge versions\",\n+ \"last 7 Safari versions\",\n+ \"last 8 Android versions\",\n+ \"last 8 ChromeAndroid versions\",\n+ \"last 8 FirefoxAndroid versions\",\n+ \"last 10 iOS versions\",\n+ \"last 5 Opera versions\"\n+ ],\n```\n\nRemember to yarn/npm/pnpm/bun install.\n\nA Quasar CLI with Webpack project relies on `/package.json > browserslist` to specify which browsers you are targeting. More info: [Browser Compatibility](/quasar-cli-webpack/browser-compatibility) page.\n\n### Step 2: Various files\n\n- Create `/babel.config.js`:\n\n ```js\n export default api => {\n return {\n presets: [\n [\n '@quasar/babel-preset-app',\n api.caller(caller => caller && caller.target === 'node')\n ? { targets: { node: 'current' } }\n : {}\n ]\n ]\n }\n }\n ```\n\n \u003cbr>\n\n- If you are using the RTL support, then edit `/postcss.config.js`. You will need to remove the `postcss-rtlcss` import and usage. This is handled automatically by Quasar CLI now:\n\n ```diff /postcss.config.js\n - import rtlcss from 'postcss-rtlcss'\n\n export default {\n plugins: [\n - rtlcss()\n ]\n }\n ```\n\n \u003cbr>\n\n Also, uninstall the `postcss-rtlcss` package.\n\n### Step 3: Copy folders from original folder\n\nFrom your original project folder, copy these as they are:\n\n- /src\n- /src-cordova\n- /src-capacitor\n- /src-electron\n- /src-pwa\n- /src-ssr (with small caveat; see next steps)\n- /src-bex (with small caveat; see next steps)\n\n### Step 4: Check the new quasar.config file\n\nThe following props are detailed in the [quasar.config file](/quasar-cli-vite/quasar-config-file) page.\n\n```diff\n+ eslint: {\n+ // fix: true,\n+ // include: [],\n+ // exclude: [],\n+ // cache: false,\n+ // rawEsbuildEslintOptions: {},\n+ // rawWebpackEslintPluginOptions: {},\n+ warnings: true,\n+ errors: true\n+ },\n\nbuild: {\n- target: {\n- browser: 'baseline-widely-available',\n+ esbuildTarget: {\n+ browser: [ 'es2022', 'firefox115', 'chrome115', 'safari14' ],\n node: 'node20'\n },\n\n+ webpackTranspile\n+ webpackTranspileDependencies\n+ webpackDevtool\n\n+ htmlFilename\n+ rtl\n+ showProgress\n+ gzip\n+ vueCompiler\n\n- extendViteConf (viteConf, { isServer, isClient }) {}\n+ extendWebpack () {}\n+ chainWebpack () {}\n\n- viteVuePluginOptions\n- vitePlugins\n\n- useFilenameHashes\n- polyfillModulePreload\n\n+ uglifyOptions\n+ scssLoaderOptions\n+ sassLoaderOptions\n+ stylusLoaderOptions\n+ lessLoaderOptions\n+ vueLoaderOptions\n+ tsLoaderOptions\n},\n\ndevServer: {\n+ server: {\n+ type: 'http'\n+ }\n},\n\nsourceFiles: {\n+ indexHtmlTemplate: 'index.html'\n}\n```\n\n### Step 5: SSR related\n\n```diff /src-ssr/server.js\nexport const renderPreloadTag = defineSsrRenderPreloadTag((file/* , { ssrContext } */) => {\n if (jsRE.test(file) === true) {\n- return `\u003clink rel=\"modulepreload\" href=\"${file}\" crossorigin>`;\n+ return `\u003cscript src=\"${file}\" defer crossorigin>\u003c/script>`;\n }\n```\n\n### Step 6: BEX related\n\n```diff /src-bex/background.js\n- declare module '@quasar/app-vite' {\n+ declare module '@quasar/app-webpack' {\n interface BexEventMap {\n // ...\n }\n}\n```\n\n```diff /src-bex/my-content-script.js\n// for ALL content script files:\n\n- declare module '@quasar/app-vite' {\n+ declare module '@quasar/app-webpack' {\n interface BexEventMap {\n // ...\n }\n}\n```\n\n### Step 7: Linting\n\nIf you are using ESLint, you might want to check the requirements for it [here](/quasar-cli-webpack/linter).\n\n### Step 8: And we're done\n\n```bash\n$ quasar prepare\n$ quasar dev\n$ quasar build\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4472,"content_sha256":"600bdf313babce713c1dedab36dbb20f07d29fa9b1da51e53e3fb70d029c85d2"},{"filename":"references/docs/quasar-cli-webpack/css-preprocessors.md","content":"---\ntitle: CSS Preprocessors\ndesc: (@quasar/app-webpack) Sass/SCSS are the out of the box supported css preprocessors in Quasar\nrelated:\n - /style/sass-scss-variables\n---\n\n**Sass** or **SCSS** (recommending any of the two flavours) are the out of the box supported css preprocessors through Quasar CLI, should you want to use them.\n\nYou won't need to install any additional packages or extend the Webpack configuration.\n\n## How to\n\nYour Vue files can contain Sass/SCSS code through the `\u003cstyle>` tag.\n\n```html\n\u003c!-- Notice lang=\"sass\" -->\n\u003cstyle lang=\"sass\">\n div\n color: #444\n background-color: #dadada\n\u003c/style>\n```\n\n```html\n\u003c!-- Notice lang=\"scss\" -->\n\u003cstyle lang=\"scss\">\n div {\n color: #444;\n background-color: #dadada;\n }\n\u003c/style>\n```\n\nAnd, of course, standard CSS is also supported:\n\n```html\n\u003cstyle>\n div {\n color: #444;\n background-color: #dadada;\n }\n\u003c/style>\n```\n\n## Variables\n\nQuasar also supplies variables (`$primary`, `$grey-3`, ...and many more) and you can directly use them. Read more about [Sass/SCSS variables](/style/sass-scss-variables).\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1079,"content_sha256":"8155ce32260ab85af7eecf32389142c605b307e246ff01264928c773656d884d"},{"filename":"references/docs/quasar-cli-webpack/developing-browser-extensions/app-icons-browser-extension.md","content":"---\ntitle: App Icons for (BEX)\ndesc: (@quasar/app-webpack) How to manage the app icons for a Quasar Browser Extension (BEX).\nscope:\n tree:\n l: src-bex\n c:\n - l: icons\n c:\n - l: icon-16x16.png\n e: Favicon on extension pages\n - l: icon-48x48.png\n e: Extension management page\n - l: icon-128x128.png\n e: Installation and web store\n---\n\nThis build target includes the icons required for browser extensions. You need all of them - and if you discover one that is new or missing, please open an issue.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/iconfactory.png\" style=\"float:right;max-width:15%;min-width:240px;padding-top:40px\">\n\n## Icon Genie CLI\n\n::: tip\nWe highly recommend using the [Icon Genie CLI](/icongenie/introduction), because it consumes a source icon and automatically clones, scales, minifies and places the icons in the appropriate directories for you. When needed, it also tells you what tags you'll need to add to your /index.html file.\n:::\n\nQuickly bootstrap the necessary images with Icon Genie CLI. For a complete list of options, please visit the [Icon Genie CLI](/icongenie/command-list) command list page.\n\n```bash\n$ icongenie generate -m bex -i /path/to/source/icon.png\n```\n\n## Manual instructions\n\n\u003cDocTree :def=\"scope.tree\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1322,"content_sha256":"78ef8b25c9ab02918d767ce51cd22ed021f9e08d91764258f57e93fe35f4a2cf"},{"filename":"references/docs/quasar-cli-webpack/developing-browser-extensions/background-script.md","content":"---\ntitle: Background Script\ndesc: (@quasar/app-webpack) How to communicate using your background script with other parts of your Browser Extension (BEX).\n---\n\nThe background script runs in the context of the BEX itself and can listen to all available browser extension events.\n\n::: warning\nIn Chrome with Manifest v3 your background script is actually a Service Worker. This does not currently apply to Firefox with Manifest v3 (yet).\n:::\n\n## Registering a background script\n\nYour `/src-bex/manifest.json` is the central point that defines your BEX. This is the place where you also define your background script(s):\n\n```json /src-bex/manifest.json\n\"chrome\": {\n \"background\": {\n \"service_worker\": \"background.js\"\n }\n},\n\n\"firefox\": {\n \"background\": {\n \"scripts\": [ \"background.js\" ]\n }\n}\n```\n\n::: warning For TS devs\nYour background and content scripts have the `.ts` extension. Use that extension in the manifest.json file as well! Examples: \"background.ts\", \"my-content-script.ts\". While the browser vendors do support only the `.js` extension, Quasar CLI will convert the file extensions automatically.\n:::\n\n## Case study\n\nLet's say we want to listen for a new tab being opened in the web browser and then react to it in our Quasar App. First, we'd need to listen for the new tab being opened and emit a new event to tell the Quasar App this has happened:\n\n```js /src-bex/background.js\n/**\n * Importing the file below initializes the extension background.\n *\n * Warnings:\n * 1. Do NOT remove the import statement below. It is required for the extension to work.\n * If you don't need createBridge(), leave it as \"import '#q-app/bex/background'\".\n * 2. Do NOT import this file in multiple background scripts. Only in one!\n * 3. Import it in your background service worker (if available for your target browser).\n */\nimport { createBridge } from '#q-app/bex/background'\n\nconst bridge = createBridge({ debug: false })\n\nchrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {\n bridge.send('bex.tab.opened', { url: tab.url })\n})\n```\n\nThen in our Quasar App, we'd listen for this in one of our component lifecycle hooks, like so:\n\n```js /Quasar App, /src\nimport { useQuasar } from 'quasar'\nimport { onBeforeUnmount } from 'vue'\n\nexport default {\n setup() {\n const $q = useQuasar()\n\n // Our function which receives the URL sent by the background script.\n function doOnTabOpened(url) {\n console.log('New Browser Tab Openend: ', url)\n }\n\n // Add our listener\n $q.bex.on('bex.tab.opened', doOnTabOpened)\n\n // Don't forget to clean it up\n onBeforeUnmount(() => {\n $q.bex.off('bex.tab.opened', doOnTabOpened)\n })\n\n return {}\n }\n}\n```\n\nThere are wide variety of events available to the browser extension background script - Google is your friend if you're trying to do something in this area.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2846,"content_sha256":"8c23f842aee3a6020dceb8a87928362f71dc0051bfe1416fc57a11a547a5e281"},{"filename":"references/docs/quasar-cli-webpack/developing-browser-extensions/bex-bridge.md","content":"---\ntitle: BEX Bridge Communication\ndesc: (@quasar/app-webpack) How to communicate between different parts of your Browser Extension (BEX) in Quasar.\n---\n\nAllowing a Quasar App to communicate with the various parts of the BEX is essential. Quasar closes this gap using a `bridge`.\n\nThere are 3 areas in a BEX which will need a communication layer:\n\n1. The Quasar App itself - this is true for all types of BEX i.e Popup, Options Page, Dev Tools or Web Page\n2. Background Script\n3. Content Script\n\n## Communication Rules\n\nYou can use our BEX bridge to directly communicate between the background script, instances of the content scripts and the popup/devtools/options page.\n\nThe use of the BEX bridge is optional for each part of the BEX, however if you want to be able to directly communicate between any bex part, then you need to create it in your background script. Under the hood, the background script acts as the main point of communication. All messages go through the bridge in the background script (and get redirected to the right recipient).\n\n## The Bridge\n\nThe bridge is a promise based event system which is shared between all parts of the BEX and as such allows you to listen for events in your Quasar App, emit them from other parts or vice versa. This is what gives Quasar BEX mode it's power.\n\nTo access the bridge from within your Quasar App (/src) you can use `$q.bex`. In other areas, the bridge is made available via creating an instance of it.\n\nLet's see how it works.\n\n### The background script\n\n::: warning\nYou can have multiple background scripts specified in your manifest.json, however, create the BEX bridge ONLY in one of those background scripts. Do not use multiple bridge instances for the background part of your BEX.\n:::\n\n```js\n/**\n * Importing the file below initializes the extension background.\n *\n * Warnings:\n * 1. Do NOT remove the import statement below. It is required for the extension to work.\n * If you don't need createBridge(), leave it as \"import '#q-app/bex/background'\".\n * 2. Do NOT import this file in multiple background scripts. Only in one!\n * 3. Import it in your background service worker (if available for your target browser).\n */\nimport { createBridge } from '#q-app/bex/background'\n\n/**\n * Call createBridge() to enable communication with the app & content scripts\n * (and between the app & content scripts), otherwise skip calling\n * createBridge() and use no bridge.\n */\nconst bridge = createBridge({ debug: false })\n```\n\n### Content scripts\n\n```js\n/**\n * Importing the file below initializes the content script.\n *\n * Warning:\n * Do not remove the import statement below. It is required for the extension to work.\n * If you don't need createBridge(), leave it as \"import '#q-app/bex/content'\".\n */\nimport { createBridge } from '#q-app/bex/content'\n\n// The use of the bridge is optional.\nconst bridge = createBridge({ debug: false })\n/**\n * bridge.portName is 'content@\u003cpath>-\u003cnumber>'\n * where \u003cpath> is the relative path of this content script\n * filename (without extension) from /src-bex\n * (eg. 'my-content-script', 'subdir/my-script')\n * and \u003cnumber> is a unique instance number (1-10000).\n */\n\n// Attach initial bridge listeners...\n\n/**\n * Leave this AFTER you attach your initial listeners\n * so that the bridge can properly handle them.\n *\n * You can also disconnect from the background script\n * later on by calling bridge.disconnectFromBackground().\n *\n * To check connection status, access bridge.isConnected\n */\nbridge\n .connectToBackground()\n .then(() => {\n console.log('Connected to background')\n })\n .catch(err => {\n console.error('Failed to connect to background:', err)\n })\n```\n\n### Popup/devtools/options page\n\n```tabs App (/src/...) vue components\n\u003c\u003c| html Composition API + script setup |>>\n\u003ctemplate>\n \u003cdiv />\n\u003c/template>\n\n\u003cscript setup>\nimport { useQuasar } from 'quasar'\nconst $q = useQuasar()\n\n// Use $q.bex (the bridge)\n// $q.bex.portName is \"app\"\n\u003c/script>\n\u003c\u003c| html Composition API + script |>>\n\u003ctemplate>\n \u003cdiv />\n\u003c/template>\n\n\u003cscript>\nimport { useQuasar } from 'quasar'\n\nexport default {\n setup () {\n const $q = useQuasar()\n // Use $q.bex (the bridge)\n // $q.bex.portName is \"app\"\n }\n}\n\u003c/script>\n\u003c\u003c| html Options API |>>\n\u003ctemplate>\n \u003cdiv />\n\u003c/template>\n\n\u003cscript>\nexport default {\n // Use this.$q.bex (the bridge)\n // this.$q.bex.portName is \"app\"\n}\n\u003c/script>\n```\n\nPlease note that the devtools/popup/options page portName will be `app`.\n\n### Messaging through the bridge\n\n```js\n// Listen to a message from the client\nbridge.on('test', message => {\n console.log(message)\n console.log(message.payload)\n console.log(message.from)\n})\n\n// Send a message and split payload into chunks\n// to avoid max size limit of BEX messages.\n// Warning! This happens automatically when the payload is an array.\n// If you actually want to send an Array, wrap it in an object.\nbridge.send({\n event: 'test',\n to: 'app',\n payload: [ 'chunk1', 'chunk2', 'chunk3', ... ]\n}).then(responsePayload => { ... }).catch(err => { ... })\n\n// Send a message and wait for a response\nbridge.send({\n event: 'test',\n to: 'background',\n payload: { banner: 'Hello from content-script' }\n}).then(responsePayload => { ... }).catch(err => { ... })\n\n// Listen to a message from the client and respond synchronously\nbridge.on('test', message => {\n console.log(message)\n return { banner: 'Hello from a content-script!' }\n})\n\n// Listen to a message from the client and respond asynchronously\nbridge.on('test', async message => {\n console.log(message)\n const result = await someAsyncFunction()\n return result\n})\nbridge.on('test', message => {\n console.log(message)\n return new Promise(resolve => {\n setTimeout(() => {\n resolve({ banner: 'Hello from a content-script!' })\n }, 1000)\n })\n})\n\n// Broadcast a message to app & content scripts\nbridge.portList.forEach(portName => {\n bridge.send({ event: 'test', to: portName, payload: 'Hello from background!' })\n})\n\n// Find any connected content script and send a message to it\nconst contentPort = bridge.portList.find(portName => portName.startsWith('content@'))\nif (contentPort) {\n bridge.send({ event: 'test', to: contentPort, payload: 'Hello from background!' })\n}\n\n// Send a message to a certain content script\nbridge\n .send({ event: 'test', to: 'content@my-content-script-2345', payload: 'Hello from a content-script!' })\n .then(responsePayload => { ... })\n .catch(err => { ... })\n\n// Listen for connection events\n// (the \"@quasar:ports\" is an internal event name registered automatically by the bridge)\n// --> ({ portList: string[], added?: string } | { portList: string[], removed?: string })\nbridge.on('@quasar:ports', ({ portList, added, removed }) => {\n console.log('Ports:', portList)\n if (added) {\n console.log('New connection:', added)\n } else if (removed) {\n console.log('Connection removed:', removed)\n }\n})\n\n// Current bridge port name (can be 'background', 'app', or 'content@\u003cname>-\u003cxxxxx>')\nconsole.log(bridge.portName)\n```\n\n::: warning Warning! Sending large amounts of data\nAll browser extensions have a hard limit on the amount of data that can be passed as communication messages (example: 50MB). If you exceed that amount on your payload, you can send chunks (**`payload` param should be an Array**).\n\n\u003cbr>\n\n```js\nbridge.send({\n event: 'some.event',\n to: 'app',\n payload: [chunk1, chunk2, ...chunkN]\n})\n```\n\n\u003cbr>\n\nWhen calculating the payload size, have in mind that the payload is wrapped in a message built by the Bridge that contains some other properties too. That takes a few bytes as well. So your chunks' size should be with a few bytes below the browser's threshold.\n:::\n\n::: warning Warning! Performance on sending an Array\nLike we've seen on the warning above, if `payload` is Array then the bridge will send a message for each of the Array's elements.\nWhen you actually want to send an Array (not split the payload into chunks), this will be **VERY** inefficient.\n\n\u003cbr>\n\nThe solution is to wrap your Array in an Object (so only one message will be sent):\n\n\u003cbr>\n\n```js\nbridge.send({\n event: 'some.event',\n to: 'background',\n payload: {\n myArray: [\n /*...*/\n ]\n }\n})\n```\n\n:::\n\n### Bridge debug mode\n\nIf you encounter problems with sending messages between the BEX parts, you could enable the debug mode for the bridges that interest you. In doing so, the communication will also be outputted to the browser console:\n\n```js Bridge debug mode\n// Dynamically set debug mode\nbridge.setDebug(true) // boolean\n\n// Log a message on the console (if debug is enabled)\nbridge.log('Hello world!')\nbridge.log('Hello', 'world!')\nbridge.log('Hello world!', { some: 'data' })\nbridge.log('Hello', 'world', '!', { some: 'object' })\n// Log a warning on the console (regardless of the debug setting)\nbridge.warn('Hello world!')\nbridge.warn('Hello', 'world!')\nbridge.warn('Hello world!', { some: 'data' })\nbridge.warn('Hello', 'world', '!', { some: 'object' })\n```\n\n### Clean up your listeners\n\nDon't forget to remove the listeners that are no longer needed, during the lifetime of your BEX:\n\n```js\nbridge.off('some.event', this.someFunction)\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9151,"content_sha256":"0b44fa7801fb884dda602682c0e62695787c6fdbb44bb4f5efb773999ddef57e"},{"filename":"references/docs/quasar-cli-webpack/developing-browser-extensions/build-commands.md","content":"---\ntitle: BEX Build Commands\ndesc: (@quasar/app-webpack) The Quasar CLI list of commands when developing or building a Browser Extension (BEX).\nscope:\n devTree:\n l: '.'\n c:\n - l: dist/bex-[chrome|firefox]--dev\n c:\n - l: '...files'\n e: Built code from /src-bex\n - l: www/\n e: Built code from /src\n prodTree:\n l: '.'\n c:\n - l: dist/bex-[chrome|firefox]\n c:\n - l: '...files'\n e: Built code from /src-bex\n - l: www/\n e: Built code from /src\n - l: Packaged.your-project-name.zip\n e:\n A zip file ready for submission to the Chrome Browser Extension Store /\n Other Chromium based stores.\n---\n\n## Developing\n\nStart developing a Browser Extension with just one command.\n\n```bash\n$ quasar dev -m bex -T [chrome|firefox]\n\n# ..or the longer form:\n$ quasar dev --mode bex -T [chrome|firefox]\n```\n\nYou may or may not have already had a `src-bex` folder, but you will definitely have one now. Now that we've created a development environment, we need to load generated browser extension into your browser.\n\nWhile you develop your BEX, you will notice that Quasar CLI builds the actual extension in the dist folder (normally in `/dist/bex-chrome--dev/` or `/dist/bex-firefox--dev` based on the dev target in \"quasar dev\" command):\n\n\u003cDocTree :def=\"scope.devTree\" />\n\n### Chrome\n\n\n\nIn line with the screenshot above, the following steps must be taken:\n\n1. In Chrome, navigate to `chrome://extensions`\n2. Toggle \"Developer Mode\".\n3. Click \"Load unpacked\". This will present you with the _folder_ selection dialog. Navigate to and select your `/dist/bex-chrome--dev/` folder.\n4. You should now see your BEX mounted in Chrome.\n\nMore information about debugging Chrome Browser Extensions can be found in the official documentation.\n\n### Other Chromium Browsers\n\nAlthough we haven't tested all the various Chromium based browsers, BEX mode should be compatible with them. Please refer to the appropriate browser documentation on how to add a browser extension to that particular browser.\n\n### Firefox\n\n\n\nIn line with the screenshot above, the following steps must be taken:\n\n1. In Firefox, navigate to `about:debugging`\n2. Click on \"This Firefox\"\n3. Click \"Load Temporary Add-on...\". This will present you with the _file_ selection dialog. Navigate to and select your `/dist/bex-firefox--dev/manifest.json` file. **Note:** Firefox requires the manifest file, not the `/dist/bex-firefox--dev` folder like Chromium browsers.\n4. You should now see your BEX mounted in Firefox.\n\nMore information about debugging Firefox temporary addons can be found in the Firefox Extension Workshop.\n\n### Hot Module Reloading (HMR)\n\nThe best developer experience that you will have is with Chrome. We've managed to make HMR fully work for it:\n\n- Full HMR for devtools/options/popup page\n- When changing the background script, the extension will automatically reload.\n- When changing a content script, the extension will automatically reload & the tabs using those content scripts will auto-refresh.\n- The popup/page will not need to be compiled in its entirety. Instead, you will be able to benefit from on-the-fly compilation only for the browser requested files, which is VERY fast.\n\nOn the other hand, we cannot offer the same experience for Firefox too. However, Firefox watches for file changes and tries to auto-reload the extension on changes, but none of the HMR features above (specified for Chrome) will work.\n\n## Debugging\n\nBrowser extensions runs in three different environments (more on upcoming pages) and it requires various environments for debugging.\n\n### With Chrome\n\nYou can find following places to investigate the errors and outputs from the console in DevTools:\n\n1. Popup - right click on the page or on the extension icon and choose `Inspect popup` for DevTools.\n2. Background scripts (e.g.: background-hooks.js) - open DevTools from `Manage extensions - background page`.\n3. Content scripts - page where your script is injected.\n4. Extension Errors - list of errors related to the extension (e.g. manifest configuration) are available in `Manage extension - Errors`.\n\n\n\n\n\nIf your code changes are not propagated to the browser you can try to: - Update or Reload extension - from the Extensions list (screenshots) - Restart browser - Restart dev process\n\nFor more information, please visit Debugging extensions.\n\n## Building for Production\n\n```bash\n$ quasar build -m bex -T [chrome|firefox]\n\n# ..or the longer form:\n$ quasar build --mode bex -T [chrome|firefox]\n```\n\nYou will be instructed which is the output folder. Normally, it's `/dist/bex-chrome/` and `/dist/bex-firefox`, based on the target specified for the \"quasar build\" command.\n\n\u003cDocTree :def=\"scope.prodTree\" />\n\n::: tip\nIf you want to test out the `your-project-name.zip` file, you can do this by dragging the file into the same place you load the Extension in development mode; for Chrome `chrome://extensions` and Firefox `about:debugging`. See the development screenshots above for more information.\n:::\n\n### A Note on Minification\n\nPart of the review process for Browser Extensions in both Chrome and Firefox must allow the relative teams to examine the code being deployed as a live extension. With this in mind, minified code is not allowed. So, to allow for the review process, Quasar will not obfuscate and minify the built code for Browser Extensions.\n\nGiven any extension will be ran directly on the user's computer, upload speed isn't a factor to worry about here, so minifying the code isn't necessary.\n\n## Publishing to the Stores\n\nSince Quasar removes the burden of building and packaging your Browser Extension, once you are finished developing your extension, it is ready to be published. The publishing process differs between browsers, but the official documentation will guide you through the process.\n\n**Chrome** - Publishing a Chrome Browser Extension\n\n**Firefox** - Publishing a Firefox Add On (Browser Extension)\n\n::: tip\nBEX mode should be compatible with all chromium based browsers. Please refer to their relative documentation on publishing extensions.\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":6194,"content_sha256":"a35d15f14fc841d5384a2571c6589b3d7f19a7f36ffbb16770baebe5df020add"},{"filename":"references/docs/quasar-cli-webpack/developing-browser-extensions/configuring-bex.md","content":"---\ntitle: Configuring BEX\ndesc: (@quasar/app-webpack) How to manage your Browser Extensions with Quasar CLI.\n---\n\nBefore we can configure anything, we need to understand how the BEX is structured. A BEX can be one (or more) of the following:\n\n1. Runs in its own tab in the browser\n2. Runs in the Developer Tools window.\n3. Runs in a Popup window.\n4. Runs as Options window.\n5. Runs in the context of a web page (injected into a website)\n\nYou do not need a new Quasar App per BEX type above as a single Quasar Application can run in **all** of the instances above. You can find out more about these in the [types section](/quasar-cli-webpack/developing-browser-extensions/types-of-bex).\n\n## quasar.config file\n\n```js /quasar.config file > sourceFiles\n// should you wish to change default files\nsourceFiles: {\n bexManifestFile?: 'src-bex/manifest.json',\n}\n```\n\n```js /quasar.config file > bex\nbex: {\n /**\n * The list of extra scripts (js/ts) not in your bex manifest that you want to\n * compile and use in your browser extension. Maybe dynamic use them?\n *\n * Each entry in the list should be a relative filename to /src-bex/\n *\n * @example [ 'my-script.ts', 'sub-folder/my-other-script.js' ]\n */\n extraScripts?: string[];\n\n /**\n * Extend the Esbuild config that is used for the bex scripts\n * (background, content scripts, dom script)\n */\n extendBexScriptsConf?: (config: EsbuildConfiguration) => void;\n\n /**\n * Should you need some dynamic changes to the Browser Extension manifest file\n * (/src-bex/manifest.json) then use this method to do it.\n */\n extendBexManifestJson?: (json: object) => void;\n}\n```\n\n## UI in /src\n\nShould you want to tamper with the Webpack config for UI in /src you have two options:\n\n```js /quasar.config file\nbuild: {\n extendWebpack(webpackCfg) { ... },\n chainWebpack(webpackChain) { ... }\n}\n```\n\nThe UI files will be injected and available as `www` folder when you build (or develop) the browser extension.\n\n## Manifest.json\n\nThe most important config file for your BEX is `/src-bex/manifest.json`. It is recommended that you read up on this file before starting your project.\n\nWhen you first add the BEX mode, you will notice that the manifest file contains three root props: `all`, `chrome` & `firefox`. The manifest for chrome is deeply merged from all+chrome, while the firefox one is generated from all+firefox. You could even have different manifest versions for each target:\n\n```json /src-bex/manifest.json\n{\n \"all\": {\n \"manifest_version\": 3,\n\n \"icons\": {\n \"16\": \"icons/icon-16x16.png\",\n \"48\": \"icons/icon-48x48.png\",\n \"128\": \"icons/icon-128x128.png\"\n },\n\n \"permissions\": [\"storage\", \"tabs\"],\n\n \"host_permissions\": [\"*://*/*\"],\n \"content_security_policy\": {\n \"extension_pages\": \"script-src 'self'; object-src 'self';\"\n },\n \"web_accessible_resources\": [\n {\n \"resources\": [\"*\"],\n \"matches\": [\"*://*/*\"]\n }\n ],\n\n \"action\": {\n \"default_popup\": \"www/index.html\"\n },\n\n \"content_scripts\": [\n {\n \"matches\": [\"\u003call_urls>\"],\n \"css\": [\"assets/content.css\"],\n \"js\": [\"my-content-script.ts\"]\n }\n ]\n },\n\n \"chrome\": {\n \"background\": {\n \"service_worker\": \"background.ts\"\n }\n },\n\n \"firefox\": {\n \"background\": {\n \"scripts\": [\"background.ts\"]\n }\n }\n}\n```\n\n::: warning For TS devs\nYour background and content scripts have the `.ts` extension. Use that extension in the manifest.json file as well! Examples: \"background.ts\", \"my-content-script.ts\". While the browser vendors do support only the `.js` extension, Quasar CLI will convert the file extensions automatically.\n:::\n\n## Background And Content Scripts\n\nBehind every BEX is a content script and a background script (manifest v2) / service-worker (manifest v3+). It's a good idea to understand what each of these are before writing your first BEX.\n\nIn summary:\n\n- **Background Script** - runs in the context of the BEX itself and can listen to all available browser extension events.\n- **Content Script** - runs in the context of the web page. There will be a new content script instance per tab running the extension.\n\n::: tip\nGiven content scripts run in the web page context, this means that only BEX's that interact with a web page can use content scripts. Popups, Options and Devtools **will not** have a _content script_ running behind them. They will all however have the _background script_.\n:::\n\n::: warning\nIn Chrome with Manifest v3 your background script is actually a Service Worker. This does not currently apply to Firefox with Manifest v3 (yet).\n:::\n\n## CSS\n\nAny styles you want to be made available to your web page (not your Quasar App) should be included as a file in `src-bex/assets/\u003cname>.css`. When adding such a file, please make sure that you reference it from your `/src-bex/manifest.json` around the content scripts that need it:\n\n```json /src-bex/manifest.json\n// example linking /src-bex/assets/content.css\n\"content_scripts\": [\n {\n \"matches\": [ \"\u003call_urls>\" ],\n \"css\": [ \"assets/content.css\" ],\n \"js\": [ /*...*/ ]\n }\n]\n```\n\n::: warning\nThis must be native CSS as it's not preprocessed via Sass.\n:::\n\n## Dynamic/other scripts\n\nShould you need other scripts to be dynamically loaded or compiled for your BEX, you can add them by editing your quasar.config file:\n\n```js /quasar.config file\nbex: {\n /**\n * The list of extra scripts (js/ts) not in your bex manifest that you want to\n * compile and use in your browser extension. Maybe dynamic use them?\n *\n * Each entry in the list should be a relative filename to /src-bex/\n *\n * @example [ 'my-script.ts', 'sub-folder/my-other-script.js' ]\n */\n extraScripts?: string[];\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5730,"content_sha256":"2ad65bf7a67e125ec25a3fbdfbc4811fe98fc22cb52caa6b4d29bab0b2f96d39"},{"filename":"references/docs/quasar-cli-webpack/developing-browser-extensions/content-scripts.md","content":"---\ntitle: Content Scripts\ndesc: (@quasar/app-webpack) How to communicate using your content script with your Quasar App and Background Script in Quasar Browser Extension mode.\n---\n\nThe content script(s) run in the context of the web page. There will be a new content script instance per tab running the extension.\n\n## Communication / Events\n\nYou communicate between the BEX parts of your app (background, content scripts & devtools/popup/options page) through our [BEX Bridge](/quasar-cli-webpack/developing-browser-extensions/bex-bridge).\n\n## Registering a content script\n\nYour `/src-bex/manifest.json` is the central point that defines your BEX. This is the place where you also define your content script(s):\n\n```json /src-bex/manifest.json\n\"content_scripts\": [\n {\n \"matches\": [ \"\u003call_urls>\" ],\n \"css\": [ \"assets/content.css\" ],\n \"js\": [ \"my-content-script.ts\" ]\n }\n]\n```\n\n::: warning For TS devs\nYour background and content scripts have the `.ts` extension. Use that extension in the manifest.json file as well! Examples: \"background.ts\", \"my-content-script.ts\". While the browser vendors do support only the `.js` extension, Quasar CLI will convert the file extensions automatically.\n:::\n\n## Case study\n\nLet's say we want to react to a button being pressed on our Quasar App and highlight some text on the underlying web page, this would be done via the content scripts like so:\n\n```js Quasar App, /src\nsetup () {\n const $q = useQuasar()\n\n async function myButtonClickHandler () {\n await $q.bex.send('highlight.content', { selector: '.some-class' })\n $q.notify('Text has been highlighted')\n }\n\n return { myButtonClickHandler }\n}\n```\n\n```css /src-bex/assets/content.css\n.bex-highlight {\n background-color: red;\n}\n```\n\n```js /src-bex/my-content-script.js:\n/**\n * Importing the file below initializes the content script.\n *\n * Warning:\n * Do not remove the import statement below. It is required for the extension to work.\n * If you don't need createBridge(), leave it as \"import '#q-app/bex/content'\".\n */\nimport { createBridge } from '#q-app/bex/content'\n\n// The use of the bridge is optional.\nconst bridge = createBridge({ debug: false })\n\nbridge.on('highlight.content', ({ payload }) => {\n const el = document.querySelector(data.selector)\n if (el !== null) {\n el.classList.add('bex-highlight')\n }\n})\n\nbridge\n .connectToBackground()\n .then(() => {\n console.log('Connected to background')\n })\n .catch(err => {\n console.error('Failed to connect to background:', err)\n })\n```\n\nContent scripts live in an isolated world, allowing a content script to makes changes to its JavaScript environment without conflicting with the page or additional content scripts.\n\nIsolated worlds do not allow for content scripts, the extension, and the web page to access any variables or functions created by the others. This also gives content scripts the ability to enable functionality that should not be accessible to the web page.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2962,"content_sha256":"cf3d88499c4f389d24f8d1f3d0aa6e73281509ce6a720b19d00f2b5d7f7f16ac"},{"filename":"references/docs/quasar-cli-webpack/developing-browser-extensions/introduction.md","content":"---\ntitle: What is a Browser Extension\ndesc: (@quasar/app-webpack) Introduction on what a Browser Extension (BEX) is.\n---\n\nA Browser Extension (BEX) is an application that runs in the browsers context and is used to customize the web browser in some way.\n\nThey are built on web technologies such as HTML, JavaScript, and CSS and will aim to fulfill a single purpose. A single BEX\ncan be built in any way the user deems fit but must contribute towards fulfilling that single purpose.\n\nHere a few things a BEX can do:\n\n- Override page content\n- Add to (or alter) the browser's interface\n- Intercept page requests\n- Be a full featured app that runs in the browser.\n- Interact with and alter the development tools of the browser.\n\nWe've all used Browser Extensions in some capacity. Quasar BEX allows you to do anything a browser extension allows but with the simplicity Quasar offers in all other modes.\n\n### Supported Browsers\n\nWhilst BEX mode has been tested and developed on Firefox and Chrome, all Chromium based browsers should be supported. Where Chrome is mentioned in the documentation, you can safely assume this will apply to the various Chromium browsers as well. If in doubt, refer to the specific browser documentation for clarification.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1248,"content_sha256":"43ca7cb1339dded0546cf1bb66c457d569341bfcf6241ca0ee7a9f26a5cb3048"},{"filename":"references/docs/quasar-cli-webpack/developing-browser-extensions/preparation.md","content":"---\ntitle: Preparation for BEX\ndesc: (@quasar/app-webpack) How to add the Browser Extension (BEX) mode into a Quasar app.\nscope:\n tree:\n l: src-bex\n c:\n - l: assets\n c:\n - l: content.css\n e: CSS file which is auto injected into the consuming webpage via the manifest.json\n - l: icons\n e: Icons of your app for all platforms\n c:\n - l: 'icon-128x128.png '\n e: Icon file at 128px x 128px\n - l: icon-16x16.png\n e: Icon file at 16px x 16px\n - l: icon-48x48.png\n e: Icon file at 48px x 48px\n - l: _locales/\n e: Optional BEX locales files that you might define in manifest\n - l: manifest.json\n e: The browser extension manifest file\n - l: background.js\n e: (or .ts) Standard background script BEX file (auto injected via manifest.json)\n - l: my-content-script.js\n e:\n (or .ts) Standard content script BEX file - auto injected via manifest.json (you can\n have multiple content scripts)\n---\n\nThe difference between building a SPA, Mobile App, Electron App, BEX or SSR is simply determined by the \"mode\" parameter in \"quasar dev\" and \"quasar build\" commands.\n\n## Add Quasar BEX Mode\n\nIn order to build a BEX, we first need to add the BEX mode to our Quasar project:\n\n```bash\n$ quasar mode add bex\n```\n\nIf you want to jump right in and start developing, you can skip the \"quasar mode\" command and issue:\n\n```bash\n$ quasar dev -m bex -T [chrome|firefox]\n```\n\nThis will add BEX mode automatically, if it is missing, by creating the `/src-bex` folder into your project.\n\n::: tip\nThe `src-bex` folder is just a standard browser extension folder so you are free to use it as you would any other browser extension project folder. Please refer to supported Browser Extension documentation to learn more.\n\n- Firefox Browser Extension Documentation\n- Google Chrome Browser Extension Documentation\n- **Other Chromium Based Browsers** - Refer to their specific documentation.\n :::\n\n## The Anatomy of \"/src-bex\"\n\nThe new folder has the following structure:\n\n\u003cDocTree :def=\"scope.tree\" />\n\nThe next section will discuss these in more detail.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2203,"content_sha256":"d2b2d2a120ef42fff44656f17445ef8abee2b5ba4e0e767ae4e2c078b4812057"},{"filename":"references/docs/quasar-cli-webpack/developing-browser-extensions/types-of-bex.md","content":"---\ntitle: Types of BEX\ndesc: (@quasar/app-webpack) How to configure each type of Browser Extensions in Quasar.\n---\n\nAs already discussed, Quasar can handle the various places where a browser extension can live, namely New Tab, Web Page, Dev Tools Options or Popup. You don't need a separate Quasar App for each of these. You can do some handy work with the router.\n\n## New Tab\n\nThis is the default way in which a BEX will run. It is accessed by clicking on the BEX icon in your browser. The Quasar App will run in that new (blank) tab.\n\n## Dev Tools, Options and Popup\n\nThese all follow the same pattern, set up a route and configure the `manifest.json` file to look at that route when it's trying to show either one of the types. For instance:\n\n```js routes.js:\nconst routes = [\n { path: '/options', component: () => import('pages/OptionsPage.vue') },\n { path: '/popup', component: () => import('pages/PopupPage.vue') },\n { path: '/devtools', component: () => import('pages/DevToolsPage.vue') }\n]\n```\n\nYou could configure your `manifest.json` file with the following so the options page is loaded from that route:\n\n#### manifest v2\n\n```json\n{\n \"manifest_version\": 2,\n\n \"options_page\": \"www/index.html#/options\", // Options Page\n \"browser_action\": {\n \"default_popup\": \"www/index.html#/popup\" // Popup Page\n },\n \"devtools_page\": \"www/index.html#/devtools\" // Dev Tools\n}\n```\n\n#### manifest v3\n\n```json\n{\n \"manifest_version\": 3,\n\n \"action\": {\n \"default_popup\": \"www/index.html#/popup\" // Popup Page\n },\n \"options_page\": \"www/index.html#/options\", // Options Page\n \"devtools_page\": \"www/index.html#/devtools\" // Dev Tools\n}\n```\n\n## Case study: Web Page\n\nThis is where the real power comes in. With a little ingenuity we can inject our Quasar application into a web page and use it as an overlay making it seem like our Quasar App is part of the page experience.\n\nHere's a brief rundown of how you could achieve this:\n\n- `src-bex/my-content-script.js`\n\nThe idea here is to create an IFrame and add our Quasar app into it, then inject that into the page.\n\nGiven our Quasar App might need to take the full height of the window (and thus stop any interaction with the underlying page) we have an event to handle setting the height of the IFrame. By default the IFrame height is just high enough to allow for the Quasar toolbar to show (and in turn allowing interaction with the rest of the page).\n\n```js /src-bex/my-content-script.js\n/**\n * Importing the file below initializes the content script.\n *\n * Warning:\n * Do not remove the import statement below. It is required for the extension to work.\n * If you don't need createBridge(), leave it as \"import '#q-app/bex/content'\".\n */\nimport { createBridge } from '#q-app/bex/content'\n\nconst bridge = createBridge({ debug: false })\n\n/**\n * When the drawer is toggled set the iFrame height to take the whole page.\n * Reset when the drawer is closed.\n */\nbridge.on('wb.drawer.toggle', ({ data, respond }) => {\n if (data.open) {\n setIFrameHeight('100%')\n } else {\n resetIFrameHeight()\n }\n respond()\n})\n\nconst iFrame = document.createElement('iframe')\nconst defaultFrameHeight = '62px'\n\n/**\n * Set the height of our iFrame housing our BEX\n * @param height\n */\nfunction setIFrameHeight(height) {\n iFrame.height = height\n}\n\n/**\n * Reset the iFrame to its default height e.g The height of the top bar.\n */\nfunction resetIFrameHeight() {\n setIFrameHeight(defaultFrameHeight)\n}\n\n/**\n * The code below will get everything going. Initialize the iFrame with defaults and add it to the page.\n * @type {string}\n */\niFrame.id = 'bex-app-iframe'\niFrame.width = '100%'\nresetIFrameHeight()\n\n// Assign some styling so it looks seamless\nObject.assign(iFrame.style, {\n position: 'fixed',\n top: '0',\n right: '0',\n bottom: '0',\n left: '0',\n border: '0',\n zIndex: '9999999', // Make sure it's on top\n overflow: 'visible'\n})\n;(function () {\n // When the page loads, insert our browser extension app.\n iFrame.src = chrome.runtime.getURL('www/index.html')\n document.body.prepend(iFrame)\n})()\n```\n\nWe can call this event from our Quasar App any time we know we're opening the drawer and thus changing the height of the IFrame to allow the whole draw to be visible.\n\n- `src-bex/assets/content.css`\n\nAdd a margin to the top of our document so our Quasar toolbar doesn't overlap the actual page content.\n\n```css\n.target-some-header-class {\n margin-top: 62px;\n}\n```\n\n- `Quasar App (/src)`\n\nThen in our Quasar app (/src), we have a function that toggles the drawer and sends an event to the content script telling it to\nresize the IFrame thus allowing our whole app to be visible:\n\n```html\n\u003cq-drawer :model-value=\"drawerIsOpen\" @update:model-value=\"drawerToggled\">\n Some Content\n\u003c/q-drawer>\n```\n\n```js\nimport { useQuasar } from 'quasar'\nimport { ref } from 'vue'\n\nsetup () {\n const $q = useQuasar()\n const drawerIsOpen = ref(true)\n\n async function drawerToggled () {\n await $q.bex.send('wb.drawer.toggle', {\n open: drawerIsOpen.value // So it knows to make it bigger / smaller\n })\n\n // Only set this once the promise has resolved so we can see the entire slide animation.\n drawerIsOpen.value = !drawerIsOpen.value\n }\n\n return { drawerToggled }\n}\n```\n\nNow you have a Quasar App running in a web page. You can now trigger other events from the Quasar App that the content\nscript can listen to and interact with the underlying page.\n\n::: warning\nBe sure to check your manifest.json file, especially around the reference to `my-content-script.js`. Note that **you can have multiple content scripts**. Whenever you create a new one, you need to reference it in the manifest file. Same for any css files created in `/src-bex/assets` folder.\n\n\u003cbr>\n\n```json /src-bex/manifest.json\n\"content_scripts\": [\n {\n \"matches\": [ \"\u003call_urls>\" ],\n \"css\": [ \"assets/content.css\" ],\n \"js\": [ \"my-content-script.js\" ]\n }\n]\n```\n\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5900,"content_sha256":"7f89072b9f84c52ca21743e278a3ec09d0b3f3645939b7d43c517550747153a4"},{"filename":"references/docs/quasar-cli-webpack/developing-capacitor-apps/app-icons-capacitor.md","content":"---\ntitle: App Icons for Capacitor\ndesc: (@quasar/app-webpack) How to manage the app icons for a Quasar hybrid mobile app with Capacitor.\nscope:\n tree:\n l: '.'\n c:\n - l: android\n c:\n - l: app\n c:\n - l: src\n c:\n - l: main\n c:\n - l: res\n c:\n - l: drawable\n c:\n - l: splash.png\n - l: drawable-land-hdpi\n c:\n - l: splash.png\n - l: drawable-land-mdpi\n c:\n - l: splash.png\n - l: drawable-land-xhdpi\n c:\n - l: splash.png\n - l: drawable-land-xxhdpi\n c:\n - l: splash.png\n - l: drawable-land-xxxhdpi\n c:\n - l: splash.png\n - l: drawable-port-hdpi\n c:\n - l: splash.png\n - l: drawable-port-mdpi\n c:\n - l: splash.png\n - l: drawable-port-xhdpi\n c:\n - l: splash.png\n - l: drawable-port-xxhdpi\n c:\n - l: splash.png\n - l: drawable-port-xxxhdpi\n c:\n - l: splash.png\n - l: mipmap-hdpi\n c:\n - l: ic_launcher.png\n - l: ic_launcher_foreground.png\n - l: ic_launcher_round.png\n - l: mipmap-mdpi\n c:\n - l: ic_launcher.png\n - l: ic_launcher_foreground.png\n - l: ic_launcher_round.png\n - l: mipmap-xhdpi\n c:\n - l: ic_launcher.png\n - l: ic_launcher_foreground.png\n - l: ic_launcher_round.png\n - l: mipmap-xxhdpi\n c:\n - l: ic_launcher.png\n - l: ic_launcher_foreground.png\n - l: ic_launcher_round.png\n - l: mipmap-xxhdpi\n c:\n - l: ic_launcher.png\n - l: ic_launcher_foreground.png\n - l: ic_launcher_round.png\n - l: ios\n c:\n - l: App\n c:\n - l: App\n c:\n - l: Assets.xcassets\n c:\n - l: AppIcon.appiconset\n c:\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: [email protected]\n - l: Splash.imageset\n c:\n - l: splash-2732x2732-1.png\n - l: splash-2732x2732-2.png\n - l: splash-2732x2732.png\n---\n\nCapacitor is one of the most complicated of all of the build targets as far as icons go, because not only do you need to place the icons in specific folders, you also need to register them in config files for both platforms (Android, iOS).\n\nIf you discover one file that is new or missing, please open an issue.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/iconfactory.png\" style=\"float:right;max-width:15%;min-width:240px;padding-top:40px\">\n\n## Icon Genie CLI\n\n::: tip\nWe highly recommend using the [Icon Genie CLI](/icongenie/introduction), because it consumes a source icon and automatically clones, scales, minifies and places the icons in the appropriate directories for you. When needed, it also tells you what tags you'll need to add to your /index.html file.\n:::\n\nQuickly bootstrap the necessary images with Icon Genie CLI. For a complete list of options, please visit the [Icon Genie CLI](/icongenie/command-list) command list page.\n\n```bash\n$ icongenie generate -m capacitor -i /path/to/source/icon.png [-b /path/to/background.png]\n```\n\nDepending on what packager (@electron/packager or electron-builder) you will be using, please see their docs on how to hook the icons.\n\n## Manual instructions\n\nUnless you are using the Icon Genie app extension, these are the files that you need to replace:\n\n\u003cDocTree :def=\"scope.tree\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5754,"content_sha256":"17a6517144e1f2da9aeb361c981e28748f0959b7b6de93884b324869d961a221"},{"filename":"references/docs/quasar-cli-webpack/developing-capacitor-apps/build-commands.md","content":"---\ntitle: Capacitor Build Commands\ndesc: (@quasar/app-webpack) The Quasar CLI list of commands when developing or building a hybrid mobile app with Capacitor.\n---\n\n## Developing\n\n```bash\n$ quasar dev -m capacitor -T [ios|android]\n\n# ..or the longer form:\n$ quasar dev --mode capacitor --target [ios|android]\n```\n\nIt will open the IDE (Android Studio / Xcode) and from there you can manually select the emulator (or multiple ones simultaneously!) and install the dev app on it/them. You can also run the dev app on a real mobile/tablet device.\n\n::: warning\nIn Android Studio, you will be greeted with a message recommending to upgrade the Gradle version. **DO NOT UPGRADE GRADLE** as it will break the Capacitor project. Same goes for any other requested upgrades.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-upgrade-notice.png\" alt=\"Gradle upgrade\" class=\"q-my-md rounded-borders\" style=\"max-width: 350px\">\n\nIf you encounter any IDE errors then click on File > Invalidate caches and restart.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-invalidate-cache.png\" alt=\"Gradle upgrade\" class=\"q-mt-md rounded-borders\" style=\"max-width: 350px\">\n\n:::\n\nIn order for you to be able to develop on a device emulator or directly on a phone (with Hot Module Reload included), Quasar CLI follows these steps:\n\n1. Detects your machine's external IP address. If there are multiple such IPs detected, then it asks you to choose one. If you'll be using a mobile phone to develop then choose the IP address of your machine that's pingable from the phone/tablet.\n2. It starts up a development server on your machine.\n3. It tells Capacitor to use the IP previously detected. This allows the app to connect to the development server.\n4. It uses the Capacitor CLI to update all of your plugins.\n5. Finally, it opens your native IDE. Run your app here, and it will automatically connect to the dev server.\n\n::: danger\nIf developing on a mobile phone/tablet, it is very important that the external IP address of your build machine is accessible from the phone/tablet, otherwise you'll get a development app with white screen only. Also check your machine's firewall to allow connections to the development chosen port.\n:::\n\n## Building for Production\n\n```bash\n$ quasar build -m capacitor -T [ios|android]\n\n# ..or the longer form:\n$ quasar build --mode capacitor --target [ios|android]\n```\n\n- These commands parse and build your `/src` folder then overwrite `/src-capacitor/www` then use the Gradle/xcodebuild to generate the final assets that go into a phone/tablet.\n\n- Built packages will be located in `/dist/capacitor` unless configured otherwise.\n\n- If you wish to skip the Gradle/xcodebuild step and only fill `/src-capacitor/www` folder:\n\n```bash\n$ quasar build -m capacitor -T [ios|android] --skip-pkg\n```\n\n- Should you wish to manually build the final assets using the IDE (Android Studio / Xcode) instead of doing a terminal build, then:\n\n```bash\n$ quasar build -m capacitor -T [ios|android] --ide\n```\n\n::: warning\nIn Android Studio, you will be greeted with a message recommending to upgrade the Gradle version. **DO NOT UPGRADE GRADLE** as it will break the Capacitor project. Same goes for any other requested upgrades.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-upgrade-notice.png\" alt=\"Gradle upgrade\" class=\"q-my-md rounded-borders\" style=\"max-width: 350px\">\n\nIf you encounter any IDE errors then click on File > Invalidate caches and restart.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-invalidate-cache.png\" alt=\"Gradle upgrade\" class=\"q-mt-md rounded-borders\" style=\"max-width: 350px\">\n\n:::\n\nIf you want a production build with debugging enabled for the UI code:\n\n```bash\n$ quasar build -m capacitor -T [ios|android] -d\n\n# ..or the longer form\n$ quasar build -m capacitor -T [ios|android] --debug\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3798,"content_sha256":"7ab91e89cb7ba8138308f5be4b8ea09254dc83d1052a66e203370ee7c493f4ac"},{"filename":"references/docs/quasar-cli-webpack/developing-capacitor-apps/capacitor-api.md","content":"---\ntitle: Capacitor APIs\ndesc: (@quasar/app-webpack) How to use the Capacitor plugins in a Quasar app.\n---\n\nYou can hook into the native device APIs by using Capacitor APIs.\n\n## Capacitor APIs\n\nA few examples of such APIs:\n\n- Background Task\n- Camera\n- Console\n- Device\n- Filesystem\n- Geolocation\n- Motion\n- Network\n- Push Notifications\n- Share\n- Splash Screen\n- Status Bar\n\n## Using a Capacitor API\n\nLet's learn by taking some examples, assuming you've added Capacitor mode to your Quasar project already.\n\n### Example: Geolocation\n\nFirst step is to read the documentation of the Capacitor API that we want to use. We look at Capacitor's Geolocation API.\n\nNow let's put this plugin to some good use. In one of your Quasar project's pages/layouts/components Vue file, we write:\n\n```html\n// some Vue file // remember this is simply an example; // only look at how we\nuse the API described in the plugin's page; // the rest of things here are of no\nimportance\n\n\u003ctemplate>\n \u003cdiv> GPS position: \u003cstrong>{{ position }}\u003c/strong> \u003c/div>\n\u003c/template>\n\n\u003cscript>\n import { ref, onMounted, onBeforeUnmount } from 'vue'\n import { Geolocation } from '@capacitor/geolocation'\n\n export default {\n setup() {\n const position = ref('determining...')\n\n function getCurrentPosition() {\n Geolocation.getCurrentPosition().then(newPosition => {\n console.log('Current', newPosition)\n position.value = newPosition\n })\n }\n\n let geoId\n\n onMounted(() => {\n getCurrentPosition()\n\n // we start listening\n geoId = Geolocation.watchPosition({}, (newPosition, err) => {\n console.log('New GPS position')\n position.value = newPosition\n })\n })\n\n onBeforeUnmount(() => {\n // we do cleanup\n Geolocation.clearWatch(geoId)\n })\n\n return {\n position\n }\n }\n }\n\u003c/script>\n```\n\n### Example: Camera\n\nFirst step is to read the documentation of the Capacitor API that we want to use. We look at Capacitor's Camera API.\n\nNow let's put this API to some good use. In one of your Quasar project's pages/layouts/components Vue file, we write:\n\n```html\n// some Vue file // remember this is simply an example; // only look at how we\nuse the API described in the plugin's page; // the rest of things here are of no\nimportance\n\n\u003ctemplate>\n \u003cdiv>\n \u003cq-btn color=\"primary\" label=\"Get Picture\" @click=\"captureImage\" />\n\n \u003cimg :src=\"imageSrc\" />\n \u003c/div>\n\u003c/template>\n\n\u003cscript>\n import { ref } from 'vue'\n import { Camera, CameraResultType } from '@capacitor/camera'\n\n export default {\n setup() {\n const imageSrc = ref('')\n\n async function captureImage() {\n const image = await Camera.getPhoto({\n quality: 90,\n allowEditing: true,\n resultType: CameraResultType.Uri\n })\n\n // The result will vary on the value of the resultType option.\n // CameraResultType.Uri - Get the result from image.webPath\n // CameraResultType.Base64 - Get the result from image.base64String\n // CameraResultType.DataUrl - Get the result from image.dataUrl\n imageSrc.value = image.webPath\n }\n\n return {\n imageSrc,\n captureImage\n }\n }\n }\n\u003c/script>\n```\n\nSome Capacitor plugins, such as Camera, have a web-based UI available when not running natively but in a standard web browser. To enable these controls, add @ionic/pwa-elements to your project:\n\n```bash\n$ npm install @ionic/pwa-elements\n```\n\nThen create a boot file to initialize them, for example `src/boot/capacitor.js`:\n\n```js\nimport { defineCustomElements } from '@ionic/pwa-elements/loader'\n\nexport default () => {\n defineCustomElements(window)\n}\n```\n\nDon't forget to call the boot script in the `quasar.config` file:\n\n```js\nboot: ['capacitor']\n```\n\nNow you are able to use the Camera API not just in native Android or iOS, but also in web based projects like a SPA or PWA.\n\n### Example: Device\n\nFirst step is to read the documentation of the Capacitor API that we want to use. Look at the Capacitor's Device API.\n\nNow let's put this API to some good use. In one of your Quasar project's pages/layouts/components Vue file, we write:\n\n```html\n// some Vue file // remember this is simply an example; // only look at how we\nuse the API described in the plugin's page; // the rest of things here are of no\nimportance\n\n\u003ctemplate>\n \u003cdiv>\n \u003cdiv>Model: {{ model }}\u003c/div>\n \u003cdiv>Manufacturer: {{ manufacturer }}\u003c/div>\n \u003c/div>\n\u003c/template>\n\n\u003cscript>\n import { ref, onMounted } from 'vue'\n import { Device } from '@capacitor/device'\n\n export default {\n setup() {\n const model = ref('Please wait...')\n const manufacturer = ref('Please wait...')\n\n onMounted(() => {\n Device.getInfo().then(info => {\n model.value = info.model\n manufacturer.value = info.manufacturer\n })\n })\n\n return {\n model,\n manufacturer\n }\n }\n }\n\u003c/script>\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4966,"content_sha256":"6296dc4633f36db3ff7964e8d29c97c85263ac13efe82e2bd17f1e6710e4b4ae"},{"filename":"references/docs/quasar-cli-webpack/developing-capacitor-apps/capacitor-version-support.md","content":"---\ntitle: Capacitor versions\ndesc: (@quasar/app-webpack) Supported Capacitor versions in Quasar. How to upgrade to a newer Capacitor version.\n---\n\nThe officially supported versions of Capacitor are v1 through v6.\n\n## Upgrading Capacitor\n\nIf you previously used a lower version of Capacitor and you want to upgrade to a newer version, then:\n\n1. Delete the /src-capacitor/ios and /src-capacitor/android folders, but make sure that you are aware of any changes that you made in those folders as you will have to redo them after step 4.\n2. Change /src-capacitor/package.json to reflect the correct versions of Capacitor dependencies (you can read them in the next appropriate section related to your desired Capacitor version).\n3. Delete yarn.lock/package-lock.json then run `yarn` / `npm install` in /src-capacitor.\n4. At this point, you will have Capacitor installed. Now you can run `quasar dev -m capacitor -T [ios|android]` or `quasar build -m capacitor -T [ios|android]` and it will add the upgraded iOS/Android platform that corresponds to your Capacitor version.\n\nIt would also be wise to check the changelog of Capacitor itself to see what breaking changes it has.\n\n## Capacitor v8\n\n::: warning Requirements\n\n- Node v22.21.1+\n- Xcode 16+ (for iOS)\n- Xcode Command Line Tools\n- Homebrew\n- Cocoapods\n- Android Studio 2024.2.1+\n- Android SDK (API 23+)\n :::\n\nAssuming that you've installed Capacitor mode already, this is how your dependencies in `/src-capacitor/package.json` should look like:\n\n```json /src-capacitor/package.json\ndependencies: {\n \"@capacitor/app\": \"^8.0.0\",\n \"@capacitor/cli\": \"^8.0.0\",\n \"@capacitor/core\": \"^8.0.0\",\n \"@capacitor/splash-screen\": \"^8.0.0\"\n}\n```\n\nThe `@capacitor/app` and `@capacitor/splash-screen` are optional, but it helps Quasar with some UI functionality if they are installed.\n\n## Capacitor v7\n\n::: warning Requirements\n\n- Xcode 16+ (for iOS)\n- Xcode Command Line Tools\n- Homebrew\n- Cocoapods\n- Android Studio 2024.2.1+\n- Android SDK (API 23+)\n :::\n\nAssuming that you've installed Capacitor mode already, this is how your dependencies in `/src-capacitor/package.json` should look like:\n\n```json /src-capacitor/package.json\ndependencies: {\n \"@capacitor/app\": \"^7.0.0\",\n \"@capacitor/cli\": \"^7.0.0\",\n \"@capacitor/core\": \"^7.0.0\",\n \"@capacitor/splash-screen\": \"^7.0.0\"\n}\n```\n\nThe `@capacitor/app` and `@capacitor/splash-screen` are optional, but it helps Quasar with some UI functionality if they are installed.\n\n## Capacitor v6\n\n::: warning Requirements\n\n- Xcode 15+ (for iOS)\n- Android Studio Jellyfish 2023.3.1.18 or newer (for Android)\n :::\n\nAssuming that you've installed Capacitor mode already, this is how your dependencies in `/src-capacitor/package.json` should look like:\n\n```json /src-capacitor/package.json\ndependencies: {\n \"@capacitor/app\": \"^6.0.0\",\n \"@capacitor/cli\": \"^6.0.0\",\n \"@capacitor/core\": \"^6.0.0\",\n \"@capacitor/splash-screen\": \"^6.0.0\"\n}\n```\n\nThe `@capacitor/app` and `@capacitor/splash-screen` are optional, but it helps Quasar with some UI functionality if they are installed.\n\n## Capacitor v5\n\n::: warning Requirements\n\n- Xcode 14.1+ (for iOS)\n- Android Studio Flamingo 2022.2.1 or newer (for Android)\n :::\n\nAssuming that you've installed Capacitor mode already, this is how your dependencies in `/src-capacitor/package.json` should look like:\n\n```json /src-capacitor/package.json\ndependencies: {\n \"@capacitor/app\": \"^5.0.0\",\n \"@capacitor/cli\": \"^5.0.0\",\n \"@capacitor/core\": \"^5.0.0\",\n \"@capacitor/splash-screen\": \"^5.0.0\"\n}\n```\n\nThe `@capacitor/app` and `@capacitor/splash-screen` are optional, but it helps Quasar with some UI functionality if they are installed.\n\n## Capacitor v4\n\nAssuming that you've installed Capacitor mode already, this is how your dependencies in `/src-capacitor/package.json` should look like:\n\n```json /src-capacitor/package.json\ndependencies: {\n \"@capacitor/app\": \"^4.0.0\",\n \"@capacitor/cli\": \"^4.0.0\",\n \"@capacitor/core\": \"^4.0.0\",\n \"@capacitor/splash-screen\": \"^4.0.0\"\n}\n```\n\nThe `@capacitor/app` and `@capacitor/splash-screen` are optional, but it helps Quasar with some UI functionality if they are installed.\n\n## Capacitor v3\n\n::: warning Known issue\nHTTPS devserver (through quasar.config file > devServer > https: true) is not supported. If you are using Capacitor plugins that depend on it, it's better to upgrade to the newer supported Capacitor versions.\n:::\n\nAssuming that you've installed Capacitor mode already, this is how your dependencies in `/src-capacitor/package.json` should look like:\n\n```json /src-capacitor/package.json\ndependencies: {\n \"@capacitor/app\": \"^1.0.0\",\n \"@capacitor/cli\": \"^3.0.0\",\n \"@capacitor/core\": \"^3.0.0\",\n \"@capacitor/splash-screen\": \"^1.0.0\"\n}\n```\n\nThe `@capacitor/app` and `@capacitor/splash-screen` are optional, but it helps Quasar with some UI functionality if they are installed.\n\nMore info for Switch to automatic Android plugin loading.\n\n## Capacitor v2\n\nAssuming that you've installed Capacitor mode already, this is how your dependencies in `/src-capacitor/package.json` should look like:\n\n```json /src-capacitor/package.json\ndependencies: {\n \"@capacitor/cli\": \"^2.0.0\",\n \"@capacitor/core\": \"^2.0.0\"\n}\n```\n\n## Capacitor v1\n\nAssuming that you've installed Capacitor mode already, this is how your dependencies in `/src-capacitor/package.json` should look like:\n\n```json /src-capacitor/package.json\ndependencies: {\n \"@capacitor/cli\": \"^1.0.0\",\n \"@capacitor/core\": \"^1.0.0\"\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5455,"content_sha256":"480e02f931bc2258f9d9690952e3a6e820f2713049582177ec14f164fb29ddd8"},{"filename":"references/docs/quasar-cli-webpack/developing-capacitor-apps/configuring-capacitor.md","content":"---\ntitle: Configuring Capacitor\ndesc: (@quasar/app-webpack) How to manage your Capacitor apps with Quasar CLI.\nrelated:\n - /quasar-cli-webpack/quasar-config-file\n---\n\nWe'll be using Quasar CLI to develop and build a Mobile App. The difference between building a SPA, PWA, Electron App or a Mobile App is simply determined by the \"mode\" parameter in \"quasar dev\" and \"quasar build\" commands.\n\nThere are two configuration files of great importance to your mobile apps. We'll go over each one.\n\n## capacitor.config.json\n\nThe most important config file for your mobile app is `/src-capacitor/capacitor.config.json`. The `/src-capacitor` folder is a Capacitor project, so please refer to Capacitor documentation in order to understand what each file from there does. But for now, have a few moments to read about capacitor.config.json.\n\nSome properties from this file will get overwritten as we'll see in next section.\n\n## quasar.config file\n\nThere are two places in the `/quasar.config` file where you can configure Quasar specific features for Capacitor.\n\n```js /quasar.config file\nreturn {\n capacitor: {\n /**\n * Automatically hide the Capacitor Splashscreen when app is ready,\n * (is using the Splashscreen Capacitor plugin).\n *\n * @default true\n */\n hideSplashscreen?: boolean;\n\n /**\n * Preparation params with which the Capacitor CLI is called\n *\n * @default [ 'sync', ctx.targetName ]\n */\n capacitorCliPreparationParams?: string[];\n\n /** If not present, will look for `package.json > name` */\n appName?: string;\n /** If not present, will look for `package.json > version` */\n version?: string;\n /** If not present, will look for `package.json > description` */\n description?: string;\n }\n}\n```\n\nAnd you can also configure:\n\n```js /quasar.config file\nreturn {\n framework: {\n config: {\n capacitor: {\n iosStatusBarPadding: true / false // add the dynamic top padding on iOS mobile devices\n }\n }\n }\n}\n```\n\nFinally, you can also disable or configure the back button hook (used for Dialogs):\n\n```js /quasar.config file\nreturn {\n framework: {\n config: {\n capacitor: {\n // Quasar handles app exit on mobile phone back button.\n backButtonExit: true / false / '*' / ['/login', '/home', '/my-page'],\n\n // On the other hand, the following completely\n // disables Quasar's back button management.\n backButton: true / false\n }\n }\n }\n}\n```\n\nShould you want to tamper with the Webpack config for UI in /src you have two options:\n\n```js /quasar.config file\nbuild: {\n extendWebpack(webpackCfg) { ... },\n chainWebpack(webpackChain) { ... }\n}\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2677,"content_sha256":"f95876dcbda3b2e4962d0148d0bcdd0a50f0b5cca9dffc4d2e2840d57e68d074"},{"filename":"references/docs/quasar-cli-webpack/developing-capacitor-apps/introduction.md","content":"---\ntitle: What is Capacitor\ndesc: (@quasar/app-webpack) Introduction on one of the technologies behind Quasar mobile apps.\n---\n\nCapacitor is a cross-platform native runtime for deploying web applications to mobile. It is maintained by Ionic and designed as a modern successor to Cordova. It supports most, but not all Cordova plugins, as well as Capacitor-specific plugins (called APIs). It exposes native device APIs in the form of JavaScript modules.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":454,"content_sha256":"59f65adfecc729c5afa5d35b8cab29e8d3f8bd76bbb86d375be74cb0b7196cc8"},{"filename":"references/docs/quasar-cli-webpack/developing-capacitor-apps/live-updates.md","content":"---\ntitle: Live Updates\ndesc: (@quasar/app-vite) How to enable live updates for a Quasar hybrid mobile app with Capacitor.\n---\n\nLive Updates, also known as Over-the-Air (OTA) or hot code updates, are a way to push updates to your app without going through the app store review process. This is particularly useful for bug fixes or minor updates that don't require a full app release.\n\n## Installation\n\nTo enable Live Updates in your Quasar Capacitor app, you need to install the `@capawesome/capacitor-live-update` plugin. First, navigate to your Capacitor project directory:\n\n```bash\ncd src-capacitor\n```\n\nThen, install the plugin:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn add @capawesome/capacitor-live-update\n\u003c\u003c| bash NPM |>>\n$ npm install --save @capawesome/capacitor-live-update\n\u003c\u003c| bash PNPM |>>\n$ pnpm add @capawesome/capacitor-live-update\n\u003c\u003c| bash Bun |>>\n$ bun add @capawesome/capacitor-live-update\n```\n\nAfter that, you need to sync the changes with your native projects:\n\n```bash\nnpx cap sync\n```\n\n## Configuration\n\nNext, you need to configure the plugin to work with Capawesome Cloud.\n\n### App ID\n\nIn order for your app to identify itself to Capawesome Cloud, you need to set the `appId` in your `capacitor.config` file. For this, you need to create an app on the Capawesome Cloud Console and get the App ID.\n\n```json /src-capacitor/capacitor.config file\n{\n \"plugins\": {\n \"LiveUpdate\": {\n \"appId\": \"00000000-0000-0000-0000-000000000000\"\n }\n }\n}\n```\n\nReplace `00000000-0000-0000-0000-000000000000` with your actual App ID from the Capawesome Cloud Console.\n\nAfter configuring the App ID, sync your Capacitor project again:\n\n```bash\nnpx cap sync\n```\n\n## Usage\n\nThe most basic usage of the Live Update plugin is to call the `sync(...)` method when the app starts. This method checks for updates, downloads them if available, and sets them as the next bundle to be applied. You can then call the `reload()` method to apply the update immediately. If the `reload()` method is not called, the new bundle will be used on the next app start.\n\n```js\nimport { LiveUpdate } from '@capawesome/capacitor-live-update'\n\nconst sync = async () => {\n const result = await LiveUpdate.sync()\n if (result.nextBundleId) {\n await LiveUpdate.reload()\n }\n}\n```\n\n## Publishing updates\n\nTo publish your first update, you need to create a bundle on Capawesome Cloud. For this, you need a bundle artifact. A bundle artifact is the build output of your web app. In Quasar, this is the `src-capacitor/www` folder. You can create a bundle artifact by running the following command:\n\n```bash\nquasar build -m capacitor -T [android|ios]\n```\n\nThis will create a `src-capacitor/www` folder with the build output of your web app. You can then upload this folder to Capawesome Cloud using the Capawesome CLI.\nTo install the Capawesome CLI, run the following command:\n\n```tabs\n\u003c\u003c| bash Yarn |>>\n$ yarn global add @capawesome/cli\n\u003c\u003c| bash NPM |>>\n$ npm i -g @capawesome/cli\n\u003c\u003c| bash PNPM |>>\n$ pnpm add -g @capawesome/cli\n\u003c\u003c| bash Bun |>>\n$ bun install -g @capawesome/cli\n```\n\nAfter installing the Capawesome CLI, you need to log in to your Capawesome Cloud account. Run the following command and follow the instructions:\n\n```bash\nnpx capawesome login\n```\n\nOnce you are logged in, you can create a bundle by running the following command:\n\n```bash\nnpx capawesome apps:bundles:create --path src-capacitor/www\n```\n\nCongratulations! You have successfully published your first live update. You can now test it by running your app on a device or emulator. The app will check for updates and apply them if available.\nFeel free to check out the documentation of the Live Update plugin to see what else you can do with it.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3697,"content_sha256":"0acb067b09dbdd1c88cba3afb6b0e49f78bed235ff7f732cd34186ca19512fc1"},{"filename":"references/docs/quasar-cli-webpack/developing-capacitor-apps/managing-google-analytics.md","content":"---\ntitle: Managing Google Analytics\ndesc: (@quasar/app-webpack) How to use analytics in a Quasar hybrid mobile app with Capacitor.\n---\n\nGetting to know your users and measuring user behavior is an important step in App Development. Unfortunately, it takes a bit of non-standard work to get Google Analytics to work after wrapping your mobile app with Capacitor. Setting up Google Analytics in a pure web application is quite easy, but Capacitor somehow prevents pageviews and events from being sent to Google Analytics.\n\nFollow this guide to implement Google Analytics into your Capacitor powered Quasar App.\n\n::: warning\nYou'll need to include a `\u003cscript>` tag provided by Google in `/index.html`, which will make your App depend on an Internet connection!\n:::\n\n## Prerequisites\n\n- Make sure all your routes have a name and path parameter specified. Otherwise, they cannot be posted to the `ga.logPage` function. Please refer to [Routing](/quasar-cli-webpack/routing) for more info on routing.\n- Have Basic knowledge of Google Analytics\n\n## Preparation\n\nBefore we can start implementing Google Analytics into your application, you'll need an account for Google Analytics and Google Tagmanager. So let's do that first. When you have these accounts, it's time to configure Tag manager. Follow the steps in this Multiminds article to do so.\n\n## Implementing this into application\n\n> For this guide, we'll assume you have a fixed sessionId that you send to Google Analytics. Google Analytics uses a sessionId to distinguish different users from each other. If you want to create an anonymous sessionId, see Analytics Documentation on user id.\n\nPlace the Tag Manager snippet into head of your `index.html` file (if you've followed the Multiminds article, you already have this.) Create a new file in your codebase called `analytics.js` with the following contents:\n\n```javascript\nexport default {\n logEvent(category, action, label, sessionId = null) {\n window.dataLayer.push({\n appEventCategory: category,\n appEventAction: action,\n appEventLabel: label,\n sessionId: sessionId\n })\n window.dataLayer.push({ event: 'appEvent' })\n },\n\n logPage(path, name, sessionId = null) {\n window.dataLayer.push({\n screenPath: path,\n screenName: name,\n sessionId: sessionId\n })\n window.dataLayer.push({ event: 'appScreenView' })\n }\n}\n```\n\nTo make sure all the pages in your application are automatically posted to Google Analytics, we create an app boot file:\n\n```bash\n$ quasar new boot google-analytics [--format ts]\n```\n\nThen we edit the newly created file: `/src/boot/google-analytics.js`:\n\n```js\nimport { defineRouter } from '#q-app/wrappers'\nimport ga from 'analytics.js'\n\nexport default defineRouter(({ router }) => {\n router.afterEach((to, from) => {\n ga.logPage(to.path, to.name, sessionId)\n })\n})\n```\n\nFinally we register the app boot file in the `/quasar.config` file. We can do so only for Capacitor wrapped apps if we want:\n\n```js\nboot: [ctx.mode.capacitor ? 'google-analytics' : '']\n```\n\nMore information about events can be found in the Analytics documentation on events.\n\nYou'll see the events and pageviews coming in when you run your app. It usually takes around 5 to 10 seconds for a pageview to be registered in the realtime view.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3292,"content_sha256":"7e99f46f92738a4583002527d5fae064464b97681b52b088e017483664b23527"},{"filename":"references/docs/quasar-cli-webpack/developing-capacitor-apps/preparation.md","content":"---\ntitle: Preparation for Capacitor App\ndesc: (@quasar/app-webpack) What you need to do before developing a Quasar hybrid mobile app with Capacitor.\n---\n\nBefore we dive in to the actual development, we need to do some preparation work.\n\n## Step 1: Installation\n\n### Android setup\n\n- You will need to install Android Studio and the Android platform SDK on your machine. You can download the Android Studio here and follow these installation steps afterwards.\n\n- Make sure that after you install the Android SDK you then accept its licenses. Open the terminal and go to the folder where the SDK was installed, in tools/bin and call `sdkmanager --licenses`.\n\n::: warning\nThe environmental variable `ANDROID_HOME` has been deprecated and replaced with `ANDROID_SDK_ROOT`. Depending on your version of Android Studio you may need one or the other. It doesn't hurt to have both set.\n:::\n\n- Add Android installation to your path:\n\n#### Unix (macOS, linux)\n\n```bash\nexport ANDROID_HOME=\"$HOME/Android/Sdk\"\nexport ANDROID_SDK_ROOT=\"$HOME/Android/Sdk\"\nPATH=$PATH:$ANDROID_SDK_ROOT/tools; PATH=$PATH:$ANDROID_SDK_ROOT/platform-tools\n```\n\n> Please note that sometimes the `/Android/Sdk` folder is added inside `/Library/` inside your user folder. Check your user folder and if the `/Android/` folder is only inside `/Library/` do: `export ANDROID_SDK_ROOT=\"$HOME/Library/Android/Sdk\"` or `export ANDROID_HOME=\"$HOME/Library/Android/Sdk\"` instead.\n\n#### Windows\n\n```bash\nsetx ANDROID_HOME \"%USERPROFILE%\\AppData\\Local\\Android\\Sdk\"\nsetx ANDROID_SDK_ROOT \"%USERPROFILE%\\AppData\\Local\\Android\\Sdk\"\nsetx path \"%path%;%ANDROID_SDK_ROOT%\\tools;%ANDROID_SDK_ROOT%\\platform-tools\"\n```\n\n- Start Android studio (check the executable in the folder that you installed it in). Next step is to install the individual SDKs:\n\n- Open the \"Configure\" menu at the bottom of the window:\n\n \n\n- Select the desired SDKs and click on \"Apply\" to install the SDKs.\n\n \n\n### iOS setup\n\nYou will need a macOS with Xcode installed. After you've installed it, open Xcode in order to get the license prompt. Accept the license, then you can close it.\n\n#### CocoaPods\n\nIf you haven't installed CocoaPods, please install it by using the command: `sudo gem install cocoapods`. Otherwise, you may encounter errors during development or building, such as:\n\n::: warning terminal warning\n[warn] Skipping pod install because CocoaPods is not installed,\n:::\n\n::: danger Xcode Error\n/path-to/your-project/src-capacitor/ios/App/Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig:1:1 unable to open configuration settings file\n:::\n\n## Step 2: Add Capacitor Quasar Mode\n\nIn order to develop/build a Mobile app, we need to add the Capacitor mode to our Quasar project. This will use the Capacitor CLI to generate a Capacitor project in `/src-capacitor` folder.\n\n```bash\n$ quasar mode add capacitor\n```\n\n## Step 3: Start Developing\n\nTo start a dev server with HMR, run the command below:\n\n```bash\n$ quasar dev -m capacitor -T [android|ios]\n```\n\nOnce the dev server is ready, your IDE will open (Android Studio or Xcode) and from there you can manually select the emulator (or multiple ones simultaneously!) and install the dev app on it/them. You can also run the dev app on a connected mobile/tablet device.\n\n::: warning\nIn Android Studio, you will be greeted with a message recommending to upgrade the Gradle version. **DO NOT UPGRADE GRADLE** as it will break the Capacitor project. Same goes for any other requested upgrades.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-upgrade-notice.png\" alt=\"Gradle upgrade\" class=\"q-my-md rounded-borders\" style=\"max-width: 350px\">\n\nIf you encounter any IDE errors then click on File > Invalidate caches and restart.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-invalidate-cache.png\" alt=\"Gradle upgrade\" class=\"q-mt-md rounded-borders\" style=\"max-width: 350px\">\n\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3861,"content_sha256":"a81ab133795c7fd3852170dfa80ef5b28cbcc82586a14892ed97252dd2708a3d"},{"filename":"references/docs/quasar-cli-webpack/developing-capacitor-apps/publishing-to-store.md","content":"---\ntitle: Publishing to Store\ndesc: (@quasar/app-webpack) How to publish a Quasar hybrid mobile app with Capacitor to Google Play Store and to Apple App Store.\n---\n\nSo, you've finished working on your Mobile App. Now it's time to deploy it. Let's learn how.\n\n## Android Publishing\n\nTo generate a release build for Android, we can use the following Quasar CLI command:\n\n```bash\n$ quasar build -m capacitor -T android\n```\n\nThis will compile the web assets (and if \"--ide\" param is also specified, it will open up Android Studio IDE where you need to trigger a release build).\n\nNext, we find our unsigned APK file generated by the Android Studio. Now, we need to sign the unsigned APK and run an alignment utility on it to optimize it and prepare it for the app store. If you already have a signing key, skip these steps and use that one instead.\n\nLet’s generate our private key using the keytool command that comes with the JDK. If this tool isn’t found, refer to the installation guide:\n\n```bash\n$ keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 20000\n```\n\nYou’ll first be prompted to create a password for the keystore. Then, answer the rest of the nice tool’s questions and when it’s all done, you should have a file called my-release-key.keystore created in the current directory.\n\n::: danger\nMake sure to save this file somewhere safe and secure, if you lose it you won’t be able to submit updates to your app!\n:::\n\nNext, we need to _zip align_ and to sign the APK. For this we use a couple of applications that can be found in the Android SDK `build-tools` folder, something like `/path/to/Android/Sdk/build-tools/VERSION/`. For example, on OS X with Android Studio installed, `zipalign` is in `~/Library/Android/Sdk/build-tools/VERSION/`.\n\nTo zip align the APK:\n\n```bash\n$ zipalign -v 4 \u003cpath-to-same-apk-file> HelloWorld.apk\n```\n\nTo sign the APK:\n\n```bash\napksigner sign --ks my-release-key.keystore --ks-key-alias alias_name \u003cpath-to-unsigned-apk-file>\n```\n\nNow we have our final release binary called HelloWorld.apk and we can release this on the Google Play Store for all the world to enjoy!\n\n(There are a few other ways to sign APKs. Refer to the official Android App Signing documentation for more information.)\n\n### Google Play Store\n\nNow that we have our release APK ready for the Google Play Store, we can create a Play Store listing and upload our APK.\n\nTo start, you’ll need to visit the Google Play Store Developer Console and create a new developer account. Unfortunately, this is not free. However, the cost is only $25 compared to Apple’s $99.\n\nOnce you have a developer account, you can go ahead and click “Publish an Android App on Google Play”.\n\nThen, you can go ahead and click the button to edit the store listing (We will upload an APK later). You’ll want to fill out the description for the app.\n\nWhen you are ready, upload the APK for the release build and publish the listing. Be patient and your hard work should be live in the wild!\n\n### Updating your App\n\nAs you develop your app, you’ll want to update it periodically.\n\nIn order for the Google Play Store to accept updated APKs, you’ll need to bump the app version (from `/package.json` or from `/quasar.config file > capacitor > version`, then rebuild the app for release.\n\n## iOS Publishing\n\nFirst, you need to enroll in Apple Developer Program. As with Google, if you have a personal account with Apple, you can create an additional one for your applications.\n\n### Connecting Xcode with your developer account\n\nAfter you receive your developer status, open Xcode on your Mac and go to Preferences > Accounts. Add your account to Xcode by clicking the `+` button on the lower left-hand side and follow the instructions.\n\n### Signing\n\nNow that you linked Xcode with your developer account, go to Preferences > Accounts, select your Apple Id on the left-hand side and then click the View Details button shown on the previous image.\n\nClick the Create button next to the iOS Distribution option.\n\nYou can learn more about maintaining your signing identities and certificates from the official documentation.\n\n### Setting up the app identifier\n\nNext, through the Apple Developer Member Center we’ll set up the app ID identifier details. Identifiers are used to allow an app to have access to certain app services like for example Apple Pay. You can login to Apple Developer Member Center with your Apple ID and password.\n\nOnce you’re logged in you should choose Certificates, Identifiers, and Profiles option. Also select the Identifiers option under the iOS Apps. Then select the `+` button in order to add a new iOS App ID.\n\nThen you’ll have to set the name of your app, use the Explicit App ID option and set the Bundle ID to the value of the id in your capacitor.config.json.\n\nAdditionally, you’ll have to choose any of the services that need to be enabled. For example, if you use Apple Pay or Wallet in your app, you need to choose those option.\n\nYou can learn more about registering app identifiers from the official documentation.\n\n### Creating the app listing\n\nApple uses iTunes Connect to manage app submissions. After your login, you should select the My Apps button, and on the next screen select the `+` button, just below the iTunes Connect My Apps header.\n\nThis will show three options in a dropdown, and you should select the New App. After this the popup appears where you have to choose the name of the application, platform, primary language, bundle ID and SKU.\n\nOnce you’re done, click on the Create button and you’ll be presented with a screen where you’ll have to set some basic options like Privacy Policy URL, category and sub category.\n\nNow, before we fill out everything in the listing, we’ll build our app and get it uploaded with Xcode. Then you’ll come back to finish the listing.\n\nYou can learn more about managing your app in iTunes Connect from the official documentation.\n\n### Building the app for production\n\n```bash\n$ quasar build -m capacitor -T ios\n```\n\nThis will compile the web assets (and if \"--ide\" param is also specified, it will open up Xcode where you need to trigger a release build).\n\n### Configuring the project in Xcode\n\nOnce Xcode opens up the project (\"--ide\" param required), you should see the details about your app in the general view.\n\nYou should just check that the bundle identifier is set up correctly, so that it’s the same as the value you specified earlier in the app ID. Also, make sure that the version and build numbers are correct. Team option should be set to your Apple developer account. Under the deployment target you can choose which devices your application will support.\n\n### Creating an archive of the application\n\nIn Xcode, select Product > Scheme > Edit Scheme to open the scheme editor. Next, select the Archive from the list on the left-hand side. Make sure that the Build configuration is set to Release.\n\nTo create an archive, choose a Generic iOS Device, or your device if it’s connected to your Mac (you can’t create an archive if simulator is selected), from the Scheme toolbar menu in the project editor.\n\nNext, select Product > Archive, and the Archive organizer appears and displays the new archive.\n\nAt this point you can click the `Upload to App Store...` button, and if everything goes fine you’ll have an uploaded app, and the only thing that’s left to do is to complete the iTunes Connect listing and submit it for review!\n\nAt this point you should get an email from iTunes Connect shortly after you uploaded the archive with the content.\n\n### Finishing the app list process\n\nNow you should head back to the iTunes Connect portal and login. Next, click on the Pricing and Availability on the left-hand side under APP STORE INFORMATION.\n\nYou don’t have to worry about forgetting to insert any crucial and required information about your application, since you’ll be notified about what’s missing and what needs to be added/changed if you try to submit the app for review before all details are filled in.\n\nNext, click on the 1.0 Prepare for Submission button on the left-hand side, as shown on the image below. When we uploaded our archive, iTunes Connect automatically determined which device sizes are supported. You’ll need to upload at least one screenshot image for each of the various app sizes that were detected by iTunes Connect.\n\nNext, you’ll have to insert Description, Keywords, Support URL and Marketing URL (optionally).\n\nIn the Build section you have to click on the `+` button and select the build that was uploaded through Xcode in the previous steps.\n\nNext, you’ll have to upload the icon, edit the rating, and set some additional info like copyright and your information. Note that the size of the icon that you’ll have to upload here will have to be 1024 by 1024 pixels. Thankfully, you can use the splash.png from the second tutorial. If you’re the sole developer then the data in the App Review Information should be your own. Finally, as the last option, you can leave the default checked option that once your app is approved that it is automatically released to the App Store.\n\nNow that we’re finished with adding all of the details to the app listing, we can press Save and then Submit for Review. Finally, you’ll be presented with the last form that you’ll have to fill out.\n\nAfter you submit your app for review you’ll see the status of it in the My Apps as Waiting for review, as shown on the image below. Also, shortly after you submit your app for review you’ll get a confirmation email from iTunes Connect that your app is in review.\n\nApple prides itself with a manual review process, which basically means it can take several days for your app to be reviewed. You’ll be notified of any issues or updates to your app status.\n\n### Updating the app\n\nSince you’ll probably want to update your app at some point you’ll first need to bump the app version (from `/package.json`), then rebuild the app for release. Once Xcode opens, follow the same steps all over again.\n\nOnce you submit for the review, you’ll have to wait for the review process again.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":10198,"content_sha256":"da84a1f01cb104da982168b538b437874b59fb67bb07ef0c6114bcd138fd875c"},{"filename":"references/docs/quasar-cli-webpack/developing-capacitor-apps/troubleshooting-and-tips.md","content":"---\ntitle: Capacitor Troubleshooting and Tips\ndesc: (@quasar/app-webpack) Tips and tricks for a Quasar hybrid mobile app with Capacitor.\n---\n\n## $q.capacitor\n\nWhile you are developing a Mobile App with Capacitor Mode, you can access `$q.capacitor` in your Vue files. This is an alias to the global `Capacitor` Object.\n\n## Android Tips\n\n### Android remote debugging\n\nIf you are debugging Android Apps, you can use Google Chrome Remote Debugging through a USB cable attached to your Android phone/tablet. It can be used for emulator too.\n\nThis way you have Chrome Dev Tools directly for your App running on the emulator/phone/table. Inspect elements, check console output, and so on and so forth.\n\n\n\n\n### Accept Licenses\n\nIf you are having problems getting Android builds to finish and you see a message like:\n\n```\n> Failed to install the following Android SDK packages as some licenses have not been accepted.\n```\n\nIf this is the case you need to accept ALL the licenses. Thankfully there is a tool for this:\n\n- Linux: `sdkmanager --licenses`\n- macOS: `~/Library/Android/sdk/tools/bin/sdkmanager --licenses`\n- Windows: `%ANDROID_SDK_ROOT%/tools/bin/sdkmanager --licenses`\n\n### Android SDK not found after installation of the SDK\n\n::: warning\nThe environmental variable `ANDROID_HOME` has been deprecated and replaced with `ANDROID_SDK_ROOT`. Depending on your version of Android Studio you may need one or the other. It doesn't hurt to have both set.\n:::\n\nSome newer Debian-based OS (e.g. ubuntu, elementary OS) might leave you with a `Android SDK not found.` after you installed and (correctly) configured the environment.\n\nThis could have two different reasons: Usually the paths aren't configured correctly. The first step is to verify if your paths are set correctly. This can be done by running the following commands:\n\n```bash\n$ echo $ANDROID_HOME\n\n# or\n\n$ echo $ANDROID_SDK_ROOT\n\n```\n\nThe expected output should be a path similar to this `$HOME/Android/Sdk`. After this run:\n\n```bash\n$ ls -la $ANDROID_HOME\n\n# or\n\n$ ls -la $ANDROID_SDK_ROOT\n```\n\nTo ensure the folder contains the SDK. The expected output should contain folders like 'tools', 'sources', 'platform-tools', etc.\n\n```bash\n$ echo $PATH\n```\n\nThe output should contain each one entry for the Android SDK 'tools'-folder and 'platform-tools'-tools. This could look like this:\n\n```bash\n/home/your_user/bin:/home/your_user/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/your_user/Android/Sdk/tools:/home/your_user/Android/Sdk/platform-tools\n```\n\n> If you ensured your paths are set correctly and still get the error, you can try the following fix: Replacing the Android Studio 'tools' folder manually\n\n### Android Studio\n\nIn Android Studio (if you open it on `/src-capacitor/android`), you will be greeted with a message recommending to upgrade the Gradle version. **DO NOT UPGRADE GRADLE** as it will break the Capacitor project. Same goes for any other requested upgrades.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-upgrade-notice.png\" alt=\"Gradle upgrade\" class=\"q-mb-md rounded-borders\" style=\"max-width: 350px\">\n\nIf you encounter any IDE errors then click on File > Invalidate caches and restart.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-invalidate-cache.png\" alt=\"Gradle upgrade\" class=\"rounded-borders\" style=\"max-width: 350px\">\n\n### Setting up device on Linux\n\nYou may bump into `?????? no permissions` problem when trying to run your App directly on an Android phone/tablet.\n\nHere's how you fix this:\n\n```bash\n# create the .rules file and insert the content\n# from below this example\nsudo vim /etc/udev/rules.d/51-android.rules\nsudo chmod 644 /etc/udev/rules.d/51-android.rules\nsudo chown root. /etc/udev/rules.d/51-android.rules\nsudo service udev restart\nsudo killall adb\n```\n\nThe content for `51-android.rules`:\n\n```\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0bb4\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0e79\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0502\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0b05\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"413c\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0489\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"091e\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"18d1\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0bb4\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"12d1\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"24e3\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"2116\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0482\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"17ef\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"1004\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"22b8\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0409\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"2080\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0955\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"2257\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"10a9\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"1d4d\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0471\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"04da\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"05c6\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"1f53\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"04e8\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"04dd\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0fce\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0930\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"19d2\", MODE=\"0666\"\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"1bbb\", MODE=\"0666\"\n```\n\nNow running `adb devices` should discover your device.\n\n## iOS Tips\n\n### iOS remote debugging\n\nIf you are debugging iOS Apps, you can use the Safari developer tools to remotely debug through a USB cable attached to your iOS phone/tablet. It can be used for emulator too.\n\nThis way you have Safari developer tools directly for your App running on the emulator/phone/table. Inspect elements, check console output, and so on and so forth.\n\nFirst enable the \"developer\" menu option in the Settings of Safari. Then if you navigate to the \"developer\" menu option you will see your emulator or connected device listed near the top. From here you can open the developer tools.\n\n### Status bar and notch safe-areas\n\nSince mobile phones have a status bar and/or notches, your app's styling might need some tweaking when building on Capacitor. In order to prevent parts of your app from going behind the status bar, there is a global CSS variable that can be used for creating a \"safe-area\". This variable can then be applied in your app's top and bottom padding or margin.\n\nQuasar has support for these CSS safe-areas by default in QHeader/QFooter and Notify. However it's important to always check your Capacitor build on several models to see if all cases of your app are dealing with the safe areas correctly.\n\nIn cases you need to manually tweak your CSS you can do so with:\n\n```\n// for your app's header\npadding-top: constant(safe-area-inset-top) // for iOS 11.0\npadding-top: env(safe-area-inset-top) // for iOS 11.2 +\n// for your app's footer\npadding-bottom: constant(safe-area-inset-bottom)\npadding-bottom: env(safe-area-inset-bottom)\n```\n\nOf course you can also use the above example with `margin` instead of `padding` depending on your app.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":7362,"content_sha256":"1e849049905d61bc55ece7e6cc86ce142b026137d86a76f82ca7173c11a1f02b"},{"filename":"references/docs/quasar-cli-webpack/developing-cordova-apps/build-commands.md","content":"---\ntitle: Mobile App Build Commands\ndesc: (@quasar/app-webpack) The Quasar CLI list of commands when developing or building a hybrid mobile app with Cordova.\n---\n\nBefore we dive in, make sure you got the Cordova CLI installed.\n\n```bash\n$ npm install -g cordova\n```\n\n## Developing\n\n```bash\n$ quasar dev -m [ios|android]\n\n# ..or the explicit form:\n$ quasar dev -m cordova -T [ios|android]\n\n# ..or the longer form:\n$ quasar dev --mode cordova --target [ios|android]\n\n# using a specific emulator (--emulator, -e)\n$ quasar dev -m ios -e iPhone-7\n# or\n$ quasar dev -m ios -e iPhone-X,com.apple.CoreSimulator.SimRuntime.iOS-12-2\n\n# passing extra parameters and/or options to\n# underlying \"cordova\" executable:\n$ quasar dev -m ios -- some params --and options --here\n# when on Windows and using Powershell:\n$ quasar dev -m ios '--' some params --and options --here\n```\n\nHowever, if you wish to open the IDE (Android Studio / Xcode) and from there to manually select the emulator (or multiple ones simultaneously!) to run the dev app on it/them (or to run the dev app on a real mobile/tablet device):\n\n```bash\n$ quasar dev -m [ios|android] --ide\n```\n\n::: warning\nIn Android Studio, you will be greeted with a message recommending to upgrade the Gradle version. **DO NOT UPGRADE GRADLE** as it will break the Cordova project. Same goes for any other requested upgrades.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-upgrade-notice.png\" alt=\"Gradle upgrade\" class=\"q-my-md rounded-borders\" style=\"max-width: 350px\">\n\nIf you encounter any IDE errors then click on File > Invalidate caches and restart.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-invalidate-cache.png\" alt=\"Gradle upgrade\" class=\"q-mt-md rounded-borders\" style=\"max-width: 350px\">\n\n:::\n\nIn order for you to be able to develop on a device emulator or directly on a phone (with Hot Module Reload included), Quasar CLI follows these steps:\n\n1. Detects your machine's external IP address. If there are multiple such IPs detected, then it asks you to choose one. If you'll be using a mobile phone to develop then choose the IP address of your machine that's pingable from the phone/tablet.\n2. It starts up a development server on your machine.\n3. It temporarily changes the `\u003ccontent/>` tag in `/src-cordova/config.xml` to point to the IP previously detected. This allows the app to connect to the development server.\n4. It defers to Cordova CLI to build a native app with the temporarily changed config.xml.\n5. Cordova CLI checks if a mobile phone / tablet is connected to your development machine. If it is, it installs the development app on it. If none is found, then it boots up an emulator and runs the development app.\n6. Finally, it reverts the temporary changes made to `/src-cordova/config.xml`.\n\n::: danger\nIf developing on a mobile phone/tablet, it is very important that the external IP address of your build machine is accessible from the phone/tablet, otherwise you'll get a development app with white screen only. Also check your machine's firewall to allow connections to the development chosen port.\n:::\n\n### Enabling iOS modern build\n\nBy default, Xcode modern build for iOS is disabled due to Cordova issues. However, if you know what you are doing and you want to enable it, do so from the `/quasar.config` file:\n\n```js\ncordova: {\n noIosLegacyBuildFlag: true\n}\n```\n\nThe above applies also if you want to specify the build type in your \"build.json\".\n\n## Building for Production\n\n```bash\n$ quasar build -m [android|ios]\n\n# ..or the explicit form:\n$ quasar build -m cordova -T [ios|android]\n\n# ..or the longer form:\n$ quasar build --mode cordova --target [ios|android]\n\n# this skips .app or .apk creation and just fills in /src-cordova/www\n$ quasar build -m [ios|android] --skip-pkg\n\n# passing extra parameters and/or options to\n# underlying \"cordova\" executable:\n$ quasar build -m ios -- some params --and options --here\n```\n\n- These commands parse and build your `/src` folder then overwrite `/src-cordova/www` then defer to Cordova CLI to trigger the actual native app creation.\n\n- Built packages will be located in `/dist/cordova` unless configured otherwise.\n\n- If you wish to skip the Cordova CLI packaging step and only fill `/src-cordova/www` folder:\n\n```bash\n$ quasar build -m [ios|android] --skip-pkg\n```\n\n- Should you wish to manually build the final assets using the IDE (Android Studio / Xcode) instead of doing a terminal build, then:\n\n```bash\n$ quasar build -m [ios|android] --ide\n```\n\n::: warning\nIn Android Studio, you will be greeted with a message recommending to upgrade the Gradle version. **DO NOT UPGRADE GRADLE** as it will break the Cordova project. Same goes for any other requested upgrades.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-upgrade-notice.png\" alt=\"Gradle upgrade\" class=\"q-my-md rounded-borders\" style=\"max-width: 350px\">\n\nIf you encounter any IDE errors then click on File > Invalidate caches and restart.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/gradle-invalidate-cache.png\" alt=\"Gradle upgrade\" class=\"q-mt-md rounded-borders\" style=\"max-width: 350px\">\n\n:::\n\nIf you want a production build with debugging enabled for the UI code:\n\n```bash\n$ quasar build -m [ios|android] -d\n\n# ..or the longer form\n$ quasar build -m [ios|android] --debug\n```\n\n::: tip\nAlso check `getCordovaBuildParams()` and `getCordovaBuildOutputFolder()` (quasar.config > cordova options) from [Configuring Cordova](/quasar-cli-webpack/developing-cordova-apps/configuring-cordova#quasar-config-file) page.\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5488,"content_sha256":"de8e9730df95bb26c21c830a107ee9cf8528e02a5485f524c07290985bc40b62"},{"filename":"references/docs/quasar-cli-webpack/developing-cordova-apps/introduction.md","content":"---\ntitle: What is Cordova\ndesc: (@quasar/app-webpack) Introduction on one of the technologies behind Quasar hybrid mobile apps.\n---\n\nApache Cordova is a mobile application development framework originally created by Nitobi. Adobe Systems purchased Nitobi in 2011, rebranded it as PhoneGap, and later released an open source version of the software called Apache Cordova.\n\nApache Cordova enables software programmers to build applications for mobile devices using CSS3, HTML5, and JavaScript instead of relying on platform-specific APIs like those in Android, iOS, or Windows Phone. It enables wrapping up of CSS, HTML, and JavaScript code depending upon the platform of the device. It extends the features of HTML and JavaScript to work with the device. The resulting applications are hybrid, meaning that they are neither truly native mobile application (because all layout rendering is done via Web views instead of the platform's native UI framework) nor purely Web-based (because they are not just Web apps, but are packaged as apps for distribution and have access to native device APIs).\n\nYou can hook into the native device APIs by using [Cordova Plugins](/quasar-cli-webpack/developing-cordova-apps/cordova-plugins).\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1226,"content_sha256":"b6947c15e954990b18d48141069220dfb7cf7da8405e76ebcbbabf6908c8c6c1"},{"filename":"references/docs/quasar-cli-webpack/developing-electron-apps/app-icons-electron.md","content":"---\ntitle: App Icons for Electron\ndesc: (@quasar/app-webpack) How to manage the app icons for a Desktop Quasar app.\nscope:\n tree:\n l: src-electron\n c:\n - l: icons\n c:\n - l: icon.ico\n - l: icon.icns\n - l: icon.png\n---\n\nThese images are used to display the icon of the application in the desktop operating system in the tray, on the desktop, in the file-browser and in relevant stores. The `icon.ico` file is for Windows and `icon.icns` is for MacOS. If you discover any that are missing, please open an issue.\n\n\u003cimg src=\"https://cdn.quasar.dev/img/iconfactory.png\" style=\"float:right;max-width:15%;min-width:240px;padding-top:40px\">\n\n## Icon Genie CLI\n\n::: tip\nWe highly recommend using the [Icon Genie CLI](/icongenie/introduction), because it consumes a source icon and automatically clones, scales, minifies and places the icons in the appropriate directories for you. When needed, it also tells you what tags you'll need to add to your /index.html file.\n:::\n\nQuickly bootstrap the necessary images with Icon Genie CLI. For a complete list of options, please visit the [Icon Genie CLI](/icongenie/command-list) command list page.\n\n```bash\n$ icongenie generate -m electron -i /path/to/source/icon.png\n```\n\n## Manual instructions\n\n\u003cDocTree :def=\"scope.tree\" />\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1307,"content_sha256":"554c2c71092d8aec9a8d35b1452640352939895e5a4cfdfb5db8d824b2ecfc24"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"quasarframework/quasar ","type":"text"},{"text":"[email protected]","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Tags:","type":"text","marks":[{"type":"strong"}]},{"text":" legacy: 1.22.10, latest: 2.19.3","type":"text"}]},{"type":"paragraph","content":[{"text":"References:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"Docs","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/_INDEX.md","title":null}}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"API Changes","type":"text"}]},{"type":"paragraph","content":[{"text":"This section documents version-specific API changes — prioritize recent major/minor releases.","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"BREAKING: ","type":"text"},{"text":"v-model","type":"text","marks":[{"type":"code_inline"}]},{"text":" -> uses ","type":"text"},{"text":"model-value","type":"text","marks":[{"type":"code_inline"}]},{"text":" + ","type":"text"},{"text":"@update:model-value","type":"text","marks":[{"type":"code_inline"}]},{"text":" instead of ","type":"text"},{"text":"value","type":"text","marks":[{"type":"code_inline"}]},{"text":" + ","type":"text"},{"text":"@input","type":"text","marks":[{"type":"code_inline"}]},{"text":" in Vue 3 ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/start/upgrade-guide/upgrade-guide.md#vue-3-and-v-model","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"BREAKING: ","type":"text"},{"text":"QDrawer","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":"QDialog","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":"QMenu","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":"QTooltip","type":"text","marks":[{"type":"code_inline"}]},{"text":" -> use ","type":"text"},{"text":"class","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"style","type":"text","marks":[{"type":"code_inline"}]},{"text":" attributes instead of ","type":"text"},{"text":"content-class","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":"content-style","type":"text","marks":[{"type":"code_inline"}]},{"text":" props ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/start/upgrade-guide/upgrade-guide.md#qdrawerqdialogqmenuqtooltip","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"BREAKING: ","type":"text"},{"text":"QImg","type":"text","marks":[{"type":"code_inline"}]},{"text":" -> completely redesigned, removed ","type":"text"},{"text":"transition","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"basic","type":"text","marks":[{"type":"code_inline"}]},{"text":" props; renamed ","type":"text"},{"text":"no-default-spinner","type":"text","marks":[{"type":"code_inline"}]},{"text":" to ","type":"text"},{"text":"no-spinner","type":"text","marks":[{"type":"code_inline"}]},{"text":" ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/start/upgrade-guide/upgrade-guide.md#qimg","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"BREAKING: ","type":"text"},{"text":"QScrollArea","type":"text","marks":[{"type":"code_inline"}]},{"text":" -> methods ","type":"text"},{"text":"getScrollPosition","type":"text","marks":[{"type":"code_inline"}]},{"text":" returns ","type":"text"},{"text":"{ top, left }","type":"text","marks":[{"type":"code_inline"}]},{"text":"; ","type":"text"},{"text":"setScrollPosition","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"setScrollPercentage","type":"text","marks":[{"type":"code_inline"}]},{"text":" require ","type":"text"},{"text":"axis","type":"text","marks":[{"type":"code_inline"}]},{"text":" parameter ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/start/upgrade-guide/upgrade-guide.md#qscrollarea","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"BREAKING: ","type":"text"},{"text":"QTable","type":"text","marks":[{"type":"code_inline"}]},{"text":" -> renamed ","type":"text"},{"text":"data","type":"text","marks":[{"type":"code_inline"}]},{"text":" prop to ","type":"text"},{"text":"rows","type":"text","marks":[{"type":"code_inline"}]},{"text":" to avoid TS naming conflicts ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/start/upgrade-guide/upgrade-guide.md#qtable","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"BREAKING: ","type":"text"},{"text":"Platform.is","type":"text","marks":[{"type":"code_inline"}]},{"text":" -> all boolean properties now explicitly ","type":"text"},{"text":"false","type":"text","marks":[{"type":"code_inline"}]},{"text":" instead of ","type":"text"},{"text":"undefined","type":"text","marks":[{"type":"code_inline"}]},{"text":" since v2.17.0 ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/repos/quasarframework/quasar/releases/vquasar-v2.17.0.md#potential-upgrade-issue","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"BREAKING: ","type":"text"},{"text":"colors","type":"text","marks":[{"type":"code_inline"}]},{"text":" utils -> ","type":"text"},{"text":"getBrand","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"setBrand","type":"text","marks":[{"type":"code_inline"}]},{"text":" replaced by ","type":"text"},{"text":"getCssVar","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"setCssVar","type":"text","marks":[{"type":"code_inline"}]},{"text":" respectively ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/start/upgrade-guide/upgrade-guide.md#color-utils","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"BREAKING: Scroll utils -> renamed ","type":"text"},{"text":"getScrollPosition","type":"text","marks":[{"type":"code_inline"}]},{"text":" to ","type":"text"},{"text":"getVerticalScrollPosition","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"animScrollTo","type":"text","marks":[{"type":"code_inline"}]},{"text":" to ","type":"text"},{"text":"animVerticalScrollTo","type":"text","marks":[{"type":"code_inline"}]},{"text":", and ","type":"text"},{"text":"setScrollPosition","type":"text","marks":[{"type":"code_inline"}]},{"text":" to ","type":"text"},{"text":"setVerticalScrollPosition","type":"text","marks":[{"type":"code_inline"}]},{"text":" ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/start/upgrade-guide/upgrade-guide.md#scroll-utils","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"BREAKING: ","type":"text"},{"text":"date","type":"text","marks":[{"type":"code_inline"}]},{"text":" utils -> ","type":"text"},{"text":"addToDate","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"subtractFromDate","type":"text","marks":[{"type":"code_inline"}]},{"text":" property names normalized (e.g., ","type":"text"},{"text":"year","type":"text","marks":[{"type":"code_inline"}]},{"text":" -> ","type":"text"},{"text":"years","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"month","type":"text","marks":[{"type":"code_inline"}]},{"text":" -> ","type":"text"},{"text":"months","type":"text","marks":[{"type":"code_inline"}]},{"text":") ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/start/upgrade-guide/upgrade-guide.md#date-utils","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"BREAKING: ","type":"text"},{"text":"QPopupEdit","type":"text","marks":[{"type":"code_inline"}]},{"text":" -> must now use the default slot with ","type":"text"},{"text":"v-slot=\"scope\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" for performance ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/start/upgrade-guide/upgrade-guide.md#qpopupedit","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"BREAKING: ","type":"text"},{"text":"GoBack","type":"text","marks":[{"type":"code_inline"}]},{"text":" directive -> removed; use router reference (","type":"text"},{"text":"$router.back()","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"$router.go(-1)","type":"text","marks":[{"type":"code_inline"}]},{"text":") instead ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/start/upgrade-guide/upgrade-guide.md#quasar-directives","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"NEW: ","type":"text"},{"text":"useQuasar","type":"text","marks":[{"type":"code_inline"}]},{"text":" composable -> primary method for accessing the ","type":"text"},{"text":"$q","type":"text","marks":[{"type":"code_inline"}]},{"text":" object within Composition API components","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"NEW: ","type":"text"},{"text":"useMeta","type":"text","marks":[{"type":"code_inline"}]},{"text":" composable -> new way to define meta tags, replacing the now deprecated ","type":"text"},{"text":"meta","type":"text","marks":[{"type":"code_inline"}]},{"text":" component property ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/start/upgrade-guide/upgrade-guide.md#meta-plugin","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"NEW: ","type":"text"},{"text":"QTable","type":"text","marks":[{"type":"code_inline"}]},{"text":" props -> added ","type":"text"},{"text":"table-row-style-fn","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"table-row-class-fn","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"grid-style-fn","type":"text","marks":[{"type":"code_inline"}]},{"text":", and ","type":"text"},{"text":"grid-class-fn","type":"text","marks":[{"type":"code_inline"}]},{"text":" in v2.18.0 ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/repos/quasarframework/quasar/releases/vquasar-v2.18.0.md#new","title":null}}]}]}]}]},{"type":"paragraph","content":[{"text":"Also changed:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"useFormChild()","type":"text","marks":[{"type":"code_inline"}]},{"text":" new composable · ","type":"text"},{"text":"QOptionsGroup","type":"text","marks":[{"type":"code_inline"}]},{"text":" props ","type":"text"},{"text":"option-value","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"option-label","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"option-disable","type":"text","marks":[{"type":"code_inline"}]},{"text":" new v2.17.0 · ","type":"text"},{"text":"QUploader","type":"text","marks":[{"type":"code_inline"}]},{"text":" prop ","type":"text"},{"text":"thumbnail-fit","type":"text","marks":[{"type":"code_inline"}]},{"text":" new v2.17.0 · ","type":"text"},{"text":"QSelect","type":"text","marks":[{"type":"code_inline"}]},{"text":" prop ","type":"text"},{"text":"disable-tab-select","type":"text","marks":[{"type":"code_inline"}]},{"text":" new v2.17.0 · ","type":"text"},{"text":"QMenu","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":"QBtnDropdown","type":"text","marks":[{"type":"code_inline"}]},{"text":" ","type":"text"},{"text":"no-esc-dismiss","type":"text","marks":[{"type":"code_inline"}]},{"text":" new v2.18.0 · ","type":"text"},{"text":"evt.qAvoidFocus","type":"text","marks":[{"type":"code_inline"}]},{"text":" new flag v2.18.0 · ","type":"text"},{"text":"QDate","type":"text","marks":[{"type":"code_inline"}]},{"text":" model-value no longer contains ","type":"text"},{"text":"changed","type":"text","marks":[{"type":"code_inline"}]},{"text":" prop · ","type":"text"},{"text":"QPagination","type":"text","marks":[{"type":"code_inline"}]},{"text":" prop ","type":"text"},{"text":"gutter","type":"text","marks":[{"type":"code_inline"}]},{"text":" new · ","type":"text"},{"text":"QImg","type":"text","marks":[{"type":"code_inline"}]},{"text":" props ","type":"text"},{"text":"loading","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"crossorigin","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"fit","type":"text","marks":[{"type":"code_inline"}]},{"text":" new · ","type":"text"},{"text":"Dialog","type":"text","marks":[{"type":"code_inline"}]},{"text":" plugin custom component props moved to ","type":"text"},{"text":"componentProps","type":"text","marks":[{"type":"code_inline"}]},{"text":" · ","type":"text"},{"text":"Loading","type":"text","marks":[{"type":"code_inline"}]},{"text":" plugin uses ","type":"text"},{"text":"html: true","type":"text","marks":[{"type":"code_inline"}]},{"text":" for HTML content instead of ","type":"text"},{"text":"sanitize","type":"text","marks":[{"type":"code_inline"}]},{"text":" · ","type":"text"},{"text":"App.vue","type":"text","marks":[{"type":"code_inline"}]},{"text":" wrapper ","type":"text"},{"text":"\u003cdiv id=\"q-app\">","type":"text","marks":[{"type":"code_inline"}]},{"text":" removed · ","type":"text"},{"text":".sync","type":"text","marks":[{"type":"code_inline"}]},{"text":" modifier replaced by ","type":"text"},{"text":"v-model:propName","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Best Practices","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"#q-app/wrappers","type":"text","marks":[{"type":"code_inline"}]},{"text":" instead of ","type":"text"},{"text":"quasar/wrappers","type":"text","marks":[{"type":"code_inline"}]},{"text":" for defining configurations and boot files — provides superior type inference and alignment with modern Quasar CLI ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/quasar-cli-vite/upgrade-guide.md:L256:258","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"Regle","type":"text","marks":[{"type":"strong"}]},{"text":" as the recommended validation library for ","type":"text"},{"text":"QInput","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"QField","type":"text","marks":[{"type":"code_inline"}]},{"text":" — provides a robust, externalized validation logic compared to inline rules ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/vue-components/input.md:L319","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Prefer ","type":"text"},{"text":"responsive CSS classes","type":"text","marks":[{"type":"strong"}]},{"text":" (e.g., ","type":"text"},{"text":"gt-sm","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"lt-md","type":"text","marks":[{"type":"code_inline"}]},{"text":") over the ","type":"text"},{"text":"Screen","type":"text","marks":[{"type":"code_inline"}]},{"text":" plugin in JavaScript — minimizes re-renders and layout shifts by leveraging CSS media queries directly ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/options/screen-plugin.md:L5","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Bootstrap custom dialog components with the ","type":"text"},{"text":"useDialogPluginComponent","type":"text","marks":[{"type":"code_inline"}]},{"text":" composable — handles the complex internal communication and lifecycle requirements of the Dialog plugin automatically ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/vue-composables/use-dialog-plugin-component.md:L13:30","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Enable the ","type":"text"},{"text":"no-transition","type":"text","marks":[{"type":"code_inline"}]},{"text":" prop on ","type":"text"},{"text":"QTree","type":"text","marks":[{"type":"code_inline"}]},{"text":" when rendering large datasets — significantly improves runtime performance by skipping expensive expansion/collapse animations ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/vue-components/tree.md:L31","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use Quasar's ","type":"text"},{"text":"useInterval","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"useTimeout","type":"text","marks":[{"type":"code_inline"}]},{"text":" composables over native browser timers — ensures automatic cancellation and memory cleanup when the component is unmounted ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/vue-composables/use-interval.md:L8:11","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Place ","type":"text"},{"text":"QPullToRefresh","type":"text","marks":[{"type":"code_inline"}]},{"text":" as a direct child of ","type":"text"},{"text":"QPage","type":"text","marks":[{"type":"code_inline"}]},{"text":" when using ","type":"text"},{"text":"QLayout","type":"text","marks":[{"type":"code_inline"}]},{"text":" — ensures correct scroll event interception and native-like pull behavior within the layout container ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/vue-components/pull-to-refresh.md:L42","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Avoid setting ","type":"text"},{"text":"Dark","type":"text","marks":[{"type":"code_inline"}]},{"text":" mode to ","type":"text"},{"text":"auto","type":"text","marks":[{"type":"code_inline"}]},{"text":" in SSR applications — prevents the \"flicker\" effect where the server renders light mode before the client synchronizes with system preferences ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/quasar-plugins/dark.md:L85:87","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Do not use ","type":"text"},{"text":"v-model","type":"text","marks":[{"type":"code_inline"}]},{"text":" with ","type":"text"},{"text":"QRouteTab","type":"text","marks":[{"type":"code_inline"}]},{"text":" components — the active state is derived directly from the current route, and manual model updates will not trigger navigation ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/vue-components/tabs.md:L128:132","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Prefer the ","type":"text"},{"text":"Loading Bar Plugin","type":"text","marks":[{"type":"strong"}]},{"text":" over manual ","type":"text"},{"text":"QAjaxBar","type":"text","marks":[{"type":"code_inline"}]},{"text":" component instances — provides a simpler, globally managed progress indicator for all Ajax calls without per-page wiring ","type":"text"},{"text":"source","type":"text","marks":[{"type":"link","attrs":{"href":"./references/docs/vue-components/ajax-bar.md:L18:19","title":null}}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"quasar-skilld","author":"@skillopedia","source":{"stars":165,"repo_name":"vue-ecosystem-skills","origin_url":"https://github.com/harlan-zw/vue-ecosystem-skills/blob/HEAD/skills/quasar-skilld/SKILL.md","repo_owner":"harlan-zw","body_sha256":"5ac396d28e62ebb31b2545182dee2cb3829ae4c7fccfcee96db2b2ead4d325dc","cluster_key":"4ff20c051e994428b9b4a9167968e4b95d228b00039dbad9c1f18c459b28fe5a","clean_bundle":{"format":"clean-skill-bundle-v1","source":"harlan-zw/vue-ecosystem-skills/skills/quasar-skilld/SKILL.md","attachments":[{"id":"51c0f14d-7369-5bb1-bad9-1460e2e77012","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/51c0f14d-7369-5bb1-bad9-1460e2e77012/attachment.md","path":"references/discussions/_INDEX.md","size":2606,"sha256":"ad9cb51f3156006da749e5697d347366a5ce8e80db26e4e2ec5ca646f929eddc","contentType":"text/markdown; charset=utf-8"},{"id":"c322ac21-08ba-520e-ac84-325e05db04e9","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c322ac21-08ba-520e-ac84-325e05db04e9/attachment.md","path":"references/discussions/discussion-18103.md","size":1228,"sha256":"3863e2fa290b8de8cb1c352859d33f662f555b7f38491a712586774aea29d2c9","contentType":"text/markdown; charset=utf-8"},{"id":"8303a260-6e3a-567e-a33c-bde6a160ab5e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8303a260-6e3a-567e-a33c-bde6a160ab5e/attachment.md","path":"references/discussions/discussion-18106.md","size":1349,"sha256":"68c3b210d3a24fb0f9db8fc6f931e0a310c544080b04d4b388820f209fdba873","contentType":"text/markdown; charset=utf-8"},{"id":"a8e936d7-fb65-52f8-9864-336930fa5c73","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a8e936d7-fb65-52f8-9864-336930fa5c73/attachment.md","path":"references/discussions/discussion-18111.md","size":959,"sha256":"07a4e7a852b90201bdbc16acdeee82152d4e62949f4aacb9f60b84904a7da9e5","contentType":"text/markdown; charset=utf-8"},{"id":"882367d7-6b4b-5c29-bf79-7b1de3f85b59","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/882367d7-6b4b-5c29-bf79-7b1de3f85b59/attachment.md","path":"references/discussions/discussion-18121.md","size":619,"sha256":"e75928038d9a955c78faaa71b850f5bb333bf1902ff1e7e45547570de46593a2","contentType":"text/markdown; charset=utf-8"},{"id":"d8077681-dd19-562c-ad35-a798fbca2843","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d8077681-dd19-562c-ad35-a798fbca2843/attachment.md","path":"references/discussions/discussion-18132.md","size":1121,"sha256":"043d030f71545e9d5d50c33908da1e3fdd0eae7e9cd62d5f88864d6811664c2d","contentType":"text/markdown; charset=utf-8"},{"id":"4e12efaa-6af9-5d73-a2a8-bb91b12b3dcc","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/4e12efaa-6af9-5d73-a2a8-bb91b12b3dcc/attachment.md","path":"references/discussions/discussion-18158.md","size":1843,"sha256":"7d1dfa636a8e5cc400d562cb14cfcbcef22cae530410cb813745026ad456ca92","contentType":"text/markdown; charset=utf-8"},{"id":"34462f1a-d866-5fa7-8030-036d67873f65","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/34462f1a-d866-5fa7-8030-036d67873f65/attachment.md","path":"references/discussions/discussion-18166.md","size":1110,"sha256":"9f781ef76977af679131853368cc5412e10bb6b1c16ef4c8c90a6a44715d04ac","contentType":"text/markdown; charset=utf-8"},{"id":"d4ceba21-5a92-5a03-87dd-d7dadc9d6a35","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d4ceba21-5a92-5a03-87dd-d7dadc9d6a35/attachment.md","path":"references/discussions/discussion-18181.md","size":1072,"sha256":"e039c932d4c67c7c10982f2bd2768bc74ebd9f3be8bd6b959d68349a9fba4ab6","contentType":"text/markdown; charset=utf-8"},{"id":"52282d81-e6db-5a7d-b5b4-6e83c097c24e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/52282d81-e6db-5a7d-b5b4-6e83c097c24e/attachment.md","path":"references/discussions/discussion-18186.md","size":800,"sha256":"d0974ef76b3e99ac7843689cde2b9bc40b9e84f9de746086a61c4a6b72317237","contentType":"text/markdown; charset=utf-8"},{"id":"dc6c6a7c-7035-52fa-9d49-659100ce97ca","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/dc6c6a7c-7035-52fa-9d49-659100ce97ca/attachment.md","path":"references/discussions/discussion-18189.md","size":1961,"sha256":"5c1c5e5cb8de2716dfd29594d944c07a6acd3a2f8d6ef950a4d95709ee5d3818","contentType":"text/markdown; charset=utf-8"},{"id":"5c1a54a0-9b16-5392-b122-a8858e302d7a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/5c1a54a0-9b16-5392-b122-a8858e302d7a/attachment.md","path":"references/discussions/discussion-18193.md","size":1320,"sha256":"b62a27258c94e695351c36365dc3682858ed9dc7410e53681d674c03956e82ef","contentType":"text/markdown; charset=utf-8"},{"id":"734d43ba-732a-5528-9a48-4fe4057b0720","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/734d43ba-732a-5528-9a48-4fe4057b0720/attachment.md","path":"references/discussions/discussion-18194.md","size":1068,"sha256":"4dc6ad9a48ceae07856e1b6318793b89bc23dd3cf78ab01d4d1bac18c2bb0caa","contentType":"text/markdown; charset=utf-8"},{"id":"79bcf049-2f8d-5c69-bfdc-8c367ad10ce3","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/79bcf049-2f8d-5c69-bfdc-8c367ad10ce3/attachment.md","path":"references/discussions/discussion-18196.md","size":1030,"sha256":"a86e1f07ae818b3534c68014ca2f7862eee0c4c4590d09bb6ccf11550c2f11f2","contentType":"text/markdown; charset=utf-8"},{"id":"b320c77f-bd02-53c5-89e5-7336faf95fe8","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b320c77f-bd02-53c5-89e5-7336faf95fe8/attachment.md","path":"references/discussions/discussion-18197.md","size":908,"sha256":"5d36f7f787cb14c7facbd59c21b687cadd87fdcb3b69436c41d6ae25cb16ad8f","contentType":"text/markdown; charset=utf-8"},{"id":"bc5cb946-71ba-507c-8f97-02aedf50a244","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/bc5cb946-71ba-507c-8f97-02aedf50a244/attachment.md","path":"references/discussions/discussion-18198.md","size":2511,"sha256":"925c701628949a5ecd4b688be6a75b9ff31cc91b2079a75ab7d4f93054793052","contentType":"text/markdown; charset=utf-8"},{"id":"23a16063-f9ca-5a17-b4ff-48c0c610ce4f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/23a16063-f9ca-5a17-b4ff-48c0c610ce4f/attachment.md","path":"references/discussions/discussion-18205.md","size":1465,"sha256":"bc1b4b2bece7312d75c3b14c7448a548e8743dcfb79f948efc82c3b151164df9","contentType":"text/markdown; charset=utf-8"},{"id":"2a8f0b6d-6c26-5eb2-b3db-74d5d7e9ae5d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/2a8f0b6d-6c26-5eb2-b3db-74d5d7e9ae5d/attachment.md","path":"references/discussions/discussion-18206.md","size":743,"sha256":"1eadf642d782741d69ecee64d760fd0cc58e88b665294471b7164fbcf5339c58","contentType":"text/markdown; charset=utf-8"},{"id":"54ea8afb-a634-5432-a2d8-fcb2912270c3","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/54ea8afb-a634-5432-a2d8-fcb2912270c3/attachment.md","path":"references/discussions/discussion-18209.md","size":1082,"sha256":"d5dc21d6226b2c3ee505b376fa6a3784ce41e7230d360a922bef15bca33a40e2","contentType":"text/markdown; charset=utf-8"},{"id":"5e65557d-cfb1-5a0d-a2d2-6f2b2c1852b1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/5e65557d-cfb1-5a0d-a2d2-6f2b2c1852b1/attachment.md","path":"references/discussions/discussion-18211.md","size":3197,"sha256":"c509e6261df6977db97948a39b4417523d347e4e89f10df2c15d2c580681c625","contentType":"text/markdown; charset=utf-8"},{"id":"ec11452b-a050-5665-8e96-e37ad1ca8f59","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ec11452b-a050-5665-8e96-e37ad1ca8f59/attachment.md","path":"references/discussions/discussion-18217.md","size":1104,"sha256":"5f1406ac3a2ee1618311dc0a29c358435fe17eda9664c4c13ed71a308cee0f44","contentType":"text/markdown; charset=utf-8"},{"id":"98076871-19eb-5090-8c84-6c551a63328e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/98076871-19eb-5090-8c84-6c551a63328e/attachment.md","path":"references/docs/_INDEX.md","size":78308,"sha256":"f498d06966ba75def5e1d23714b6eaa73946fe203309224939ac86a1510806d0","contentType":"text/markdown; charset=utf-8"},{"id":"90bd762f-8815-57ce-a912-ecb60e1ce31d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/90bd762f-8815-57ce-a912-ecb60e1ce31d/attachment.md","path":"references/docs/__elements.md","size":17952,"sha256":"820a49df60f577ecc0ae9a481a2fcb6c1c4a2c43c82b693b2dd44809c8bf9a0b","contentType":"text/markdown; charset=utf-8"},{"id":"94d78e0a-1f0b-54e9-ba4c-007cfeaad22d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/94d78e0a-1f0b-54e9-ba4c-007cfeaad22d/attachment.md","path":"references/docs/api-explorer/api-explorer.md","size":262,"sha256":"99dd0bd4ab12f4c62119d00b70fad64ea61563ee1c381bbd462be5d891871ff8","contentType":"text/markdown; charset=utf-8"},{"id":"58ec1f4c-cbc3-5d50-be09-a9f9e13bf360","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/58ec1f4c-cbc3-5d50-be09-a9f9e13bf360/attachment.md","path":"references/docs/app-extensions/development-guide/index-api.md","size":16562,"sha256":"f0ffa3cf233b48e55c24caf2458930cf84234446d2a82f9347acab13b95d96f0","contentType":"text/markdown; charset=utf-8"},{"id":"376d6dd5-ef9e-5d3c-8dcc-fb89605a4e43","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/376d6dd5-ef9e-5d3c-8dcc-fb89605a4e43/attachment.md","path":"references/docs/app-extensions/development-guide/install-api.md","size":9489,"sha256":"b5174a556776a882b533363aea0f080bebb991c67b4d7275bf917c18d468970e","contentType":"text/markdown; charset=utf-8"},{"id":"84e9ebaa-259b-5811-9af8-913a3803ec3b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/84e9ebaa-259b-5811-9af8-913a3803ec3b/attachment.md","path":"references/docs/app-extensions/development-guide/introduction.md","size":13697,"sha256":"a9d598337a377b7e1aac798a65d7d9c80c9d1fcb011db96a86a6f48410ca2c1e","contentType":"text/markdown; charset=utf-8"},{"id":"8f62d143-8572-508a-a4db-83d4ae1f5a3e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8f62d143-8572-508a-a4db-83d4ae1f5a3e/attachment.md","path":"references/docs/app-extensions/development-guide/prompts-api.md","size":6498,"sha256":"834773742ecb35bfaaf710c91996dd214060d0049220d823b4b5ea9530650cf8","contentType":"text/markdown; charset=utf-8"},{"id":"f45b866b-234b-5526-aa4b-35410a544210","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f45b866b-234b-5526-aa4b-35410a544210/attachment.md","path":"references/docs/app-extensions/development-guide/uninstall-api.md","size":4755,"sha256":"e31cf9f468019f2dd0adc7a4fe02d4ca52cd792166fc5d95d8c2e30a4796a8ce","contentType":"text/markdown; charset=utf-8"},{"id":"1c9e08ff-fffc-5a23-bcdb-6ba7e220d8d0","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1c9e08ff-fffc-5a23-bcdb-6ba7e220d8d0/attachment.md","path":"references/docs/app-extensions/discover.md","size":3178,"sha256":"872adce850713f8962859563b2fc519af7505cd5e7f06d4b1d5710cebd7e90fa","contentType":"text/markdown; charset=utf-8"},{"id":"17f004fb-03b0-5c2c-bbd8-deac4890e857","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/17f004fb-03b0-5c2c-bbd8-deac4890e857/attachment.md","path":"references/docs/app-extensions/introduction.md","size":4430,"sha256":"347471a8296d7ec8e3b4f5c077e73ce202b4eda5f44901354bee3cd0f16b2d90","contentType":"text/markdown; charset=utf-8"},{"id":"86daeeb2-7add-5139-9e83-3ebaf822d542","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/86daeeb2-7add-5139-9e83-3ebaf822d542/attachment.md","path":"references/docs/app-extensions/tips-and-tricks/chain-webpack.md","size":2516,"sha256":"051f087ced86021e8d198134261471dd4570c4723b4ae2bf29a49589a3a66e68","contentType":"text/markdown; charset=utf-8"},{"id":"f372f9d3-88ea-5e79-b9a5-738d1b54090d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f372f9d3-88ea-5e79-b9a5-738d1b54090d/attachment.md","path":"references/docs/app-extensions/tips-and-tricks/inject-quasar-plugin.md","size":1977,"sha256":"ec0631a0afcedea4b18664e1b516609e2a1f4f4d5364670f48c6aadff2f67006","contentType":"text/markdown; charset=utf-8"},{"id":"d6b1adee-1a36-5959-a7b5-a74b7642a0c1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d6b1adee-1a36-5959-a7b5-a74b7642a0c1/attachment.md","path":"references/docs/app-extensions/tips-and-tricks/introduction.md","size":364,"sha256":"70c953866fca9baf334bf729fa313d6adcfa8519432a67cce526f54eb2b3bc4a","contentType":"text/markdown; charset=utf-8"},{"id":"1f7d5def-548f-56fe-bfde-97c04c6a1534","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1f7d5def-548f-56fe-bfde-97c04c6a1534/attachment.md","path":"references/docs/app-extensions/tips-and-tricks/json-api.md","size":10044,"sha256":"64a5eacf78b10374044b744755f05b857ec44225de72a14693b376d34ece8a05","contentType":"text/markdown; charset=utf-8"},{"id":"bff08012-9678-5350-8315-1bb7aca2415c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/bff08012-9678-5350-8315-1bb7aca2415c/attachment.md","path":"references/docs/app-extensions/tips-and-tricks/provide-a-directive.md","size":4157,"sha256":"e2256043cc8854cd8c978bd61821cef8d81a68d05efd7c61add01b6ffd431d29","contentType":"text/markdown; charset=utf-8"},{"id":"d34648f9-c210-5a2e-99b9-5b0dd67e9c36","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d34648f9-c210-5a2e-99b9-5b0dd67e9c36/attachment.md","path":"references/docs/app-extensions/tips-and-tricks/provide-a-ui-component.md","size":4256,"sha256":"749b2628af50db3c53c350018813215a9f0bfe419e0d9e63a81d5293681eda09","contentType":"text/markdown; charset=utf-8"},{"id":"f3a0e060-555a-58c3-8e3a-5507d5cf9b1c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f3a0e060-555a-58c3-8e3a-5507d5cf9b1c/attachment.md","path":"references/docs/app-extensions/tips-and-tricks/starter-kit-equivalent.md","size":8037,"sha256":"7dfb9a6944174719f00a94cbe850d06654fff83a06e4e1b256b3cbfdd6c59f64","contentType":"text/markdown; charset=utf-8"},{"id":"33d61457-351a-5e5c-a63a-28898d41c2e5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/33d61457-351a-5e5c-a63a-28898d41c2e5/attachment.md","path":"references/docs/components/components.md","size":171,"sha256":"b06015e2f24e5de64a5c807c402cd06f7d2c1e5acb1ef2f1841c30bcc9ee1e01","contentType":"text/markdown; charset=utf-8"},{"id":"d3ca75f6-0afc-5915-a458-b630ee1d413e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d3ca75f6-0afc-5915-a458-b630ee1d413e/attachment.md","path":"references/docs/docs.md","size":148,"sha256":"2d911e0476ccab366c3313b0927880a61a88e6d7c3fcdfeb866d19f67a7cd8f7","contentType":"text/markdown; charset=utf-8"},{"id":"6177c421-e658-52ba-83d2-a86fe1d6f0bc","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/6177c421-e658-52ba-83d2-a86fe1d6f0bc/attachment.md","path":"references/docs/how-to-contribute/commit-conventions.md","size":4316,"sha256":"674f9ef0a91b0b953fecbea14c78c67b78d417b3f0c3880fe702752590850dc4","contentType":"text/markdown; charset=utf-8"},{"id":"1177f71a-da37-5284-9757-db8e6d97812d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1177f71a-da37-5284-9757-db8e6d97812d/attachment.md","path":"references/docs/how-to-contribute/contribution-guide.md","size":16193,"sha256":"4eb79bdc9e41d6f4bbac5c9d08e10c184465201e8d2ebf5d058a4feaa7da0fd5","contentType":"text/markdown; charset=utf-8"},{"id":"6ace47b1-d870-5f53-b3f2-8e3e4fded066","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/6ace47b1-d870-5f53-b3f2-8e3e4fded066/attachment.md","path":"references/docs/how-to-contribute/new-project.md","size":943,"sha256":"716a1054f3cacd3db6961af3b59767eae810bea7d2d5d0127188441aa8c7a7be","contentType":"text/markdown; charset=utf-8"},{"id":"4dd17bb8-401d-5e15-81e4-3907f6c03c32","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/4dd17bb8-401d-5e15-81e4-3907f6c03c32/attachment.md","path":"references/docs/how-to-contribute/project-maintainer.md","size":2402,"sha256":"0bcabebf4ae333c598946d6628075b35111e74dfab507dcbd1b145847a76e341","contentType":"text/markdown; charset=utf-8"},{"id":"7512255a-d930-5e5e-a319-c2708e25021a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7512255a-d930-5e5e-a319-c2708e25021a/attachment.md","path":"references/docs/how-to-contribute/running-projects.md","size":3487,"sha256":"e7c019db44b342a0fc4cf4286f6bebde1679124f505a12ea091732503c9b66e6","contentType":"text/markdown; charset=utf-8"},{"id":"3489f7ce-1d3e-58f8-91ce-b5e263e1fc88","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3489f7ce-1d3e-58f8-91ce-b5e263e1fc88/attachment.md","path":"references/docs/icongenie/app-icons-list.md","size":2289,"sha256":"c0e4e4289ae43cfbdb54bf6ced1e9516deb4b517f80db4b29df68da6601e24fb","contentType":"text/markdown; charset=utf-8"},{"id":"4e578402-d08b-543a-90d2-df8033167123","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/4e578402-d08b-543a-90d2-df8033167123/attachment.md","path":"references/docs/icongenie/command-list.md","size":15235,"sha256":"dbba4d3bd67ae40a9d3076521189e59eed0fd097bd5ead70c89a586aadb6ec34","contentType":"text/markdown; charset=utf-8"},{"id":"aff587f5-5589-5a15-a29f-4c27547f371d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/aff587f5-5589-5a15-a29f-4c27547f371d/attachment.md","path":"references/docs/icongenie/installation.md","size":5985,"sha256":"e91658595f3ae0cec570f9c846be4ce647341d804be867613f1c3f7847812503","contentType":"text/markdown; charset=utf-8"},{"id":"4f93020b-aa99-5b8f-bd3f-d98d496deecc","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/4f93020b-aa99-5b8f-bd3f-d98d496deecc/attachment.md","path":"references/docs/icongenie/introduction.md","size":1760,"sha256":"400205d87c2357eeaef82a7f727ccb5d0dc937b0826345a223f46544b237532f","contentType":"text/markdown; charset=utf-8"},{"id":"8feb736d-241f-5f99-9810-31049a93a099","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8feb736d-241f-5f99-9810-31049a93a099/attachment.md","path":"references/docs/icongenie/profile-files.md","size":7855,"sha256":"6d0d40915f8aefbfc5cf2ae7bbc49f3e173b5954be8dc45a787836d83e6f8acb","contentType":"text/markdown; charset=utf-8"},{"id":"015cc931-8a7e-5e2b-ac44-36ed7b4337fb","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/015cc931-8a7e-5e2b-ac44-36ed7b4337fb/attachment.md","path":"references/docs/index.md","size":5342,"sha256":"365617c956740c9cf4a828d7fe3216bf737edbe15eefb69cbb399da8eb218b9d","contentType":"text/markdown; charset=utf-8"},{"id":"b517f85d-97da-519f-b45a-6bff7fa4c8d3","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b517f85d-97da-519f-b45a-6bff7fa4c8d3/attachment.md","path":"references/docs/integrations/integrations.md","size":118,"sha256":"385d0b0369ba49f29960468afd79080cc056883fe4215632e47284689f06b787","contentType":"text/markdown; charset=utf-8"},{"id":"548516b3-935e-5cdf-b8b0-84e69254de03","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/548516b3-935e-5cdf-b8b0-84e69254de03/attachment.md","path":"references/docs/introduction-to-quasar/introduction-to-quasar.md","size":6900,"sha256":"1fecd68996d8213523da0c9c80489047b3a3f06ad2d9453c27b71836493c972f","contentType":"text/markdown; charset=utf-8"},{"id":"54d7d310-0dab-5c05-823e-b4a3bc9924f1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/54d7d310-0dab-5c05-823e-b4a3bc9924f1/attachment.md","path":"references/docs/layout/drawer.md","size":4843,"sha256":"684451b6e04edf8e9ee687b85c2c816ab6c6143bba87514ee4f199084070e1c5","contentType":"text/markdown; charset=utf-8"},{"id":"88192792-f762-5fc3-bfcd-d21a9fb850c0","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/88192792-f762-5fc3-bfcd-d21a9fb850c0/attachment.md","path":"references/docs/layout/gallery/gallery.md","size":408,"sha256":"391deca814b4ae008ac105392906daa7adeb4c103e649e6b7c9944872ed3c17b","contentType":"text/markdown; charset=utf-8"},{"id":"f074b0c3-4121-54f9-b142-57c8f1d17044","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f074b0c3-4121-54f9-b142-57c8f1d17044/attachment.md","path":"references/docs/layout/grid/column.md","size":3592,"sha256":"8e45d44c17d9f377c7bf1ad8883bae1ebdb1e8ca93804b898e3603836a3a625e","contentType":"text/markdown; charset=utf-8"},{"id":"19f8084b-0325-5a59-aebb-f1527412ceff","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/19f8084b-0325-5a59-aebb-f1527412ceff/attachment.md","path":"references/docs/layout/grid/flex-playground/flex-playground.md","size":574,"sha256":"8f74f4b47fcb60b46ed5c23e414c90f4938e52767f96d8d355ddeaaad0e5a6d0","contentType":"text/markdown; charset=utf-8"},{"id":"f4d6d7b8-1a24-5bda-ab35-268417d6f355","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f4d6d7b8-1a24-5bda-ab35-268417d6f355/attachment.md","path":"references/docs/layout/grid/flexbox-patterns.md","size":3771,"sha256":"bbeb3340cbe6fb871541f079ee8368890cd4a787f6316a561e34d8a152cc0a1e","contentType":"text/markdown; charset=utf-8"},{"id":"a24ffac1-89cc-56fb-9b49-95cd1ff386d6","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a24ffac1-89cc-56fb-9b49-95cd1ff386d6/attachment.md","path":"references/docs/layout/grid/gutter.md","size":4177,"sha256":"25de617947ea0ecb3453452f5c4aceee0da19b27223767e331406a77c78754f9","contentType":"text/markdown; charset=utf-8"},{"id":"cf6d8639-435f-54d3-93ad-692211cf793d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/cf6d8639-435f-54d3-93ad-692211cf793d/attachment.md","path":"references/docs/layout/grid/introduction-to-flexbox.md","size":11174,"sha256":"3d2dfd490d5a3f9728db0593773a7daa6cae29d051739cd9e716a766fba7e1d6","contentType":"text/markdown; charset=utf-8"},{"id":"41887a8e-d204-5a33-96cc-2927f8fc9ada","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/41887a8e-d204-5a33-96cc-2927f8fc9ada/attachment.md","path":"references/docs/layout/grid/row.md","size":4204,"sha256":"498a44c68210d42cc42fadb4d1caf06c381804a527443b8bedb1e5c7b611e331","contentType":"text/markdown; charset=utf-8"},{"id":"b9141550-d724-5647-a707-b41255b1aac7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b9141550-d724-5647-a707-b41255b1aac7/attachment.md","path":"references/docs/layout/header-and-footer.md","size":1994,"sha256":"a7d92f08275b260a16f2f66bea0baef4fe9b9df52d914b71386bbf95fe9865a2","contentType":"text/markdown; charset=utf-8"},{"id":"048a53ce-a9af-540b-a14a-5b105e0a9b4c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/048a53ce-a9af-540b-a14a-5b105e0a9b4c/attachment.md","path":"references/docs/layout/layout/layout.md","size":4805,"sha256":"6485d2ae7d2ab4eb817f2930c300ea47d1c903dfedec15ecd656d5e9ca080046","contentType":"text/markdown; charset=utf-8"},{"id":"12b1d5b5-55cf-5769-a92c-e746fcd346da","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/12b1d5b5-55cf-5769-a92c-e746fcd346da/attachment.md","path":"references/docs/layout/page-scroller.md","size":1864,"sha256":"2555ce4903f97ba83f7dc2c53b316d0847a177f40a4b18d91e62a834967da506","contentType":"text/markdown; charset=utf-8"},{"id":"e71e8c57-182b-520b-aad5-1f1eb5da6ac4","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e71e8c57-182b-520b-aad5-1f1eb5da6ac4/attachment.md","path":"references/docs/layout/page-sticky.md","size":1993,"sha256":"90a10193643d7ff713e0306a7cb8584dbe08cf0e2c96883fd2753ab627c7522e","contentType":"text/markdown; charset=utf-8"},{"id":"331fc9e0-2b61-5ecc-8edb-e0c2c0cc38bc","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/331fc9e0-2b61-5ecc-8edb-e0c2c0cc38bc/attachment.md","path":"references/docs/layout/page.md","size":2670,"sha256":"21404171f1974378edff1969558a305ff4d0d1b2946e44bdbe83de040b39400c","contentType":"text/markdown; charset=utf-8"},{"id":"b126c5ad-4784-556a-9b89-f1e2c6eb9b7d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b126c5ad-4784-556a-9b89-f1e2c6eb9b7d/attachment.md","path":"references/docs/layout/routing-with-layouts-and-pages.md","size":7800,"sha256":"eba0f41327acf9b8322028c7db027855bdfcca6d15389572d1f92f9c8860dcc6","contentType":"text/markdown; charset=utf-8"},{"id":"edeecf8d-0798-5e53-a0e9-b194458b84bd","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/edeecf8d-0798-5e53-a0e9-b194458b84bd/attachment.md","path":"references/docs/meet-the-team/meet-the-team.md","size":4077,"sha256":"dc3b9c5f115b3be1c698a4a45e48041dd6eb0e9bc5def696781213b916fad767","contentType":"text/markdown; charset=utf-8"},{"id":"fb502c53-fce8-5388-83f8-0510e2183ffc","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/fb502c53-fce8-5388-83f8-0510e2183ffc/attachment.md","path":"references/docs/options/animations.md","size":5692,"sha256":"8dff41fde7d4460ccad9258f19b17fff2b1cda074605635f78cdd7bbf69c2fd2","contentType":"text/markdown; charset=utf-8"},{"id":"c341abba-7e0b-5493-9c63-825105a5e679","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c341abba-7e0b-5493-9c63-825105a5e679/attachment.md","path":"references/docs/options/app-icons.md","size":1014,"sha256":"165db69c97bcfd3a4a66657ed74f6850a97406a6bf2256b4675eb5e4b0e8ca07","contentType":"text/markdown; charset=utf-8"},{"id":"6a9839fb-b99f-528b-8950-d9044afc1761","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/6a9839fb-b99f-528b-8950-d9044afc1761/attachment.md","path":"references/docs/options/app-internationalization.md","size":8236,"sha256":"9037db794f7ca8bf58c000008457ca0d2a4704efaea03387d203b268e5d1eb2b","contentType":"text/markdown; charset=utf-8"},{"id":"69ac0a72-0428-59df-a1de-840d3258de5f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/69ac0a72-0428-59df-a1de-840d3258de5f/attachment.md","path":"references/docs/options/global-node.md","size":496,"sha256":"3e4867293a9b6237849233fa6080d7ffc03b68549d39d6cf07fe4f24086a15c6","contentType":"text/markdown; charset=utf-8"},{"id":"238d609f-7444-5173-a3d3-f999404ab105","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/238d609f-7444-5173-a3d3-f999404ab105/attachment.md","path":"references/docs/options/installing-icon-libraries.md","size":4609,"sha256":"573f6373c64ae9107ffd957ff39400b04807b056daffcf56f3ca4ba1cff449d8","contentType":"text/markdown; charset=utf-8"},{"id":"a0b9c32a-998a-5c18-9c3e-99b620efc87f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a0b9c32a-998a-5c18-9c3e-99b620efc87f/attachment.md","path":"references/docs/options/platform-detection.md","size":7712,"sha256":"9c17b6012778a8a93966ac5fbcaf20216d3eed9b553ca39c8817e22e2858f1da","contentType":"text/markdown; charset=utf-8"},{"id":"22b1b0b5-8f57-5c93-86bc-4e080f112a0f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/22b1b0b5-8f57-5c93-86bc-4e080f112a0f/attachment.md","path":"references/docs/options/quasar-icon-sets.md","size":8972,"sha256":"e7fd5ce93d5caa9d4703d4a86911541f75eea5d9614082f5c8e9ea3706f20254","contentType":"text/markdown; charset=utf-8"},{"id":"0586997c-f3f0-5ec9-9855-33a668e84480","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/0586997c-f3f0-5ec9-9855-33a668e84480/attachment.md","path":"references/docs/options/quasar-language-packs.md","size":9810,"sha256":"f5b53007bd00fc51dc9bbcddab49adb4c528d603404d00d33d4cfea0ad1dadc5","contentType":"text/markdown; charset=utf-8"},{"id":"d6bd4344-d7a0-51e6-b844-c825f09165c2","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d6bd4344-d7a0-51e6-b844-c825f09165c2/attachment.md","path":"references/docs/options/rtl-support.md","size":6945,"sha256":"81176161871098f2f0dcbcb2d8bf2cc21324ef45755fc2e8a409f2f819ead4f4","contentType":"text/markdown; charset=utf-8"},{"id":"b61446da-7514-53b7-ae82-d83785bf42e0","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b61446da-7514-53b7-ae82-d83785bf42e0/attachment.md","path":"references/docs/options/screen-plugin.md","size":2848,"sha256":"f6f38640d4e7145ad86886f58ff9249e7320311a594f439c902a6d4751f89272","contentType":"text/markdown; charset=utf-8"},{"id":"d1d2f376-a2fc-59d0-a73a-dfe2be5e669c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d1d2f376-a2fc-59d0-a73a-dfe2be5e669c/attachment.md","path":"references/docs/options/seo.md","size":1011,"sha256":"f4f924dfbb4caa14989caca8384c3c651820232cec45cae78bb14d265e20d462","contentType":"text/markdown; charset=utf-8"},{"id":"11f6f23c-01d1-5077-a114-cad39c505b47","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/11f6f23c-01d1-5077-a114-cad39c505b47/attachment.md","path":"references/docs/options/the-q-object.md","size":4833,"sha256":"d7c4657350f16b75d9c3ac2a4984f84e76ae5567a7706fdf5a20ce67fbb91a6b","contentType":"text/markdown; charset=utf-8"},{"id":"ec484d80-4ab6-5387-a416-2e2af0dd75d5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ec484d80-4ab6-5387-a416-2e2af0dd75d5/attachment.md","path":"references/docs/options/transitions/transitions.md","size":1146,"sha256":"cf8ff1a74e899879d48ad42e22ae0b328d19f4bb0d62b5755bdda7612d8bf963","contentType":"text/markdown; charset=utf-8"},{"id":"a024be28-5790-5710-bfa3-82771aa045fc","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a024be28-5790-5710-bfa3-82771aa045fc/attachment.md","path":"references/docs/quasar-cli-vite/ajax-requests.md","size":2562,"sha256":"5b7a38f8f898aa3b28519aad0d6a3fd7bc7bb31f122af9c11f3e86199cc2af5d","contentType":"text/markdown; charset=utf-8"},{"id":"2c3f60ac-ac26-563c-933b-76fce747e5f3","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/2c3f60ac-ac26-563c-933b-76fce747e5f3/attachment.md","path":"references/docs/quasar-cli-vite/api-proxying.md","size":2128,"sha256":"b9d0f1d791b2e916f30fb11d5b08743498269223bdf821764ef352b53b503f01","contentType":"text/markdown; charset=utf-8"},{"id":"fd0fca29-66b5-57b9-990e-fa335bbf7b65","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/fd0fca29-66b5-57b9-990e-fa335bbf7b65/attachment.md","path":"references/docs/quasar-cli-vite/boot-files.md","size":14858,"sha256":"19a44a6f680d44295e2553d1a66b11516e14f5c08b86c4fd6dbd39346c5f88e2","contentType":"text/markdown; charset=utf-8"},{"id":"688d2f01-b294-5ceb-963e-5d6b400ce9c8","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/688d2f01-b294-5ceb-963e-5d6b400ce9c8/attachment.md","path":"references/docs/quasar-cli-vite/browser-compatibility.md","size":1486,"sha256":"017425999643c70cc40a05276bf03655d72b956814dfddf5de06412b69f09305","contentType":"text/markdown; charset=utf-8"},{"id":"fba3cfc0-3148-5a5e-abbc-6e544a9c000f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/fba3cfc0-3148-5a5e-abbc-6e544a9c000f/attachment.md","path":"references/docs/quasar-cli-vite/commands-list.md","size":24481,"sha256":"993c99b2483ec7c586dc7ce8f1c9902bf843f5e21bc041663a647956b74c5186","contentType":"text/markdown; charset=utf-8"},{"id":"4f135f87-fa57-55a1-b83d-d5ec1ac560d8","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/4f135f87-fa57-55a1-b83d-d5ec1ac560d8/attachment.md","path":"references/docs/quasar-cli-vite/convert-to-quasar-cli-with-vite.md","size":4131,"sha256":"6d98ed1c71e6362712f393c9688f506a9ac3ca7de07cd38331d116f3c86cd8d4","contentType":"text/markdown; charset=utf-8"},{"id":"e1e9427e-0bdf-5a56-a905-2a3e522abe07","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e1e9427e-0bdf-5a56-a905-2a3e522abe07/attachment.md","path":"references/docs/quasar-cli-vite/css-preprocessors.md","size":1378,"sha256":"1d9a7e347d1513f0ec22a9bf390c103ad331be8820126cb7235244d181b996e1","contentType":"text/markdown; charset=utf-8"},{"id":"94808390-ac5f-5794-8f85-74624bd8c45d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/94808390-ac5f-5794-8f85-74624bd8c45d/attachment.md","path":"references/docs/quasar-cli-vite/developing-browser-extensions/app-icons-browser-extension.md","size":1319,"sha256":"61821a9424380409cad70ecb50a68c9404b6c93953faded094c05ab5125884d4","contentType":"text/markdown; charset=utf-8"},{"id":"9e019bf6-aa60-55df-852c-f568a458491c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9e019bf6-aa60-55df-852c-f568a458491c/attachment.md","path":"references/docs/quasar-cli-vite/developing-browser-extensions/background-script.md","size":2843,"sha256":"783a65bebd87fcd97838284c10c77242f2fb0f48ed8f6223e342b8a6ab61fe77","contentType":"text/markdown; charset=utf-8"},{"id":"cf87a725-270c-53bb-a647-1eeb97b57e4d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/cf87a725-270c-53bb-a647-1eeb97b57e4d/attachment.md","path":"references/docs/quasar-cli-vite/developing-browser-extensions/bex-bridge.md","size":9148,"sha256":"f81085e066fa7c2c3d666c745181d185e3198dd6beb15757a9bcd6d9cc4b7444","contentType":"text/markdown; charset=utf-8"},{"id":"a0032634-850a-5f54-87db-c40ea9a47aba","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a0032634-850a-5f54-87db-c40ea9a47aba/attachment.md","path":"references/docs/quasar-cli-vite/developing-browser-extensions/build-commands.md","size":6191,"sha256":"74f046a92ce46eb5e2e1b5294376be18d6f8590ce127c01fd485e5b85e749517","contentType":"text/markdown; charset=utf-8"},{"id":"9cec0914-5c48-576a-ac3d-879bc26b94b7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9cec0914-5c48-576a-ac3d-879bc26b94b7/attachment.md","path":"references/docs/quasar-cli-vite/developing-browser-extensions/configuring-bex.md","size":5879,"sha256":"fe2c2a62e2550ef46464301c9a00da58cbfb1d13f7463b652a795a45443dcb0a","contentType":"text/markdown; charset=utf-8"},{"id":"fbfc7f85-ff20-5aa7-9fbb-7dea0785f6f6","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/fbfc7f85-ff20-5aa7-9fbb-7dea0785f6f6/attachment.md","path":"references/docs/quasar-cli-vite/developing-browser-extensions/content-scripts.md","size":2956,"sha256":"91b54368a51961ea9d0a629408eb1545a4d2d46646a66fcd6ddd9f8a8e129fe6","contentType":"text/markdown; charset=utf-8"},{"id":"3135d8fe-c4d7-5ccf-91bc-712af47b4f41","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3135d8fe-c4d7-5ccf-91bc-712af47b4f41/attachment.md","path":"references/docs/quasar-cli-vite/developing-browser-extensions/introduction.md","size":1245,"sha256":"5f0e652f07b925691f5d62f5a08ad60052ecdf2a4018dfb8119cfed7542e8cc6","contentType":"text/markdown; charset=utf-8"},{"id":"df33b938-0c9e-568c-8138-cdee321c4e07","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/df33b938-0c9e-568c-8138-cdee321c4e07/attachment.md","path":"references/docs/quasar-cli-vite/developing-browser-extensions/preparation.md","size":2200,"sha256":"9464edc17cac9418a5085d34c9dd74914a3c192666bd94069d67d7b872f7248f","contentType":"text/markdown; charset=utf-8"},{"id":"d49d0725-0974-552e-95ea-5d201a047056","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d49d0725-0974-552e-95ea-5d201a047056/attachment.md","path":"references/docs/quasar-cli-vite/developing-browser-extensions/types-of-bex.md","size":5897,"sha256":"9b415781ba5ef89181f1be5516eef264266683d8be2eec95c823679ab7dc6669","contentType":"text/markdown; charset=utf-8"},{"id":"c653badf-502a-5e41-9095-0192eef95eca","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c653badf-502a-5e41-9095-0192eef95eca/attachment.md","path":"references/docs/quasar-cli-vite/developing-capacitor-apps/app-icons-capacitor.md","size":5751,"sha256":"45e2beacd0f240902d30eee04f641ba5f540d93fd931bdb48065a38d6e9b0311","contentType":"text/markdown; charset=utf-8"},{"id":"d4ae5e8a-fa92-50fc-a41e-01797e2f20d3","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d4ae5e8a-fa92-50fc-a41e-01797e2f20d3/attachment.md","path":"references/docs/quasar-cli-vite/developing-capacitor-apps/build-commands.md","size":3795,"sha256":"a2f831b8ecf0d77735d8cdee95e80ef9d0f9ade02af745cd3b5685ec38bae5d9","contentType":"text/markdown; charset=utf-8"},{"id":"9386d291-20a1-5c78-bc01-415486e84a0e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9386d291-20a1-5c78-bc01-415486e84a0e/attachment.md","path":"references/docs/quasar-cli-vite/developing-capacitor-apps/capacitor-api.md","size":4963,"sha256":"513b8d776be23654211f5661dd06b725d41e68855cd857d8216839aacbaeeb80","contentType":"text/markdown; charset=utf-8"},{"id":"88113141-9734-5af6-9ebc-529749685249","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/88113141-9734-5af6-9ebc-529749685249/attachment.md","path":"references/docs/quasar-cli-vite/developing-capacitor-apps/capacitor-version-support.md","size":5452,"sha256":"d4412c5703f2f0a5136b27ecce856e28e77a6a3f17b6f9c796a29c2f8b166d8b","contentType":"text/markdown; charset=utf-8"},{"id":"250a5ae6-0caa-504a-9627-a200aee736c2","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/250a5ae6-0caa-504a-9627-a200aee736c2/attachment.md","path":"references/docs/quasar-cli-vite/developing-capacitor-apps/configuring-capacitor.md","size":2832,"sha256":"47a4519c63148fac7add7192d7af5738978518069dae960df64a4ce37d5c7cd3","contentType":"text/markdown; charset=utf-8"},{"id":"04745213-c45d-5da1-a399-add75aa7c998","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/04745213-c45d-5da1-a399-add75aa7c998/attachment.md","path":"references/docs/quasar-cli-vite/developing-capacitor-apps/introduction.md","size":451,"sha256":"cd27783abef6620643a4ebd9ae768ddf0dc3c3edf42d0b341bc9423f1e7b0250","contentType":"text/markdown; charset=utf-8"},{"id":"3d05eb0a-9b48-552f-8a4a-e22d1bdb99f2","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3d05eb0a-9b48-552f-8a4a-e22d1bdb99f2/attachment.md","path":"references/docs/quasar-cli-vite/developing-capacitor-apps/live-updates.md","size":3697,"sha256":"0acb067b09dbdd1c88cba3afb6b0e49f78bed235ff7f732cd34186ca19512fc1","contentType":"text/markdown; charset=utf-8"},{"id":"194016ad-730e-5c89-a795-f52be70f5f70","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/194016ad-730e-5c89-a795-f52be70f5f70/attachment.md","path":"references/docs/quasar-cli-vite/developing-capacitor-apps/managing-google-analytics.md","size":3286,"sha256":"86d10d2894da29027365a773b076517857329a9a17dcf2d7ac4aea0e0941d187","contentType":"text/markdown; charset=utf-8"},{"id":"1ccc2d68-c5a8-50b9-b358-81c275775955","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1ccc2d68-c5a8-50b9-b358-81c275775955/attachment.md","path":"references/docs/quasar-cli-vite/developing-capacitor-apps/preparation.md","size":3858,"sha256":"cdcc6ae4c9c3a7493ec5a8f6ae752ecb4247f0890edf43a829032b8339fa8671","contentType":"text/markdown; charset=utf-8"},{"id":"edcaf30a-88b9-5a3f-af2e-7cee5084cbbe","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/edcaf30a-88b9-5a3f-af2e-7cee5084cbbe/attachment.md","path":"references/docs/quasar-cli-vite/developing-capacitor-apps/publishing-to-store.md","size":10195,"sha256":"8921ebfcfc2e59e12a1c38edc1cb4cc0459ee3365fe549e90a433855603ca1de","contentType":"text/markdown; charset=utf-8"},{"id":"573e280c-d210-54ad-9e20-05f147ba5d5b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/573e280c-d210-54ad-9e20-05f147ba5d5b/attachment.md","path":"references/docs/quasar-cli-vite/developing-capacitor-apps/troubleshooting-and-tips.md","size":7359,"sha256":"2a56add4b7bd735293ca3ae40ba15deca63154c7a1d01335ed4c10fa4b09a11f","contentType":"text/markdown; charset=utf-8"},{"id":"caf9d43f-8940-5fcd-b1e3-91b91c11ee2c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/caf9d43f-8940-5fcd-b1e3-91b91c11ee2c/attachment.md","path":"references/docs/quasar-cli-vite/developing-cordova-apps/app-icons-cordova.md","size":8327,"sha256":"66c71d2626fd9fc447db2fb436c2dc30932c5174e7c7a8d3a7e31f4d7b130cb0","contentType":"text/markdown; charset=utf-8"},{"id":"88c0314d-d4bb-5476-b000-39284a784409","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/88c0314d-d4bb-5476-b000-39284a784409/attachment.md","path":"references/docs/quasar-cli-vite/developing-cordova-apps/build-commands.md","size":5482,"sha256":"93eb12be0de36053badd70d2b740eb23f32dced0bf9f034243d9f5557caf871e","contentType":"text/markdown; charset=utf-8"},{"id":"50b6e234-04ad-5c87-ad3b-6caf81688681","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/50b6e234-04ad-5c87-ad3b-6caf81688681/attachment.md","path":"references/docs/quasar-cli-vite/developing-cordova-apps/configuring-cordova.md","size":5019,"sha256":"1041e1a1449067939684e8a8debc1c8e6b7eb960062df90274182a8eb32634ef","contentType":"text/markdown; charset=utf-8"},{"id":"c67b4fa4-d121-54ef-b8fd-d5952cab07e8","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c67b4fa4-d121-54ef-b8fd-d5952cab07e8/attachment.md","path":"references/docs/quasar-cli-vite/developing-cordova-apps/cordova-plugins.md","size":6351,"sha256":"7eb346646c6bf906598de211329b57ae5c50f435a4ee601f1b9a742863da6401","contentType":"text/markdown; charset=utf-8"},{"id":"6e774ac0-d3c7-571a-8bbe-a7ffd852be20","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/6e774ac0-d3c7-571a-8bbe-a7ffd852be20/attachment.md","path":"references/docs/quasar-cli-vite/developing-cordova-apps/introduction.md","size":1220,"sha256":"7338f2f08459f71b3356121ea1563b6fd9c7db1d8208fb004095264ef19e42dc","contentType":"text/markdown; charset=utf-8"},{"id":"95d66820-c9ea-59e7-b593-716a72f10245","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/95d66820-c9ea-59e7-b593-716a72f10245/attachment.md","path":"references/docs/quasar-cli-vite/developing-cordova-apps/managing-google-analytics.md","size":3358,"sha256":"ec38453726c69b1fcee4449a7eeadcc41549791af4dc66ef79a207737e2ad479","contentType":"text/markdown; charset=utf-8"},{"id":"812306ff-14bc-5f34-8e8c-41993b73e5af","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/812306ff-14bc-5f34-8e8c-41993b73e5af/attachment.md","path":"references/docs/quasar-cli-vite/developing-cordova-apps/preparation.md","size":7376,"sha256":"13123b911d01dc91184e3f9470e36d4ca1703c383ee8b561cf4a09787fb3b53d","contentType":"text/markdown; charset=utf-8"},{"id":"aa199c84-1119-5a93-b28b-6049ce14a108","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/aa199c84-1119-5a93-b28b-6049ce14a108/attachment.md","path":"references/docs/quasar-cli-vite/developing-cordova-apps/publishing-to-store.md","size":10739,"sha256":"fddf445e7b22e7a3cdb531f3597bbc765a857dc8c4cd887723512e55829f508d","contentType":"text/markdown; charset=utf-8"},{"id":"311a2b66-eb15-56a3-b68e-e8991da3e19f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/311a2b66-eb15-56a3-b68e-e8991da3e19f/attachment.md","path":"references/docs/quasar-cli-vite/developing-cordova-apps/troubleshooting-and-tips.md","size":11073,"sha256":"48b30913c89431630e6b1fee1c88c1c035d8733f7e444f5a11a3871050fe4284","contentType":"text/markdown; charset=utf-8"},{"id":"ed58b1ae-048c-5be6-a12d-12b6ac23b8b5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ed58b1ae-048c-5be6-a12d-12b6ac23b8b5/attachment.md","path":"references/docs/quasar-cli-vite/developing-electron-apps/app-icons-electron.md","size":1304,"sha256":"04891e6e6f783a2eb9348b25a28a724faf6f8cb7fcc85aa92473e6bf58b55093","contentType":"text/markdown; charset=utf-8"},{"id":"651bda1a-b307-523f-9a76-50e78a4ef295","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/651bda1a-b307-523f-9a76-50e78a4ef295/attachment.md","path":"references/docs/quasar-cli-vite/developing-electron-apps/build-commands.md","size":3314,"sha256":"90e366bba1f16a721a085768b5016fadaa8b7bf3f9f45a41b478dca77889a0c4","contentType":"text/markdown; charset=utf-8"},{"id":"6a17f080-38dd-5278-ad4d-5ea734676019","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/6a17f080-38dd-5278-ad4d-5ea734676019/attachment.md","path":"references/docs/quasar-cli-vite/developing-electron-apps/configuring-electron.md","size":4884,"sha256":"468f20149bd236798bd4ec490257b653125736dbac0ab3b3a03ac300620abab1","contentType":"text/markdown; charset=utf-8"},{"id":"6c0c3b58-7e42-5cd8-8e23-9309cf278c77","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/6c0c3b58-7e42-5cd8-8e23-9309cf278c77/attachment.md","path":"references/docs/quasar-cli-vite/developing-electron-apps/electron-accessing-files.md","size":3643,"sha256":"4b311d06f792b735ac6f1101d26ccdc6c07b959d6c75ddc7205d3356d3631839","contentType":"text/markdown; charset=utf-8"},{"id":"b5f10029-88cb-54d5-9639-7064755d6925","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b5f10029-88cb-54d5-9639-7064755d6925/attachment.md","path":"references/docs/quasar-cli-vite/developing-electron-apps/electron-packages.md","size":388,"sha256":"7501ea165472540b1de80be1359f5ce8759425af167ce3606170b2ca4da73608","contentType":"text/markdown; charset=utf-8"},{"id":"93a3389e-8acd-5a9c-b376-5fc164c3bd41","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/93a3389e-8acd-5a9c-b376-5fc164c3bd41/attachment.md","path":"references/docs/quasar-cli-vite/developing-electron-apps/electron-preload-script.md","size":3282,"sha256":"392e37cfb8ea44e5b158ee5a3b60b22ed89f14d7d64f0f081a01786bff5e496d","contentType":"text/markdown; charset=utf-8"},{"id":"343d22de-80fe-5bf7-ac1d-388247077cca","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/343d22de-80fe-5bf7-ac1d-388247077cca/attachment.md","path":"references/docs/quasar-cli-vite/developing-electron-apps/electron-security-concerns.md","size":6245,"sha256":"5d8f5921eb9303cb55ecdd8f6e5235200afe264a852c048ddc56f2abac6750cd","contentType":"text/markdown; charset=utf-8"},{"id":"0ae6e448-2d9c-5159-a1cf-ee7224f31b3a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/0ae6e448-2d9c-5159-a1cf-ee7224f31b3a/attachment.md","path":"references/docs/quasar-cli-vite/developing-electron-apps/electron-upgrade-guide.md","size":791,"sha256":"8dd26ac39976fbde67dde32eead03ab4f09dd6a5071fca92aaa80e9e663bf00f","contentType":"text/markdown; charset=utf-8"},{"id":"fd28bc77-0567-5f41-8bfb-55a163724ee7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/fd28bc77-0567-5f41-8bfb-55a163724ee7/attachment.md","path":"references/docs/quasar-cli-vite/developing-electron-apps/electron-with-typescript.md","size":770,"sha256":"fe7f6f3962ffba856a26a7e38601ed36052b0aa52be7331a793fc5efef2a9f1b","contentType":"text/markdown; charset=utf-8"},{"id":"118d9bbd-bdc3-573a-a6f0-c223b224759d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/118d9bbd-bdc3-573a-a6f0-c223b224759d/attachment.md","path":"references/docs/quasar-cli-vite/developing-electron-apps/frameless-electron-window.md","size":4371,"sha256":"a719f690b742bde25e41c4c29ab523d3bc758536fb244c20d5d49c36408d3720","contentType":"text/markdown; charset=utf-8"},{"id":"cb39dc18-1a8c-5413-aab7-8f1f2f1ced88","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/cb39dc18-1a8c-5413-aab7-8f1f2f1ced88/attachment.md","path":"references/docs/quasar-cli-vite/developing-electron-apps/introduction.md","size":1872,"sha256":"0dead261353aecdff7b4853b2b217fd268532ef8fae6a36da982cffa00be59f4","contentType":"text/markdown; charset=utf-8"},{"id":"0a1b10a1-fe0c-58f5-9504-9a0922318475","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/0a1b10a1-fe0c-58f5-9504-9a0922318475/attachment.md","path":"references/docs/quasar-cli-vite/developing-electron-apps/preparation.md","size":3399,"sha256":"dd8357f8f4b4c4a8a0f151bf323e45b65e4966707942c8e9ea5a505982423e17","contentType":"text/markdown; charset=utf-8"},{"id":"d5224750-1434-56aa-931f-4c10acd4bc25","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d5224750-1434-56aa-931f-4c10acd4bc25/attachment.md","path":"references/docs/quasar-cli-vite/developing-electron-apps/troubleshooting-and-tips.md","size":1589,"sha256":"92b93b964bc22d8d6c9e7199673a0ebf615285b0b93f1b0a8c5139901439d69d","contentType":"text/markdown; charset=utf-8"},{"id":"e627c99e-17ac-5c3c-854f-539fbe238504","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e627c99e-17ac-5c3c-854f-539fbe238504/attachment.md","path":"references/docs/quasar-cli-vite/developing-mobile-apps.md","size":1085,"sha256":"1b6d2889aacf0bf8d8d14d0f317fd4a6d29e86d1a7029565c84293c64d183b4b","contentType":"text/markdown; charset=utf-8"},{"id":"fda972fb-bfce-591b-97b1-30da954cbdb2","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/fda972fb-bfce-591b-97b1-30da954cbdb2/attachment.md","path":"references/docs/quasar-cli-vite/developing-pwa/app-icons-pwa.md","size":4990,"sha256":"3c1423baf346550f830a00f59661418e30fa23c9a50e404de6c1bd3bb5488fee","contentType":"text/markdown; charset=utf-8"},{"id":"9dd2450d-79f2-5474-89ca-2d1f8e9d3080","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9dd2450d-79f2-5474-89ca-2d1f8e9d3080/attachment.md","path":"references/docs/quasar-cli-vite/developing-pwa/build-commands.md","size":837,"sha256":"5c166f507c983be11b34d646f75f42b848e08e6962988cd3baddcc493f534b74","contentType":"text/markdown; charset=utf-8"},{"id":"8ef7f67a-2714-5638-81ea-d30150aa34cc","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8ef7f67a-2714-5638-81ea-d30150aa34cc/attachment.md","path":"references/docs/quasar-cli-vite/developing-pwa/configuring-pwa.md","size":10420,"sha256":"f0da12eac27dbd6cd5ff606c9b140d463a85801a428a6708c72ddb38c4513773","contentType":"text/markdown; charset=utf-8"},{"id":"f58133e1-8379-56fd-9b14-3d8367f0ce8f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f58133e1-8379-56fd-9b14-3d8367f0ce8f/attachment.md","path":"references/docs/quasar-cli-vite/developing-pwa/handling-service-worker.md","size":4145,"sha256":"91de19b626b876ada4b9f7a6bd6484d3135f0b0a3ffe72b3bedecd6e3d7177db","contentType":"text/markdown; charset=utf-8"},{"id":"7d0e9f00-5995-5555-b8c6-bd42b81ef630","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7d0e9f00-5995-5555-b8c6-bd42b81ef630/attachment.md","path":"references/docs/quasar-cli-vite/developing-pwa/hmr-for-dev.md","size":890,"sha256":"691db15a2b173001d837ec29525376eea6ebf906264c0d83417af6ac9566381f","contentType":"text/markdown; charset=utf-8"},{"id":"7e0ca05b-1676-5041-9398-93e2b3f1b645","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7e0ca05b-1676-5041-9398-93e2b3f1b645/attachment.md","path":"references/docs/quasar-cli-vite/developing-pwa/introduction.md","size":2275,"sha256":"dcee5b5e92f6ab9a35e0cb8c1427cf17f94671f2c72700657b20837bfc26bde2","contentType":"text/markdown; charset=utf-8"},{"id":"8c64d0bf-a0b6-582f-ab90-23e425f7b88e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8c64d0bf-a0b6-582f-ab90-23e425f7b88e/attachment.md","path":"references/docs/quasar-cli-vite/developing-pwa/preparation.md","size":1940,"sha256":"c60b5672bd9d7b5e397d660b1784e329997a91188e7ecafc87e15e872736bcf3","contentType":"text/markdown; charset=utf-8"},{"id":"c08c254a-f4f1-5e14-825d-bde0bbeb2a5f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c08c254a-f4f1-5e14-825d-bde0bbeb2a5f/attachment.md","path":"references/docs/quasar-cli-vite/developing-pwa/pwa-with-typescript.md","size":695,"sha256":"0aac53c26732fac8577d7ffafecc5393e6d798fcce1ca5d4d027295e0a47c5d5","contentType":"text/markdown; charset=utf-8"},{"id":"530849d3-066c-5b8e-8ce0-17a008152298","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/530849d3-066c-5b8e-8ce0-17a008152298/attachment.md","path":"references/docs/quasar-cli-vite/developing-spa/app-icons-spa.md","size":1809,"sha256":"aefbb9eeabbbed21d92c3bfd8ab1abe9ced0fa51d1080a75b9b6b860483f8d0b","contentType":"text/markdown; charset=utf-8"},{"id":"a351d33c-45de-5e6d-8bc5-e420add2c73a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a351d33c-45de-5e6d-8bc5-e420add2c73a/attachment.md","path":"references/docs/quasar-cli-vite/developing-spa/build-commands.md","size":373,"sha256":"e75c5ee2f3856e27db426181b6969b47a6170951b92d2d8d393631abfe392fc0","contentType":"text/markdown; charset=utf-8"},{"id":"2dbaba77-4dac-537e-a4bb-7f4145ca6880","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/2dbaba77-4dac-537e-a4bb-7f4145ca6880/attachment.md","path":"references/docs/quasar-cli-vite/developing-spa/deploying.md","size":10690,"sha256":"b9f344939e520e8867e2cffd8e16a9b08098f11feb2a628a029bf043ba2f62ae","contentType":"text/markdown; charset=utf-8"},{"id":"51be1de2-129d-5a44-9832-b0c4cfa83fd1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/51be1de2-129d-5a44-9832-b0c4cfa83fd1/attachment.md","path":"references/docs/quasar-cli-vite/developing-spa/introduction.md","size":1018,"sha256":"14f61601731543ad673c1cc5f2154ef1d3e6410c69787058bb82f48fedaa8e35","contentType":"text/markdown; charset=utf-8"},{"id":"969f31e1-101d-58a6-8fe3-7391c486ed92","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/969f31e1-101d-58a6-8fe3-7391c486ed92/attachment.md","path":"references/docs/quasar-cli-vite/developing-ssr/app-icons-ssr.md","size":5313,"sha256":"a26189a0c37e62d5e7123eb5c12f4fb42e37d6aa258576685d4fd6de215388bd","contentType":"text/markdown; charset=utf-8"},{"id":"9ac748f3-09d3-5e8b-9035-a6df8b41313d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9ac748f3-09d3-5e8b-9035-a6df8b41313d/attachment.md","path":"references/docs/quasar-cli-vite/developing-ssr/build-commands.md","size":506,"sha256":"a7cd8f5133a3ccb79293e1b54108c832fe025359fb62c41304459e459e7d3549","contentType":"text/markdown; charset=utf-8"},{"id":"4004d315-aa4a-500f-a9b0-a826ad85f15f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/4004d315-aa4a-500f-a9b0-a826ad85f15f/attachment.md","path":"references/docs/quasar-cli-vite/developing-ssr/client-side-hydration.md","size":2887,"sha256":"35d81abaeec8fa2e402e89075ef8c804f03fae22d1ed8aabf056dff9c2b4305c","contentType":"text/markdown; charset=utf-8"},{"id":"ec94b4ee-5a78-5a2d-a2c8-0bb779f3d5f4","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ec94b4ee-5a78-5a2d-a2c8-0bb779f3d5f4/attachment.md","path":"references/docs/quasar-cli-vite/developing-ssr/configuring-ssr.md","size":8053,"sha256":"d4e4e54ce54884c817969b194a4d4f3bb8948c660047d8cd2c67b773d6371d25","contentType":"text/markdown; charset=utf-8"},{"id":"0344fb56-b952-5caa-be0e-39604b111350","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/0344fb56-b952-5caa-be0e-39604b111350/attachment.md","path":"references/docs/quasar-cli-vite/developing-ssr/deploying.md","size":2196,"sha256":"0654d4703c933cf409f1ba37f352a2bafb06a81f894616e3ac43a70318ddd6e4","contentType":"text/markdown; charset=utf-8"},{"id":"c1a9e996-345e-53d9-9a53-bee99e0b034e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c1a9e996-345e-53d9-9a53-bee99e0b034e/attachment.md","path":"references/docs/quasar-cli-vite/developing-ssr/handling-404-and-500-errors.md","size":4400,"sha256":"deb4b3fd3ae7d000db58c80a082e54c2ff2c9d53c7e6813d1a68f8e92a1987c9","contentType":"text/markdown; charset=utf-8"},{"id":"b3f9831b-df8a-5e12-b428-7ab5fbfa3e96","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b3f9831b-df8a-5e12-b428-7ab5fbfa3e96/attachment.md","path":"references/docs/quasar-cli-vite/developing-ssr/introduction.md","size":2323,"sha256":"cebebb90af2774e74adaca4b985e11b2bc2b392a51765986d2b03776e779759d","contentType":"text/markdown; charset=utf-8"},{"id":"0fae909e-242e-5fc7-a5eb-05dd6b5dec14","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/0fae909e-242e-5fc7-a5eb-05dd6b5dec14/attachment.md","path":"references/docs/quasar-cli-vite/developing-ssr/preparation.md","size":1069,"sha256":"a3a3030d8f26d13563975e5d9a26f078635bab0d7e8120b3eaf23b5b9466c80e","contentType":"text/markdown; charset=utf-8"},{"id":"80cf6ce9-3135-5bbd-84c2-5b9937f47fa3","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/80cf6ce9-3135-5bbd-84c2-5b9937f47fa3/attachment.md","path":"references/docs/quasar-cli-vite/developing-ssr/seo-for-ssr.md","size":771,"sha256":"a6ac6fd10d4f7540d1c3ec2ca315eeab85436af39a2b95ca7463f4121c68fccd","contentType":"text/markdown; charset=utf-8"},{"id":"def59721-f41a-53ff-bc51-12ca07b5beee","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/def59721-f41a-53ff-bc51-12ca07b5beee/attachment.md","path":"references/docs/quasar-cli-vite/developing-ssr/ssr-context.md","size":2841,"sha256":"be1d0523f7fd6049342774cfdb32c5d8732690b6ceeeb77180048c9e4d990587","contentType":"text/markdown; charset=utf-8"},{"id":"1a5b4fa6-7ab2-5492-80cc-d6632541c374","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1a5b4fa6-7ab2-5492-80cc-d6632541c374/attachment.md","path":"references/docs/quasar-cli-vite/developing-ssr/ssr-frequently-asked-questions.md","size":2071,"sha256":"e619ca1d3d83acc070b2781406bb8554860a77ca021d2f8d4db3ed4eee14d18a","contentType":"text/markdown; charset=utf-8"},{"id":"7edf6f9f-22dd-5898-93f0-72c8595706c2","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7edf6f9f-22dd-5898-93f0-72c8595706c2/attachment.md","path":"references/docs/quasar-cli-vite/developing-ssr/ssr-middleware.md","size":12237,"sha256":"e2c8ff8d5189be0fe26697050a0461bcfde07227c753fa89b35416a90745224f","contentType":"text/markdown; charset=utf-8"},{"id":"8e2c97b1-d050-54d3-84f5-79baaf7fd186","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8e2c97b1-d050-54d3-84f5-79baaf7fd186/attachment.md","path":"references/docs/quasar-cli-vite/developing-ssr/ssr-webserver.md","size":16051,"sha256":"a7870022164d344087ba1309e59541e2a2f3ffba933b2d408c45885be229204b","contentType":"text/markdown; charset=utf-8"},{"id":"357afc1b-da75-5cf5-a49e-27304ead355a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/357afc1b-da75-5cf5-a49e-27304ead355a/attachment.md","path":"references/docs/quasar-cli-vite/developing-ssr/ssr-with-pwa.md","size":847,"sha256":"e253a7f8bb2a4523abca1d54c9d4a8e8bcad9115e324c6de46c9ac12db61c896","contentType":"text/markdown; charset=utf-8"},{"id":"d7ab9f63-23e6-555e-8193-1dc90b73ee28","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d7ab9f63-23e6-555e-8193-1dc90b73ee28/attachment.md","path":"references/docs/quasar-cli-vite/developing-ssr/ssr-with-typescript.md","size":254,"sha256":"ebbf2eb76a77c440f07403027c8f5ce486a3759bd40f4149296cfb272b0750d3","contentType":"text/markdown; charset=utf-8"},{"id":"aa007b1a-7f3f-55ae-ae22-c284807ddf72","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/aa007b1a-7f3f-55ae-ae22-c284807ddf72/attachment.md","path":"references/docs/quasar-cli-vite/developing-ssr/vue-ssr-directives.md","size":1653,"sha256":"4f98138395cca988ce10d23dd09c9e6f09776dd9744f5698e9e74e775c591c1a","contentType":"text/markdown; charset=utf-8"},{"id":"56a9608e-07dd-5a47-a445-3556586b63f0","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/56a9608e-07dd-5a47-a445-3556586b63f0/attachment.md","path":"references/docs/quasar-cli-vite/developing-ssr/writing-universal-code.md","size":5483,"sha256":"cae434002bcfbcaaf40226bdbaf5fca591a17e46e1c21b6a7fa4b976097e666b","contentType":"text/markdown; charset=utf-8"},{"id":"eb5bb661-cf6f-55c9-9454-5d23d1702be1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/eb5bb661-cf6f-55c9-9454-5d23d1702be1/attachment.md","path":"references/docs/quasar-cli-vite/directory-structure.md","size":4621,"sha256":"ba4bcadd1da1ecf8bd79742b12d2ce3f0298b7b5c0f2a50c280954268ee2ae89","contentType":"text/markdown; charset=utf-8"},{"id":"56bfdbc7-ee86-50df-b871-41436fa46ec5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/56bfdbc7-ee86-50df-b871-41436fa46ec5/attachment.md","path":"references/docs/quasar-cli-vite/handling-assets.md","size":2669,"sha256":"8ae3393a80cabcacf827807ad2bdb37c24acdc64f3e4ced127752dc088f2e2b6","contentType":"text/markdown; charset=utf-8"},{"id":"50f7be0b-26ea-5024-8cef-4b5eaeacb2c2","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/50f7be0b-26ea-5024-8cef-4b5eaeacb2c2/attachment.md","path":"references/docs/quasar-cli-vite/handling-process-env.md","size":9016,"sha256":"3b81cbb51f08eace905ab670f0a900ec19e97bcc8b1f7e71a3fbb1bba112fe0e","contentType":"text/markdown; charset=utf-8"},{"id":"82f4f45d-cfc1-5e52-a177-dac1c7d9ac0e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/82f4f45d-cfc1-5e52-a177-dac1c7d9ac0e/attachment.md","path":"references/docs/quasar-cli-vite/handling-vite.md","size":9042,"sha256":"9737d001b4d57e6fa590428110d41465b1f32dd17905db842e8f6cebba1f8864","contentType":"text/markdown; charset=utf-8"},{"id":"ef5d430e-263f-5c08-95f5-46005093c2d2","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ef5d430e-263f-5c08-95f5-46005093c2d2/attachment.md","path":"references/docs/quasar-cli-vite/lazy-loading.md","size":3353,"sha256":"b3cb2be6723cdaacb3e7502fecfdf79c2e26b2acd283bb21c185b349059ac88a","contentType":"text/markdown; charset=utf-8"},{"id":"e36ecc57-2ef3-5ee7-ac1e-1309263b28e8","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e36ecc57-2ef3-5ee7-ac1e-1309263b28e8/attachment.md","path":"references/docs/quasar-cli-vite/linter.md","size":9037,"sha256":"61a23a0622b5fac36923dcf9b08a7d5ba59baac2f8b0507bda8caaa22a936c0e","contentType":"text/markdown; charset=utf-8"},{"id":"93e8555e-17e7-539f-8d21-b8ee4dcfb802","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/93e8555e-17e7-539f-8d21-b8ee4dcfb802/attachment.md","path":"references/docs/quasar-cli-vite/opening-dev-server-to-public.md","size":4681,"sha256":"b2307f5b8d61f70c687c5388d128aab5edc74bcd8c51f20614559726b9ede72e","contentType":"text/markdown; charset=utf-8"},{"id":"78f9a84f-6e22-509e-b30f-4d760ec4cb0f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/78f9a84f-6e22-509e-b30f-4d760ec4cb0f/attachment.md","path":"references/docs/quasar-cli-vite/prefetch-feature.md","size":9792,"sha256":"f3c3554df73948d9816db8632027c4d1cda9aba50b14b7a2e808fb055604d50d","contentType":"text/markdown; charset=utf-8"},{"id":"61b2fa31-6849-56f8-8ce9-19f9b547b005","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/61b2fa31-6849-56f8-8ce9-19f9b547b005/attachment.md","path":"references/docs/quasar-cli-vite/quasar-config-file.md","size":25252,"sha256":"76757414f929627b6b73c386fe0b6f5ba61f8bef7d85aee7f0621475a3aaae22","contentType":"text/markdown; charset=utf-8"},{"id":"aef1157d-059f-5ea9-b63e-e26b66c6d653","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/aef1157d-059f-5ea9-b63e-e26b66c6d653/attachment.md","path":"references/docs/quasar-cli-vite/routing.md","size":1662,"sha256":"19011330d0ed69baa907a80d934f6a18ef830ba727576aa3672cf6eee9e71e4a","contentType":"text/markdown; charset=utf-8"},{"id":"fe41d704-7142-5aa4-ba26-a10ecdc03068","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/fe41d704-7142-5aa4-ba26-a10ecdc03068/attachment.md","path":"references/docs/quasar-cli-vite/state-management-with-pinia.md","size":6107,"sha256":"73275aea403cab4281b32bcccec67aa4762aefcf1000b36c11cd9e8f0f41629e","contentType":"text/markdown; charset=utf-8"},{"id":"e4b21520-1444-55b6-a147-337e7e462a4b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e4b21520-1444-55b6-a147-337e7e462a4b/attachment.md","path":"references/docs/quasar-cli-vite/supporting-ts.md","size":9323,"sha256":"350b7733f7c5ebbd924407be18997d0113fd0643680b2219397f9c6933d16d05","contentType":"text/markdown; charset=utf-8"},{"id":"32b0ef44-0c42-5af1-835e-a2de72cc0f1e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/32b0ef44-0c42-5af1-835e-a2de72cc0f1e/attachment.md","path":"references/docs/quasar-cli-vite/testing-and-auditing.md","size":2538,"sha256":"5f70f54d39f97118da552c5239426f6905d41d55c6bf492e3f2b0542e74db1a2","contentType":"text/markdown; charset=utf-8"},{"id":"6693ea64-dcf6-53f6-a5ea-a8e27b115f12","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/6693ea64-dcf6-53f6-a5ea-a8e27b115f12/attachment.md","path":"references/docs/quasar-cli-vite/upgrade-guide.md","size":48904,"sha256":"d95d4a9f7068f20cb26054b9d3c4d055bee81b2659f5fdff64faf11cc940254d","contentType":"text/markdown; charset=utf-8"},{"id":"f4537aa2-bd2c-5c7a-ad2b-cd2662c917bb","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f4537aa2-bd2c-5c7a-ad2b-cd2662c917bb/attachment.md","path":"references/docs/quasar-cli-webpack/ajax-requests.md","size":2567,"sha256":"16a1fa5f4f837006a3f0808000cccd521fa06b9e6ac484cf14458cdf0f1d306a","contentType":"text/markdown; charset=utf-8"},{"id":"035624bf-7ebc-57d7-ae17-9f3ed75dd75a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/035624bf-7ebc-57d7-ae17-9f3ed75dd75a/attachment.md","path":"references/docs/quasar-cli-webpack/api-proxying.md","size":1310,"sha256":"f0f7d53f0ce6fb41e8eec562c3db5e77cc1b252d3da99414fdfb5643cef97d18","contentType":"text/markdown; charset=utf-8"},{"id":"475bae2d-8754-550d-a760-df72655daf36","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/475bae2d-8754-550d-a760-df72655daf36/attachment.md","path":"references/docs/quasar-cli-webpack/boot-files.md","size":14857,"sha256":"7599def232bd79e8994265c8195354d0beaca90245ad1985149dd51635728357","contentType":"text/markdown; charset=utf-8"},{"id":"ef9d5388-bb3e-52ea-8cde-cf018dffebc8","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ef9d5388-bb3e-52ea-8cde-cf018dffebc8/attachment.md","path":"references/docs/quasar-cli-webpack/browser-compatibility.md","size":1220,"sha256":"c46559d46e2c534cfca6aa7f230bfdc9bc52cc1a8f55a59d55b3f260362a852c","contentType":"text/markdown; charset=utf-8"},{"id":"ba0f4b9f-54b6-5ccc-afaf-64729737d516","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ba0f4b9f-54b6-5ccc-afaf-64729737d516/attachment.md","path":"references/docs/quasar-cli-webpack/commands-list.md","size":24506,"sha256":"d6d6d95b2fc9a862262b323cd0048413e949d9e8ba8ff2611f6be8779e888a68","contentType":"text/markdown; charset=utf-8"},{"id":"c12dc773-e88c-5b5b-ba56-6c2cafbf2938","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c12dc773-e88c-5b5b-ba56-6c2cafbf2938/attachment.md","path":"references/docs/quasar-cli-webpack/convert-to-quasar-cli-with-webpack.md","size":4472,"sha256":"600bdf313babce713c1dedab36dbb20f07d29fa9b1da51e53e3fb70d029c85d2","contentType":"text/markdown; charset=utf-8"},{"id":"ad0494dd-283c-538c-9869-5d4d0c5d1ac2","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ad0494dd-283c-538c-9869-5d4d0c5d1ac2/attachment.md","path":"references/docs/quasar-cli-webpack/css-preprocessors.md","size":1079,"sha256":"8155ce32260ab85af7eecf32389142c605b307e246ff01264928c773656d884d","contentType":"text/markdown; charset=utf-8"},{"id":"97abb848-7587-55c8-909f-ad7715ab504e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/97abb848-7587-55c8-909f-ad7715ab504e/attachment.md","path":"references/docs/quasar-cli-webpack/developing-browser-extensions/app-icons-browser-extension.md","size":1322,"sha256":"78ef8b25c9ab02918d767ce51cd22ed021f9e08d91764258f57e93fe35f4a2cf","contentType":"text/markdown; charset=utf-8"},{"id":"b1b55099-c4ab-589f-809d-46b474bcf0fc","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b1b55099-c4ab-589f-809d-46b474bcf0fc/attachment.md","path":"references/docs/quasar-cli-webpack/developing-browser-extensions/background-script.md","size":2846,"sha256":"8c23f842aee3a6020dceb8a87928362f71dc0051bfe1416fc57a11a547a5e281","contentType":"text/markdown; charset=utf-8"},{"id":"c03320f4-2d1d-548c-9b77-2a99981654cf","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c03320f4-2d1d-548c-9b77-2a99981654cf/attachment.md","path":"references/docs/quasar-cli-webpack/developing-browser-extensions/bex-bridge.md","size":9151,"sha256":"0b44fa7801fb884dda602682c0e62695787c6fdbb44bb4f5efb773999ddef57e","contentType":"text/markdown; charset=utf-8"},{"id":"4bcea6d4-b313-581a-a269-7dd006baeb2e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/4bcea6d4-b313-581a-a269-7dd006baeb2e/attachment.md","path":"references/docs/quasar-cli-webpack/developing-browser-extensions/build-commands.md","size":6194,"sha256":"a35d15f14fc841d5384a2571c6589b3d7f19a7f36ffbb16770baebe5df020add","contentType":"text/markdown; charset=utf-8"},{"id":"717e873a-cace-5e9b-b6de-16c2b5807d5e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/717e873a-cace-5e9b-b6de-16c2b5807d5e/attachment.md","path":"references/docs/quasar-cli-webpack/developing-browser-extensions/configuring-bex.md","size":5730,"sha256":"2ad65bf7a67e125ec25a3fbdfbc4811fe98fc22cb52caa6b4d29bab0b2f96d39","contentType":"text/markdown; charset=utf-8"},{"id":"bcc96e31-f3e2-567d-b2b0-0aeb594dce81","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/bcc96e31-f3e2-567d-b2b0-0aeb594dce81/attachment.md","path":"references/docs/quasar-cli-webpack/developing-browser-extensions/content-scripts.md","size":2962,"sha256":"cf3d88499c4f389d24f8d1f3d0aa6e73281509ce6a720b19d00f2b5d7f7f16ac","contentType":"text/markdown; charset=utf-8"},{"id":"9b76bb2c-1f24-5bbf-bffc-0857c2ca318a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9b76bb2c-1f24-5bbf-bffc-0857c2ca318a/attachment.md","path":"references/docs/quasar-cli-webpack/developing-browser-extensions/introduction.md","size":1248,"sha256":"43ca7cb1339dded0546cf1bb66c457d569341bfcf6241ca0ee7a9f26a5cb3048","contentType":"text/markdown; charset=utf-8"},{"id":"73a52a4d-fe87-5a56-8fd7-2f5a082e292b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/73a52a4d-fe87-5a56-8fd7-2f5a082e292b/attachment.md","path":"references/docs/quasar-cli-webpack/developing-browser-extensions/preparation.md","size":2203,"sha256":"d2b2d2a120ef42fff44656f17445ef8abee2b5ba4e0e767ae4e2c078b4812057","contentType":"text/markdown; charset=utf-8"},{"id":"64043361-6f5a-5f8f-92b2-c7e65f01441f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/64043361-6f5a-5f8f-92b2-c7e65f01441f/attachment.md","path":"references/docs/quasar-cli-webpack/developing-browser-extensions/types-of-bex.md","size":5900,"sha256":"7f89072b9f84c52ca21743e278a3ec09d0b3f3645939b7d43c517550747153a4","contentType":"text/markdown; charset=utf-8"},{"id":"de9c78a5-66c3-5e8d-bfd7-0879a62aa3cc","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/de9c78a5-66c3-5e8d-bfd7-0879a62aa3cc/attachment.md","path":"references/docs/quasar-cli-webpack/developing-capacitor-apps/app-icons-capacitor.md","size":5754,"sha256":"17a6517144e1f2da9aeb361c981e28748f0959b7b6de93884b324869d961a221","contentType":"text/markdown; charset=utf-8"},{"id":"f9a41e96-4cd5-52c3-b9f8-b2b3ee2e8ef7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f9a41e96-4cd5-52c3-b9f8-b2b3ee2e8ef7/attachment.md","path":"references/docs/quasar-cli-webpack/developing-capacitor-apps/build-commands.md","size":3798,"sha256":"7ab91e89cb7ba8138308f5be4b8ea09254dc83d1052a66e203370ee7c493f4ac","contentType":"text/markdown; charset=utf-8"},{"id":"19d23988-ec6c-5028-9889-e95e27495ecc","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/19d23988-ec6c-5028-9889-e95e27495ecc/attachment.md","path":"references/docs/quasar-cli-webpack/developing-capacitor-apps/capacitor-api.md","size":4966,"sha256":"6296dc4633f36db3ff7964e8d29c97c85263ac13efe82e2bd17f1e6710e4b4ae","contentType":"text/markdown; charset=utf-8"},{"id":"b64dcc4d-cfda-5cc2-8289-744750840aee","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b64dcc4d-cfda-5cc2-8289-744750840aee/attachment.md","path":"references/docs/quasar-cli-webpack/developing-capacitor-apps/capacitor-version-support.md","size":5455,"sha256":"480e02f931bc2258f9d9690952e3a6e820f2713049582177ec14f164fb29ddd8","contentType":"text/markdown; charset=utf-8"},{"id":"a89e2ecd-36dd-579b-bf2c-5bd3ddf5efdb","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a89e2ecd-36dd-579b-bf2c-5bd3ddf5efdb/attachment.md","path":"references/docs/quasar-cli-webpack/developing-capacitor-apps/configuring-capacitor.md","size":2677,"sha256":"f95876dcbda3b2e4962d0148d0bcdd0a50f0b5cca9dffc4d2e2840d57e68d074","contentType":"text/markdown; charset=utf-8"},{"id":"fd8a9f7f-4cd5-564b-8166-a6cb55747c4c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/fd8a9f7f-4cd5-564b-8166-a6cb55747c4c/attachment.md","path":"references/docs/quasar-cli-webpack/developing-capacitor-apps/introduction.md","size":454,"sha256":"59f65adfecc729c5afa5d35b8cab29e8d3f8bd76bbb86d375be74cb0b7196cc8","contentType":"text/markdown; charset=utf-8"},{"id":"a4c697e5-1b6f-5149-a2d5-4d565fc3835f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a4c697e5-1b6f-5149-a2d5-4d565fc3835f/attachment.md","path":"references/docs/quasar-cli-webpack/developing-capacitor-apps/live-updates.md","size":3697,"sha256":"0acb067b09dbdd1c88cba3afb6b0e49f78bed235ff7f732cd34186ca19512fc1","contentType":"text/markdown; charset=utf-8"},{"id":"902de85e-3c52-563f-9312-d0c756c4ea96","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/902de85e-3c52-563f-9312-d0c756c4ea96/attachment.md","path":"references/docs/quasar-cli-webpack/developing-capacitor-apps/managing-google-analytics.md","size":3292,"sha256":"7e99f46f92738a4583002527d5fae064464b97681b52b088e017483664b23527","contentType":"text/markdown; charset=utf-8"},{"id":"7e913b2f-c45e-5a57-926c-401f507b7f1a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7e913b2f-c45e-5a57-926c-401f507b7f1a/attachment.md","path":"references/docs/quasar-cli-webpack/developing-capacitor-apps/preparation.md","size":3861,"sha256":"a81ab133795c7fd3852170dfa80ef5b28cbcc82586a14892ed97252dd2708a3d","contentType":"text/markdown; charset=utf-8"},{"id":"f8fb0d64-a193-5e73-b6f3-e7dcbeeb15a5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f8fb0d64-a193-5e73-b6f3-e7dcbeeb15a5/attachment.md","path":"references/docs/quasar-cli-webpack/developing-capacitor-apps/publishing-to-store.md","size":10198,"sha256":"da84a1f01cb104da982168b538b437874b59fb67bb07ef0c6114bcd138fd875c","contentType":"text/markdown; charset=utf-8"},{"id":"cb7761cf-fbd4-5d3e-bb02-1e790be03af0","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/cb7761cf-fbd4-5d3e-bb02-1e790be03af0/attachment.md","path":"references/docs/quasar-cli-webpack/developing-capacitor-apps/troubleshooting-and-tips.md","size":7362,"sha256":"1e849049905d61bc55ece7e6cc86ce142b026137d86a76f82ca7173c11a1f02b","contentType":"text/markdown; charset=utf-8"},{"id":"75f87435-974a-559a-b4d1-6ce10949c0d5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/75f87435-974a-559a-b4d1-6ce10949c0d5/attachment.md","path":"references/docs/quasar-cli-webpack/developing-cordova-apps/app-icons-cordova.md","size":8330,"sha256":"412de2fba34bd40b1fcd8300e833ef6e7e8656efcf04135f410b087bd986a6ec","contentType":"text/markdown; charset=utf-8"},{"id":"df56b7d6-b5c9-5bad-867c-48e1dcdd18bc","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/df56b7d6-b5c9-5bad-867c-48e1dcdd18bc/attachment.md","path":"references/docs/quasar-cli-webpack/developing-cordova-apps/build-commands.md","size":5488,"sha256":"de8e9730df95bb26c21c830a107ee9cf8528e02a5485f524c07290985bc40b62","contentType":"text/markdown; charset=utf-8"},{"id":"ac52ae5c-1613-5348-8292-a876b950208c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ac52ae5c-1613-5348-8292-a876b950208c/attachment.md","path":"references/docs/quasar-cli-webpack/developing-cordova-apps/configuring-cordova.md","size":4866,"sha256":"f400bc805259473ff88d8fd6b90093790c5748cedd47aeac49487650695ab3a4","contentType":"text/markdown; charset=utf-8"},{"id":"a953230a-795e-59f4-af7d-74bfd6b44210","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a953230a-795e-59f4-af7d-74bfd6b44210/attachment.md","path":"references/docs/quasar-cli-webpack/developing-cordova-apps/cordova-plugins.md","size":6354,"sha256":"8f678c54454432a351d80515de864d17beab29038fea06b01efc4f162f8fb492","contentType":"text/markdown; charset=utf-8"},{"id":"f48b2400-2677-5569-8a6f-fa5a7958124e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f48b2400-2677-5569-8a6f-fa5a7958124e/attachment.md","path":"references/docs/quasar-cli-webpack/developing-cordova-apps/introduction.md","size":1226,"sha256":"b6947c15e954990b18d48141069220dfb7cf7da8405e76ebcbbabf6908c8c6c1","contentType":"text/markdown; charset=utf-8"},{"id":"8b3ae538-8f90-56e5-8c22-2571bc308631","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8b3ae538-8f90-56e5-8c22-2571bc308631/attachment.md","path":"references/docs/quasar-cli-webpack/developing-cordova-apps/managing-google-analytics.md","size":3364,"sha256":"2b06e7791d2d9c2dc6fc3db87665ee483eb15f94b7fb0785ac867ad834fb831d","contentType":"text/markdown; charset=utf-8"},{"id":"1ea17595-e8ab-5c18-851b-c5244eea8e4b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1ea17595-e8ab-5c18-851b-c5244eea8e4b/attachment.md","path":"references/docs/quasar-cli-webpack/developing-cordova-apps/preparation.md","size":7385,"sha256":"a709317ede97ffff50095239fa95fbb19ee839a7f62053dfde17f4b5ced6781b","contentType":"text/markdown; charset=utf-8"},{"id":"6095db99-c5a7-5a97-b372-afda5a14e7d6","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/6095db99-c5a7-5a97-b372-afda5a14e7d6/attachment.md","path":"references/docs/quasar-cli-webpack/developing-cordova-apps/publishing-to-store.md","size":10742,"sha256":"6377d3893bed23ae2c360abfd582fbcdf3f9fc5b332b4d69ae982743f4dc5db6","contentType":"text/markdown; charset=utf-8"},{"id":"9574682b-bbe6-56ee-859d-7599b62a7215","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9574682b-bbe6-56ee-859d-7599b62a7215/attachment.md","path":"references/docs/quasar-cli-webpack/developing-cordova-apps/troubleshooting-and-tips.md","size":11076,"sha256":"44d2ffbaaaecd2bf1e7c7d6e699b1548817ff16a3afddcdb212b6ac3f4d433e0","contentType":"text/markdown; charset=utf-8"},{"id":"cb65d585-0805-58b9-8da9-07e1587662cf","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/cb65d585-0805-58b9-8da9-07e1587662cf/attachment.md","path":"references/docs/quasar-cli-webpack/developing-electron-apps/app-icons-electron.md","size":1307,"sha256":"554c2c71092d8aec9a8d35b1452640352939895e5a4cfdfb5db8d824b2ecfc24","contentType":"text/markdown; charset=utf-8"},{"id":"64aac8ea-50c4-5ce4-83b2-73c0d3878d1f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/64aac8ea-50c4-5ce4-83b2-73c0d3878d1f/attachment.md","path":"references/docs/quasar-cli-webpack/developing-electron-apps/build-commands.md","size":3323,"sha256":"31af74620cdfda29fd570f8e01775ffe5cb7c478b2ae3565e7896667ad10a963","contentType":"text/markdown; charset=utf-8"},{"id":"84ce10c4-e634-5bd5-8146-d5da6731af8b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/84ce10c4-e634-5bd5-8146-d5da6731af8b/attachment.md","path":"references/docs/quasar-cli-webpack/developing-electron-apps/configuring-electron.md","size":4730,"sha256":"fac74b69bd0b86e331ebd96b7b44acb66211f379eb1462c31fc938a3b486a568","contentType":"text/markdown; charset=utf-8"},{"id":"42dece57-11f0-5fb8-8bdf-f432167c7f47","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/42dece57-11f0-5fb8-8bdf-f432167c7f47/attachment.md","path":"references/docs/quasar-cli-webpack/developing-electron-apps/electron-accessing-files.md","size":3646,"sha256":"50ea7ee1f303f81051275d468e7110cd810d9d6c5bfbca7bc9a04c6c3b4e0b74","contentType":"text/markdown; charset=utf-8"},{"id":"01a7a245-e9dc-51ab-ab12-407339e12cf4","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/01a7a245-e9dc-51ab-ab12-407339e12cf4/attachment.md","path":"references/docs/quasar-cli-webpack/developing-electron-apps/electron-packages.md","size":391,"sha256":"2f7ef19efbd696abff0b4876af88c32ac94f1cf1735f4dd2f1347663dc4921e8","contentType":"text/markdown; charset=utf-8"},{"id":"04c5d74c-7369-5bc6-92d5-62540c4f674d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/04c5d74c-7369-5bc6-92d5-62540c4f674d/attachment.md","path":"references/docs/quasar-cli-webpack/developing-electron-apps/electron-preload-script.md","size":3285,"sha256":"6a9c62295643e195c485123c41143f621084721e3deadc95989dd54d1e9a27af","contentType":"text/markdown; charset=utf-8"},{"id":"a978cbc5-17a5-5b99-9162-0394fc1de781","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a978cbc5-17a5-5b99-9162-0394fc1de781/attachment.md","path":"references/docs/quasar-cli-webpack/developing-electron-apps/electron-security-concerns.md","size":6251,"sha256":"27a1398ebefbfb20b3e78bbb45ba95b0b95f96ac489a5c9a89100c589c343d7e","contentType":"text/markdown; charset=utf-8"},{"id":"34835764-f1e6-538d-8fd4-457b8e3abb0b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/34835764-f1e6-538d-8fd4-457b8e3abb0b/attachment.md","path":"references/docs/quasar-cli-webpack/developing-electron-apps/electron-upgrade-guide.md","size":794,"sha256":"d1bd80e473515ab7cd888a8615d6eea7063b9c2b352266a38ea23724bf23756c","contentType":"text/markdown; charset=utf-8"},{"id":"8caf9afa-7bba-509f-ad95-bde27c1d0af1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8caf9afa-7bba-509f-ad95-bde27c1d0af1/attachment.md","path":"references/docs/quasar-cli-webpack/developing-electron-apps/electron-with-typescript.md","size":773,"sha256":"8763c5006f567463f0e8697297151992d1be0eb2c9acde1a25fce1167df27219","contentType":"text/markdown; charset=utf-8"},{"id":"a8a2c3b2-6563-56d4-9445-ddfce56852eb","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a8a2c3b2-6563-56d4-9445-ddfce56852eb/attachment.md","path":"references/docs/quasar-cli-webpack/developing-electron-apps/frameless-electron-window.md","size":4374,"sha256":"686c2f825a1b0d53d88c6bffe403a0cc060bbcbe4fe06b3c37ffd21882b884d2","contentType":"text/markdown; charset=utf-8"},{"id":"30828fc2-67cb-5c92-9482-0936abde84a9","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/30828fc2-67cb-5c92-9482-0936abde84a9/attachment.md","path":"references/docs/quasar-cli-webpack/developing-electron-apps/introduction.md","size":1878,"sha256":"3487f27265652d6d90d9c5897c8d467d4a28ce5e084b261abb509bc9184abd7b","contentType":"text/markdown; charset=utf-8"},{"id":"f23b1cd6-ed47-535b-87f9-84b0ce408884","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f23b1cd6-ed47-535b-87f9-84b0ce408884/attachment.md","path":"references/docs/quasar-cli-webpack/developing-electron-apps/preparation.md","size":3402,"sha256":"632cceab4fe70e226b26e4a05010bdd5566f863f0fb0b632056cf6e0321d5f0a","contentType":"text/markdown; charset=utf-8"},{"id":"7ec0e188-49cd-5a53-a6e9-9936c465f2bf","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7ec0e188-49cd-5a53-a6e9-9936c465f2bf/attachment.md","path":"references/docs/quasar-cli-webpack/developing-electron-apps/troubleshooting-and-tips.md","size":1592,"sha256":"08baba48ea010168a5a9732ea329bb05c30ef563b1eebd1c16791315244ece21","contentType":"text/markdown; charset=utf-8"},{"id":"165d98c7-a0d2-58f5-9268-e70551a8094e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/165d98c7-a0d2-58f5-9268-e70551a8094e/attachment.md","path":"references/docs/quasar-cli-webpack/developing-mobile-apps.md","size":1094,"sha256":"c4be9b469b4f1060e91884053063302cfbd285313f1418a422f9787d1a5219a9","contentType":"text/markdown; charset=utf-8"},{"id":"d898cf45-0e5e-5b99-8cbe-32ac0a5284b5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d898cf45-0e5e-5b99-8cbe-32ac0a5284b5/attachment.md","path":"references/docs/quasar-cli-webpack/developing-pwa/app-icons-pwa.md","size":4993,"sha256":"f6ec07f3609ddb733eb994544b74bc3af062044017c5bbe42f1e4e3a8a774b3b","contentType":"text/markdown; charset=utf-8"},{"id":"5cd5fec9-1cf9-5ec9-ad7f-08f06989fc2d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/5cd5fec9-1cf9-5ec9-ad7f-08f06989fc2d/attachment.md","path":"references/docs/quasar-cli-webpack/developing-pwa/build-commands.md","size":840,"sha256":"9777e272bb219b22f96bd04fbde5fd9c295e03ace661fdf7c16480a065e88aa7","contentType":"text/markdown; charset=utf-8"},{"id":"e27ccf6b-b9d2-575a-8c01-67c18985e055","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e27ccf6b-b9d2-575a-8c01-67c18985e055/attachment.md","path":"references/docs/quasar-cli-webpack/developing-pwa/configuring-pwa.md","size":9335,"sha256":"4e9e43fbbf1cba83ba5a49fd5563813e72ca5ec4670b364415b9f8471ed5b18a","contentType":"text/markdown; charset=utf-8"},{"id":"90462a4c-a283-5365-8a81-186468f48a6e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/90462a4c-a283-5365-8a81-186468f48a6e/attachment.md","path":"references/docs/quasar-cli-webpack/developing-pwa/handling-service-worker.md","size":4058,"sha256":"13503ef67dfdcc77556506da746a2566f6a507e4a52b9b0af93b85e0b2275ad7","contentType":"text/markdown; charset=utf-8"},{"id":"c1684fc0-d283-5d56-94fb-9050cc847d9f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c1684fc0-d283-5d56-94fb-9050cc847d9f/attachment.md","path":"references/docs/quasar-cli-webpack/developing-pwa/hmr-for-dev.md","size":893,"sha256":"bf2a7ddee22256e9cde14cbf14ab88b38d191d4ad9a92fa8bbc6a7988bda9947","contentType":"text/markdown; charset=utf-8"},{"id":"b8227df2-dbad-52b0-97f2-8a0c891e7666","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b8227df2-dbad-52b0-97f2-8a0c891e7666/attachment.md","path":"references/docs/quasar-cli-webpack/developing-pwa/introduction.md","size":2278,"sha256":"a16fe891437764675f767621d1a55eb0f187280de5e1f48f4a486e9de5869bb2","contentType":"text/markdown; charset=utf-8"},{"id":"9319bf30-aa6e-5c44-bb32-48fcf68d960e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9319bf30-aa6e-5c44-bb32-48fcf68d960e/attachment.md","path":"references/docs/quasar-cli-webpack/developing-pwa/preparation.md","size":1949,"sha256":"c61ecde8daa1fb30fb573605058eb27a182846e67482b0c7dc193f85396b67c3","contentType":"text/markdown; charset=utf-8"},{"id":"cbdec720-3103-5510-986c-9906da112bc7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/cbdec720-3103-5510-986c-9906da112bc7/attachment.md","path":"references/docs/quasar-cli-webpack/developing-pwa/pwa-with-typescript.md","size":698,"sha256":"3db96e87e9b1b628a81551684baf588e61ccf0bae7b1328ec8cdde145b80c89a","contentType":"text/markdown; charset=utf-8"},{"id":"41cd799c-8b96-5f29-8b0d-256b49c1754e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/41cd799c-8b96-5f29-8b0d-256b49c1754e/attachment.md","path":"references/docs/quasar-cli-webpack/developing-spa/app-icons-spa.md","size":1810,"sha256":"9d5a5d6d9c14f29d075ccc306a296c64e28a2eefc892e42f07ee3aa7f3f90696","contentType":"text/markdown; charset=utf-8"},{"id":"0d99e2d0-c3ee-578b-b092-3430cce3e31f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/0d99e2d0-c3ee-578b-b092-3430cce3e31f/attachment.md","path":"references/docs/quasar-cli-webpack/developing-spa/build-commands.md","size":376,"sha256":"5bb2bc5e6ed31f4610a26f1932cddaad309c2d966c2a37eb619a4791fa2c8f36","contentType":"text/markdown; charset=utf-8"},{"id":"c35f579f-16b0-515e-b99b-9bebc797f22b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c35f579f-16b0-515e-b99b-9bebc797f22b/attachment.md","path":"references/docs/quasar-cli-webpack/developing-spa/deploying.md","size":8597,"sha256":"9043d0ac097275d5cc31a73d28266b842f44006b841be669dd8d11301903efa3","contentType":"text/markdown; charset=utf-8"},{"id":"eacc1dc5-1d6c-5727-82f5-199ed2d0ec49","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/eacc1dc5-1d6c-5727-82f5-199ed2d0ec49/attachment.md","path":"references/docs/quasar-cli-webpack/developing-spa/introduction.md","size":1021,"sha256":"b0c1260725c8a6f4d407df925deef8373d7d36d1c96da547a65e8a6895be48d7","contentType":"text/markdown; charset=utf-8"},{"id":"eb7de099-77a5-559c-aa0f-3e6b823d5fac","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/eb7de099-77a5-559c-aa0f-3e6b823d5fac/attachment.md","path":"references/docs/quasar-cli-webpack/developing-ssr/app-icons-ssr.md","size":5312,"sha256":"4b8506abd6bf76e309feabaaba583874f324a5113e1cf67a0eb1422ef4cbd961","contentType":"text/markdown; charset=utf-8"},{"id":"73b929fb-12bf-5069-a3cd-09fc66912ec7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/73b929fb-12bf-5069-a3cd-09fc66912ec7/attachment.md","path":"references/docs/quasar-cli-webpack/developing-ssr/build-commands.md","size":637,"sha256":"8476d8e738ac85dab9610c68857db4fb8dd3e265ba751ebeb3db2981f5bc2573","contentType":"text/markdown; charset=utf-8"},{"id":"603522d0-b060-5a78-93e2-7f10947b2c64","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/603522d0-b060-5a78-93e2-7f10947b2c64/attachment.md","path":"references/docs/quasar-cli-webpack/developing-ssr/client-side-hydration.md","size":2890,"sha256":"920ce8bf64bfee9bd70c9f278b3f177d8b890e90e272bab12a2c9ac4bc508583","contentType":"text/markdown; charset=utf-8"},{"id":"72856898-f83e-5b8c-9f41-053ed7f31eed","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/72856898-f83e-5b8c-9f41-053ed7f31eed/attachment.md","path":"references/docs/quasar-cli-webpack/developing-ssr/configuring-ssr.md","size":8042,"sha256":"9828139efeed3c9b62f10ea6229049ec362450132f157424abe8d12a72efa3aa","contentType":"text/markdown; charset=utf-8"},{"id":"f206926f-5691-5a0c-8476-618e9323b1a8","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f206926f-5691-5a0c-8476-618e9323b1a8/attachment.md","path":"references/docs/quasar-cli-webpack/developing-ssr/deploying.md","size":2224,"sha256":"c83aeab9270affcaac81b9a4f7dfc76e297ef0e9347b68f6ad8639f51f8cd833","contentType":"text/markdown; charset=utf-8"},{"id":"baf1d671-0dc2-576a-8f52-ad91040cd27b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/baf1d671-0dc2-576a-8f52-ad91040cd27b/attachment.md","path":"references/docs/quasar-cli-webpack/developing-ssr/handling-404-and-500-errors.md","size":4403,"sha256":"421771b39e7861ab6fb1eb48239c7f9c017eb2f5171214eec2eadc6bb81021e3","contentType":"text/markdown; charset=utf-8"},{"id":"5dd3334c-ab71-5b3c-be6a-bb2df22118a1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/5dd3334c-ab71-5b3c-be6a-bb2df22118a1/attachment.md","path":"references/docs/quasar-cli-webpack/developing-ssr/introduction.md","size":2326,"sha256":"704d91771dcb4826f8b56502f467f232aacfa1f0217c1926b5b48eb960da9476","contentType":"text/markdown; charset=utf-8"},{"id":"3c054444-c596-56d7-8c24-9d4fa8bd887c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3c054444-c596-56d7-8c24-9d4fa8bd887c/attachment.md","path":"references/docs/quasar-cli-webpack/developing-ssr/preparation.md","size":1078,"sha256":"82089b65b3cb532886b6c170a07cdddac305f50dae18b46462ec53d141afc202","contentType":"text/markdown; charset=utf-8"},{"id":"06e9eac0-fde1-5312-b023-aa05d15bb77f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/06e9eac0-fde1-5312-b023-aa05d15bb77f/attachment.md","path":"references/docs/quasar-cli-webpack/developing-ssr/seo-for-ssr.md","size":774,"sha256":"f4e7f078ea753f6d09b7061468cc649c8843d7da6ba41920b212a2597b9e45cd","contentType":"text/markdown; charset=utf-8"},{"id":"7af1e24a-c45e-5712-8ea1-08563205133b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7af1e24a-c45e-5712-8ea1-08563205133b/attachment.md","path":"references/docs/quasar-cli-webpack/developing-ssr/ssr-context.md","size":2856,"sha256":"f777e0187d58dfee4d881512a9eaa4bc56ff08210c957ade7da0c974936be4a7","contentType":"text/markdown; charset=utf-8"},{"id":"ba63bf59-edab-5c2d-be94-3551ddab8982","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ba63bf59-edab-5c2d-be94-3551ddab8982/attachment.md","path":"references/docs/quasar-cli-webpack/developing-ssr/ssr-frequently-asked-questions.md","size":2086,"sha256":"d85b188e7db7a497f3e78934e84eca7a1df14a07cca06ea1a6081e092db4a0bc","contentType":"text/markdown; charset=utf-8"},{"id":"c58f663b-b271-556c-aea6-e9f144aeac86","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c58f663b-b271-556c-aea6-e9f144aeac86/attachment.md","path":"references/docs/quasar-cli-webpack/developing-ssr/ssr-middleware.md","size":12243,"sha256":"50ca898d5be601dca72be969caa5bc819d960d420dfc70ca9279410afdcccfd2","contentType":"text/markdown; charset=utf-8"},{"id":"38bee671-a40f-5f1f-bb9c-1db22bbcb5a9","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/38bee671-a40f-5f1f-bb9c-1db22bbcb5a9/attachment.md","path":"references/docs/quasar-cli-webpack/developing-ssr/ssr-webserver.md","size":16064,"sha256":"f9e217629ceef7b374d8ddeaec1519473500054e66e27ccccd7d9d70ee343bdc","contentType":"text/markdown; charset=utf-8"},{"id":"790662ca-a81e-5c8b-b7d4-062e53ed9272","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/790662ca-a81e-5c8b-b7d4-062e53ed9272/attachment.md","path":"references/docs/quasar-cli-webpack/developing-ssr/ssr-with-pwa.md","size":853,"sha256":"26d9eeaa01ae2a09a0472b6dc5659cb26b575b1941af9815d6273ad3ce28d9c5","contentType":"text/markdown; charset=utf-8"},{"id":"9b7a02da-4d05-56d6-a1ec-5b9f764b9322","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9b7a02da-4d05-56d6-a1ec-5b9f764b9322/attachment.md","path":"references/docs/quasar-cli-webpack/developing-ssr/ssr-with-typescript.md","size":257,"sha256":"bc318efa27a905a25c70f25385405123f82793b48409d27ffe8eb007ab666a80","contentType":"text/markdown; charset=utf-8"},{"id":"72e90a3b-b039-5d48-b9f2-dfc9205967c9","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/72e90a3b-b039-5d48-b9f2-dfc9205967c9/attachment.md","path":"references/docs/quasar-cli-webpack/developing-ssr/vue-ssr-directives.md","size":1656,"sha256":"66ba592568fd8853fa1272a46a3aa1c8e75253d47bb0b7771391a3aa2b5e94e8","contentType":"text/markdown; charset=utf-8"},{"id":"bcff2ec0-37c1-56ca-a54a-7a1896806b41","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/bcff2ec0-37c1-56ca-a54a-7a1896806b41/attachment.md","path":"references/docs/quasar-cli-webpack/developing-ssr/writing-universal-code.md","size":5491,"sha256":"04ec0312a64fc5d33d792a43f4abd08713fa8677c9e0c9552f5dc6a6edbb1088","contentType":"text/markdown; charset=utf-8"},{"id":"52579174-7473-55e6-8589-b627d4e9a89f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/52579174-7473-55e6-8589-b627d4e9a89f/attachment.md","path":"references/docs/quasar-cli-webpack/directory-structure.md","size":4753,"sha256":"2e8ac0451a2955089073337ba9aea888fa17b969a43630f147909a89a077f376","contentType":"text/markdown; charset=utf-8"},{"id":"19b198aa-2e6f-5ab9-80fe-3d6b169ce038","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/19b198aa-2e6f-5ab9-80fe-3d6b169ce038/attachment.md","path":"references/docs/quasar-cli-webpack/handling-assets.md","size":5006,"sha256":"0f9df67cc1fa7a50035294a905fb2fdb352ac23aab722ac52f3d3e6fd78e6ab8","contentType":"text/markdown; charset=utf-8"},{"id":"074fe443-ffb5-5fc2-bce6-fb2b278baddf","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/074fe443-ffb5-5fc2-bce6-fb2b278baddf/attachment.md","path":"references/docs/quasar-cli-webpack/handling-process-env.md","size":9005,"sha256":"9415556aefde57122328b76463f8375e1a4d83641b99dbc32132a684e842bfbd","contentType":"text/markdown; charset=utf-8"},{"id":"36767ce4-3273-5b87-a701-895670870795","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/36767ce4-3273-5b87-a701-895670870795/attachment.md","path":"references/docs/quasar-cli-webpack/handling-webpack.md","size":8755,"sha256":"b9af28490a3387f2f1dd331ea918dc4ab6331fd5bd173eaee1f50c62ab1eea62","contentType":"text/markdown; charset=utf-8"},{"id":"6c148950-94cc-547a-a3a2-6659d2f38be9","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/6c148950-94cc-547a-a3a2-6659d2f38be9/attachment.md","path":"references/docs/quasar-cli-webpack/lazy-loading.md","size":5998,"sha256":"014ea61f8e5fc2437b8fc01580546e581058625b200260ada6e53064ad03de65","contentType":"text/markdown; charset=utf-8"},{"id":"8ea0aafa-6a9a-5831-9f93-2c66f7b5305b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8ea0aafa-6a9a-5831-9f93-2c66f7b5305b/attachment.md","path":"references/docs/quasar-cli-webpack/linter.md","size":9090,"sha256":"0f7a5e35c1f831ec7f700289c05cc0ff19341a7b6f4836bf2f5962f4687d194a","contentType":"text/markdown; charset=utf-8"},{"id":"5475b0d2-c60d-52cc-b91f-09a47e728cab","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/5475b0d2-c60d-52cc-b91f-09a47e728cab/attachment.md","path":"references/docs/quasar-cli-webpack/opening-dev-server-to-public.md","size":4680,"sha256":"8321bdaa0441067dedca8850c45badcca507910421e599050bb5d4a4071a9bcb","contentType":"text/markdown; charset=utf-8"},{"id":"e9dc2fb0-1673-5c60-81d6-c573e12b9512","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e9dc2fb0-1673-5c60-81d6-c573e12b9512/attachment.md","path":"references/docs/quasar-cli-webpack/prefetch-feature.md","size":9720,"sha256":"2fd73b10e5a465073bb7ae31e447a20805fbaaf281d65b1e528218bf2f9befc6","contentType":"text/markdown; charset=utf-8"},{"id":"174881cf-0870-5f7a-86cb-9182a949a55d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/174881cf-0870-5f7a-86cb-9182a949a55d/attachment.md","path":"references/docs/quasar-cli-webpack/quasar-config-file.md","size":27445,"sha256":"8e2203d47e23749eecb7b9e457d1cebc68763d1532de6d33bdc67cbb1126df79","contentType":"text/markdown; charset=utf-8"},{"id":"8944421a-4c8a-5c5c-9a33-683de4eec303","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8944421a-4c8a-5c5c-9a33-683de4eec303/attachment.md","path":"references/docs/quasar-cli-webpack/routing.md","size":1596,"sha256":"b4e491f79cab4c610797da59e1623a2f9a3ba0388fe32b210e7fa1754cd0baeb","contentType":"text/markdown; charset=utf-8"},{"id":"ae3fdfe5-46b9-506c-bd4d-e0a841e1e65d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ae3fdfe5-46b9-506c-bd4d-e0a841e1e65d/attachment.md","path":"references/docs/quasar-cli-webpack/state-management-with-pinia.md","size":6115,"sha256":"106e37680cbedd7547de04020ca2fb8c7b5ec49b1daeb4874f06cd03e615cf15","contentType":"text/markdown; charset=utf-8"},{"id":"9ea5f4a1-f30f-5164-b748-8c18492d087b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9ea5f4a1-f30f-5164-b748-8c18492d087b/attachment.md","path":"references/docs/quasar-cli-webpack/supporting-ts.md","size":9339,"sha256":"6bce68dce6129e729a35ab8c82b85338a1c1e95feedf69dad530105319570cb8","contentType":"text/markdown; charset=utf-8"},{"id":"39f8202a-0241-555f-bef1-47fa2f0f3fd1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/39f8202a-0241-555f-bef1-47fa2f0f3fd1/attachment.md","path":"references/docs/quasar-cli-webpack/testing-and-auditing.md","size":2541,"sha256":"021491fdf5395cbc7562dca9f74cae55eb954dc750949f3b8f73a906ecb54312","contentType":"text/markdown; charset=utf-8"},{"id":"5a1b1dbf-3f43-5653-b8c0-ff8f51f6092f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/5a1b1dbf-3f43-5653-b8c0-ff8f51f6092f/attachment.md","path":"references/docs/quasar-cli-webpack/upgrade-guide.md","size":67323,"sha256":"ed7b0570ea6cb8cb89eb86e8b3a379c085ffa7c20394e11be3614936f2f391eb","contentType":"text/markdown; charset=utf-8"},{"id":"fddfa86a-23a2-5df9-ae18-ce14a04e113f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/fddfa86a-23a2-5df9-ae18-ce14a04e113f/attachment.md","path":"references/docs/quasar-plugins/addressbar-color.md","size":1734,"sha256":"09d7e6663599c6597003c4851151b53ba61dd81d74091918a4c753e4fc297609","contentType":"text/markdown; charset=utf-8"},{"id":"75183cab-b1d4-5062-91fb-c80f09e0a2f0","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/75183cab-b1d4-5062-91fb-c80f09e0a2f0/attachment.md","path":"references/docs/quasar-plugins/app-fullscreen.md","size":2285,"sha256":"c670e64a780721767de34e2e9b32d6544dbd07f035ecfb83a9d627b1d78a51ec","contentType":"text/markdown; charset=utf-8"},{"id":"9970a8f8-38ae-5610-8b0c-abb34e0c6f63","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9970a8f8-38ae-5610-8b0c-abb34e0c6f63/attachment.md","path":"references/docs/quasar-plugins/app-visibility.md","size":1080,"sha256":"c058d21f9daab93bde864d077373e7a2d53cd133753914e019578a4a3fcb6143","contentType":"text/markdown; charset=utf-8"},{"id":"a5d5faea-7d0a-5e25-a247-b76d4da8c336","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a5d5faea-7d0a-5e25-a247-b76d4da8c336/attachment.md","path":"references/docs/quasar-plugins/bottom-sheet.md","size":1679,"sha256":"8ff99f6e8e1c7e6de3210184662d7da8a7cec0f837d2a6d1bfdd7df393cec71d","contentType":"text/markdown; charset=utf-8"},{"id":"2107632d-d296-538d-b874-43daeb9885fc","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/2107632d-d296-538d-b874-43daeb9885fc/attachment.md","path":"references/docs/quasar-plugins/cookies.md","size":7110,"sha256":"03b7e241ef9ee1a341494eb4ce2d8ca09a572803710298c7a12b8423e698b439","contentType":"text/markdown; charset=utf-8"},{"id":"c28d436a-a2a1-57ad-adb3-a1dc03057f2f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c28d436a-a2a1-57ad-adb3-a1dc03057f2f/attachment.md","path":"references/docs/quasar-plugins/dark.md","size":2464,"sha256":"18b4dd0e7f62db551d6618b107542c436f76be3774bbc46b9b138e16f53e5a68","contentType":"text/markdown; charset=utf-8"},{"id":"1124c354-a51f-51ae-8731-2f5bc4b3bb1d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1124c354-a51f-51ae-8731-2f5bc4b3bb1d/attachment.md","path":"references/docs/quasar-plugins/dialog.md","size":13170,"sha256":"4a4e53e081b4fd05b83b20b1f9eed81193237015581292d32ccf397faac90f32","contentType":"text/markdown; charset=utf-8"},{"id":"f65d1738-362e-5320-839d-9e431f98e161","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f65d1738-362e-5320-839d-9e431f98e161/attachment.md","path":"references/docs/quasar-plugins/loading-bar.md","size":2542,"sha256":"f3edfbf42b360fef560a100490b71e3f28458df1d704c6645bec0153b301c1ec","contentType":"text/markdown; charset=utf-8"},{"id":"69ff0af2-aae6-5d44-9a90-69e2b1f5758e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/69ff0af2-aae6-5d44-9a90-69e2b1f5758e/attachment.md","path":"references/docs/quasar-plugins/loading.md","size":3916,"sha256":"dc6bffccb03e22f6c3ec7662f24aad313e1da419f3560d6414ab47c1766384c6","contentType":"text/markdown; charset=utf-8"},{"id":"d71c944e-057d-55d0-92d9-f1e6d935c039","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d71c944e-057d-55d0-92d9-f1e6d935c039/attachment.md","path":"references/docs/quasar-plugins/meta.md","size":8954,"sha256":"71c46e4c4cbfb2e6394ee776cc42a7f4c572c74524adb9b12dfbf1485cd368a7","contentType":"text/markdown; charset=utf-8"},{"id":"5907686a-9691-5ebf-afb9-1537cc144711","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/5907686a-9691-5ebf-afb9-1537cc144711/attachment.md","path":"references/docs/quasar-plugins/notify.md","size":6700,"sha256":"84ee885a26b0d429472f952dbf0f544022d27b888bcaa73e6e6dae67bac117b4","contentType":"text/markdown; charset=utf-8"},{"id":"c14708f5-9027-5971-9144-4509350e6ae5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c14708f5-9027-5971-9144-4509350e6ae5/attachment.md","path":"references/docs/quasar-plugins/web-storage.md","size":2281,"sha256":"6909c2f23641ac9ca32f73d57d289725c535cb8f38f3950debcb57be1534e4e9","contentType":"text/markdown; charset=utf-8"},{"id":"504893a7-6b3a-5d0e-b1db-ffb43706c66c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/504893a7-6b3a-5d0e-b1db-ffb43706c66c/attachment.md","path":"references/docs/quasar-utils/color-utils.md","size":5123,"sha256":"a1754b1fc77599407a49e566da1a825ebab1dd7016216cd47cbacb20bea8ef89","contentType":"text/markdown; charset=utf-8"},{"id":"50babeab-f0f6-5285-a594-0d1e4c8193c2","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/50babeab-f0f6-5285-a594-0d1e4c8193c2/attachment.md","path":"references/docs/quasar-utils/date-utils.md","size":17253,"sha256":"35db2a950970dd6b0648e6195f5c57e861292ca14847fae23270f9223282540a","contentType":"text/markdown; charset=utf-8"},{"id":"e192a96e-2e2a-587d-9a82-05126b20df73","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e192a96e-2e2a-587d-9a82-05126b20df73/attachment.md","path":"references/docs/quasar-utils/dom-utils.md","size":3236,"sha256":"73d34fab0b920b863a2e446b038c2e30c8185aa11a2287129c313e19c82ac7e4","contentType":"text/markdown; charset=utf-8"},{"id":"670342c1-8262-5487-8155-c036e4639486","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/670342c1-8262-5487-8155-c036e4639486/attachment.md","path":"references/docs/quasar-utils/event-bus-util.md","size":1889,"sha256":"683cb11c42f47f4697a0a49b9da31631f19e5c22ad44dc1d79a472d5bd0af300","contentType":"text/markdown; charset=utf-8"},{"id":"3730b2a9-77c7-5fda-933b-849a99299fb1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3730b2a9-77c7-5fda-933b-849a99299fb1/attachment.md","path":"references/docs/quasar-utils/formatter-utils.md","size":2340,"sha256":"b165cf32bf676a09a65e7f5b403656f19a8a6f2073d1bd539364f3565bb2d65c","contentType":"text/markdown; charset=utf-8"},{"id":"460efeac-abcf-5694-84d1-13eb48f07baa","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/460efeac-abcf-5694-84d1-13eb48f07baa/attachment.md","path":"references/docs/quasar-utils/morph-utils.md","size":10656,"sha256":"3520eeaaa7b4c503baab7068bd0cee9d6a42f105506f6cac45244597362e5b8f","contentType":"text/markdown; charset=utf-8"},{"id":"895de105-cdd8-5667-bc86-eede2939b1cf","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/895de105-cdd8-5667-bc86-eede2939b1cf/attachment.md","path":"references/docs/quasar-utils/other-utils.md","size":16086,"sha256":"3eda2cb9ba977427e2a381ba579c5dd6f93aa6e603d010e47143891ebd7ad255","contentType":"text/markdown; charset=utf-8"},{"id":"b4560e9c-2ae1-575d-8d10-31e7a208c0ac","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b4560e9c-2ae1-575d-8d10-31e7a208c0ac/attachment.md","path":"references/docs/quasar-utils/scrolling-utils.md","size":3724,"sha256":"9b6b63ed8432030880b93241a66dffaf5a9a1595233b6943983dfcff03f2c585","contentType":"text/markdown; charset=utf-8"},{"id":"f49ca824-dc93-5c1c-9320-2e488dc1e447","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f49ca824-dc93-5c1c-9320-2e488dc1e447/attachment.md","path":"references/docs/quasar-utils/type-checking-utils.md","size":1141,"sha256":"7cd1be491ed55e883ea93848856cc07de59a82b1234c164018d005839203e640","contentType":"text/markdown; charset=utf-8"},{"id":"0fdf715a-ca30-595c-95cc-c416c9cd25c1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/0fdf715a-ca30-595c-95cc-c416c9cd25c1/attachment.md","path":"references/docs/security/dos-and-donts.md","size":12541,"sha256":"91383aad44f99c13e03d4ce682248c29e1b6e3be251fb50713da709e55af9693","contentType":"text/markdown; charset=utf-8"},{"id":"57154cb2-b6bb-5de9-9ce0-eff13a986284","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/57154cb2-b6bb-5de9-9ce0-eff13a986284/attachment.md","path":"references/docs/security/report-a-vulnerability.md","size":711,"sha256":"1f99d4e42377231a4611c9c8574becf3a55e3377f4202ce5b7ae9fffd024c7e2","contentType":"text/markdown; charset=utf-8"},{"id":"40bdc85a-5d22-56b8-abde-2815563ae27c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/40bdc85a-5d22-56b8-abde-2815563ae27c/attachment.md","path":"references/docs/sponsors-and-backers/sponsors-and-backers.md","size":1757,"sha256":"8f9c454b03840297b27f971bf16fbfde92bab7a58391939843084502f6ac8a84","contentType":"text/markdown; charset=utf-8"},{"id":"0f42ec33-6e07-56fd-ae65-f3a5acd372f8","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/0f42ec33-6e07-56fd-ae65-f3a5acd372f8/attachment.md","path":"references/docs/start/how-to-use-vue.md","size":12703,"sha256":"e3225a3a08a3cf5bdb05e0f3eede6bb4f291e36f1c2e9e6f56f547d6846c7b65","contentType":"text/markdown; charset=utf-8"},{"id":"5243873c-121f-5d09-a75a-9d46375d97cd","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/5243873c-121f-5d09-a75a-9d46375d97cd/attachment.md","path":"references/docs/start/pick-quasar-flavour.md","size":5777,"sha256":"7dba35bb79a55a763c0ed5363b82e50e2642487e7c78bd9a62639ea34d6774a3","contentType":"text/markdown; charset=utf-8"},{"id":"222f2d18-cba6-55e1-8939-f1132a6eeec4","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/222f2d18-cba6-55e1-8939-f1132a6eeec4/attachment.md","path":"references/docs/start/playground.md","size":1109,"sha256":"14ec74cc12701747f30a2844fa46e9267095bc235aed2d0cb88d809210eba9b0","contentType":"text/markdown; charset=utf-8"},{"id":"685e0fdd-bb01-531c-af64-f6ef2ed2023e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/685e0fdd-bb01-531c-af64-f6ef2ed2023e/attachment.md","path":"references/docs/start/quasar-cli.md","size":6051,"sha256":"7294495cef0ceacb47514cd1d66ece4085a69572fb8e865691fbdc10444bb3be","contentType":"text/markdown; charset=utf-8"},{"id":"32b56d88-a11e-59c0-93e9-39aa4ac78c65","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/32b56d88-a11e-59c0-93e9-39aa4ac78c65/attachment.md","path":"references/docs/start/quick-start.md","size":3722,"sha256":"1b938b1a4666ed99d094bc50261d1565190b1a426ac538ef412884b3ecba26f1","contentType":"text/markdown; charset=utf-8"},{"id":"3cad809a-c06e-5f8f-b429-e44cfc592329","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3cad809a-c06e-5f8f-b429-e44cfc592329/attachment.md","path":"references/docs/start/release-notes/release-notes.md","size":340,"sha256":"4c6667642aa699aa272bbd6b86a017fe878532c884117a7e3b225635810c6927","contentType":"text/markdown; charset=utf-8"},{"id":"a13743b1-2694-51ab-9c05-f16551a49203","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a13743b1-2694-51ab-9c05-f16551a49203/attachment.md","path":"references/docs/start/umd/umd.md","size":4711,"sha256":"1cfd745a61d15d72f8cafafd79f63e93d200ad108335ce36f30c6d87c380b62f","contentType":"text/markdown; charset=utf-8"},{"id":"63b7d0c6-0dd5-525e-9992-dee1240005d4","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/63b7d0c6-0dd5-525e-9992-dee1240005d4/attachment.md","path":"references/docs/start/upgrade-guide/upgrade-guide.md","size":44438,"sha256":"7c0712cd0bbc1f17cfb7b8c1ffa2b5c0cd172bc36e936f00de4cf1dc00b6a808","contentType":"text/markdown; charset=utf-8"},{"id":"65f38f48-2630-5b48-b53e-0ddfb7ab93e8","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/65f38f48-2630-5b48-b53e-0ddfb7ab93e8/attachment.md","path":"references/docs/start/vite-plugin/vite-plugin.md","size":2628,"sha256":"127f652cbcbeabaeaaf06566b0e000ca9be997fab8ca6539e6b3d32966f2727a","contentType":"text/markdown; charset=utf-8"},{"id":"20754bda-8239-57b6-925e-6be74c6b3678","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/20754bda-8239-57b6-925e-6be74c6b3678/attachment.md","path":"references/docs/start/vs-code-configuration.md","size":5079,"sha256":"4da81880ca1ebd8ca7347b5db94f2e51393518980d0fc4c08bc20b4484aa4917","contentType":"text/markdown; charset=utf-8"},{"id":"54d27fc7-0671-500d-bf02-7bd6b3bf181d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/54d27fc7-0671-500d-bf02-7bd6b3bf181d/attachment.md","path":"references/docs/start/vue-cli-plugin.md","size":2913,"sha256":"f9c31c65f9b52d60a3bf5ecedbf81f748d5857099d605611ba04842ca2b8d3d0","contentType":"text/markdown; charset=utf-8"},{"id":"44fb06e5-8eb7-5e74-8386-b4ad30b1b1b8","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/44fb06e5-8eb7-5e74-8386-b4ad30b1b1b8/attachment.md","path":"references/docs/style/body-classes.md","size":2850,"sha256":"c45cdeacf3c945fcaf1a8a4cc7f496eaf4fda12330828d68dbd7f67c3adac99d","contentType":"text/markdown; charset=utf-8"},{"id":"241fddb3-7442-50e6-9a21-23daf550db60","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/241fddb3-7442-50e6-9a21-23daf550db60/attachment.md","path":"references/docs/style/breakpoints.md","size":1710,"sha256":"1c3c8646b1b6cdfa83a1e9e08bd4f94092cb7dc5913919522ad9e6d24162e431","contentType":"text/markdown; charset=utf-8"},{"id":"a103e042-fc36-5fbe-8ef0-ac14c5b19ac8","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a103e042-fc36-5fbe-8ef0-ac14c5b19ac8/attachment.md","path":"references/docs/style/color-palette/color-palette.md","size":7212,"sha256":"0dac7168111b211b2b7c8696d35bf67b97431838feae7ca5ccde6b4f76e9953a","contentType":"text/markdown; charset=utf-8"},{"id":"6f126e12-eb3b-55a0-a392-bd7824db5588","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/6f126e12-eb3b-55a0-a392-bd7824db5588/attachment.md","path":"references/docs/style/dark-mode.md","size":1776,"sha256":"2d8b9556f630e4484d2d7ffc9838424a9c72bfce412877e85e9fa72ebe724121","contentType":"text/markdown; charset=utf-8"},{"id":"328102b5-fe05-5d48-bf2b-c9c4a545c66b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/328102b5-fe05-5d48-bf2b-c9c4a545c66b/attachment.md","path":"references/docs/style/other-helper-classes.md","size":4053,"sha256":"7d735d3db70d1e691c765a47cb311a468693f0d3a94b01e5762bbbc273cf7a0c","contentType":"text/markdown; charset=utf-8"},{"id":"8488fc72-3d66-575a-aa19-acb2af003d40","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8488fc72-3d66-575a-aa19-acb2af003d40/attachment.md","path":"references/docs/style/positioning.md","size":3944,"sha256":"f2982b5ace3bd2ca59b62d1b270ca09029577cf60fb98dbc3b28205c5de294a4","contentType":"text/markdown; charset=utf-8"},{"id":"678879f5-2422-5368-bfbb-7d1a41e4d0bf","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/678879f5-2422-5368-bfbb-7d1a41e4d0bf/attachment.md","path":"references/docs/style/sass-scss-variables/sass-scss-variables.md","size":3697,"sha256":"c33a39fbf14972cae6480e3153f903df6c24e1463f6b8b7840e8593a14c2737e","contentType":"text/markdown; charset=utf-8"},{"id":"71b32d0b-969a-531b-887e-938a062ba8a4","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/71b32d0b-969a-531b-887e-938a062ba8a4/attachment.md","path":"references/docs/style/shadows.md","size":1673,"sha256":"7450a2d61b8d87aca5de99bc3c980ab31a8d804cf1d470cdba4ae3fef019960d","contentType":"text/markdown; charset=utf-8"},{"id":"490f47ce-c7ff-5d77-a818-a18912f34fd4","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/490f47ce-c7ff-5d77-a818-a18912f34fd4/attachment.md","path":"references/docs/style/spacing.md","size":9560,"sha256":"dec55dd96ed7f663bfb87227919fc3f310c407f0ce6c1720f1ea134cbbcfbc31","contentType":"text/markdown; charset=utf-8"},{"id":"dcbdebb8-fa9f-5ef8-b06a-865149c65953","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/dcbdebb8-fa9f-5ef8-b06a-865149c65953/attachment.md","path":"references/docs/style/theme-builder/theme-builder.md","size":501,"sha256":"80ded8425524409e1c82f3fbaeee33ddcd738e561f71533981a403ad8f3e424c","contentType":"text/markdown; charset=utf-8"},{"id":"c67b3dd0-f0ad-5756-9b35-87ad9ac2cbd8","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c67b3dd0-f0ad-5756-9b35-87ad9ac2cbd8/attachment.md","path":"references/docs/style/typography/typography.md","size":2376,"sha256":"3c9ce2ae888405d80e135a41e38e480e2b3bf433163107e362863b7ccee8e71b","contentType":"text/markdown; charset=utf-8"},{"id":"dd62e96d-3c2e-5940-8f69-cdade1508c29","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/dd62e96d-3c2e-5940-8f69-cdade1508c29/attachment.md","path":"references/docs/style/visibility.md","size":7459,"sha256":"fb73bc51578e0d57a30ae2015be795008bf5679cc064ac63ad654e247e6ec677","contentType":"text/markdown; charset=utf-8"},{"id":"9f6bef2e-9f68-5c5e-8f91-d3dad29e8701","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9f6bef2e-9f68-5c5e-8f91-d3dad29e8701/attachment.md","path":"references/docs/video-tutorials/video-tutorials.md","size":341,"sha256":"e05d0538e1917ca6f21640e1ad986988178015749768a5a8b3715c91d97eb517","contentType":"text/markdown; charset=utf-8"},{"id":"24632765-d410-5408-b51f-f596567106e9","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/24632765-d410-5408-b51f-f596567106e9/attachment.md","path":"references/docs/vue-components/ajax-bar.md","size":2739,"sha256":"87bea90a7809a34d7dc8b89f3d9cbff6b230f0ba413a75368d112364e795e82e","contentType":"text/markdown; charset=utf-8"},{"id":"13430fb3-1505-563c-8fe0-176e1353a5e0","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/13430fb3-1505-563c-8fe0-176e1353a5e0/attachment.md","path":"references/docs/vue-components/avatar.md","size":1054,"sha256":"569ed948000451e9044cc93f798f1aa29faf93ff14e3b70843e8819294b48fa2","contentType":"text/markdown; charset=utf-8"},{"id":"9b1bae1f-3732-54b8-9a2c-1b601cfc20b9","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9b1bae1f-3732-54b8-9a2c-1b601cfc20b9/attachment.md","path":"references/docs/vue-components/badge.md","size":814,"sha256":"1a968ebcde70f70fceb98b11f8dc256e525f14b74f4c765369a08cc3454ddfbc","contentType":"text/markdown; charset=utf-8"},{"id":"f301f309-f62b-563b-9715-7e37deadaf41","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f301f309-f62b-563b-9715-7e37deadaf41/attachment.md","path":"references/docs/vue-components/banner.md","size":732,"sha256":"e922d2b36d0002173f9165431394550132f5d1649dbe0998312e78a48176f56a","contentType":"text/markdown; charset=utf-8"},{"id":"9af2de30-f053-551b-89c7-51da707b54e2","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9af2de30-f053-551b-89c7-51da707b54e2/attachment.md","path":"references/docs/vue-components/bar.md","size":1581,"sha256":"399cb7fad4a9bfd67c0fdadea02be279dff56192dbb9cea3842fecec5f65e3da","contentType":"text/markdown; charset=utf-8"},{"id":"3f743b55-fd47-5190-9959-eee02fcf44f0","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3f743b55-fd47-5190-9959-eee02fcf44f0/attachment.md","path":"references/docs/vue-components/breadcrumbs.md","size":1347,"sha256":"a6b85bf30b78878180bfdf371ab7794ab7cd8f26bc34571c64474521ccee2960","contentType":"text/markdown; charset=utf-8"},{"id":"957b45e5-e77f-555d-b9ed-17e92447a128","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/957b45e5-e77f-555d-b9ed-17e92447a128/attachment.md","path":"references/docs/vue-components/button-dropdown.md","size":1189,"sha256":"953dc57e7d8d50186cf15b838a3a39f86aea3f9259b42e06398245c7d2c7f48c","contentType":"text/markdown; charset=utf-8"},{"id":"e9768fe6-4bf7-5aae-b7c0-47c300c38749","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e9768fe6-4bf7-5aae-b7c0-47c300c38749/attachment.md","path":"references/docs/vue-components/button-group.md","size":815,"sha256":"75944df6e9913364e7ac21bafd2248418ff1f86ce9bf1fa5c3decf0c81db716f","contentType":"text/markdown; charset=utf-8"},{"id":"138217cf-fd21-5893-8714-2dd80fe7943a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/138217cf-fd21-5893-8714-2dd80fe7943a/attachment.md","path":"references/docs/vue-components/button-toggle.md","size":1875,"sha256":"bbe84cc1772291b80b1a7065ef0441fa23632ad7739d1948e99a0fc463edbba4","contentType":"text/markdown; charset=utf-8"},{"id":"398f6a51-b0ff-5f9f-945c-63ec62dd7772","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/398f6a51-b0ff-5f9f-945c-63ec62dd7772/attachment.md","path":"references/docs/vue-components/button.md","size":4903,"sha256":"cafae3ec4d82c507ad480c1457a37532b101c05534b7e1473189d14e87c64f85","contentType":"text/markdown; charset=utf-8"},{"id":"8112c4c4-316d-55a5-9484-96d48e8b534e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8112c4c4-316d-55a5-9484-96d48e8b534e/attachment.md","path":"references/docs/vue-components/card.md","size":2474,"sha256":"1ab0e1d7da50db2d189c4ef99a77ebb2f08291904548a1f26c22aab308f7d078","contentType":"text/markdown; charset=utf-8"},{"id":"f0cb52d9-1882-57f6-a30d-908e5a6eee24","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f0cb52d9-1882-57f6-a30d-908e5a6eee24/attachment.md","path":"references/docs/vue-components/carousel.md","size":3803,"sha256":"c96990d974d53ce43943ee39446f174115b01b8d72844017f4d269829bcb4d13","contentType":"text/markdown; charset=utf-8"},{"id":"5e1151e2-ac26-5a62-9a23-721607ba7efa","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/5e1151e2-ac26-5a62-9a23-721607ba7efa/attachment.md","path":"references/docs/vue-components/chat.md","size":1255,"sha256":"07589179bc6ab9ee7045c7da5750a573745bbd9494af587a9b769431fddee84c","contentType":"text/markdown; charset=utf-8"},{"id":"00e5d86d-d72a-53e5-89d9-c791eae6168d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/00e5d86d-d72a-53e5-89d9-c791eae6168d/attachment.md","path":"references/docs/vue-components/checkbox.md","size":3561,"sha256":"daaad70baeefe3e244c29bb8036c71d12204c74e50c3b827b1a9cd9f2a6f25d8","contentType":"text/markdown; charset=utf-8"},{"id":"844fb166-8484-58bc-9bcc-d33b2db4a1f1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/844fb166-8484-58bc-9bcc-d33b2db4a1f1/attachment.md","path":"references/docs/vue-components/chip.md","size":1131,"sha256":"587483e06139962d8540613d5f45b0870c401351e647a9aac68395c0626b757c","contentType":"text/markdown; charset=utf-8"},{"id":"fff600ad-a335-5d19-aaae-ce9d5a776b69","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/fff600ad-a335-5d19-aaae-ce9d5a776b69/attachment.md","path":"references/docs/vue-components/circular-progress.md","size":1652,"sha256":"ef3ed4b1248c549025568849462d6f0072edbcc39db7007a232d180e05f5445d","contentType":"text/markdown; charset=utf-8"},{"id":"59d9f566-83df-5eb1-8755-d78f761fa807","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/59d9f566-83df-5eb1-8755-d78f761fa807/attachment.md","path":"references/docs/vue-components/color-picker.md","size":1952,"sha256":"96cadaa173c5b45922b85c23f5725b330dad14f3fa6f68864411b1aa2adbb370","contentType":"text/markdown; charset=utf-8"},{"id":"711ac15b-b51c-5da5-a07a-51b80e3e75a4","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/711ac15b-b51c-5da5-a07a-51b80e3e75a4/attachment.md","path":"references/docs/vue-components/date.md","size":7804,"sha256":"0bcd84336a319f80a3b7796c68b4fa5ff11c5202e1133adf8a0547a9b878a73b","contentType":"text/markdown; charset=utf-8"},{"id":"1e054408-f507-5755-8504-5b34d46458a6","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1e054408-f507-5755-8504-5b34d46458a6/attachment.md","path":"references/docs/vue-components/dialog.md","size":4456,"sha256":"9a6fbfc487954e0f69fa7674bd637dcb57cc4c59f684ef7f97fba440aa3fd291","contentType":"text/markdown; charset=utf-8"},{"id":"f76f581c-1d5c-5cb0-8dbc-f7ff56c29919","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f76f581c-1d5c-5cb0-8dbc-f7ff56c29919/attachment.md","path":"references/docs/vue-components/editor.md","size":5627,"sha256":"f32e6a11565f623b4419f436ac0d28dc36548ae695f3543904afcc4389cc4004","contentType":"text/markdown; charset=utf-8"},{"id":"b872a719-49b8-5918-9e42-a7a26d74e36c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b872a719-49b8-5918-9e42-a7a26d74e36c/attachment.md","path":"references/docs/vue-components/expansion-item.md","size":2002,"sha256":"5b97382ec92006dcb07599f1b8445d8dd66a6734fbe6da8ada8ba05e2ed55755","contentType":"text/markdown; charset=utf-8"},{"id":"0456ada3-f97c-5e92-808f-facb2c0d1cd2","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/0456ada3-f97c-5e92-808f-facb2c0d1cd2/attachment.md","path":"references/docs/vue-components/field.md","size":6473,"sha256":"c2573eb2820aaafdb91a33ba2293556bccb1187b7f6e242913119d40f224b96d","contentType":"text/markdown; charset=utf-8"},{"id":"d86d1eeb-8acf-5723-a010-9c2622eb1cde","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d86d1eeb-8acf-5723-a010-9c2622eb1cde/attachment.md","path":"references/docs/vue-components/file.md","size":3906,"sha256":"84d34d89ad3511982c2b39a238461e008775514a93f3c122e4881c7333c548f2","contentType":"text/markdown; charset=utf-8"},{"id":"ce2691f1-cd33-5969-9949-8ddbc7bc8c6f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ce2691f1-cd33-5969-9949-8ddbc7bc8c6f/attachment.md","path":"references/docs/vue-components/floating-action-button.md","size":2717,"sha256":"92d7a66db28a6dac034c89fcbe9d088f382bb0950bcb94e5743643aa81268f8e","contentType":"text/markdown; charset=utf-8"},{"id":"1ff41ca6-8488-5c8a-b883-53e5ecc0cb15","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1ff41ca6-8488-5c8a-b883-53e5ecc0cb15/attachment.md","path":"references/docs/vue-components/form.md","size":4811,"sha256":"0f407ab868b77f38217af19a1fd307e7ed5b45d2dcf79f29648bc3e44b090731","contentType":"text/markdown; charset=utf-8"},{"id":"c23b9ab5-cdce-539c-bffa-5eedd77cd765","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c23b9ab5-cdce-539c-bffa-5eedd77cd765/attachment.md","path":"references/docs/vue-components/icon.md","size":32032,"sha256":"c97592cb7fdb36c6b5cc56b5586f7f2e53398d43a443c660e285633a8507dc46","contentType":"text/markdown; charset=utf-8"},{"id":"16d38484-fadd-5932-905d-0bb3bc06ef4c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/16d38484-fadd-5932-905d-0bb3bc06ef4c/attachment.md","path":"references/docs/vue-components/img.md","size":3220,"sha256":"7c283393160f00220311a1cd63251084be84f198266b6a349c27562158cf5182","contentType":"text/markdown; charset=utf-8"},{"id":"d64f3444-3952-52cc-ba57-728ec1c6cd6b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d64f3444-3952-52cc-ba57-728ec1c6cd6b/attachment.md","path":"references/docs/vue-components/infinite-scroll.md","size":2138,"sha256":"6435232d941aa8b9aa47760580d04228c3f69fa2fb532cf0799e5baa4f2738cc","contentType":"text/markdown; charset=utf-8"},{"id":"af9fea07-53c9-5c4c-8b2d-83d6d0e03b4b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/af9fea07-53c9-5c4c-8b2d-83d6d0e03b4b/attachment.md","path":"references/docs/vue-components/inner-loading.md","size":1453,"sha256":"2756e7f23fb55101ff4e1c41a6cdd307cf9e176595878aac1cad4d45320ea7c9","contentType":"text/markdown; charset=utf-8"},{"id":"ed6a2693-6b56-5ea4-a6bf-20f270720ba9","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ed6a2693-6b56-5ea4-a6bf-20f270720ba9/attachment.md","path":"references/docs/vue-components/input.md","size":11729,"sha256":"30e0e407f74a8831a93451c2f7e0e301898a9133649e493974c3a29e49251f62","contentType":"text/markdown; charset=utf-8"},{"id":"40649143-1637-5a76-9f4a-2436d333c9aa","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/40649143-1637-5a76-9f4a-2436d333c9aa/attachment.md","path":"references/docs/vue-components/intersection.md","size":2928,"sha256":"0348733eca220ef4e0e522f7d29d85aae6dfbc0578b779d548310ceed3de6547","contentType":"text/markdown; charset=utf-8"},{"id":"4a331821-ca73-589a-8226-0e43d1604f5b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/4a331821-ca73-589a-8226-0e43d1604f5b/attachment.md","path":"references/docs/vue-components/knob.md","size":2141,"sha256":"517aa42141ea9668a72ba8cb20220b042163ec01315bfb8df9cf21d5f1bf3346","contentType":"text/markdown; charset=utf-8"},{"id":"1a18881e-f98e-50c0-9e94-2ee3bcdcb666","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1a18881e-f98e-50c0-9e94-2ee3bcdcb666/attachment.md","path":"references/docs/vue-components/linear-progress.md","size":1744,"sha256":"27054e27ff8fb07c41b2361d14190cbb8dcc5b4bd02771958a19947406f99183","contentType":"text/markdown; charset=utf-8"},{"id":"69cb7515-0dce-5df1-8d3d-c9435e08cea8","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/69cb7515-0dce-5df1-8d3d-c9435e08cea8/attachment.md","path":"references/docs/vue-components/list-and-list-items.md","size":3664,"sha256":"9753b0b933f9983cfa4059b18245f0b742d2e9d235f2ae006b64cd2746441e97","contentType":"text/markdown; charset=utf-8"},{"id":"aa0c62a9-36c3-5392-a0c4-b7c0315c2222","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/aa0c62a9-36c3-5392-a0c4-b7c0315c2222/attachment.md","path":"references/docs/vue-components/markup-table.md","size":1568,"sha256":"d05c4afffb117040a13749084819796b12900e8b7d51332fe15903cffee89901","contentType":"text/markdown; charset=utf-8"},{"id":"9f58efa7-88f8-5247-baa6-8a70fee1cdc8","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9f58efa7-88f8-5247-baa6-8a70fee1cdc8/attachment.md","path":"references/docs/vue-components/menu/menu.md","size":2852,"sha256":"6c6f17a525a21ab02b99654b650ebf3e46204128aff8e928734e088ffb77f416","contentType":"text/markdown; charset=utf-8"},{"id":"5a476908-4a10-55b4-ba3a-85e20cec83a9","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/5a476908-4a10-55b4-ba3a-85e20cec83a9/attachment.md","path":"references/docs/vue-components/no-ssr.md","size":1855,"sha256":"e122f1d9960821e82d183bf2a56b50e548aa7030caea464cc5cb9ac1bc96f03f","contentType":"text/markdown; charset=utf-8"},{"id":"b6e8e346-b5d7-55ab-a52f-a74519ade5b7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b6e8e346-b5d7-55ab-a52f-a74519ade5b7/attachment.md","path":"references/docs/vue-components/option-group.md","size":2746,"sha256":"f8026168e094107472a7b422dbed05cb809f162da8fc5e089141449ec0c6fa16","contentType":"text/markdown; charset=utf-8"},{"id":"929e2576-a1a3-5ff5-9f59-ca6a6a5d923b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/929e2576-a1a3-5ff5-9f59-ca6a6a5d923b/attachment.md","path":"references/docs/vue-components/pagination.md","size":1477,"sha256":"24a65d01eeded81446883481207a433a00622c10b7d1540d8b83e0deebb57b69","contentType":"text/markdown; charset=utf-8"},{"id":"4f10c895-0b46-51fc-9e52-0bcadc2549c4","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/4f10c895-0b46-51fc-9e52-0bcadc2549c4/attachment.md","path":"references/docs/vue-components/parallax.md","size":1680,"sha256":"ad2846e08ba1b833d8baf0161110bc9a1ccd6981dc3d494e800db44a42e6510a","contentType":"text/markdown; charset=utf-8"},{"id":"1b38bff6-6b3f-52e8-b992-da27fcdaea16","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1b38bff6-6b3f-52e8-b992-da27fcdaea16/attachment.md","path":"references/docs/vue-components/popup-edit.md","size":3863,"sha256":"a49375ba37d27e02f7b7c9fa087993415bf86ef0c3e75eb4db91d5b436b0ee9a","contentType":"text/markdown; charset=utf-8"},{"id":"fbb02d41-4a09-5352-a199-12f884f83e6b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/fbb02d41-4a09-5352-a199-12f884f83e6b/attachment.md","path":"references/docs/vue-components/popup-proxy.md","size":1975,"sha256":"c5a0543fbc8a500174bd27772f3ccc0441fa30c63e76d69bc05c446376e12f0e","contentType":"text/markdown; charset=utf-8"},{"id":"123e9a6f-c06e-53c8-9864-b45b66f1dd4b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/123e9a6f-c06e-53c8-9864-b45b66f1dd4b/attachment.md","path":"references/docs/vue-components/pull-to-refresh.md","size":1622,"sha256":"7d07c433e456c1195008ab78d438f55615e229893f7c676b1a9cb471580713a5","contentType":"text/markdown; charset=utf-8"},{"id":"b6ff310f-a863-5094-af9b-9f1e6e7e0c11","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b6ff310f-a863-5094-af9b-9f1e6e7e0c11/attachment.md","path":"references/docs/vue-components/radio.md","size":2373,"sha256":"25a2d308fc7e38cd9d32aff2fdbe07bc90dc1f16f9f372269f9add9d89235759","contentType":"text/markdown; charset=utf-8"},{"id":"79d6a663-b3e6-5bba-8159-1c97f8d0d82b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/79d6a663-b3e6-5bba-8159-1c97f8d0d82b/attachment.md","path":"references/docs/vue-components/range.md","size":4030,"sha256":"7a68e8d80f724c104494ca3d9595fc70598235050beee574e63a75becb71eb0d","contentType":"text/markdown; charset=utf-8"},{"id":"7fe7df90-70a7-53c8-8c07-95792815e12e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7fe7df90-70a7-53c8-8c07-95792815e12e/attachment.md","path":"references/docs/vue-components/rating.md","size":1877,"sha256":"937d88edaf1abb46702138c004e730aca5aede0414c17249ca7c5eedbbaa54a4","contentType":"text/markdown; charset=utf-8"},{"id":"55a73673-96a4-5569-9536-cba26be02db7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/55a73673-96a4-5569-9536-cba26be02db7/attachment.md","path":"references/docs/vue-components/resize-observer.md","size":771,"sha256":"f46f1d5c21f887bf366aacb705508b02b659b7cfe0c67463e07fe53e916e766e","contentType":"text/markdown; charset=utf-8"},{"id":"e5137674-33c5-5399-b4e7-d0737f42eca2","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e5137674-33c5-5399-b4e7-d0737f42eca2/attachment.md","path":"references/docs/vue-components/responsive.md","size":1785,"sha256":"a8064268b0881e17039ae3ffac72ecd8628e50aad4656d2ccb3ffbfbe97b767e","contentType":"text/markdown; charset=utf-8"},{"id":"9d51dca8-7816-5d5b-8844-a07441f58b6c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9d51dca8-7816-5d5b-8844-a07441f58b6c/attachment.md","path":"references/docs/vue-components/scroll-area.md","size":1895,"sha256":"0d1f43524f99cb55c04cbbe43c9d381ffd511dcd56be21e9b6d7eb435eb51dce","contentType":"text/markdown; charset=utf-8"},{"id":"370062aa-9fdc-5341-8ac5-776069edf9c1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/370062aa-9fdc-5341-8ac5-776069edf9c1/attachment.md","path":"references/docs/vue-components/scroll-observer.md","size":2737,"sha256":"8f1c27a43ca2cc37f7c8cf6fd8d737ecafdcf1e0dfa27c99b7477a63f5cf36e0","contentType":"text/markdown; charset=utf-8"},{"id":"7dd81c9d-3d9c-50f6-89fa-6cf007b4ac74","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7dd81c9d-3d9c-50f6-89fa-6cf007b4ac74/attachment.md","path":"references/docs/vue-components/select.md","size":13457,"sha256":"14a3c0d4b325bc41198b9685c687a2f83f7a043956ffbdffe24d9f5b95a61515","contentType":"text/markdown; charset=utf-8"},{"id":"51663c7a-8459-5030-8800-97bf9dac7e93","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/51663c7a-8459-5030-8800-97bf9dac7e93/attachment.md","path":"references/docs/vue-components/separator.md","size":1015,"sha256":"94a241bb335a66b0721181b952b38d3f32cb13b3181aa672192dd552083979f9","contentType":"text/markdown; charset=utf-8"},{"id":"9440b179-012e-51fc-bcf4-5002485fe89c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9440b179-012e-51fc-bcf4-5002485fe89c/attachment.md","path":"references/docs/vue-components/skeleton.md","size":1825,"sha256":"702eb2c990666e21d1f77a3612a1d57bacba7f30a5ac78d2532c61d042a6403b","contentType":"text/markdown; charset=utf-8"},{"id":"88b17814-e5b7-5238-85b4-335a3a812e08","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/88b17814-e5b7-5238-85b4-335a3a812e08/attachment.md","path":"references/docs/vue-components/slide-item.md","size":1209,"sha256":"7652043e4a5c0ec931125d686e2889dc8389e122f4bd23bbbced49fd961dc941","contentType":"text/markdown; charset=utf-8"},{"id":"8450b095-d034-5601-aad4-9f643e6d3b0b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8450b095-d034-5601-aad4-9f643e6d3b0b/attachment.md","path":"references/docs/vue-components/slide-transition.md","size":690,"sha256":"a58b0ead4e10f31e8007bfaa9ab72909ffabca37d7a6c353eb44614dd9fa92d8","contentType":"text/markdown; charset=utf-8"},{"id":"157d2c41-133f-5138-956e-2db27e1b2c57","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/157d2c41-133f-5138-956e-2db27e1b2c57/attachment.md","path":"references/docs/vue-components/slider.md","size":3524,"sha256":"0c63353a9766c73676252d3a3648ed3a6d760bc799ce052e0f97faa794456dba","contentType":"text/markdown; charset=utf-8"},{"id":"91f005be-ee7e-531a-9bf3-04148717017f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/91f005be-ee7e-531a-9bf3-04148717017f/attachment.md","path":"references/docs/vue-components/space.md","size":557,"sha256":"71274bc9042bbce68ba4c05ae7cf3fd1131dafb04bb3ec189e5179cb3bb57231","contentType":"text/markdown; charset=utf-8"},{"id":"f57f9d25-e443-509b-8942-faa8c7ae69ad","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f57f9d25-e443-509b-8942-faa8c7ae69ad/attachment.md","path":"references/docs/vue-components/spinners.md","size":1698,"sha256":"e5ac8d20b6bfabc0a8842c07be888d6984de16f560edad2223817fc21254c093","contentType":"text/markdown; charset=utf-8"},{"id":"7c507f1e-1837-5005-8509-a54dc2c3b241","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7c507f1e-1837-5005-8509-a54dc2c3b241/attachment.md","path":"references/docs/vue-components/splitter.md","size":2053,"sha256":"34dcd9849550fb9dc59fb3e4c39bcf567082881678d3ffdfe96df6d5a952f5dc","contentType":"text/markdown; charset=utf-8"},{"id":"3ddf74df-fa0c-5466-8182-a1aa6fc310ab","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3ddf74df-fa0c-5466-8182-a1aa6fc310ab/attachment.md","path":"references/docs/vue-components/stepper.md","size":3030,"sha256":"f7b24f79aa6eed89124d00778acd20e285b3d8b1fa3ed662a60f8d811f18ea31","contentType":"text/markdown; charset=utf-8"},{"id":"4b190909-9338-551f-a63a-c7e4f3bd38ed","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/4b190909-9338-551f-a63a-c7e4f3bd38ed/attachment.md","path":"references/docs/vue-components/tab-panels.md","size":2427,"sha256":"2e1e842dd9dc9cfc8df85229c86efc4fcd88e2c24bdc110777f4cff8de28d3cf","contentType":"text/markdown; charset=utf-8"},{"id":"54d97da3-6079-534c-893a-c7b7f57c7b87","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/54d97da3-6079-534c-893a-c7b7f57c7b87/attachment.md","path":"references/docs/vue-components/table.md","size":16441,"sha256":"e9d00def5f8230d50c439f654df612b9d394abd73264d2de96c52e797a1af1ab","contentType":"text/markdown; charset=utf-8"},{"id":"1caa922b-f537-5281-9d26-ad67c509eb50","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1caa922b-f537-5281-9d26-ad67c509eb50/attachment.md","path":"references/docs/vue-components/tabs.md","size":7990,"sha256":"d81306a0f1945369fcc67f98986b387b2725b9b4cc84f26f765d1d77753d6676","contentType":"text/markdown; charset=utf-8"},{"id":"32733040-ddf1-5ead-a509-9878eb2a04f2","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/32733040-ddf1-5ead-a509-9878eb2a04f2/attachment.md","path":"references/docs/vue-components/time.md","size":4274,"sha256":"89a69ffc8fe43bfc701c1fd48de5ab1b24af863c875241dfb81d2d143708253e","contentType":"text/markdown; charset=utf-8"},{"id":"5d943ac9-80d6-51bc-9e74-d0e82d975ae9","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/5d943ac9-80d6-51bc-9e74-d0e82d975ae9/attachment.md","path":"references/docs/vue-components/timeline.md","size":1993,"sha256":"dec58c7ad9a488bd54d5addfdcc517bbf540da7228f8c4067265f448d35a5ba1","contentType":"text/markdown; charset=utf-8"},{"id":"e97fafea-2d5d-5ef1-afde-20d6a71da70f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e97fafea-2d5d-5ef1-afde-20d6a71da70f/attachment.md","path":"references/docs/vue-components/toggle.md","size":3547,"sha256":"625b7509e4cf944708f244f4dd174ff899be76019bf7e65eef4da26de4e7a55c","contentType":"text/markdown; charset=utf-8"},{"id":"c452f665-8604-5821-ac86-5197a7286ce0","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c452f665-8604-5821-ac86-5197a7286ce0/attachment.md","path":"references/docs/vue-components/toolbar.md","size":1053,"sha256":"1ea7e9848bbe7736fc5ff220b631b29489ccd7be6a6012c7ecf24f1f90ab3c83","contentType":"text/markdown; charset=utf-8"},{"id":"e4b0c2b1-c202-5808-971b-5f56d3f4fbf3","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e4b0c2b1-c202-5808-971b-5f56d3f4fbf3/attachment.md","path":"references/docs/vue-components/tooltip/tooltip.md","size":2238,"sha256":"64314624a9759a31c092ad3acbc2677f3b9ef92ba123af6c6978a61be6f5079c","contentType":"text/markdown; charset=utf-8"},{"id":"722809b1-59f2-520d-9ef6-cefbbbcb19e5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/722809b1-59f2-520d-9ef6-cefbbbcb19e5/attachment.md","path":"references/docs/vue-components/tree.md","size":8485,"sha256":"a08007abb4de76d64a5737f0e9f71966c0cd3da00de93326eee56a66e76a3990","contentType":"text/markdown; charset=utf-8"},{"id":"d2155d48-8fff-55ec-9c7d-969da6c7741d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d2155d48-8fff-55ec-9c7d-969da6c7741d/attachment.md","path":"references/docs/vue-components/uploader.md","size":13744,"sha256":"159a40adc5e8c3be7293041f878d6af461d0796c8f3388cb40e4d57653e194a9","contentType":"text/markdown; charset=utf-8"},{"id":"ee1a433b-a0db-57a6-a495-9d934c6da7d5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ee1a433b-a0db-57a6-a495-9d934c6da7d5/attachment.md","path":"references/docs/vue-components/video.md","size":742,"sha256":"af44b6bc852bebd33542c286690fbde9b1fe06ac69a2d25545b73353b926260d","contentType":"text/markdown; charset=utf-8"},{"id":"7fc34dc3-508b-5f5a-a9b9-3bfcd6281e66","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7fc34dc3-508b-5f5a-a9b9-3bfcd6281e66/attachment.md","path":"references/docs/vue-components/virtual-scroll.md","size":5586,"sha256":"1601f64089629c2376a704832d0f4da1ad811e9598be20d559ebb0f5cf60dcfe","contentType":"text/markdown; charset=utf-8"},{"id":"4f6404b0-a6e8-5ede-890a-0e63a072ac9e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/4f6404b0-a6e8-5ede-890a-0e63a072ac9e/attachment.md","path":"references/docs/vue-composables/use-dialog-plugin-component.md","size":3403,"sha256":"fbacd433e4db1fddfd52c5681f3707774765a9902b78aaa253878899724fff35","contentType":"text/markdown; charset=utf-8"},{"id":"960b556f-a766-5adc-98ef-03b574c8cf71","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/960b556f-a766-5adc-98ef-03b574c8cf71/attachment.md","path":"references/docs/vue-composables/use-form-child.md","size":729,"sha256":"1f222d9e01d5758c63176c69be7186ae32f63d7ce611c09fc6f6c903e8342f19","contentType":"text/markdown; charset=utf-8"},{"id":"bc38a995-68f8-5b8c-a7f4-236ff9e3df09","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/bc38a995-68f8-5b8c-a7f4-236ff9e3df09/attachment.md","path":"references/docs/vue-composables/use-hydration.md","size":872,"sha256":"97541d08c76ace8f7e6211179a4b9024fd90bb49f4fe3a3a2ad888419efdedfd","contentType":"text/markdown; charset=utf-8"},{"id":"a9af5ee7-d458-5cb0-852c-21ac453ab08e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a9af5ee7-d458-5cb0-852c-21ac453ab08e/attachment.md","path":"references/docs/vue-composables/use-id.md","size":1098,"sha256":"b91171f36cffe5f92d95eaf185a78f1f453b4c282df9ec2e33ca434c6b5ffb7f","contentType":"text/markdown; charset=utf-8"},{"id":"1cc947de-4e65-540d-b0a9-c78c231dbda4","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1cc947de-4e65-540d-b0a9-c78c231dbda4/attachment.md","path":"references/docs/vue-composables/use-interval.md","size":1524,"sha256":"8a4f5d4f1af48073ecfdd84d51f93cf7433decb96a4c0ea50fe8aeb31cb682f4","contentType":"text/markdown; charset=utf-8"},{"id":"1491de6c-c5cf-576e-9f3a-a3e56b788ab5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1491de6c-c5cf-576e-9f3a-a3e56b788ab5/attachment.md","path":"references/docs/vue-composables/use-meta.md","size":1420,"sha256":"a207a654c49930ae9c6cc8b12f7a789119fe2317003eaca5ebba35b090ca5a04","contentType":"text/markdown; charset=utf-8"},{"id":"dfa3461f-6692-5863-b427-b02e24b5828d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/dfa3461f-6692-5863-b427-b02e24b5828d/attachment.md","path":"references/docs/vue-composables/use-quasar.md","size":879,"sha256":"6b4cafaff4d94bc9ee46f008a1afeaf32b1461db0716e370fdc39eee8d05aa19","contentType":"text/markdown; charset=utf-8"},{"id":"2f1893dd-8957-58f6-8e07-d0cbc54abf14","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/2f1893dd-8957-58f6-8e07-d0cbc54abf14/attachment.md","path":"references/docs/vue-composables/use-render-cache.md","size":3241,"sha256":"9e0d77c54cb8a9d948d1a8db0e7648ad41dd70a78d42f40f683cefce5311c7a9","contentType":"text/markdown; charset=utf-8"},{"id":"64dd9e08-26b4-5ffe-8a29-b94b77937e90","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/64dd9e08-26b4-5ffe-8a29-b94b77937e90/attachment.md","path":"references/docs/vue-composables/use-split-attrs.md","size":998,"sha256":"4a6bc8d54963e641352c561ade3970ddaff03af0517fd18bbfb982b696c2a36b","contentType":"text/markdown; charset=utf-8"},{"id":"f100b28e-f657-58b2-b219-28473786fdeb","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f100b28e-f657-58b2-b219-28473786fdeb/attachment.md","path":"references/docs/vue-composables/use-tick.md","size":1605,"sha256":"ef5bcaeb656e45b737faa0e4848a09f3d585cbf9b9f93815a2e47a43be6f3409","contentType":"text/markdown; charset=utf-8"},{"id":"e9e201c6-a193-51f7-a818-b1e8b7559e51","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e9e201c6-a193-51f7-a818-b1e8b7559e51/attachment.md","path":"references/docs/vue-composables/use-timeout.md","size":1879,"sha256":"46733573afb18b95bb007f9d193009f883ab03f0d35ba3ef32c692300b5e21cf","contentType":"text/markdown; charset=utf-8"},{"id":"db125776-022b-567f-98f5-2dac77b64251","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/db125776-022b-567f-98f5-2dac77b64251/attachment.md","path":"references/docs/vue-directives/close-popup.md","size":2052,"sha256":"c99c72952d9331a0464d1c7db0b01cc0e72252d41a466ea3a6b527189552a3ef","contentType":"text/markdown; charset=utf-8"},{"id":"f9f660ac-97e0-57b9-8145-84910bb22259","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f9f660ac-97e0-57b9-8145-84910bb22259/attachment.md","path":"references/docs/vue-directives/intersection.md","size":3434,"sha256":"8a20c3ccba02da31f9da30b456330536816be407339155c78716aaea02c75dba","contentType":"text/markdown; charset=utf-8"},{"id":"1f856d5a-0fe7-5c13-9753-bafa7596d9e8","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1f856d5a-0fe7-5c13-9753-bafa7596d9e8/attachment.md","path":"references/docs/vue-directives/material-ripples.md","size":2073,"sha256":"b02f82ea8c48385b2fd33a7907273cbd6cbbe17dd8180e2f1cdf2ef033b38756","contentType":"text/markdown; charset=utf-8"},{"id":"98e0be5d-4052-5a23-9316-755c7d2f8829","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/98e0be5d-4052-5a23-9316-755c7d2f8829/attachment.md","path":"references/docs/vue-directives/morph.md","size":1083,"sha256":"2af6aec5a02b2365ed02c41be0fcdabd280a13130b9c3859b89d95023408af68","contentType":"text/markdown; charset=utf-8"},{"id":"67fb0d37-cb4d-5102-9ff9-cc73cab161c7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/67fb0d37-cb4d-5102-9ff9-cc73cab161c7/attachment.md","path":"references/docs/vue-directives/mutation.md","size":1548,"sha256":"222a87c658f3bbcff5ea2f2c728267c462711dae7abb41c38cee4e2b788352e7","contentType":"text/markdown; charset=utf-8"},{"id":"5eebfc4a-6f42-548e-9244-98ff7c908e47","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/5eebfc4a-6f42-548e-9244-98ff7c908e47/attachment.md","path":"references/docs/vue-directives/scroll-fire.md","size":967,"sha256":"31884aa61c0aca3b198935dcfd4bc3d595de89b7fb4518f36829e628a3a7589b","contentType":"text/markdown; charset=utf-8"},{"id":"0c8f4cd2-f700-5b0c-a3a5-9d5817d81081","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/0c8f4cd2-f700-5b0c-a3a5-9d5817d81081/attachment.md","path":"references/docs/vue-directives/scroll.md","size":1646,"sha256":"62ac872dce23c2671dd04406723eccb250a39bc7db76f1eb67e419bf14469335","contentType":"text/markdown; charset=utf-8"},{"id":"57fe06dd-613e-5e7a-9b40-1250c3472479","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/57fe06dd-613e-5e7a-9b40-1250c3472479/attachment.md","path":"references/docs/vue-directives/touch-hold.md","size":2391,"sha256":"8914fa5a23fa18603db42fa3672f02ffd39d522da2041a47e885ebb68576a47c","contentType":"text/markdown; charset=utf-8"},{"id":"5cf37ff0-30dd-5698-ad75-b22bc800daa5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/5cf37ff0-30dd-5698-ad75-b22bc800daa5/attachment.md","path":"references/docs/vue-directives/touch-pan.md","size":3289,"sha256":"953ac9bbac7011aa47a801513ba9bb94272b95bfbefc787f18820e4dd73f3af1","contentType":"text/markdown; charset=utf-8"},{"id":"386a25be-e044-5d43-9c77-8051dd72dc4f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/386a25be-e044-5d43-9c77-8051dd72dc4f/attachment.md","path":"references/docs/vue-directives/touch-repeat.md","size":2767,"sha256":"72c503da51f7bdf2392878f89920546bcad9261227d112b9996b1c38e9bdf78b","contentType":"text/markdown; charset=utf-8"},{"id":"1ca4dfab-b8ae-5589-9caf-6d118d816d1d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1ca4dfab-b8ae-5589-9caf-6d118d816d1d/attachment.md","path":"references/docs/vue-directives/touch-swipe.md","size":2177,"sha256":"fb9a3699d362ad0e94c4c785ec1d111f408961a31794933cacaae1beca6ea443","contentType":"text/markdown; charset=utf-8"},{"id":"39192662-e383-51c6-bdc2-d1e251ad0622","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/39192662-e383-51c6-bdc2-d1e251ad0622/attachment.md","path":"references/docs/why-donate.md","size":6558,"sha256":"0e66aae7f88ce000dd57e265c09b10806900bad0290ad9f998c6b0e8bb7fbc32","contentType":"text/markdown; charset=utf-8"},{"id":"64201bac-5634-573e-804c-f111895222f3","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/64201bac-5634-573e-804c-f111895222f3/attachment.md","path":"references/issues/_INDEX.md","size":3297,"sha256":"9e825460cc2d4bfa27b6e32d54f2c36e24222f1cdd3e2c93e367b7e0a49d7309","contentType":"text/markdown; charset=utf-8"},{"id":"778ee682-6bc7-5f56-81eb-867e6260a75f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/778ee682-6bc7-5f56-81eb-867e6260a75f/attachment.md","path":"references/issues/issue-11113.md","size":472,"sha256":"eb02e610b9eabc0d5fcf669f083dbf3fb827a8d75cc5adb43f8268b1bfac6266","contentType":"text/markdown; charset=utf-8"},{"id":"7eed8f55-02da-5423-a465-85b5aa671739","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7eed8f55-02da-5423-a465-85b5aa671739/attachment.md","path":"references/issues/issue-11139.md","size":1302,"sha256":"2cafc1f8e41f310082a96175bb06305ffee60922594f56351b8e581d5f3a0900","contentType":"text/markdown; charset=utf-8"},{"id":"6a09c205-2d0f-55a3-b523-375a3d0e52c8","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/6a09c205-2d0f-55a3-b523-375a3d0e52c8/attachment.md","path":"references/issues/issue-12822.md","size":1822,"sha256":"b1912e25a12770c7544edd0ecdf61e1c45a58d17452ec9cc7221b6529e748f64","contentType":"text/markdown; charset=utf-8"},{"id":"131d3369-624b-5f21-9ca6-c327379c6214","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/131d3369-624b-5f21-9ca6-c327379c6214/attachment.md","path":"references/issues/issue-13951.md","size":1321,"sha256":"822d22ea20c615774a905578e5fb43b670f240747c169a7c5e265a192f4d1384","contentType":"text/markdown; charset=utf-8"},{"id":"de7cbed7-fb3b-58a4-b8c4-c40ffe4bc41d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/de7cbed7-fb3b-58a4-b8c4-c40ffe4bc41d/attachment.md","path":"references/issues/issue-14032.md","size":896,"sha256":"0218db411b3aa74e9eb9e1aa1dbc9a0371a9976ff8538acffce96f178458e734","contentType":"text/markdown; charset=utf-8"},{"id":"3a9935ed-7819-5b24-bb5e-fab060a61731","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3a9935ed-7819-5b24-bb5e-fab060a61731/attachment.md","path":"references/issues/issue-14077.md","size":1720,"sha256":"0d07c1126755fd4e69969b50f9af2cecfa8ef3156c07ac2f2e945bb14acc308f","contentType":"text/markdown; charset=utf-8"},{"id":"2ca7d4b8-0bf5-5b76-8204-5f0439665179","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/2ca7d4b8-0bf5-5b76-8204-5f0439665179/attachment.md","path":"references/issues/issue-15144.md","size":1120,"sha256":"5b97c71033df80a585135abbbb5321920c42e2f2d2b22257140eb57ba4273957","contentType":"text/markdown; charset=utf-8"},{"id":"423aa943-be7d-5e27-8ad0-364831e15d95","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/423aa943-be7d-5e27-8ad0-364831e15d95/attachment.md","path":"references/issues/issue-15652.md","size":1042,"sha256":"b2f769b39ba951eb03d95428c9ccff5e2ad848b3fe22adb7da3869e663fea74f","contentType":"text/markdown; charset=utf-8"},{"id":"c936c57c-a0fc-52f9-a1bd-ac4ff5a1f463","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c936c57c-a0fc-52f9-a1bd-ac4ff5a1f463/attachment.md","path":"references/issues/issue-15833.md","size":1188,"sha256":"323a972f801dc5b417b738f2b59cefbed024c936bfa738f8385d85e43a14a36e","contentType":"text/markdown; charset=utf-8"},{"id":"1900d711-a541-5653-a49e-61dad2aa61cc","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1900d711-a541-5653-a49e-61dad2aa61cc/attachment.md","path":"references/issues/issue-16019.md","size":1264,"sha256":"7dcbc0ba510ddb539aaff674801e5d3237bfbba9d7de292f426d3bffe835c7ba","contentType":"text/markdown; charset=utf-8"},{"id":"8ef93193-809f-5672-aa4e-3b9e8162d605","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8ef93193-809f-5672-aa4e-3b9e8162d605/attachment.md","path":"references/issues/issue-16167.md","size":1180,"sha256":"ae805453d9fa00f48f0363c9d702bd106b9ee8080ef1dcb35a3ac7fec8a2b85f","contentType":"text/markdown; charset=utf-8"},{"id":"c32ac602-94d0-5540-a524-3a6b2e8c574a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c32ac602-94d0-5540-a524-3a6b2e8c574a/attachment.md","path":"references/issues/issue-1670.md","size":1319,"sha256":"f66eb863d15ba75e74b3ad36328c5f5a299d11acf6522536a2fa99023e6ce6e1","contentType":"text/markdown; charset=utf-8"},{"id":"74b8f8aa-722b-5e60-ac4d-936edf7840a7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/74b8f8aa-722b-5e60-ac4d-936edf7840a7/attachment.md","path":"references/issues/issue-17081.md","size":3308,"sha256":"79f88ae0a25e0b5e8ae67248d5337267a55a21a2d2b7b36bf232134db70b7116","contentType":"text/markdown; charset=utf-8"},{"id":"4762fb92-6fde-5c9e-9c2b-2a61340ed402","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/4762fb92-6fde-5c9e-9c2b-2a61340ed402/attachment.md","path":"references/issues/issue-17194.md","size":987,"sha256":"8a4af3f648e62947ed0d0615dd5c2d8830917076bc04a43b8bcbdd3cbe1b9c01","contentType":"text/markdown; charset=utf-8"},{"id":"b92ef9d2-da4f-5b60-af16-fea88f98229c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b92ef9d2-da4f-5b60-af16-fea88f98229c/attachment.md","path":"references/issues/issue-17424.md","size":1445,"sha256":"d85c93759578a43085af767351f882cedc57ed23e5a0cb1ffed40b344bb26ce4","contentType":"text/markdown; charset=utf-8"},{"id":"d946e729-0844-55e0-8f25-00377bfe3441","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d946e729-0844-55e0-8f25-00377bfe3441/attachment.md","path":"references/issues/issue-17520.md","size":1162,"sha256":"f0e152a33175396325c4429fe155bbe7de5d032a1813412b7653c8b8f303a0f6","contentType":"text/markdown; charset=utf-8"},{"id":"f444eba8-ca6c-5543-94b2-fa70046a7f4a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f444eba8-ca6c-5543-94b2-fa70046a7f4a/attachment.md","path":"references/issues/issue-17603.md","size":1124,"sha256":"26e675c86302cd2a5265031d253954f770c76a65f51dc85d4a7f0f230516a4a5","contentType":"text/markdown; charset=utf-8"},{"id":"b5b45034-b303-54e7-a39d-77033e52136f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b5b45034-b303-54e7-a39d-77033e52136f/attachment.md","path":"references/issues/issue-17764.md","size":1928,"sha256":"2583e80273f9f265f58dc1a5e4519010f5b2554429ae0431becd58a7733e4d23","contentType":"text/markdown; charset=utf-8"},{"id":"39a92e3c-2e65-5365-b3ec-6b486bc1bd23","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/39a92e3c-2e65-5365-b3ec-6b486bc1bd23/attachment.md","path":"references/issues/issue-17918.md","size":1734,"sha256":"f5804e64fe2f164aba352e3c3806da72307c177f4359f098d15dabf35b97a5c0","contentType":"text/markdown; charset=utf-8"},{"id":"82345927-806c-541d-a2e2-a789c6692eaa","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/82345927-806c-541d-a2e2-a789c6692eaa/attachment.md","path":"references/issues/issue-18060.md","size":2049,"sha256":"b00383341ffd309f61d685ff7eb3ceeb53deec07b64f2a5bf087ba55059333ac","contentType":"text/markdown; charset=utf-8"},{"id":"6e4362f3-210e-571a-bdfe-5fe79b85fcda","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/6e4362f3-210e-571a-bdfe-5fe79b85fcda/attachment.md","path":"references/issues/issue-18065.md","size":1749,"sha256":"26b1696002300f8971c633d920caec831eb559d2263a28e2758ba68463d5b2d3","contentType":"text/markdown; charset=utf-8"},{"id":"aad7bc00-659a-5d22-a093-a9c45453439a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/aad7bc00-659a-5d22-a093-a9c45453439a/attachment.md","path":"references/issues/issue-18199.md","size":1447,"sha256":"e66642b1acdff85d07badf243d5c8f9530d0d0c26515b84bda4dfa855dfb941d","contentType":"text/markdown; charset=utf-8"},{"id":"b99eee08-bc95-598f-8f11-96836ddb31d5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b99eee08-bc95-598f-8f11-96836ddb31d5/attachment.md","path":"references/issues/issue-2299.md","size":2008,"sha256":"5d9072925e982816d50760d281337b601d89a8805003e75be8adf7c0b62fadbd","contentType":"text/markdown; charset=utf-8"},{"id":"cdf32146-5c19-5513-8b00-4330bec34808","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/cdf32146-5c19-5513-8b00-4330bec34808/attachment.md","path":"references/issues/issue-2575.md","size":2865,"sha256":"23c192acc5995e4aab3bee5d293c8fb588b3cfea2f35082f8605e5d20f889268","contentType":"text/markdown; charset=utf-8"},{"id":"91db866a-49a0-5c94-b773-aabd15afe6ad","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/91db866a-49a0-5c94-b773-aabd15afe6ad/attachment.md","path":"references/issues/issue-4533.md","size":1594,"sha256":"37846f6fc3b413836b8bd31116d7817434337e560ce9e6ac7e69765b53ed4cec","contentType":"text/markdown; charset=utf-8"},{"id":"2c6edb64-9ca6-556f-a976-b5227f5762b9","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/2c6edb64-9ca6-556f-a976-b5227f5762b9/attachment.md","path":"references/issues/issue-5890.md","size":3246,"sha256":"0cc3db15d65b032c8902320ddf573596ed4f9f4c2b31e59ce35a1dae19e4c5ce","contentType":"text/markdown; charset=utf-8"},{"id":"0a9e1573-6cf2-595f-b578-b3b9189c6e24","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/0a9e1573-6cf2-595f-b578-b3b9189c6e24/attachment.md","path":"references/issues/issue-6775.md","size":4382,"sha256":"5d5d833f0bc63070d3070c56869a262b9f32d4a605a0da23529a87eb916bc919","contentType":"text/markdown; charset=utf-8"},{"id":"b408b082-bf33-593b-8120-c83327bd3666","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b408b082-bf33-593b-8120-c83327bd3666/attachment.md","path":"references/issues/issue-7836.md","size":3154,"sha256":"898fe43527a90b67a28daa5cda5c398ccbe1d3a8b5957011c137af14430bcdbe","contentType":"text/markdown; charset=utf-8"},{"id":"1a173fca-04bd-5c67-a610-4052164d6852","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1a173fca-04bd-5c67-a610-4052164d6852/attachment.md","path":"references/issues/issue-8513.md","size":1483,"sha256":"46a8efa16f3e59fd00abf832628fee6030883d0918c2d884a261cf693c39c976","contentType":"text/markdown; charset=utf-8"},{"id":"357bf8d6-cd9d-58b0-a8c7-1419359771ab","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/357bf8d6-cd9d-58b0-a8c7-1419359771ab/attachment.md","path":"references/issues/issue-8956.md","size":1650,"sha256":"78ec89ee1ba2ffbc07d9406018fe77204601903c81092f7788dc22fe3ed5dd4d","contentType":"text/markdown; charset=utf-8"},{"id":"bdd55141-f08e-514e-8f7a-d70d2776c033","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/bdd55141-f08e-514e-8f7a-d70d2776c033/attachment.md","path":"references/releases/_INDEX.md","size":1490,"sha256":"663d9807e5a3ead93db40aa620acf5554b7af0b92f84114cb8b55d1a92c7f8a4","contentType":"text/markdown; charset=utf-8"},{"id":"099c8993-857e-5d30-ac38-6a2baa9e9cac","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/099c8993-857e-5d30-ac38-6a2baa9e9cac/attachment.md","path":"references/releases/vquasar-v2.16.10.md","size":576,"sha256":"ce8eff52ae4492713cb0bf82df3acb10b5632f6bdc0a1586547306342b84db75","contentType":"text/markdown; charset=utf-8"},{"id":"ab89ea55-dd8d-5cba-8be2-523acd319274","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ab89ea55-dd8d-5cba-8be2-523acd319274/attachment.md","path":"references/releases/vquasar-v2.16.11.md","size":559,"sha256":"55d12ae99b98d32a5ae56934f10484d6d75b6236b9c95ae5d08ffb91bd17f17e","contentType":"text/markdown; charset=utf-8"},{"id":"563bffa9-4a11-59cc-ba09-bee1910e0a4d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/563bffa9-4a11-59cc-ba09-bee1910e0a4d/attachment.md","path":"references/releases/vquasar-v2.16.7.md","size":548,"sha256":"62276e460e3ce98abe34b942b044af4ffd51d9e81f96c60ce2f60a8ab798bac6","contentType":"text/markdown; charset=utf-8"},{"id":"81b530d8-237e-58fd-9fcd-702a75dd6929","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/81b530d8-237e-58fd-9fcd-702a75dd6929/attachment.md","path":"references/releases/vquasar-v2.16.8.md","size":522,"sha256":"6b9ef56d117acd5e57cc9207727c579a765b4acf92d4ff686dff7fc7d1bbb123","contentType":"text/markdown; charset=utf-8"},{"id":"228fc078-703e-52f2-a5d8-6c81f489bb23","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/228fc078-703e-52f2-a5d8-6c81f489bb23/attachment.md","path":"references/releases/vquasar-v2.16.9.md","size":741,"sha256":"a5fb934767187ac832069407447ebbdba14fc6269eb5e4f81c799a86f5d94720","contentType":"text/markdown; charset=utf-8"},{"id":"000ad14a-b308-5cdf-955f-07ea7b28487e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/000ad14a-b308-5cdf-955f-07ea7b28487e/attachment.md","path":"references/releases/vquasar-v2.17.0.md","size":2081,"sha256":"9e27a3267f32665a0e1138da7e27599702451d64634b8f2dd8666780f050043d","contentType":"text/markdown; charset=utf-8"},{"id":"e60b9198-61c0-5209-aa2b-6a5876f117ce","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e60b9198-61c0-5209-aa2b-6a5876f117ce/attachment.md","path":"references/releases/vquasar-v2.17.1.md","size":798,"sha256":"be8c4cc37bfc2f96e0d81171d26e07d6dc3da01b87556c9cc66ebc93fda1de94","contentType":"text/markdown; charset=utf-8"},{"id":"424d2252-a1dc-51b0-86c1-c7aaf0838645","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/424d2252-a1dc-51b0-86c1-c7aaf0838645/attachment.md","path":"references/releases/vquasar-v2.17.2.md","size":735,"sha256":"fe0cc9f71bf772cedc632518d0277db486a1050dca8e2acb2835bd5623b7bfcd","contentType":"text/markdown; charset=utf-8"},{"id":"98dc24b1-e837-504c-bb26-f122d5d29fac","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/98dc24b1-e837-504c-bb26-f122d5d29fac/attachment.md","path":"references/releases/vquasar-v2.17.3.md","size":564,"sha256":"57f3c03f636e804c00515dd08a94b0b136ac61404f25d91c335e37112fe11969","contentType":"text/markdown; charset=utf-8"},{"id":"7eea6b31-9ed1-5040-bc11-9ad586fc1c5f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7eea6b31-9ed1-5040-bc11-9ad586fc1c5f/attachment.md","path":"references/releases/vquasar-v2.17.4.md","size":474,"sha256":"5c37d1eb7680da1a57167d8929619ea67bce7a333de67a1298daef05acac3483","contentType":"text/markdown; charset=utf-8"},{"id":"95bb02e2-c42d-5bfc-80e6-f318f9326402","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/95bb02e2-c42d-5bfc-80e6-f318f9326402/attachment.md","path":"references/releases/vquasar-v2.17.5.md","size":553,"sha256":"2a2b4d14f2a314b6ef00929f98af022371ae89fc8c959e2423b121819242a60a","contentType":"text/markdown; charset=utf-8"},{"id":"d5026c8f-1a84-51d0-937d-23c0ab29b5ef","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d5026c8f-1a84-51d0-937d-23c0ab29b5ef/attachment.md","path":"references/releases/vquasar-v2.17.6.md","size":448,"sha256":"1e2fcac758b7c89b0c3f8db7ccb4c8289ccd8f7bbba1a1e6dea3b743b97b0953","contentType":"text/markdown; charset=utf-8"},{"id":"f22549a3-2e14-512e-9f0e-0ace1fb1ce15","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f22549a3-2e14-512e-9f0e-0ace1fb1ce15/attachment.md","path":"references/releases/vquasar-v2.17.7.md","size":610,"sha256":"aee24c7f706f18507efecddc2b371e40360ea8dcfce79c21c51a57d798a3bf7f","contentType":"text/markdown; charset=utf-8"},{"id":"86b72420-9749-50ce-9c02-524e2b5b1e30","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/86b72420-9749-50ce-9c02-524e2b5b1e30/attachment.md","path":"references/releases/vquasar-v2.18.0.md","size":1402,"sha256":"1aeb785b10cccf4fbdbba7e5ac19c86f0e6bbaf127221219fd82c2709da095bd","contentType":"text/markdown; charset=utf-8"},{"id":"37c387a1-5e14-563a-a102-7659b806a836","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/37c387a1-5e14-563a-a102-7659b806a836/attachment.md","path":"references/releases/vquasar-v2.18.1.md","size":592,"sha256":"0fbf6e59e6bc9a94ef3765f0351e0cefc708eac8e10b6c90086da1c63f973f4d","contentType":"text/markdown; charset=utf-8"},{"id":"98d2f20c-fcb8-534f-bc9e-7eeba4282422","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/98d2f20c-fcb8-534f-bc9e-7eeba4282422/attachment.md","path":"references/releases/vquasar-v2.18.2.md","size":1353,"sha256":"602c79dde1e44b5a9b73af908598f1b3e1fd81f58908836cef489198e2706fa2","contentType":"text/markdown; charset=utf-8"},{"id":"a702aaf3-688b-5370-be68-cb86d425502c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a702aaf3-688b-5370-be68-cb86d425502c/attachment.md","path":"references/releases/vquasar-v2.18.3.md","size":440,"sha256":"5c480bd72c5e87508d86dd64289cc38a4b81581ecf79471f987926d3e991bbdd","contentType":"text/markdown; charset=utf-8"},{"id":"ef2b421a-4831-5957-a544-4c484efc0e14","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ef2b421a-4831-5957-a544-4c484efc0e14/attachment.md","path":"references/releases/vquasar-v2.18.4.md","size":496,"sha256":"7059a1ca586bc90ff5bc05db7c3fea9af65c58d12adeb63e64e9fba36df97cbb","contentType":"text/markdown; charset=utf-8"},{"id":"c149fdb1-bb2d-56a4-9038-9761de76fb99","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c149fdb1-bb2d-56a4-9038-9761de76fb99/attachment.md","path":"references/releases/vquasar-v2.18.5.md","size":584,"sha256":"a760fe5451d83a80fff739403f86b3918eac0bd52c4bae7cb000c3b3c0c72361","contentType":"text/markdown; charset=utf-8"},{"id":"326245e2-6f20-5b60-acbe-34805b739737","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/326245e2-6f20-5b60-acbe-34805b739737/attachment.md","path":"references/releases/vquasar-v2.18.6.md","size":465,"sha256":"3a4260bb0b4c836631affff78c860eefb5eb443c3595733c37a6f592fb984784","contentType":"text/markdown; charset=utf-8"}],"bundle_sha256":"51c959d1dcf61b84c4343976aaade7200c58939c55e3a583c0fc32ed6d1d0744","attachment_count":462,"text_attachments":462,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"skills/quasar-skilld/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"web-development","category_label":"Web"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"web-development","metadata":{"version":"2.19.3","generated_at":"2026-04-07T00:00:00.000Z","references_synced_at":"2026-04-07T00:00:00.000Z"},"import_tag":"clean-skills-v1","description":"Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time. ALWAYS use when writing code importing \"quasar\". Consult for debugging, best practices, or modifying quasar."}},"renderedAt":1782987572513}

quasarframework/quasar Tags: legacy: 1.22.10, latest: 2.19.3 References: Docs API Changes This section documents version-specific API changes — prioritize recent major/minor releases. - BREAKING: - uses + instead of + in Vue 3 source - BREAKING: / / / - use and attributes instead of / props source - BREAKING: - completely redesigned, removed and props; renamed to source - BREAKING: - methods returns ; and require parameter source - BREAKING: - renamed prop to to avoid TS naming conflicts source - BREAKING: - all boolean properties now explicitly instead of since v2.17.0 source - BREAKING: uti…