Capacitor Template
The Capacitor template provides a cross-platform native app development solution using web technologies, perfect for building mobile applications that can run on iOS and Android.
Technical Stack
- Capacitor - Cross-platform native runtime
- Vue 3 - Progressive JavaScript framework
- TypeScript - Type-safe development
- Vite - Fast build tool and dev server
- Vue Router - Client-side routing
- Pinia - State management library
- Vue i18n - Internationalization
- Tailwind CSS - Utility-first CSS framework
Quick Start
1. Create Project
bash
# Initialize project
vup init my-capacitor-project
cd my-capacitor-project
# Add Capacitor template
vup add my-capacitor-app2. Install Dependencies
bash
# Install dependencies
pnpm install3. Start Development
bash
# Start development server
cd apps/my-capacitor-app
pnpm devThe application will be available at http://localhost:9305.
Project Structure
apps/my-capacitor-app/
├── src/
│ ├── assets/ # Static assets
│ │ └── images/ # Image files
│ ├── locales/ # Internationalization
│ │ ├── index.ts # i18n configuration
│ │ ├── en_US.ts # English translations
│ │ └── zh_CN.ts # Chinese translations
│ ├── api/ # API layer
│ │ ├── request.ts
│ │ └── types.ts
│ ├── modules/
│ │ └── demo/
│ │ ├── api/
│ │ │ └── task.ts
│ │ ├── components/
│ │ │ └── DemoTaskBoard.vue
│ │ ├── locales/
│ │ │ ├── en_US.ts
│ │ │ └── zh_CN.ts
│ │ ├── stores/
│ │ │ └── useDemoTaskStore.ts
│ │ ├── types/
│ │ │ └── task.ts
│ │ └── views/
│ │ ├── DemoLayout.vue
│ │ ├── DemoGuidePage.vue
│ │ └── DemoExamplePage.vue
│ ├── router/ # Vue Router
│ │ ├── index.ts # Router configuration
│ │ └── routes.ts # Route definitions
│ ├── views/ # Page components
│ │ └── empty/
│ │ └── Empty.vue
│ ├── App.vue # Root component
│ ├── main.ts # Application entry point
│ └── vue-shim.d.ts # Vue type declarations
├── .env.example # Environment variables example
├── auto-imports.d.ts # Auto imports declarations
├── public/ # Public assets
│ ├── favicon.ico
├── capacitor.config.json # Capacitor configuration
├── package.json # Dependencies and scripts
├── tsconfig.json # TypeScript configuration
└── vite.config.js # Vite configurationCore Features
Vue 3 with Capacitor
vue
<template>
<div class="container">
<h1>{{ title }}</h1>
<p>{{ description }}</p>
<button @click="handleNativeAction">Call Native Function</button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { Capacitor } from '@capacitor/core';
const title = ref('Capacitor App');
const description = ref('Cross-platform native app with web technologies');
const handleNativeAction = async () => {
if (Capacitor.isNativePlatform()) {
// Call native function
const { Toast } = await import('@capacitor/toast');
await Toast.show({
text: 'Hello from native!',
duration: 'short',
});
} else {
// Fallback for web
alert('Hello from web!');
}
};
</script>
<style scoped>
.container {
@apply p-4 bg-white rounded-lg shadow-md;
}
</style>Native Plugin Integration
typescript
// utils/native.ts
import { Capacitor } from '@capacitor/core';
import { Camera, CameraResultType } from '@capacitor/camera';
import { Geolocation } from '@capacitor/geolocation';
import { Device } from '@capacitor/device';
export class NativeService {
static async takePicture(): Promise<string> {
if (!Capacitor.isNativePlatform()) {
throw new Error('Camera is only available on native platforms');
}
const image = await Camera.getPhoto({
quality: 90,
allowEditing: true,
resultType: CameraResultType.Uri,
});
return image.webPath || '';
}
static async getCurrentPosition(): Promise<GeolocationPosition> {
if (!Capacitor.isNativePlatform()) {
throw new Error('Geolocation is only available on native platforms');
}
const coordinates = await Geolocation.getCurrentPosition();
return coordinates;
}
static async getDeviceInfo(): Promise<any> {
const info = await Device.getInfo();
return info;
}
}Internationalization
typescript
// locales/en_US.ts
export default {
common: {
title: 'Capacitor Application',
description: 'Cross-platform native app with web technologies',
button: 'Call Native Function',
},
navigation: {
home: 'Home',
demo: 'Demo',
docs: 'Documentation',
},
};Tailwind CSS Styling
vue
<template>
<div class="min-h-screen bg-gray-100">
<header class="bg-white shadow-sm">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<h1 class="text-3xl font-bold text-gray-900">
{{ $t('common.title') }}
</h1>
</div>
</header>
<main class="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
<div class="px-4 py-6 sm:px-0">
<div class="border-4 border-dashed border-gray-200 rounded-lg h-96">
<p class="text-center text-gray-500 mt-20">
{{ $t('common.description') }}
</p>
</div>
</div>
</main>
</div>
</template>Development Tools
Capacitor Configuration
json
// capacitor.config.json
{
"appId": "com.example.myapp",
"appName": "My Capacitor App",
"webDir": ".output",
"bundledWebRuntime": false,
"server": {
"androidScheme": "https"
},
"plugins": {
"SplashScreen": {
"launchShowDuration": 2000,
"backgroundColor": "#ffffff",
"androidSplashResourceName": "splash",
"androidScaleType": "CENTER_CROP",
"showSpinner": true,
"androidSpinnerStyle": "large",
"iosSpinnerStyle": "small",
"spinnerColor": "#999999",
"splashFullScreen": true,
"splashImmersive": true
}
}
}Vite Configuration
javascript
// vite.config.js
import path from 'path';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import AutoImport from 'unplugin-auto-import/vite';
import { defineConfig, mergeConfig } from 'vite';
export default mergeConfig(
defineConfig({
root: '.',
plugins: [
vue(),
vueJsx(),
AutoImport({
imports: ['vue', 'vue-router', 'pinia', 'vue-i18n'],
dts: path.resolve(__dirname, 'auto-imports.d.ts'),
vueTemplate: true,
}),
],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@_shared': path.resolve(__dirname, '../../_shared'),
},
},
css: {
postcss: path.resolve(__dirname, '../../postcss.config.js'),
},
build: {
target: 'es2015',
minify: 'esbuild',
sourcemap: false,
outDir: '.output',
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router', 'pinia'],
utils: ['lodash-es', 'dayjs'],
},
},
},
},
server: {
host: '0.0.0.0',
port: 9305,
open: false,
cors: true,
},
})
);TypeScript Configuration
json
// tsconfig.json
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./.output",
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@_shared/*": ["../../_shared/*"]
}
},
"include": [
"src/**/*",
"src/**/*.vue",
"src/*.vue",
"./auto-imports.d.ts",
"src/vue-shim.d.ts"
]
}Available Scripts
json
{
"scripts": {
"dev": "vite",
"build": "tsc --noEmit && vite build",
"ios:add": "npx cap add ios",
"ios:build": "pnpm build && npx cap sync ios",
"ios:open": "npx cap open ios",
"ios": "pnpm ios:build && pnpm ios:open",
"android:add": "npx cap add android",
"android:build": "pnpm build && npx cap sync android",
"android:open": "npx cap open android",
"android": "pnpm android:build && pnpm android:open",
"lint": "eslint src/ --ext .vue,.ts,.js",
"lint:fix": "eslint src/ --ext .vue,.ts,.js --fix",
"format": "prettier --write \"src/**/*.{js,ts,vue,json,css,scss}\"",
"format:check": "prettier --check \"src/**/*.{js,ts,vue,json,css,scss}\""
}
}Related Examples
For isolated capability demos, refer to the base repository examples/ directory (for example examples/mock).
Platform Requirements
iOS Development
- Xcode 14.0 or later
- iOS SDK 12.0 or later
- CocoaPods for dependency management
Android Development
- Android Studio with Android SDK
- Java Development Kit (JDK) 11 or later
- Android SDK API level 21 or later
Development Workflow
1. Web Development
bash
cd apps/my-capacitor-app
# Start web development server
pnpm dev
# Build for production
pnpm build2. Add Native Platforms
bash
cd apps/my-capacitor-app
# Add iOS platform
pnpm ios:add
# Add Android platform
pnpm android:add3. Build and Sync Native Assets
bash
cd apps/my-capacitor-app
# Build and sync for iOS
pnpm ios:build
# Build and sync for Android
pnpm android:build4. Open in Native IDEs
bash
cd apps/my-capacitor-app
# Open iOS project in Xcode
pnpm ios:open
# Open Android project in Android Studio
pnpm android:openBuild and Deployment
Web Build
bash
cd apps/my-capacitor-app
# Build for web
pnpm build
# The built files will be in the .output directoryNative Build
bash
cd apps/my-capacitor-app
# Build and sync for iOS
pnpm ios:build
# Build iOS app
pnpm ios:open
# Then build in Xcode
# Build and sync for Android
pnpm android:build
# Build Android app
pnpm android:open
# Then build in Android Studio