One Quasar Project, Multiple Build Targets: Managing Cross-Platform Complexity
Learn how to use a single Quasar CLI project to target SPA, SSR, PWA, and Electron, reducing code duplication while managing platform-specific constraints.
29 Aug 2025, 19:22 UTC

When building a modern application, developers often face a frustrating choice: maintain separate repositories for a web app (SPA), a progressive web app (PWA), and a desktop wrapper (Electron), or struggle to force one codebase to fit all. Maintaining multiple repositories leads to logic drift, inconsistent UI updates, and a synchronization nightmare for shared business rules.
The Quasar Framework solves this by allowing a single source tree to target multiple build modes—including SPA, SSR, PWA, Electron, and Cordova. The takeaway is that while this drastically reduces code duplication, it requires a disciplined approach to handling platform-specific APIs and server-side constraints.
The Role of quasar.conf.js
The heart of the multi-target strategy is the quasar.conf.js file. Unlike a standard Vite project where you might manually swap configuration files, Quasar uses this central file to determine how the CLI processes your code. When you switch targets—for example, running quasar dev -m electron versus quasar dev -m ssr—the CLI adjusts the entry points and build pipelines automatically.
Because all components live in the same src directory, you can write your UI logic once. However, you must ensure your code is resilient enough to run in a browser, a Node.js environment (for SSR), or a native shell.
Handling Platform-Specific Contexts
The biggest risk in a multi-target project is assuming the environment is always the browser. In Server-Side Rendering (SSR), your code executes on the server before reaching the client. Attempting to access window, document, or localStorage directly during the server-side phase will crash the application.
To manage this, Quasar provides the $q object for platform detection. This allows for conditional rendering or logic without breaking the build process:
<!-- Example of platform-specific logic in a component -->
<script setup>
import { onMounted } from 'vue';
import { useQuasar } from 'quasar';
const $q = useQuasar();
onMounted(() => {
// This is safe because onMounted only runs on the client
if ($q.platform.is.electron) {
console.log('Running in the desktop app');
}
});
</script>
<template>
<div v-if="$q.platform.is.mobile">
<p>Mobile-optimized navigation</p>
</div>
<div v-else>
<p>Desktop dashboard</p>
</div>
</template>
Practical Example: Adding Electron to an SPA
Suppose you have a web-based dashboard and now need to release a desktop Electron app for internal teams. Instead of duplicating code, you configure the build in the CLI. This example assumes you are using Quasar v2+ with @quasar/app-vite.
- Verify your version: Check
package.jsonto ensure you are using@quasar/app-vite. - Add the mode: Run the following command in your terminal (requires project root permissions):
This installs the necessary dependencies and creates the required folder structures.quasar mode add electron - Develop SPA: Run
quasar dev -m spato test the web version. - Develop Electron: Run
quasar dev -m electronto launch the native window version.
The output will be distinct: dist/spa for the web and dist/electron for the desktop app, but the source code remains identical.
Trade-offs and Limitations
While the single repository approach is efficient, it is not a "set and forget" solution. You must account for the following:
- CSS Complexity: A layout that looks great on a responsive browser might feel cramped in a Cordova mobile wrapper. You must use Quasar's responsive utility classes rather than relying on a single fixed layout.
- SSR Constraints: Adding SSR requires a
src-ssrserver entry. You must guard browser-only APIs withonMountedor platform checks to avoid server-side crashes. - PWA Caching: PWA mode generates a service worker. You must handle versioning and update activation to prevent users from seeing stale HTML.
Verification and Rollback
To verify the result, run quasar build -m spa and quasar build -m electron. Check that the dist/ folder contains separate directories for each target. If the Electron addition causes dependency conflicts, you can remove the mode by deleting the src-electron directory and removing the electron and electron-builder packages from your package.json.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.