A step-by-step guide for shipping a vibe-coded web app to Google Play from a Windows machine — covering tool installation, Capacitor setup, signing, and the full Play Store submission process.
If you're using Lunadeck, the build and signing steps (Parts 4–6) are handled for you automatically. This guide is for building and publishing locally, or for understanding what Lunadeck does under the hood.
What you'll need before starting:
A Windows 10 or Windows 11 computer (64-bit)
At least 12 GB of free disk space
At least 8 GB of RAM (16 GB recommended — the Android emulator is a memory hog)
A credit/debit card ($25 one-time Google Play fee)
Your exported web app project (ZIP from Bolt.new, Lovable, etc.)
About 2–4 hours for initial setup, then ~3 weeks for the publishing process
Part 1: Install the Required Tools
You need four things: Node.js, Java (JDK), Android Studio, and Capacitor (installed in Part 3).
1.1 Install Node.js (v22+)
Capacitor 8 requires Node.js 22 or newer. The easiest way to manage Node.js versions on Windows is with nvm-windows — a separate project from the Linux/Mac nvm, same concept, different tool.
Option A: Using nvm-windows (recommended)
If you already have Node.js installed, uninstall it first via Settings > Apps. nvm-windows can conflict with existing installations because it manages Node.js through symlinks, and an existing install creates PATH conflicts.
Run the installer. Accept the default installation directory, or choose your own — just avoid paths with spaces. The installer will also ask where to create the Node.js symlink; the default is fine.
Close and reopen your terminal after installation.
Then install Node.js 22:
# Open PowerShell or Command Prompt as Administrator# (nvm-windows requires admin rights to create symlinks)nvm install 22nvm use 22# Verifynode --version # Should show v22.x.xnpm --version
Important: Run nvm install and nvm use from an Administrator terminal. Right-click PowerShell or Command Prompt and select "Run as administrator."
Option B: Direct installer from nodejs.org
Go to https://nodejs.org and download the Windows installer (.msi) for Node.js 22.x. Run it and accept all defaults. Simpler, but makes it harder to switch Node versions later.
node --version
1.2 Install Java (JDK 17)
Android Studio bundles its own JDK, but having one system-wide avoids surprises — particularly keytool not being found when you need to sign your app.
Go to https://adoptium.net/ (Eclipse Temurin) and download the JDK 17 Windows .msi installer.
Run the installer. When prompted about custom setup, make sure "Set JAVA_HOME variable" is checked — this saves you from configuring it manually.
Accept the defaults and finish.
Verify in a new terminal window:
java -version
If java is not recognized after installation, set JAVA_HOME manually:
Press Win + S, search for "Environment Variables", and click "Edit the system environment variables"
Click "Environment Variables" at the bottom
Under System variables, click New:
Variable name: JAVA_HOME
Variable value: C:\Program Files\Eclipse Adoptium\jdk-17.x.x-hotspot (adjust to your actual path)
Find the Path variable, click Edit, and add a new entry: %JAVA_HOME%\bin
The AppData folder is hidden by default. To see it in File Explorer, click View > Show > Hidden items (Windows 11) or View > Hidden items (Windows 10).
Press Win + S, search for "Environment Variables", and click "Edit the system environment variables"
Find Path under System variables, click Edit, and add:
%ANDROID_HOME%\platform-tools
%ANDROID_HOME%\tools
%ANDROID_HOME%\tools\bin
%ANDROID_HOME%\cmdline-tools\latest\bin
Click OK on everything
Restart your terminal and verify:
adb --version
Part 2: Export and Prepare Your Web App
2.1 Export from your vibe coding tool
In Bolt.new: click the project title > Export > Download. Other tools have similar export options. Unzip the downloaded file:
mkdir C:\Users\YOUR_USERNAME\my-appcd C:\Users\YOUR_USERNAME\my-app# Windows 10 1803+ has tar built in:tar -xf %USERPROFILE%\Downloads\your-project.zip -C .
Or right-click the .zip in File Explorer and select "Extract All...".
2.2 Identify your build output directory
Capacitor needs to know where your built app ends up:
Framework
Build command
Output folder
Vite (React/Vue/Svelte)
npm run build
dist
Create React App
npm run build
build
Angular
ng build
dist\your-app
Next.js (static export)
next build
out
2.3 Make sure your app builds
cd C:\Users\YOUR_USERNAME\my-appnpm installnpm run build
Common issues with vibe-coded exports:
Missing .env variables — create a .env file with the needed API keys
Dependency conflicts — delete node_modules and package-lock.json, then re-run npm install
TypeScript errors — fix the specific file and line the error points to
Note: If your app has a backend (API routes, database), Capacitor wraps the frontend only. Your backend still needs to be hosted separately (Supabase, Railway, etc.) and your app must point to that hosted URL.
Part 3: Add Capacitor to Your Project
3.1 Install Capacitor
cd C:\Users\YOUR_USERNAME\my-appnpm install @capacitor/core @capacitor/cli
3.2 Initialize Capacitor
npx cap init
You'll be prompted for:
App name — the name users see under the icon
App Package ID — a unique reverse-domain identifier like com.yourname.myapp. Permanent — cannot be changed after publishing.
Web asset directory — the build output folder from Part 2 (usually dist or build)
Verify the generated capacitor.config.ts:
import type { CapacitorConfig } from '@capacitor/cli';const config: CapacitorConfig = { appId: 'com.yourname.myapp', appName: 'My App', webDir: 'dist' // Must match your actual build output folder};export default config;
Critical: webDir must point to the folder containing your built index.html. A wrong value produces a blank screen.
3.3 Add the Android platform
npm install @capacitor/androidnpm run buildnpx cap add android
This creates an android\ folder — a complete Android Studio project.
3.4 Sync web code to the Android project
Run this every time you change your web code:
npm run buildnpx cap sync
Part 4: Test Your App
4.1 Open in Android Studio
npx cap open android
The first open downloads Gradle dependencies — this takes several minutes. Do not upgrade Gradle if prompted.
4.2 Run on an emulator
In Android Studio:
Open Device Manager (phone icon with wrench)
Click Create Virtual Device, pick a Pixel device, and download a system image (API 34+)
Select the emulator from the device dropdown and click Run (▶)
Emulator performance on Windows: The Android emulator uses hardware acceleration via Intel HAXM or Windows Hypervisor Platform (WHPX). If it's extremely slow, make sure hardware virtualization is enabled in your BIOS/UEFI (usually "Intel VT-x" or "AMD-V"). You can also enable Windows Hypervisor Platform in Windows Features (Settings > Apps > Optional features > More Windows features).
4.3 Run on a physical device
Enable Developer Options: Settings > About Phone > tap "Build Number" 7 times
Enable USB Debugging: Settings > Developer Options > USB Debugging
Connect via USB and accept the debugging prompt
Select your device in Android Studio and click Run
4.4 Common issues
Blank white screen — webDir is wrong or you forgot npm run build before npx cap sync.
App crashes immediately — check Logcat (View > Tool Windows > Logcat) for errors.
API calls failing — localhost in the emulator refers to the emulator itself. Use 10.0.2.2 to reach your development machine's localhost, or use your deployed backend URL.
Part 5: Prepare for Release
5.1 Set your app icon and splash screen
npm install @capacitor/assets --save-dev
Create an assets\ folder at the project root and add:
icon-only.png — at least 1024×1024 px, square, no transparency
icon-foreground.png — foreground layer for adaptive icons (1024×1024 px)
icon-background.png — background layer for adaptive icons (1024×1024 px)
splash.png — at least 2732×2732 px
splash-dark.png — dark mode splash (same size)
Generate all Android icon and splash variants:
npx capacitor-assets generate
5.2 Update your app version
In android\app\build.gradle:
versionCode 1 // Integer, must increase with every Play Store uploadversionName "1.0" // Human-readable string shown to users
5.3 Configure app permissions
In android\app\src\main\AndroidManifest.xml, inside the <manifest> tag:
<!-- Internet access (included by default in Capacitor, but verify) --><uses-permission android:name="android.permission.INTERNET" /><!-- Add only what your app actually uses: --><!-- <uses-permission android:name="android.permission.CAMERA" /> --><!-- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> --><!-- <uses-permission android:name="android.permission.RECORD_AUDIO" /> -->
If keytool is not recognized: Java's bin directory isn't in your PATH. Fix your JAVA_HOME and PATH (see Part 1.2), or use the full path to keytool.exe. In PowerShell, prefix it with &:
Back up this keystore file and both passwords. Losing it means you can never update your app on Google Play. Store a copy in a password manager and on external storage.
6.2 Configure Gradle signing
Create android\keystore.properties (do NOT commit this to git — add it to .gitignore):
cd C:\Users\YOUR_USERNAME\my-appnpm run buildnpx cap synccd android.\gradlew.bat bundleRelease
Windows difference: On Linux/macOS the command is ./gradlew bundleRelease. On Windows it's .\gradlew.bat bundleRelease. In Command Prompt (no .\ needed): gradlew bundleRelease.
If the build fails — read the error output carefully. Common causes: missing SDK components (fix in SDK Manager), Gradle version mismatch (don't upgrade when prompted), Java version issues (confirm JDK 17 is installed and JAVA_HOME points to it).
Choose Personal or Organization account (Personal is fine for indie developers)
Pay the one-time $25 USD registration fee
Complete identity verification
Wait 24–48 hours for activation
Personal accounts created after November 2023 require a device verification step. Install the Google Play Console mobile app on an Android device, sign in with the same Google account, and follow the verification steps.
Part 8: The Closed Testing Requirement
New personal developer accounts cannot publish directly to production. Google requires:
Uploading your app to a closed test track
Having at least 12 testers opted in
Those testers must remain opted in for 14 consecutive days
Only then can you apply for production access
8.1 Create your app listing
In Google Play Console, click Create app and work through all required sections:
Store listing — app description, at least 2 phone screenshots, 1024×500 feature graphic, 512×512 icon, category, contact details
Content rating — complete the IARC questionnaire honestly
Target audience — if not specifically for children, do not select children as target
Privacy policy — required if your app collects any user data; a simple page on GitHub Pages or Notion works
8.2 Set up closed testing and upload your build
Go to Testing > Closed testing in the left sidebar
Under Testers, create a list with at least 12 Gmail addresses
Click Create new release, accept Play App Signing, and upload your .aab file
Add release notes and click Start rollout
Share the generated opt-in link with your testers
Testers must click the link on an Android device, accept the invitation, and install the app. After 14 days with all testers opted in, you can apply for production access from the app Dashboard.
Part 9: Publish to Production
Once you have production access:
Go to Production > Create new release
Upload your .aab file
Add release notes and select distribution countries
Click Start rollout to production
First-submission review typically takes a few hours to several days. If approved, your app goes live.
Part 10: Updating Your App
# 1. Make your code changes# 2. Rebuildnpm run buildnpx cap sync# 3. Bump versionCode in android\app\build.gradle (must be higher than last upload)# 4. Build the new bundlecd android.\gradlew.bat bundleRelease# 5. Upload the new .aab in Google Play Console# Production > Create new release > upload > rollout
Quick Reference
# === ONE-TIME SETUP ===npm install @capacitor/core @capacitor/clinpx cap initnpm install @capacitor/androidnpx cap add android# === EVERY CODE CHANGE ===npm run buildnpx cap sync# === TESTING ===npx cap open androidnpx cap run android# === RELEASE BUILD ===cd android.\gradlew.bat bundleRelease# Output: android\app\build\outputs\bundle\release\app-release.aab
Troubleshooting
"SDK location not found" — ANDROID_HOME is not set. Follow Part 1.3 Step 4 and restart your terminal. You can also create android\local.properties with:
"JAVA_HOME is not set" or "java is not recognized" — Add JAVA_HOME as a system environment variable pointing to your JDK (e.g., C:\Program Files\Eclipse Adoptium\jdk-17.0.13+11-hotspot) and add %JAVA_HOME%\bin to Path.
Gradle fails with "Could not determine java version" — Multiple Java versions installed. Make sure JAVA_HOME points specifically to JDK 17.
"capacitor.config.ts: webDir does not exist" — Run npm run build first.
App shows blank screen — Verify webDir matches the actual build output folder and that index.html is inside it.
"INSTALL_FAILED_UPDATE_INCOMPATIBLE" — Uninstall the old version from your device before running again.
gradlew.bat not recognized or permission denied — Make sure you're in the android\ directory. In PowerShell, use .\gradlew.bat. In Command Prompt, just gradlew bundleRelease.
keytool not recognized — Java's bin folder is not in your PATH. Fix your PATH or use the full path to keytool.exe as shown in Part 6.1.
Long path errors — Android projects can exceed Windows' default 260-character path limit. Enable long paths in PowerShell (as Admin):
Emulator is extremely slow — Enable hardware virtualization in BIOS/UEFI (Intel VT-x or AMD-V), then enable Windows Hypervisor Platform in Windows Features.
Realistic Expectations
The timeline is longer than you expect. Between the 14-day testing requirement, Google's review process, and debugging, plan for 3–4 weeks from start to live.
Capacitor wraps, it doesn't transform. Your app behaves exactly like it does in a mobile browser. Test in Chrome's mobile emulation mode and fix layout issues before wrapping.
Performance won't match a true native app. Animations may be janky on older phones, background tasks are limited, and push notifications require extra setup.
Google can reject your app. Common reasons: missing privacy policy, misleading store listing, or the app being deemed too simple. Read Google's developer policies before submitting.
Finding 12 testers is harder than it sounds. Start recruiting before you finish building. Developer communities on Discord and Reddit (r/androiddev, r/betatesting) organize tester exchanges.