Skip to main content

Overview

CicloVital uses Capacitor to build native mobile applications from the React web app. Capacitor provides a native runtime and bridge that allows web apps to run on iOS and Android while accessing native device features.

Capacitor Version

The project uses the following Capacitor packages:
package.json
"@capacitor/core": "^7.4.2",
"@capacitor/cli": "^8.0.1",
"@capacitor/android": "^7.4.2"
Capacitor 7 is the latest major version with improved performance, better plugin APIs, and enhanced TypeScript support.

Configuration File

The main Capacitor configuration is stored in capacitor.config.json at the project root:
capacitor.config.json
{
  "appId": "com.ciclovital.app",
  "appName": "CicloVital",
  "webDir": "dist",
  "bundledWebRuntime": false
}

Configuration Properties

PropertyValueDescription
appIdcom.ciclovital.appUnique identifier for the app (reverse domain format)
appNameCicloVitalDisplay name shown on the device home screen
webDirdistDirectory containing built web assets (Vite output)
bundledWebRuntimefalseUses system WebView instead of bundling Capacitor runtime

Project Structure

After running npx cap add android, the project structure includes:
ciclovital/
├── android/                 # Native Android project
│   ├── app/
│   │   ├── src/main/
│   │   │   ├── assets/     # Web assets copied here
│   │   │   ├── java/       # Native Java/Kotlin code
│   │   │   └── AndroidManifest.xml
│   │   └── build.gradle
│   ├── build.gradle
│   └── variables.gradle     # Android SDK versions
├── src/                     # React source code
├── dist/                    # Built web assets
├── capacitor.config.json    # Capacitor configuration
├── package.json
└── vite.config.js

Core Capacitor Workflow

1

Build Web Assets

Compile your React app into static files:
npm run build
This creates optimized files in the dist directory using Vite.
2

Sync with Native Projects

Copy web assets and update native projects:
npx cap sync
This command:
  • Copies dist contents to native platform asset directories
  • Updates native dependencies based on installed plugins
  • Applies configuration changes from capacitor.config.json
For a specific platform:
npx cap sync android
3

Open Native IDE

Open the native project in its respective IDE:
npx cap open android
This opens Android Studio with the android directory.
4

Run on Device

Build and run directly on a device or emulator:
npx cap run android

Capacitor CLI Commands

Essential Commands

# Initialize Capacitor in an existing project
npx cap init

# Add a platform (Android or iOS)
npx cap add android
npx cap add ios

# Copy web assets only (faster than sync)
npx cap copy android

# Update Capacitor dependencies
npx cap update

# List installed plugins
npx cap ls

# Check Capacitor environment
npx cap doctor

Sync vs Copy vs Update

CommandWhat It Does
syncCopy web assets + update native dependencies + apply config
copyCopy web assets only (faster for quick iterations)
updateUpdate Capacitor core and official plugins to latest versions

Native Code Integration

The native Android app extends BridgeActivity to integrate with Capacitor:
android/app/src/main/java/com/ciclovital/app/MainActivity.java
package com.ciclovital.app;

import com.getcapacitor.BridgeActivity;

public class MainActivity extends BridgeActivity {}
This provides the JavaScript-to-native bridge that powers Capacitor plugins.

Permissions

The Android app requests the following permissions in AndroidManifest.xml:
android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
Additional permissions (camera, location, notifications, etc.) are automatically added by Capacitor plugins when installed.

Installing Capacitor Plugins

Capacitor plugins provide access to native device features. Install plugins as npm packages:
# Install a plugin
npm install @capacitor/camera

# Sync to update native projects
npx cap sync

Common Official Plugins

Here are some popular Capacitor plugins you might want to add:
Access the device camera and photo library.
npm install @capacitor/camera
npx cap sync
import { Camera, CameraResultType } from '@capacitor/camera';

const takePicture = async () => {
  const image = await Camera.getPhoto({
    quality: 90,
    allowEditing: false,
    resultType: CameraResultType.Uri
  });
};
Persistent key-value storage.
npm install @capacitor/preferences
npx cap sync
import { Preferences } from '@capacitor/preferences';

await Preferences.set({ key: 'theme', value: 'dark' });
const { value } = await Preferences.get({ key: 'theme' });
Access device GPS and location services.
npm install @capacitor/geolocation
npx cap sync
import { Geolocation } from '@capacitor/geolocation';

const coordinates = await Geolocation.getCurrentPosition();
Send and receive push notifications.
npm install @capacitor/push-notifications
npx cap sync
Requires additional Firebase configuration for Android.
Control the device status bar appearance.
npm install @capacitor/status-bar
npx cap sync
import { StatusBar, Style } from '@capacitor/status-bar';

