framework-to-capacitor
Skill75 starsChanged 32 days agoMITView on GitHub
Configures a web framework build so Capacitor can ship it as an iOS/Android app. Use for Next.js static export (output 'export', out/), Nuxt 4 (ssr false, nuxt generate, .output/public), Angular (dist/<project>/browser), SvelteKit adapter-static (SvelteKit 2 svelte.config.js or SvelteKit 3 vite.config), React/Vue/Svelte/Solid on Vite, and React Router framework SPA mode. Covers webDir mismatch, blank white screen after cap sync, missing index.html, SSR/API routes/middleware/server actions that cannot run in the app, next/image errors, deep-link reloads landing on the home page, router base paths, and env variables. Do not use for whole-app store readiness (webapp-to-capacitor), Cordova projects (cordova-to-capacitor), Capacitor major upgrades (capacitor-app-upgrades), or UI kits (ionic-design, konsta-ui, tailwind-capacitor).
- Installs packages
1 other project uses a version of this.
Adopted by
Most recently taken up by
- Aver005/agent-skillstheir own version, first seen Feb 14, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- Aver005/agent-skills★ 2same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository56 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- capacitor-accessibilitySkill
- capacitor-app-intentsSkill
- capacitor-apple-review-preflightSkill
- capacitor-app-storeSkill
- capacitor-app-upgradesSkill
- capacitor-app-upgrade-v4-to-v5Skill
- capacitor-app-upgrade-v5-to-v6Skill
- capacitor-app-upgrade-v6-to-v7Skill
- capacitor-app-upgrade-v7-to-v8Skill
- capacitor-app-upgrade-v8-to-v9Skill
- capacitor-best-practicesSkill
- capacitor-ci-cdSkill
- capacitor-deep-linkingSkill
- capacitor-ios-resizabilitySkill
- capacitor-ios-security-hardeningSkill
- capacitor-keyboardSkill
- capacitor-mcpSkill
- capacitor-offline-firstSkill
- capacitor-performanceSkill
- capacitor-plugin-spm-supportSkill
- capacitor-pluginsSkill
- capacitor-plugin-upgradesSkill
- capacitor-plugin-upgrade-v4-to-v5Skill
- capacitor-plugin-upgrade-v5-to-v6Skill
- capacitor-plugin-upgrade-v6-to-v7Skill
- capacitor-plugin-upgrade-v7-to-v8Skill
- capacitor-plugin-upgrade-v8-to-v9Skill
- capacitor-push-notificationsSkill
- capacitor-securitySkill
- capacitor-splash-screenSkill
- capacitor-testingSkill
- capacitor-uiscene-migrationSkill
- capawesome-live-update-migrationSkill
- capgo-cli-usageSkill
- capgo-cloudSkill
- capgo-live-updatesSkill
- capgo-native-buildsSkill
- capgo-organization-managementSkill
- capgo-release-managementSkill
- capgo-release-workflowsSkill
- cocoapods-to-spmSkill
- cordova-to-capacitorSkill
- debugging-capacitorSkill
- ionic-appflow-migrationSkill
- ionic-designSkill
- ionic-enterprise-sdk-migrationSkill
- ios-android-logsSkill
- konsta-uiSkill
- safe-area-handlingSkill
- skill-creatorSkill
- sqlite-to-fast-sqlSkill
- subscription-app-revenueSkill
- tailwind-capacitorSkill
- webapp-to-capacitorSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 3 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 21
Do not use for:
- Distinctive: line 47
Read the snapshot. Identify framework, major version, and the current build output directory.
- Very specific: line 72
Add one script that always builds before syncing, e.g.
- Distinctive: line 73
Run the verification below on both platforms.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Framework to Capacitor
Make a framework emit a static bundle that Capacitor can copy into the native projects, and wire the scripts so build -> cap sync is one step.
When to Use
TRIGGER when:
- Adding Capacitor to a Next.js, Nuxt, Angular, SvelteKit, Vite (React/Vue/Svelte/Solid), React Router, Qwik, or Astro project.
npx cap syncfails withThe web assets directory (./dist) must contain an index.html file.orCould not find the web assets directory: ./dist.- The app launches to a white screen or loads the wrong page after a reload or deep link.
- The framework build fails because of SSR-only features (
output: 'export'errors,prerendererrors, API routes, middleware, server actions).
Do not use for:
- Store readiness, native UX, permissions, billing, review risk ->
webapp-to-capacitor,capacitor-app-store,capacitor-apple-review-preflight. - Cordova/PhoneGap apps ->
cordova-to-capacitor. - Capacitor version upgrades ->
capacitor-app-upgrades. - Live updates setup ->
capgo-live-updates.
Live Project Snapshot
Detected framework and build dependencies:
!node -e "const fs=require('fs');if(!fs.existsSync('package.json'))process.exit(0);const pkg=JSON.parse(fs.readFileSync('package.json','utf8'));const matchers=['next','nuxt','react','react-router','@react-router/dev','vue','@angular/core','@angular/build','@sveltejs/kit','@sveltejs/adapter-static','@builder.io/qwik','@qwik.dev/core','astro','@remix-run/react','solid-js','@solidjs/start','vite','@capacitor/core','@capacitor/cli'];const out=[];for(const section of ['dependencies','devDependencies']){for(const [name,version] of Object.entries(pkg[section]||{})){if(matchers.includes(name))out.push(section+'.'+name+'='+version)}}for(const [name,cmd] of Object.entries(pkg.scripts||{})){if(['build','export','generate','sync','cap:sync'].includes(name))out.push('scripts.'+name+'='+cmd)}console.log(out.join('\n'))"
Relevant framework and Capacitor config paths:
!find . -maxdepth 3 -not -path '*/node_modules/*' \( -name 'next.config.*' -o -name 'nuxt.config.*' -o -name 'vite.config.*' -o -name 'angular.json' -o -name 'svelte.config.*' -o -name 'react-router.config.*' -o -name 'astro.config.*' -o -name 'capacitor.config.json' -o -name 'capacitor.config.ts' -o -name 'capacitor.config.js' \)
Core Facts (apply to every framework)
- Capacitor copies
webDirinto the native app. It never runs Node. SSR, API routes, middleware, ISR, server actions,cookies()/headers(), and image optimization servers do not exist at runtime. Move them to a hosted backend and call it over HTTPS. - The app is served from
capacitor://localhost(iOS) andhttps://localhost(Android). Your backend must allow those origins for CORS, or useCapacitorHttp. - Capacitor's local server returns the root
index.htmlfor any path without a file extension. History-mode SPA routing (createWebHistory,BrowserRouter, Angular defaultPathLocationStrategy) works; hash routing is not required. - The same fallback means per-route HTML files (Next.js export, SvelteKit prerender, Astro) are never served for extensionless URLs. A cold start or
location.reload()on/settings/loads the rootindex.html. Keep navigation client-side and route deep links throughApp.addListener('appUrlOpen', ...)+ your router. - Asset paths: keep the framework's base at
/(Vitebase, Angular<base href="/">, NextbasePath/assetPrefixunset). A CDN or sub-path base used for web hosting breaks asset loading in the app; use a separate mobile build config. - Environment variables are inlined at build time (
NEXT_PUBLIC_*,VITE_*,NUXT_PUBLIC_*,PUBLIC_*in SvelteKit, Angularenvironment.ts). Rebuild before everycap sync; never point production builds atlocalhost. - Capacitor 8 needs Node 22+. Capacitor 9 (currently
@next, not GA) needs Node 24+. Some framework majors also raise Node minimums (SvelteKit 3: Node 22.17+).
Procedure
- Read the snapshot. Identify framework, major version, and the current build output directory. If several apps live in a monorepo, ask which one ships to mobile.
- Load the matching reference (only the one in play):
| Framework in package.json | Load | webDir |
next | references/nextjs.md | out |
nuxt | references/vue-nuxt.md | .output/public |
vue + vite (no Nuxt) | references/vue-nuxt.md | dist |
react + vite, react-router/@react-router/dev, CRA | references/react.md | dist, build/client, or build |
@angular/core | references/angular.md | dist/<project>/browser |
@sveltejs/kit or svelte + vite | references/svelte.md | build or dist |
solid-js, @builder.io/qwik/@qwik.dev/core, astro, @remix-run/* | references/other-frameworks.md | varies |
- Inventory server-only features before changing config (grep for
app/api/,pages/api/,middleware.ts/proxy.ts,'use server',getServerSideProps,+page.server.ts,+server.ts,server/api/,@angular/ssr). Report the list to the user and agree where each moves (external API, client fetch, or native plugin) before deleting anything. - Make the static build work and inspect the output directory: it must contain
index.htmlat its root. - Install and initialise Capacitor (use the repo's package manager for installs):
npm install @capacitor/core @capacitor/ios @capacitor/android
npm install -D @capacitor/cli
npx cap init "App Name" com.company.app --web-dir <webDir>
npx cap add ios
npx cap add android- Add one script that always builds before syncing, e.g.
"build:mobile": "<framework build> && cap sync". - Run the verification below on both platforms.
Minimal config (androidScheme: 'https' is the default since Capacitor 6; only set it to keep an older origin):
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.company.app',
appName: 'App Name',
webDir: 'dist',
};
export default config;Live Reload
Capacitor 8: npx cap run ios -l --host <LAN-IP> --port <port>. Capacitor 9: npx cap run ios --url http://<LAN-IP>:<port> (the -l/--host/--port/--https flags were merged into --url). The dev server must listen on the LAN (--host 0.0.0.0 / server.host: true in Vite). Never commit server.url into capacitor.config.*.
Verification
npm run build
test -f <webDir>/index.html && echo "index.html OK"
npx cap sync
npx cap run ios # or open in Xcode
npx cap run androidThen on device/simulator:
- App opens on the first screen without a white flash beyond the splash.
- Navigate to a nested route, background + resume, and confirm the route survives.
- Open a deep link (
xcrun simctl openurl booted <url>/adb shell am start -a android.intent.action.VIEW -d <url>) and confirm it lands on the right screen. - Inspect the WebView (Safari Web Inspector /
chrome://inspect) for 404s on JS/CSS and CORS errors. grep -rn "localhost:\|127.0.0.1" <webDir>returns nothing unexpected.
Error Handling
| Symptom / error | Cause | Fix |
The web assets directory (./dist) must contain an index.html file. | webDir points at the wrong folder or SSR build has no index.html | Set webDir to the static output listed above; enable static/SPA mode |
Could not find the web assets directory: ./out. | Build not run or different output dir | Run the build first; match webDir to the real folder |
White screen, console Failed to load resource for /_next/... or /assets/... | Non-root base path / CDN assetPrefix | Use / base for the mobile build |
| White screen, no 404s | JS error at boot (often window/document during prerender, or SSR-only import) | Inspect WebView console; guard browser-only code |
| Reload or deep link opens home page or hydration error | Capacitor serves root index.html for extensionless paths | Client-side navigation + appUrlOpen handler; see framework reference |
Page "/x/[id]" is missing "generateStaticParams()" (Next.js) | Dynamic route in export mode | Pre-generate params or switch to a query-string/client route |
Image Optimization using the default loader is not compatible with output: export | next/image default loader | images.unoptimized: true or custom loader |
| API call works in browser, fails on device | CORS for capacitor://localhost / https://localhost, or localhost URL baked in | Allow origins on backend, or enable CapacitorHttp; fix env var |
References
references/nextjs.md- Next.js 14-16 static export, App Router traps, dynamic routes, images.references/react.md- Vite React, React Router framework SPA mode, CRA legacy.references/vue-nuxt.md- Vue + Vite, Nuxt 4 SPA generate.references/angular.md- Angular 17+ application builder output, SSR removal.references/svelte.md- SvelteKit 2 and 3 with adapter-static, plain Svelte + Vite.references/other-frameworks.md- Solid, Qwik, Astro, Remix v2.
Related skills: webapp-to-capacitor (store readiness), capacitor-deep-linking, safe-area-handling, capgo-live-updates.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

