VS Code Agent Mode for Quasar Capacitor project
Hello kind people of the internet. This blog is in two parts:
-
Part 1 - A
copilot-intructions.md
tailored for Quasar-Capacitor-Android -
Part 2 - A link to Burke Hollands video on Agent Mode
Part 1 - Copilot Instructions
The Agent will write your code, and butter your toast!
To get an Agent to actually write my code was kinda like getting my Roomba to also vacuum my car...seemed like more work than it was worth. But it's the future, and this was my first foray into the AI assisted apocalypse.
But, Surprise! The code the Agent created actually worked!
You first need to create a copilot-instructions.md
file.
And this is the main point of this blog: Create an INSTRUCTIONS file for Copilot to follow.
Below is a sample instructions file that I used along with a bit of info for how to set it up in VS Code. I was attempting to create a simple Quasar and Capacitor app targeting both SPA and Android. You will no doubt need to alter the instructions file to suit your needs.
Here's a link to the GitHub repo that was actually created by the Agent using the provided instructions:
https://github.com/tenace2/ScaffoldQuasarCapacitorV3
My copilot-intructions.md
file acts as a guide to the Agent in VS Code for how to handle building your applications. If you were writing Python apps, you would of course need very different instructions.
I would not suggest directly copying everything from my copilot-instructions.md
below.
- There are some odd-ball tic-mark characters in the note which will probably throw syntax errors.
- Also, there are no doubt oversights in the content and coding standards that are not ideal, such as avoiding Typescript.
- And I attempted to force keeping Capacitor at version 6 (I had my reasons)...and as of May 2025 timeframe Capacitor is at v7.
- And the instructions were created with the idea of writing a combo SPA and Android app...you may not want a combo app.
Lessons Learned Using Agent
I used the Agent (Claude Sonnet 4) in VS Code to leverage a tutorial for scaffolding a Quasar Capacitor app (ref Readme in my Repo. It was a bit of messy sausage making. You may not like the ingredients or the process, but hey, the results were tasty enough. For instance:
-
I had to turn off ESLint as it consumed tokens (quickly rate limited my Agent session).
-
Don't use Typescript. Threw lots of problems which consumed agent tokens.
-
Remember to "accept changes" before proceeding to next steps (update files).
-
Copilot will sometimes create new terminal sessions! And then try to execute next-step commands in an out-of-context directory (maybe your root). Watch for this.
-
As of May 2025, there is no way to save your Copilot chat so you can review it later (forensics). And it does not keep much chat history. This kinda stinks. Perplexity and Claude allow you to go back a review your chats, which is often super valuable.
Suggest first watch Burke Hollands video below (as he's very good at explaining things).
Once you have you copilot-instructions.md
you add it to a root folder for your project. Following screen shot is after I was done using Copilot Agent to build my project.
Then in VS Code under Copilot set it to Agent mode.
Once you have Copilot set to Agent, prompt it to read your instructions and insure they seem complete, error free, etc. Here's a sample prompt:
I would like your help, using Agent mode, to create a fairly simple Quasar and Capacitor app (based on Vue.js) targeting Android.
I have created a copilot-instructions.md file in my project root directory to help. Please review the instructions and provide any necessary feedback before we get started.
This should start you on the road to "vibe coding".
But it should be called "sausage making coding".
It's often messy, and it's difficult to get the recipe (instructions) just right so the agent doesn't go off-the-rails.
Your milage may vary. Results are not guaranteed.
copilot-instructions.md
File
Vue 3 + Quasar + Capacitor Development Guidelines
Core Principles
-
Use Vue 3 Composition API with
<script setup>
syntax -
Follow Quasar's component conventions and responsive design
-
Implement Capacitor platform-specific code in /src-capacitor
-
Use Pinia for state management when complex state is needed
-
For simple apps, local component state is acceptable
-
Extensive use of console.log is recommended for debugging during development
JavaScript vs TypeScript Preference
Use JavaScript, NOT TypeScript:
-
When creating Quasar projects, select "Javascript" not "Typescript"
-
Use
.js
file extensions for all custom files -
Use
.vue
files with JavaScript<script setup>
blocks -
Avoid TypeScript syntax like type annotations, interfaces, or generics
-
Keep code simple and accessible for JavaScript developers
File Extensions to Use:
-
quasar.config.js
(not .ts) -
router/routes.js
(not .ts) -
stores/*.js
(not .ts) -
All custom JavaScript files should use
.js
extension
Avoid TypeScript Patterns:
// ✅ Good - JavaScript
const apiKey = import.meta.env.VITE_GOOGLE_MAPS_API_KEY
// ❌ Avoid - TypeScript syntax
const apiKey: string = import.meta.env.VITE_GOOGLE_MAPS_API_KEY
Version Management (Critical)
-
Maintain Capacitor v6.x.x compatibility with Quasar
-
Ensure matching versions between root and /src-capacitor package.json
-
Specify exact versions when installing plugins (e.g., @capacitor/android@6.0.0)
-
Use Node.js v18+ as recommended for Capacitor v6
Logging Standards
-
Use descriptive log messages with context
-
Include platform information in logs
-
Log plugin availability checks
-
Remove console.logs before production builds
Component Standards
Quasar Components:
-
Use QBtn instead of native buttons
-
Apply responsive classes (e.g.,
col-md-6
) -
Leverage Quasar's built-in CSS variables and theming
Capacitor Integration:
-
Wrap native API calls in try/catch
-
Console log all try/catch
-
Import plugins consistently:
import { PluginName } from '@capacitor/plugin-name'
-
Store platform-specific configs in /src-capacitor/android|ios
-
Handle permissions gracefully for mobile platforms
-
Test plugins in both browser and native environments
-
Log both success and error states
-
Provide user-friendly error messages
-
Include platform context in error logs
-
Suggested error handling pattern for plugins:
try {
const result = await Camera.getPhoto(options);
console.log('Camera success:', { platform: Capacitor.getPlatform(), result });
} catch (error) {
console.error('Camera error:', { platform: Capacitor.getPlatform(), error });
// Show user-friendly message
}
Android Permissions & Configuration
AndroidManifest.xml Location:
/src-capacitor/android/app/src/main/AndroidManifest.xml
Permission Management Guidelines:
- Research Plugin Requirements:
-
Always check Capacitor plugin documentation for required permissions
-
Add permissions incrementally as you add plugins
- Common Plugin Permissions:
<!-- Internet -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Geolocation Plugin -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-feature android:name="android.hardware.location.gps" />
Project Structure
-
/src/components
: Reusable Vue components -
/src/composables
: Custom composition functions -
/src/stores
: Pinia store modules (when needed) -
/src-capacitor
: Native platform code and configurations -
/src/assets
: Static assets and Quasar theme files -
Maintain separate package.json files in root and /src-capacitor
Android Studio Guidelines
-
DO NOT upgrade Gradle when prompted
-
DO NOT upgrade other Android dependencies automatically
-
Use "File > Invalidate caches and restart" if encountering IDE errors
Development Workflow
-
Test changes in both SPA mode (npm run dev) and Capacitor mode (quasar dev -m capacitor -T android)
-
Run npx cap sync after plugin installations
-
Build dist folder before major Capacitor operations
Build Process
-
npm run build
- Creates dist folder -
npx cap sync
- Syncs changes to native projects -
npx cap run android
- Build and run on device -
Always sync after adding new plugins or assets
Build Tool & Environment Configuration
Quasar Build Tool:
-
Use Quasar CLI with Vite (recommended) rather than Webpack
-
When creating new projects, select "Quasar CLI with Vite" option
-
Vite provides faster development builds and modern tooling
Environment Variables (Vite-specific):
-
Use
VITE_
prefix for any environment variable accessed in Vue components -
Access variables via
import.meta.env.VITE_YOUR_VARIABLE
-
Variables without
VITE_
prefix are only available at build-time -
Use
import.meta.env.MODE
to check development vs production -
example usage:
// Get API key from Vite env variables
const apiKey = import.meta.env.VITE_GOOGLE_MAPS_API_KEY;
const mapId = import.meta.env.VITE_GOOGLE_MAPS_MAP_ID;
Environment File Setup:
Create .env
file in project root:
# .env file (DO NOT COMMIT TO VERSION CONTROL)
# Vite requires VITE_ prefix for client-side access
VITE_GOOGLE_MAPS_API_KEY=your_actual_google_maps_key_here
VITE_GOOGLE_MAPS_MAP_ID=your_actual_google_maps_map_id_here
Create a .gitignore
file
# .gitignore file
.env
.env.local
.env.*.local
Platform Detection & Development Indicators
Always Include Platform Indicator in Development:
-
Show visible indicator when app is running in SPA vs Native mode
-
Use Capacitor.isNativePlatform() and Capacitor.getPlatform()
-
Position indicator prominently (top-right corner recommended)
-
Only show in development builds (process.env.NODE_ENV === 'development')
Plugin Feature Testing Strategy:
- SPA Testing (npm run dev):
-
Test basic UI, routing, and web-compatible features
-
If plugin features fail, assume they require native environment
-
Use fallback UI/messages for native-only features
- Native Testing (quasar dev -m capacitor -T android):
-
Test all plugin features including device-specific APIs
-
Verify permissions are properly requested
-
Test actual device hardware features
Feature Detection Pattern:
-
Always check Capacitor.isPluginAvailable() before using plugins
-
Implement graceful fallbacks for web environment
-
Show appropriate user messages when features are unavailable
-
Use try/catch for all native API calls
Common Web vs Native Plugin Behaviors:
-
Camera: Web uses browser APIs, Native uses device camera
-
Geolocation: Web uses browser geolocation, Native uses GPS
-
Storage: Web uses localStorage, Native uses secure storage
-
Network: Basic detection works in web, detailed info native-only
Suggested App Components:
Suggest adding this to main App.vue or Layout:
<!-- Add to MainLayout.vue or App.vue -->
`<template>
`<q-layout view="lHh Lpr lFf">
<!-- Platform Indicator -->
<PlatformIndicator v-if="isDevelopment" />
<!-- Rest of your layout -->
`<q-page-container>
<router-view />
</q-page-container>
</q-layout>
</template>
`<script setup>
import PlatformIndicator from 'components/PlatformIndicator.vue';
// Use Vite syntax
const isDevelopment = import.meta.env.MODE === 'development';
</script>
Suggest the following for the PlatformIndicator.vue component in /src/components/PlatformIndicator.vue
:
<!-- Platform Indicator Component (always include in dev) -->
`<template>
`<div class="platform-indicator" v-if="isDevelopment">
`<q-chip :color="platformColor" text-color="white" icon="info">
{{ platformText }}
</q-chip>
`</div>
`</template>
`<script setup>
import { Capacitor } from '@capacitor/core';
import { computed } from 'vue';
// Use Vite syntax
const isDevelopment = import.meta.env.MODE === 'development';
const isNative = Capacitor.isNativePlatform();
const platform = Capacitor.getPlatform();
const platformColor = computed(() => {
return isNative ? 'positive' : 'info';
});
const platformText = computed(() => {
if (isNative) {
return `Native: ${platform}`;
}
return 'SPA/Web Mode';
});
</script>
`<style scoped>
.platform-indicator {
position: fixed;
top: 10px;
right: 10px;
z-index: 9999;
}
</style>
Again: the above instructions are tuned to what I was attempting.
Part 2 - Burke Hollands YouTube
Burke Holland has a great video on implementing Agent mode in VS Code that I highly suggest you watch. While I didn't implement what he described, it blazed the trail.
https://www.youtube.com/watch?v=dutyOc_cAEU