await StatusBar.setStyle({ style: Style.Dark });
Trigger haptic feedback (vibrations).
npm install @capacitor/haptics
npx cap sync
import { Haptics, ImpactStyle } from '@capacitor/haptics';

await Haptics.impact({ style: ImpactStyle.Medium });

Registering Custom Plugins

If you create a custom plugin, register it in MainActivity.java:
package com.ciclovital.app;

import com.getcapacitor.BridgeActivity;
import com.example.customplugin.CustomPlugin;

public class MainActivity extends BridgeActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // Register custom plugin
        registerPlugin(CustomPlugin.class);
    }
}

Platform-Specific Configuration

You can add platform-specific settings to capacitor.config.json:
capacitor.config.json
{
  "appId": "com.ciclovital.app",
  "appName": "CicloVital",
  "webDir": "dist",
  "bundledWebRuntime": false,
  "android": {
    "buildOptions": {
      "keystorePath": "/path/to/keystore",
      "keystoreAlias": "ciclovital"
    },
    "backgroundColor": "#ffffff",
    "allowMixedContent": false,
    "captureInput": true,
    "webContentsDebuggingEnabled": true
  },
  "plugins": {
    "SplashScreen": {
      "launchShowDuration": 2000,
      "backgroundColor": "#ffffff",
      "showSpinner": false
    }
  }
}

Android-Specific Options

OptionDescription
backgroundColorDefault background color for the WebView
allowMixedContentAllow HTTP content in HTTPS pages (not recommended)
captureInputCapture keyboard input events
webContentsDebuggingEnabledEnable Chrome DevTools debugging

Development Configuration

For development with live reload, temporarily add a server configuration:
capacitor.config.json
{
  "appId": "com.ciclovital.app",
  "appName": "CicloVital",
  "webDir": "dist",
  "bundledWebRuntime": false,
  "server": {
    "url": "http://192.168.1.100:5173",
    "cleartext": true
  }
}
The server configuration makes the app load content from your dev server instead of bundled assets. This is useful during development but must be removed before production builds.
1

Start Dev Server

npm run dev
2

Find Your Local IP

# On Linux/Mac
ifconfig | grep "inet "

# On Windows
ipconfig
3

Update Config

Add the server block with your local IP and port.
4

Rebuild and Run

npx cap copy android
npx cap run android

TypeScript Configuration

For TypeScript projects, install type definitions:
npm install --save-dev @capacitor/cli
Capacitor plugins include their own TypeScript definitions, so you get full IntelliSense support.

Updating Capacitor

To update Capacitor to the latest version:
1

Update Core Packages

npm install @capacitor/core@latest @capacitor/cli@latest
npm install @capacitor/android@latest
2

Update Native Projects

npx cap sync
3

Review Migration Guide

Check the Capacitor migration guide for breaking changes between major versions.

Debugging Capacitor Apps

Chrome DevTools (Android)

1

Enable WebView Debugging

Add to capacitor.config.json:
{
  "android": {
    "webContentsDebuggingEnabled": true
  }
}
2

Connect Device

Run your app on a device or emulator:
npx cap run android
3

Open Chrome DevTools

  1. Open Chrome browser
  2. Navigate to chrome://inspect
  3. Click Inspect under your device

Native Logs

View native Android logs:
# View all logs
adb logcat

# Filter by app
adb logcat | grep -i ciclovital

# View Capacitor bridge logs
adb logcat | grep -i Capacitor

Environment-Specific Builds

Manage different configurations for development, staging, and production:
// capacitor.config.ts (TypeScript alternative)
import { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: process.env.APP_ID || 'com.ciclovital.app',
  appName: 'CicloVital',
  webDir: 'dist',
  bundledWebRuntime: false,
  server: process.env.NODE_ENV === 'development' ? {
    url: `http://${process.env.DEV_SERVER_HOST}:5173`,
    cleartext: true
  } : undefined
};

export default config;

Troubleshooting

Plugin Not Found

If a plugin isn’t recognized:
npx cap sync android
npx cap open android
Then rebuild in Android Studio.

WebView Blank Screen

Ensure web assets are built and synced:
npm run build
npx cap copy android

CORS Errors

Capacitor apps use the capacitor://localhost scheme, which bypasses CORS. If you see CORS errors, your API server may need to allow this origin, or use Capacitor’s HTTP plugin:
npm install @capacitor/http
import { CapacitorHttp } from '@capacitor/http';

const response = await CapacitorHttp.get({
  url: 'https://api.ciclovital.com/data'
});

Resources

Capacitor Docs

Official Capacitor documentation

Plugin Registry

Browse available Capacitor plugins

Android Setup

Build and run the Android app

API Reference

Capacitor API documentation

Build docs developers (and LLMs) love