К основному содержанию
скилл CX Codex

framework-to-capacitor — скилл для Claude Code: сборка веб-фреймворка

Настраивает статическую сборку Next.js, Nuxt, Angular, SvelteKit или Vite так, чтобы Capacitor упаковал её в приложение для iOS и Android.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add Cap-go/capgo-skills --skill framework-to-capacitor -a claude-code
Открыть на GitHub

Что делает framework-to-capacitor

Скилл разбирается, почему npx cap sync падает с ошибкой про отсутствующий index.html или почему после синхронизации приложение открывается белым экраном. Он смотрит на package.json, находит фреймворк и его мажорную версию, а затем подгружает нужный справочник: для Next.js это references/nextjs.md с webDir out, для Nuxt — .output/public, для Angular — dist/<project>/browser, для SvelteKit — build или dist.

Перед правкой конфигов скилл ищет серверные куски: app/api/, middleware.ts, 'use server', getServerSideProps, +page.server.ts, @angular/ssr. Capacitor не запускает Node, поэтому SSR, API-роуты и серверные экшены в приложении не работают — их придётся вынести на внешний бэкенд и звать по HTTPS. Список таких мест скилл показывает вам и согласует, куда что переезжает, прежде чем удалять код.

Дальше он ставит @capacitor/core, @capacitor/ios, @capacitor/android и @capacitor/cli, выполняет npx cap init с вашим webDir, добавляет платформы и предлагает один скрипт вида build:mobile, который собирает проект и сразу синхронизирует. Учтите: Capacitor 8 требует Node 22+, а SvelteKit 3 поднимает минимум до Node 22.17. Переменные окружения вроде NEXT_PUBLIC_* и VITE_* вшиваются на этапе сборки, так что перед каждым cap sync нужен свежий билд, и продакшен не должен смотреть на localhost.

Какие задачи решает

  • починить падение cap sync из-за отсутствующего index.html
  • убрать белый экран после синхронизации
  • найти и вынести серверные роуты, которые не работают в приложении
  • согласовать webDir с реальной папкой сборки фреймворка
  • сделать сборку и синхронизацию одной командой

Примеры запросов агенту

  • настрой сборку Next.js под Capacitor, у меня белый экран после cap sync
  • проверь, какие API-роуты и middleware не заработают в мобильном приложении
  • добавь скрипт build:mobile, который собирает проект и делает cap sync

Как установить framework-to-capacitor

1Через Skills CLI (Vercel)

npx skills add Cap-go/capgo-skills --skill framework-to-capacitor -a claude-code

2Вручную: положить файлы

~/.claude/skills/framework-to-capacitor/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/framework-to-capacitor/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Вопросы о framework-to-capacitor

Как установить framework-to-capacitor в Claude?

Выполните npx skills add Cap-go/capgo-skills --skill framework-to-capacitor -a claude-code. После этого файл скилла лежит в ~/.claude/skills/framework-to-capacitor/SKILL.md.

Что делает framework-to-capacitor?

Приводит сборку веб-фреймворка к статическому бандлу, который Capacitor копирует в нативные проекты, и связывает сборку с cap sync в один шаг.

Какие фреймворки он поддерживает?

Next.js, Nuxt, Angular, SvelteKit, React, Vue, Svelte и Solid на Vite, React Router в режиме SPA, а также Qwik, Astro и Remix. Для каждого свой справочник и своё значение webDir.

Исходный текст

SKILL.md · MIT
---
name: framework-to-capacitor
description: 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).
allowed-tools:
  - Bash(node -e *)
  - Bash(find *)
---

# 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 sync` fails with `The web assets directory (./dist) must contain an index.html file.` or `Could 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, `prerender` errors, 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 `webDir` into 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) and `https://localhost` (Android). Your backend must allow those origins for CORS, or use `CapacitorHttp`.
- Capacitor's local server returns the root `index.html` for any path without a file extension. History-mode SPA routing (`createWebHistory`, `BrowserRouter`, Angular default `PathLocationStrategy`) 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 root `index.html`. Keep navigation client-side and route deep links through `App.addListener('appUrlOpen', ...)` + your router.
- Asset paths: keep the framework's base at `/` (Vite `base`, Angular `<base href="/">`, Next `basePath`/`assetPrefix` unset). 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, Angular `environment.ts`). Rebuild before every `cap sync`; never point production builds at `localhost`.
- 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

