Skip to main content

nextjs-capacitor

Project-agnostic guide for setting up Next.js with Capacitor for native mobile support and Ionic React for UI components. Includes core setup, optional enhancements, and complete push notifications implementation.

Quellinformationen

Repository
pmarashian/cursor-agent-skills
Letzte Quellaktivität
13. Februar 2026 um 19:51
Erkannte Sprache von SKILL.md
Englisch
Sterne
2
Forks
1

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
nextjs-capacitor
description
Project-agnostic guide for setting up Next.js with Capacitor for native mobile support and Ionic React for UI components. Includes core setup, optional enhancements, and complete push notifications implementation.
# Next.js + Capacitor + Ionic React Setup ## Purpose This skill provides a comprehensive, project-agnostic guide for setting up a Next.js application with Capacitor for native mobile support and Ionic React for UI components. It covers core setup requirements, optional enhancements, and complete push notification implementation. ## When to Use Use this skill when: - Setting up a new Next.js project with Capacitor and Ionic React - Adding Capacitor to an existing Next.js application - Configuring push notifications for a Capacitor app - Troubleshooting Capacitor build or sync issues - Understanding the conditional static export pattern for Next.js + Capacitor ## Architecture Overview ### Project Structure Options You can organize your project in two ways: **Option A: Root-level `src/` directory** (Single app) ``` your-project/ ├── src/ # Next.js frontend at root │ └── app/ ├── backend/ # Optional backend (if monorepo) ├── capacitor.config.ts └── package.json ``` - Capacitor `webDir`: `"dist"` - Common for single-app projects **Option B: Separate `frontend/` directory** (Monorepo) ``` your-project/ ├── frontend/ # Next.js frontend │ └── src/ │ └── app/ ├── backend/ # Backend API ├── capacitor.config.ts └── package.json ``` - Capacitor `webDir`: `"frontend/dist"` - Better for projects with separate frontend/backend ### Key Concepts - **Conditional Static Export**: Next.js only exports statically when `CAPACITOR_BUILD=true`, allowing normal Next.js development - **Capacitor Integration**: Capacitor wraps the static Next.js build into native iOS/Android apps - **Ionic React**: Provides mobile-optimized UI components that work on web and native ## Core Setup Instructions ### Step 1: Create Next.js Project ```bash npx create-next-app@latest . --typescript --app --tailwind --eslint --src-dir ``` When prompted: - Choose **TypeScript** (recommended) - Choose **App Router** (required) - Choose **Tailwind CSS** (optional but recommended) - Choose **ESLint** (recommended) ### Step 2: Install Core Dependencies ```bash # Capacitor Core npm install @capacitor/core @capacitor/cli @capacitor/android @capacitor/ios # Ionic React npm install @ionic/react ionicons # Optional but recommended Capacitor plugins npm install @capacitor/splash-screen @capacitor/status-bar @capacitor/app ``` ### Step 3: Initialize Capacitor ```bash npx cap init ``` When prompted: - **App name**: YourAppName - **App ID**: com.yourcompany.yourapp (use reverse domain notation) - **Web dir**: `dist` (for root `src/`) or `frontend/dist` (for monorepo) This creates `capacitor.config.ts` at the root level. ### Step 4: Configure Capacitor Update `capacitor.config.ts`: ```typescript import type { CapacitorConfig } from "@capacitor/cli"; const config: CapacitorConfig = { appId: "com.yourcompany.yourapp", appName: "YourAppName", webDir: "dist", // or "frontend/dist" for monorepo plugins: { SplashScreen: { launchAutoHide: false, // Control manually for better UX }, StatusBar: { style: "DARK", overlaysWebView: false, backgroundColor: "#000000", }, }, }; export default config; ``` ### Step 5: Configure Next.js Update `next.config.js`: ```javascript /** @type {import('next').NextConfig} */ const nextConfig = { // Only use static export when building for Capacitor ...(process.env.CAPACITOR_BUILD === "true" && { output: "export", images: { unoptimized: true, // Required for static export }, trailingSlash: true, distDir: "dist", // Must match Capacitor's webDir }), transpilePackages: ["@ionic/react", "@ionic/core", "@stencil/core"], eslint: { ignoreDuringBuilds: true, }, typescript: { ignoreBuildErrors: true, }, webpack: (config, { isServer }) => { // Handle Stencil dynamic imports and Node.js polyfills if (!isServer) { config.resolve.fallback = { ...config.resolve.fallback, fs: false, crypto: false, stream: false, util: false, path: false, os: false, tls: false, net: false, dns: false, child_process: false, http: false, https: false, zlib: false, querystring: false, url: false, buffer: false, timers: false, "timers/promises": false, diagnostics_channel: false, }; } // Ignore dynamic import warnings for Stencil config.module = { ...config.module, unknownContextCritical: false, unknownContextRegExp: /^\.\/.*$/, unknownContextRequest: ".", }; return config; }, }; module.exports = nextConfig; ``` **Important**: The conditional static export allows normal Next.js development while enabling Capacitor builds when needed. ### Step 6: Update TypeScript Config Update `tsconfig.json`: ```json { "compilerOptions": { "target": "ES2017", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": false, "noEmit": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "incremental": true, "plugins": [ { "name": "next" } ], "paths": { "@/*": ["./src/*"] } }, "include": [ "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "next-env.d.ts", "dist/types/**/*.ts" ], "exclude": ["node_modules"] } ``` ### Step 7: Create Root Layout Create `src/app/layout.tsx`: ```tsx import type { Metadata } from "next"; import "@ionic/react/css/core.css"; import "@ionic/react/css/normalize.css"; import "@ionic/react/css/structure.css"; import "@ionic/react/css/typography.css"; import "@ionic/react/css/padding.css"; import "@ionic/react/css/float-elements.css"; import "@ionic/react/css/text-alignment.css"; import "@ionic/react/css/text-transformation.css"; import "@ionic/react/css/flex-utils.css"; import "@ionic/react/css/display.css"; import "@ionic/react/css/ionic.bundle.css"; import "@ionic/react/css/palettes/dark.css"; import "./globals.css"; import IonicApp from "./IonicApp"; export const metadata: Metadata = { title: "YourAppName", description: "Your app description", }; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="en"> <head> <meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <meta name="format-detection" content="telephone=no" /> <meta name="msapplication-tap-highlight" content="no" /> <link rel="manifest" href="/manifest.json" /> <meta name="theme-color" content="#31d53d" /> </head> <body className="" style={{ overflow: "hidden" }}> <IonicApp>{children}</IonicApp> </body> </html> ); } ``` ### Step 8: Create Basic IonicApp Component Create `src/app/IonicApp.tsx`: ```tsx "use client"; import { IonApp, setupIonicReact } from "@ionic/react"; setupIonicReact(); export default function IonicApp({ children }: { children: React.ReactNode }) { return <IonApp>{children}</IonApp>; } ``` ### Step 9: Create Global Styles Create `src/app/globals.css`: ```css @tailwind base; @tailwind components; @tailwind utilities; :root { --ion-color-primary: #31d53d; --ion-color-primary-rgb: 49, 213, 61; --ion-color-primary-contrast: #ffffff; --ion-color-primary-contrast-rgb: 255, 255, 255; --ion-color-primary-shade: #2bbb36; --ion-color-primary-tint: #46d954; } body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } ``` ### Step 10: Update Package Scripts Update `package.json` scripts: ```json { "scripts": { "dev": "next dev -p 3001", "build": "next build", "start": "next start", "lint": "next lint", "cap:sync": "CAPACITOR_BUILD=true next build && cap sync", "cap:ios": "CAPACITOR_BUILD=true next build && cap sync ios", "cap:android": "CAPACITOR_BUILD=true next build && cap sync android", "cap:open:ios": "cap open ios", "cap:open:android": "cap open android" } } ``` ### Step 11: Add Native Platforms ```bash # iOS npx cap add ios npx cap sync # Android npx cap add android npx cap sync ``` ## Optional Enhancements ### Enhanced IonicApp Component You can enhance the basic `IonicApp.tsx` with additional features: ```tsx "use client"; import { useEffect } from "react"; import { IonApp, setupIonicReact } from "@ionic/react"; import { Capacitor } from "@capacitor/core"; import { SplashScreen } from "@capacitor/splash-screen"; import { StatusBar, Style } from "@capacitor/status-bar"; import { App, AppState } from "@capacitor/app"; setupIonicReact(); export default function IonicApp({ children }: { children: React.ReactNode }) { useEffect(() => { // Add platform class to body for CSS targeting if (Capacitor.isNativePlatform()) { document.body.classList.add('native-platform'); } else { document.body.classList.add('web-platform'); // Add debug safe area indicators for Chrome DevTools testing document.documentElement.style.setProperty('--safe-area-inset-top', '44px'); document.documentElement.style.setProperty('--safe-area-inset-bottom', '34px'); } // Configure StatusBar on native platforms if (Capacitor.isNativePlatform()) { try { StatusBar.setStyle({ style: Style.Dark }); StatusBar.setOverlaysWebView({ overlay: false }); StatusBar.setBackgroundColor({ color: "#000000" }); } catch (error) { console.warn("Failed to configure status bar:", error); } try { // Hide splash screen after app loads setTimeout(() => { SplashScreen.hide({ fadeOutDuration: 200 }); }, 100); } catch (error) { console.warn("Failed to hide splash screen:", error); } // Listen for app state changes const stateListener = App.addListener("appStateChange", (state: AppState) => { if (state.isActive) { // Handle app becoming active console.log("App became active"); } }); return () => { document.body.classList.remove('native-platform', 'web-platform'); stateListener.remove(); }; } }, []); return <IonApp>{children}</IonApp>; }
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen