Home Services Blog Developers Job Board Find Jobs with AI Add Profile
MY APP
Android 72%
iOS 55%
Web / PWA 88%
Home
Menu
Saved
👤
Profile
Vue.js · Mobile

BUILD
CROSS-PLATFORM
WITH QUASAR

Web + Android + iOS from a single Vue 3 codebase using Quasar Framework. Setup, routing, Capacitor integration, and multi-target deployment — all in one guide.

👨‍💻
Sonu Sahani
Full Stack Developer · CodeCraft Systems
📅 Dec 15, 2024 ⏱ 7 min read 👁 1.9k views
Quasar Vue 3 Capacitor Android iOS PWA Mobile

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.

📦 Stack Used

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

🌐
SPA / SSR
quasar build
📲
PWA
-m pwa
🤖
Android
-m capacitor
🍎
iOS
-m capacitor
🖥
Desktop
-m electron

Install Quasar CLI & Create Project

terminal — install & scaffold
# 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

my-app/
├─src/
│ ├─assets/  # images, fonts
│ ├─boot/   # app plugins (axios, pinia)
│ ├─components/
│ ├─composables/
│ ├─layouts/  # MainLayout.vue
│ ├─pages/   # routed views
│ ├─router/  # routes/index.js
│ ├─stores/  # Pinia stores
│ └─App.vue
├─quasar.config.js  # ← main config
├─capacitor.config.json  # mobile config
└─package.json

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.

src/layouts/MainLayout.vue
<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>
src/router/routes.js
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.

src/boot/axios.js
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.

FeatureCapacitorCordovaReact 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
terminal — add Capacitor to Quasar
# 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
capacitor.config.json
{
  "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

01
SPA / Web
Run quasar build → outputs to dist/spa/. Deploy to Nginx, Vercel, Netlify, or any static host. Works with your Laravel API backend.
02
PWA (Progressive Web App)
Run quasar build -m pwa. Generates a service worker, manifest.json, and offline support automatically. Users can "Add to Home Screen" on Android and iOS.
03
Android APK / AAB
Run 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.
04
iOS IPA (Mac only)
Run 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.
terminal — all build commands
# 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
✅ Platform-Specific Code

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 vs NativeScript vs React Native

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.

🏁 Key Takeaways

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.

SHARE THIS ARTICLE: 𝕏 Twitter 💼 LinkedIn
👨‍💻
Sonu Sahani
Full Stack Developer · CodeCraft Systems

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.