Skills ionic
Expert guidance for Ionic, the open-source framework for building cross-platform mobile, desktop, and progressive web apps using web technologies (HTML, CSS, JavaScript/TypeScript). Helps developers build apps with Ionic's UI components, integrate with native device APIs via Capacitor, and deploy to iOS, Android, and web from a single codebase.
git clone https://github.com/TerminalSkills/skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/TerminalSkills/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/ionic" ~/.claude/skills/terminalskills-skills-ionic && rm -rf "$T"
skills/ionic/SKILL.md- global npm install
Ionic — Cross-Platform Apps with Web Technologies
Overview
Ionic, the open-source framework for building cross-platform mobile, desktop, and progressive web apps using web technologies (HTML, CSS, JavaScript/TypeScript). Helps developers build apps with Ionic's UI components, integrate with native device APIs via Capacitor, and deploy to iOS, Android, and web from a single codebase.
Instructions
Project Setup
# Install Ionic CLI npm install -g @ionic/cli # Create a new project (React, Angular, or Vue) ionic start my-app tabs --type=react cd my-app # Run in browser ionic serve # Add native platforms ionic cap add ios ionic cap add android # Build and sync to native ionic cap sync ionic cap open ios # Opens Xcode ionic cap open android # Opens Android Studio
UI Components
// src/pages/Home.tsx — Ionic React component with native-feeling UI // Ionic provides 100+ UI components that adapt to iOS/Android automatically. import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonList, IonItem, IonLabel, IonBadge, IonSearchbar, IonRefresher, IonRefresherContent, IonFab, IonFabButton, IonIcon, IonSegment, IonSegmentButton, IonCard, IonCardHeader, IonCardTitle, IonCardContent, IonChip, IonAvatar, } from "@ionic/react"; import { add, filterOutline } from "ionicons/icons"; import { useState } from "react"; const Home: React.FC = () => { const [segment, setSegment] = useState("all"); const [searchText, setSearchText] = useState(""); const handleRefresh = async (event: CustomEvent) => { await fetchTasks(); event.detail.complete(); // Dismiss the refresher spinner }; return ( <IonPage> <IonHeader> <IonToolbar> <IonTitle>Tasks</IonTitle> </IonToolbar> <IonToolbar> <IonSearchbar value={searchText} onIonInput={(e) => setSearchText(e.detail.value ?? "")} placeholder="Search tasks..." /> </IonToolbar> <IonToolbar> <IonSegment value={segment} onIonChange={(e) => setSegment(e.detail.value as string)}> <IonSegmentButton value="all"><IonLabel>All</IonLabel></IonSegmentButton> <IonSegmentButton value="active"><IonLabel>Active</IonLabel></IonSegmentButton> <IonSegmentButton value="done"><IonLabel>Done</IonLabel></IonSegmentButton> </IonSegment> </IonToolbar> </IonHeader> <IonContent> <IonRefresher slot="fixed" onIonRefresh={handleRefresh}> <IonRefresherContent /> </IonRefresher> <IonList> {tasks.map((task) => ( <IonItem key={task.id} routerLink={`/task/${task.id}`}> <IonAvatar slot="start"> <img src={task.assignee.avatar} alt="" /> </IonAvatar> <IonLabel> <h2>{task.title}</h2> <p>{task.description}</p> </IonLabel> <IonBadge slot="end" color={task.priority === "high" ? "danger" : "medium"}> {task.priority} </IonBadge> </IonItem> ))} </IonList> <IonFab vertical="bottom" horizontal="end" slot="fixed"> <IonFabButton routerLink="/task/new"> <IonIcon icon={add} /> </IonFabButton> </IonFab> </IonContent> </IonPage> ); };
Native APIs with Capacitor
// src/services/native.ts — Access device features via Capacitor plugins import { Camera, CameraResultType, CameraSource } from "@capacitor/camera"; import { Geolocation } from "@capacitor/geolocation"; import { LocalNotifications } from "@capacitor/local-notifications"; import { Share } from "@capacitor/share"; import { Haptics, ImpactStyle } from "@capacitor/haptics"; import { Preferences } from "@capacitor/preferences"; // Camera — take photo or pick from gallery export async function takePhoto(): Promise<string> { const image = await Camera.getPhoto({ quality: 80, allowEditing: false, resultType: CameraResultType.Uri, source: CameraSource.Prompt, // Let user choose camera or gallery }); return image.webPath!; } // Geolocation export async function getCurrentPosition() { const coords = await Geolocation.getCurrentPosition({ enableHighAccuracy: true, }); return { lat: coords.coords.latitude, lng: coords.coords.longitude, }; } // Local notifications export async function scheduleReminder(title: string, body: string, date: Date) { await LocalNotifications.schedule({ notifications: [{ title, body, id: Date.now(), schedule: { at: date }, }], }); } // Share export async function shareContent(title: string, text: string, url?: string) { await Share.share({ title, text, url }); } // Haptic feedback export async function hapticTap() { await Haptics.impact({ style: ImpactStyle.Light }); } // Local storage (key-value, persists across app restarts) export async function savePreference(key: string, value: string) { await Preferences.set({ key, value }); } export async function getPreference(key: string): Promise<string | null> { const { value } = await Preferences.get({ key }); return value; }
Theming
/* src/theme/variables.css — Custom theme */ :root { --ion-color-primary: #4f46e5; --ion-color-primary-rgb: 79, 70, 229; --ion-color-primary-contrast: #ffffff; --ion-color-primary-shade: #463ec9; --ion-color-primary-tint: #6158e8; --ion-color-secondary: #06b6d4; --ion-color-success: #22c55e; --ion-color-warning: #f59e0b; --ion-color-danger: #ef4444; --ion-font-family: 'Inter', system-ui, sans-serif; } /* Dark mode — Ionic auto-detects system preference */ @media (prefers-color-scheme: dark) { :root { --ion-background-color: #0f172a; --ion-text-color: #e2e8f0; --ion-card-background: #1e293b; } }
Installation
npm install -g @ionic/cli npm install @ionic/react @ionic/react-router npm install @capacitor/core @capacitor/cli npm install @capacitor/camera @capacitor/geolocation # Per-plugin
Examples
Example 1: Setting up Ionic with a custom configuration
User request:
I just installed Ionic. Help me configure it for my TypeScript + React workflow with my preferred keybindings.
The agent creates the configuration file with TypeScript-aware settings, configures relevant plugins/extensions for React development, sets up keyboard shortcuts matching the user's preferences, and verifies the setup works correctly.
Example 2: Extending Ionic with custom functionality
User request:
I want to add a custom ui components to Ionic. How do I build one?
The agent scaffolds the extension/plugin project, implements the core functionality following Ionic's API patterns, adds configuration options, and provides testing instructions to verify it works end-to-end.
Guidelines
- Capacitor over Cordova — Capacitor is Ionic's modern native runtime; it supports any web framework and has better plugin ecosystem
- Platform-adaptive components — Ionic components auto-adapt to iOS/Android look; don't override platform styles unless necessary
- Lazy load pages — Use React.lazy or Angular lazy modules for each page; keeps initial bundle small
- Test in browser first — Develop and debug with
; only test on device for native features (camera, GPS)ionic serve - Use Ionic's CSS utilities — Ionic includes padding, margin, text alignment utilities; avoid writing custom CSS for spacing
- Progressive Web App first — Ionic apps are PWAs by default; test the web version before adding native platforms
- Capacitor plugins for native — Always use Capacitor plugins over direct Cordova plugins; they have better TypeScript support
- Live reload on device —
for instant feedback during native testingionic cap run ios --livereload --external