1. 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.
2. 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 |

3. 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.
4. Make the static build work and inspect the output directory: it must contain `index.html` at its root.
5. Install and initialise Capacitor (use the repo's package manager for installs):

```bash
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
```

6. Add one script that always builds before syncing, e.g. `"build:mobile": "<framework build> && cap sync"`.
7. 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):

```ts
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

```bash
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 android
```

Then 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`.

© Cap-go · MIT · Cap-go/capgo-skills

Похожие скиллы

Всё по теме «Мобильная разработка» →
capacitor-expert capawesome-team Скилл-справочник по Capacitor: архитектура, CLI, плагины, интеграция с фреймворками и Capawesome Cloud. Пригодится, когда агент собирает или чинит кросс-платформенное приложение. CX Codex +1 1 100установок capacitor-app-creation capawesome-team Скилл ведёт агента по шагам при создании Capacitor-приложения с нуля: каркас веб-проекта, настройка, нативные платформы, запуск. CX Codex +1 820установок vue-expert https://github.com/Jeffallan Помогает писать Vue 3 код на Composition API, настраивать Nuxt 3, Pinia и Vite. Пригодится для компонентов, PWA и гибридных приложений. CX Codex +1 4 500установок ionic Mindrally Задаёт агенту правила разработки на Ionic: структура проекта, компоненты, стили, ленивая загрузка и работа с Firebase. CX Codex +1 797установок internationalization-i18n Mindrally Скилл задаёт агенту правила интернационализации: переводы, форматирование дат и чисел, RTL-раскладка. Пригодится, когда приложение выходит на новые языки. CX Codex +1 978установок bun-sveltekit secondsky Подсказывает агенту, как собирать и запускать SvelteKit на Bun: SSR, адаптер, bun:sqlite и работа с файлами. CX Codex +1 499установок

Из того же набора29

capacitor-push-notifications Скилл для настройки и отладки удалённых пушей в Capacitor: FCM на Android, APNs на iOS. Пригодится, когда registration не срабатывает или уведомления не показываются. CX Codex +1 1 100установок capacitor-splash-screen Скилл разбирается, почему в приложении Capacitor мелькает белый экран или сплэш не исчезает, и правит конфиг, тему Android 12+ и iOS storyboard. CX Codex +1 1 100установок capacitor-keyboard Разбирает поведение экранной клавиатуры в приложениях на Capacitor: режимы resize на iOS, высоты событий, edge-to-edge на Android. Пригодится, когда поле ввода уезжает под клавиатуру. CX Codex +1 1 000установок tailwind-capacitor Настраивает Tailwind CSS v4 в приложениях на Capacitor и разбирает грабли мобильной вёрстки: safe-area, тёмная тема, варианты под iOS и Android. CX Codex +1 955установок capgo-live-updates Помогает подключить и отладить живые обновления Capgo в приложении на Capacitor: первый бандл, режимы autoUpdate, откаты. CX Codex +1 848установок konsta-ui Скилл помогает агенту собирать интерфейс Capacitor-приложения на Konsta UI v5 с Tailwind CSS v4 и разбираться, почему компоненты остались без стилей. CX Codex +1 836установок cocoapods-to-spm Переводит iOS-проект Capacitor с CocoaPods на Swift Package Manager и подсказывает, что делать с плагинами без Package.swift. CX Codex +1 796установок capacitor-app-upgrades Ведёт приложение на Capacitor через мажорные версии по одной, с обязательным шагом UIScene для iOS перед Capacitor 9. CX Codex +1 771установок

Спонсоры проекта

Компании, которые помогают держать аналитику открытой