AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Ionic Capacitor

skill-gabriel-tutor-ionic-capacitor-skills-ionic-capacitor · by gabriel-tutor

>

No reviews yet
0 installs
34 views
0.0% view→install

Install

$ agentstack add skill-gabriel-tutor-ionic-capacitor-skills-ionic-capacitor

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-gabriel-tutor-ionic-capacitor-skills-ionic-capacitor)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
6mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Ionic Capacitor? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Ionic Capacitor Development Skill

Build performant, native-feeling mobile apps using Ionic UI components and Capacitor's native runtime. This skill covers the full stack: project setup, component patterns, state management, native APIs, theming, and deployment across React, Angular, and Vue.

Quick Decision: Which Framework?

| Factor | React | Angular | Vue | |--------|-------|---------|-----| | Learning curve | Moderate | Steeper | Gentle | | Ecosystem | Largest | Enterprise-strong | Growing fast | | State management | Zustand/TanStack Query | Signals + Services | Pinia | | Best for | Startups, flexibility | Enterprise, structure | Simplicity, speed | | Ionic integration | @ionic/react | @ionic/angular | @ionic/vue |

All three are first-class citizens in Ionic. Pick based on team familiarity. Read references/react.md, references/angular.md, or references/vue.md for framework-specific deep dives.

Project Setup

Create a New Project

# Install Ionic CLI
npm install -g @ionic/cli

# Create project (pick your framework)
ionic start myApp tabs --type=react      # React
ionic start myApp tabs --type=angular    # Angular
ionic start myApp tabs --type=vue        # Vue

# Templates: blank, tabs, sidemenu, list, conference

Project Structure (Universal)

myApp/
├── src/
│   ├── components/       # Reusable UI components
│   ├── pages/            # Route-level page components
│   ├── services/         # API calls, business logic
│   ├── hooks/            # Custom hooks (React/Vue)
│   ├── store/            # State management
│   ├── theme/
│   │   └── variables.css # Ionic CSS custom properties
│   ├── assets/           # Static files (images, fonts)
│   └── App.tsx           # Root component
├── public/
├── capacitor.config.ts   # Capacitor configuration
├── ionic.config.json     # Ionic CLI configuration
└── package.json

Capacitor Configuration

// capacitor.config.ts
import type { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: 'com.yourcompany.appname',    // Reverse domain notation
  appName: 'Your App Name',
  webDir: 'dist',                       // Build output directory
  server: {
    // For development live reload (remove in production):
    // url: 'http://192.168.1.x:8100',
    // cleartext: true,
    androidScheme: 'https',             // Always use https
  },
  ios: {
    contentInset: 'automatic',          // Safe area handling
    preferredContentMode: 'mobile',
  },
  android: {
    allowMixedContent: false,           // Security: keep false in prod
  },
  plugins: {
    SplashScreen: {
      launchAutoHide: true,
      androidScaleType: 'CENTER_CROP',
      splashFullScreen: true,
      splashImmersive: true,
    },
    StatusBar: {
      style: 'dark',                    // 'dark' or 'light'
    },
  },
};

export default config;

Add Native Platforms

# Build web assets first
ionic build

# Add platforms
ionic cap add ios
ionic cap add android

# Sync web assets to native projects
ionic cap sync

# Open native IDEs
ionic cap open ios      # Opens Xcode
ionic cap open android  # Opens Android Studio

Core Component Patterns

Page Structure — The Foundation

Every page follows this pattern. Never skip it — Ionic's scroll behavior, safe areas, and transitions depend on this structure.


  
    
      Page Title
    
  

  
    {/* iOS large title support */}
    
      
        Page Title
      
    

    {/* Your page content */}
  

The collapse="condense" header creates the native iOS large-title-to-small-title scroll effect. Always include it for iOS native feel.

Navigation Patterns

Tabs — Best for apps with 3-5 top-level sections:


  
    
    
    
  
  
    
      
      Home
    
    {/* ... */}
  

Side Menu — Best for apps with many sections:


  
    
      
        Menu
      
    
    
      
        
          Page 1
        
      
    
  
  

Stack Navigation — For drill-down flows:

Always set defaultHref so back navigation works even when the user deep-links into a page.

Lists — The Workhorse Component

Lists appear everywhere in mobile apps. Use the right pattern:

{/* Basic list */}

  
    
      Primary Text
      Secondary text
    
  

{/* Sliding items with actions */}

  
    
      Archive
    
    
      Swipe me
    
    
      Delete
    
  

{/* Virtual scroll for large lists (performance critical) */}
{/* Use framework-specific virtual scroll or @ionic/react's IonContent */}

Grid Layout — Responsive Image/Card Galleries

Use IonGrid with IonRow and IonCol for responsive grid layouts like photo galleries, dashboards, or card grids. This is the correct approach for multi-column layouts (not IonList):

{/* Photo/Image Gallery — use IonGrid, NOT IonList */}

  
    {photos.map((photo) => (
      
        
          
          
            {photo.date}
          
        
      
    ))}
  

{/* Dashboard stats grid */}

  
    
    
    
    
  

Column sizing: size sets the default (out of 12 columns). Use sizeSm, sizeMd, sizeLg, sizeXl for responsive breakpoints. For example, size="6" sizeMd="4" sizeLg="3" gives 2 columns on mobile, 3 on tablet, 4 on desktop.

Forms — Getting Input Right


  
    
  

  
    
  

  
    
      Bug Report
      Feature Request
    
  

  
    Enable notifications
  

  
    
      0
      100
    
  

Use labelPlacement="stacked" and fill="outline" for modern form styling. Use fill="solid" for a softer look.

Overlays — Modals, Alerts, Action Sheets

{/* Modal — Present complex UI */}
 setShowModal(false)}
  breakpoints={[0, 0.5, 1]}       // Sheet modal with stops
  initialBreakpoint={0.5}          // Start half-open
  handle={true}                     // Show drag handle
>
  
    {/* Modal content */}
  

{/* Alert — Simple decisions */}
const [presentAlert] = useIonAlert();
presentAlert({
  header: 'Confirm',
  message: 'Are you sure?',
  buttons: ['Cancel', { text: 'OK', role: 'confirm' }],
});

{/* Action Sheet — List of actions */}
const [presentActionSheet] = useIonActionSheet();
presentActionSheet({
  header: 'Actions',
  buttons: [
    { text: 'Share', icon: shareOutline },
    { text: 'Delete', role: 'destructive', icon: trashOutline },
    { text: 'Cancel', role: 'cancel' },
  ],
});

{/* Toast — Non-intrusive feedback */}
const [presentToast] = useIonToast();
presentToast({
  message: 'Item saved!',
  duration: 2000,
  position: 'bottom',
  color: 'success',
});

{/* Loading — Block UI during operations */}
const [presentLoading, dismissLoading] = useIonLoading();
await presentLoading({ message: 'Saving...' });
await saveData();
await dismissLoading();

Cards — Content Containers


  
  
    Category
    Card Title
  
  
    Card description text goes here.
  
  
    
      
        
      
    
  

Pull-to-Refresh and Infinite Scroll


  
    
  

  {/* Your list content */}

  
    
  

Skeleton Loading — Perceived Performance

{isLoading ? (
  
    {[...Array(5)].map((_, i) => (
      
        
          
        
        
          
          
        
      
    ))}
  
) : (
  
)}

Theming — Native Look and Feel

Platform-Adaptive Styling

Ionic automatically adapts to iOS and Material Design. The mode is set per-platform but can be overridden:

// Force a specific mode globally
// In app setup:
setupIonicReact({ mode: 'ios' });  // or 'md'

CSS Custom Properties

Ionic's design system is built on CSS variables. Override them in theme/variables.css:

:root {
  /* Primary brand color — generates shade/tint automatically */
  --ion-color-primary: #3880ff;
  --ion-color-primary-rgb: 56, 128, 255;
  --ion-color-primary-contrast: #ffffff;
  --ion-color-primary-shade: #3171e0;
  --ion-color-primary-tint: #4c8dff;

  /* Application-level variables */
  --ion-background-color: #ffffff;
  --ion-text-color: #000000;
  --ion-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

  /* Stepped colors (for subtle backgrounds) */
  --ion-color-step-50: #f2f2f2;
  --ion-color-step-100: #e6e6e6;
  /* ... up to step-950 */
}

Use the Ionic Color Generator to produce correct shade/tint/contrast values.

Dark Mode

Three approaches (pick one):

/* 1. Always dark */
@import '@ionic/react/css/palettes/dark.always.css';

/* 2. Follow system preference (recommended) */
@import '@ionic/react/css/palettes/dark.system.css';

/* 3. Toggle via CSS class */
@import '@ionic/react/css/palettes/dark.class.css';
/* Then add/remove .ion-palette-dark class on  */

Add this meta tag for native UI elements:

Per-Component Styling

Use CSS Shadow Parts and CSS variables:

/* Target shadow DOM parts */
ion-button::part(native) {
  border-radius: 20px;
}

/* Component-level CSS variables */
ion-item {
  --background: transparent;
  --border-color: var(--ion-color-light);
  --padding-start: 16px;
}

CSS Utility Classes

Ionic provides utility classes for common styling. Import them in your global CSS:

/* Import all utilities at once */
@import '@ionic/react/css/ionic.bundle.css';  /* React */
@import '@ionic/angular/css/ionic.bundle.css'; /* Angular */
@import '@ionic/vue/css/ionic.bundle.css';     /* Vue */

Padded content
Top margin, no padding

Centered text

Mobile only
Tablet & desktop only

> For complete utility class reference, Shadow Parts, and customization recipes, read references/styling.md.

Capacitor Native APIs

Installation Pattern

npm install @capacitor/camera    # Install the plugin
ionic cap sync                   # Sync to native projects

Camera

import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';

const takePhoto = async () => {
  const image = await Camera.getPhoto({
    quality: 90,
    allowEditing: false,
    resultType: CameraResultType.Uri,      // or Base64, DataUrl
    source: CameraSource.Camera,           // or Photos, Prompt
    width: 1024,                           // Max width
    saveToGallery: true,
  });
  return image.webPath;  // Use this for 
};

Geolocation

import { Geolocation } from '@capacitor/geolocation';

const getCurrentPosition = async () => {
  const coordinates = await Geolocation.getCurrentPosition({
    enableHighAccuracy: true,
    timeout: 10000,
  });
  return {
    lat: coordinates.coords.latitude,
    lng: coordinates.coords.longitude,
  };
};

// Watch position changes
const watchId = await Geolocation.watchPosition(
  { enableHighAccuracy: true },
  (position, err) => { /* handle updates */ }
);
// Later: Geolocation.clearWatch({ id: watchId });

Push Notifications

import { PushNotifications } from '@capacitor/push-notifications';

const initPush = async () => {
  const permStatus = await PushNotifications.requestPermissions();
  if (permStatus.receive === 'granted') {
    await PushNotifications.register();
  }

  PushNotifications.addListener('registration', (token) => {
    console.log('FCM token:', token.value);
    // Send token to your server
  });

  PushNotifications.addListener('pushNotificationReceived', (notification) => {
    console.log('Push received:', notification);
  });

  PushNotifications.addListener('pushNotificationActionPerformed', (action) => {
    console.log('Push action:', action);
    // Navigate based on action.notification.data
  });
};

Filesystem

import { Filesystem, Directory, Encoding } from '@capacitor/filesystem';

// Write a file
await Filesystem.writeFile({
  path: 'data/config.json',
  data: JSON.stringify(config),
  directory: Directory.Data,
  encoding: Encoding.UTF8,
  recursive: true,  // Create directories as needed
});

