Why Quasar?
Most cross-platform frameworks force you to choose: React Native for mobile, or a web framework for browsers. Quasar Framework takes a different approach — one Vue 3 codebase, multiple build targets, zero compromises.
With a single quasar build command you get a production SPA, SSR, PWA, Android APK, iOS IPA, and even an Electron desktop app. Quasar ships 70+ Material Design components that adapt their appearance to each platform automatically.
Quasar CLI v2, Vue 3 Composition API, Vite, Capacitor 6 (iOS/Android), Node 20, Android Studio / Xcode. Connects to a Laravel 11 REST API backend.
One Codebase → 5 Targets
Install Quasar CLI & Create Project
# Install Quasar CLI globally npm i -g @quasar/cli # Create new project (interactive wizard) npm create quasar@latest my-app # Wizard options to choose: # ✓ Quasar App with Vite # ✓ Vue 3 Composition API (with <script setup>) # ✓ Pinia (state management) # ✓ Vue Router # ✓ ESLint + Prettier cd my-app npm install quasar dev # → http://localhost:9000
Project Structure
Layouts, Pages & Routing
Quasar uses a layout-driven routing system. A layout wraps multiple pages — think of it as your shell with header, drawer, and footer. Pages are the content inside.
<template> <q-layout view="lHh Lpr lFf"> <q-header elevated> <q-toolbar> <q-btn flat dense round icon="menu" @click="leftDrawer = !leftDrawer" /> <q-toolbar-title>My App</q-toolbar-title> </q-toolbar> </q-header> <q-drawer v-model="leftDrawer" show-if-above bordered> <q-list> <q-item v-for="link in navLinks" :key="link.title" :to="link.path" clickable v-ripple> <q-item-section avatar><q-icon :name="link.icon" /></q-item-section> <q-item-section>{{ link.title }}</q-item-section> </q-item> </q-list> </q-drawer> <q-page-container> <router-view /> </q-page-container> </q-layout> </template> <script setup> import { ref } from 'vue' const leftDrawer = ref(false) const navLinks = [ { title: 'Dashboard', icon: 'dashboard', path: '/' }, { title: 'Profile', icon: 'person', path: '/profile' }, { title: 'Settings', icon: 'settings', path: '/settings' }, ] </script>
const routes = [ { path: '/', component: () => import('layouts/MainLayout.vue'), children: [ { path: '', component: () => import('pages/IndexPage.vue') }, { path: 'profile', component: () => import('pages/ProfilePage.vue') }, { path: 'settings', component: () => import('pages/SettingsPage.vue') }, ] }, // Auth pages (no drawer/header) { path: '/auth', component: () => import('layouts/AuthLayout.vue'), children: [ { path: 'login', component: () => import('pages/LoginPage.vue') }, { path: 'register', component: () => import('pages/RegisterPage.vue') }, ] }, // 404 { path: '/:catchAll(.*)*', component: () => import('pages/ErrorNotFound.vue') } ]
Connect to Laravel API
Configure Axios as a Quasar boot plugin — boot files run once at app startup before Vue mounts. This is where you set base URLs, auth headers, and interceptors.
import { boot } from 'quasar/wrappers' import axios from 'axios' const api = axios.create({ baseURL: process.env.VITE_API_URL || 'https://api.yourapp.com', headers: { 'Accept': 'application/json' } }) // Inject Sanctum token on every request api.interceptors.request.use(config => { const token = localStorage.getItem('token') if (token) config.headers.Authorization = `Bearer ${token}` return config }) // Global 401 → redirect to login api.interceptors.response.use( res => res, err => { if (err.response?.status === 401) { localStorage.removeItem('token') window.location.href = '/auth/login' } return Promise.reject(err) } ) export default boot(({ app }) => { app.config.globalProperties.$api = api }) export { api }
Capacitor — Deploy to Android & iOS
Capacitor bridges your web app to native device APIs. Add it to Quasar with one command, then build and open the native project in Android Studio or Xcode.
| Feature | Capacitor | Cordova | React Native |
|---|---|---|---|
| Web Tech | ✓ HTML/CSS/JS | ✓ HTML/CSS/JS | ~ JSX only |
| Native APIs | ✓ Modern | ~ Legacy | ✓ Deep |
| Live Reload | ✓ Yes | ~ Slow | ✓ Yes |
| Plugin Ecosystem | ✓ Rich | ~ Outdated | ✓ Huge |
| Quasar Support | ✓ Official | ✓ Legacy | ✗ Separate |
# Add Capacitor mode to your Quasar project quasar mode add capacitor # Install Capacitor packages npm install @capacitor/core @capacitor/cli npm install @capacitor/android @capacitor/ios # Add native platforms npx cap add android npx cap add ios
{
"appId": "com.codecraft.myapp",
"appName": "My App",
"webDir": "dist/capacitor/www",
"bundledWebRuntime": false,
"plugins": {
"SplashScreen": {
"launchShowDuration": 2000,
"backgroundColor": "#f4f7fb"
},
"StatusBar": {
"style": "Dark",
"backgroundColor": "#f4f7fb"
}
}
}
Build & Deploy — All Targets
quasar build → outputs to dist/spa/. Deploy to Nginx, Vercel, Netlify, or any static host. Works with your Laravel API backend.quasar build -m pwa. Generates a service worker, manifest.json, and offline support automatically. Users can "Add to Home Screen" on Android and iOS.quasar build -m capacitor -T android then npx cap open android. Opens Android Studio where you sign and generate your release APK/AAB for the Play Store.quasar build -m capacitor -T ios then npx cap open ios. Opens Xcode — set your signing team, bump build number, archive and upload to App Store Connect.# Web SPA quasar build # PWA quasar build -m pwa # Android (build + sync + open Android Studio) quasar build -m capacitor -T android npx cap sync android npx cap open android # iOS (Mac only) quasar build -m capacitor -T ios npx cap sync ios npx cap open ios # Live reload on device during development quasar dev -m capacitor -T android --ide
Use $q.platform.is.mobile, $q.platform.is.android, $q.platform.is.ios inside Vue components to conditionally render platform-specific UI. Quasar automatically applies Material Design on Android and iOS Human Interface Guidelines on iOS.
Quasar renders in a WebView (like Capacitor/Cordova) — not truly native widgets. For apps that need deep native performance (60fps animations, heavy gestures), consider React Native or NativeScript. For standard business apps, dashboards, and CRUD — Quasar is significantly faster to ship.
Quasar is the fastest way to ship a Vue 3 app to web, Android, and iOS. One team, one codebase, one deployment pipeline. For B2B SaaS, internal tools, and MVPs — this tradeoff is overwhelmingly worth it.
PWA first, then Capacitor. Deploy the PWA build first — it works on all devices instantly, no app store review, and users install it from the browser. Add Capacitor (native app) only when you need push notifications, deep native APIs, or App Store presence.
Pair with Laravel API. Quasar + Laravel is a powerful stack — Quasar handles all UI and mobile targets, Laravel handles auth (Sanctum), business logic, and the database. The boot plugin pattern keeps the API layer clean and testable.
6+ years building Vue.js & Laravel apps for UK, USA & global clients. Shipped multiple Quasar apps to Android & iOS alongside Vue 3 web products from a single codebase — the stack we recommend for every cross-platform project.