// Read a file
const result = await Filesystem.readFile({
  path: 'data/config.json',
  directory: Directory.Data,
  encoding: Encoding.UTF8,
});

Other Core Plugins

| Plugin | Install | Key Methods | |--------|---------|-------------| | @capacitor/app | npm i @capacitor/app | App.addListener('appStateChange'), App.getLaunchUrl() | | @capacitor/browser | npm i @capacitor/browser | Browser.open({ url }) | | @capacitor/clipboard | npm i @capacitor/clipboard | Clipboard.write(), Clipboard.read() | | @capacitor/device | npm i @capacitor/device | Device.getInfo(), Device.getId() | | @capacitor/haptics | npm i @capacitor/haptics | Haptics.impact(), Haptics.vibrate() | | @capacitor/keyboard | npm i @capacitor/keyboard | Keyboard.show(), Keyboard.hide() | | @capacitor/network | npm i @capacitor/network | Network.getStatus(), Network.addListener() | | @capacitor/preferences | npm i @capacitor/preferences | Preferences.set(), Preferences.get() | | @capacitor/share | npm i @capacitor/share | Share.share({ title, text, url }) | | @capacitor/splash-screen | npm i @capacitor/splash-screen | SplashScreen.hide(), SplashScreen.show() | | @capacitor/status-bar | npm i @capacitor/status-bar | StatusBar.setStyle(), StatusBar.hide() | | @capacitor/action-sheet | npm i @capacitor/action-sheet | ActionSheet.showActions({ options }) | | @capacitor/app-launcher | npm i @capacitor/app-launcher | AppLauncher.canOpenUrl(), openUrl() | | @capacitor/dialog | npm i @capacitor/dialog | Dialog.alert(), confirm(), prompt() | | @capacitor/google-maps | npm i @capacitor/google-maps | GoogleMap.create(), addMarker(), setCamera() | | @capacitor/local-notifications | npm i @capacitor/local-notifications | LocalNotifications.schedule(), requestPermissions() | | @capacitor/motion | npm i @capacitor/motion | Motion.addListener('accel'), 'orientation' | | @capacitor/screen-reader | npm i @capacitor/screen-reader | ScreenReader.isEnabled(), speak() | | @capacitor/text-zoom | npm i @capacitor/text-zoom | TextZoom.get(), set(), getPreferred() | | @capacitor/toast | npm i @capacitor/toast | Toast.show({ text, position, duration }) |

> For full plugin documentation with code examples, read references/native-plugins.md.

Performance Optimization

Lazy Loading Routes

Split your app into chunks. Load pages only when navigated to:

// React
const Tab1 = React.lazy(() => import('./pages/Tab1'));
const Tab2 = React.lazy(() => import('./pages/Tab2'));

// Wrap in Suspense with skeleton fallback
}>
  

Image & Render Optimization

  • Use ` instead of for lazy loading; ` in lists
  • Memoize with useMemo/useCallback (React), computed (Vue), trackBy (Angular)
  • Avoid inline object creation in JSX props

Bundle Size

Import only what you use: import { IonButton } from '@ionic/react' — never import * as Ionic. Analyze with npx source-map-explorer dist/assets/*.js.

Virtual Scrolling for Large Lists

For lists with 100+ items, use virtual scrolling to render only visible items. Each framework has its approach — see the framework-specific reference files.

Development Workflow

ionic serve                           # Browser preview
ionic cap run ios -l --external       # Live reload on iOS device
ionic cap run android -l --external   # Live reload on Android
ionic build && ionic cap sync         # Build + sync to native projects
ionic cap open ios                    # Open Xcode
ionic cap open android                # Open Android Studio

Debugging: Browser via ionic serve DevTools • iOS via Safari > Develop > [Device] • Android via chrome://inspect

Deployment

iOS: Apple Developer account ($99/yr) → configure signing in Xcode → set Bundle ID matching appId → Product > Archive → uploa

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.