Short answer: how to turn code into an app depends on who will use it and where. If other people need it, the fastest path is almost always a web app: wrap the code in a simple interface, push it to GitHub, and deploy it to a host that gives you a URL. If it has to run offline on someone’s computer, package it as a desktop executable. If it has to live in the App Store or Google Play, build the web version first and wrap it later. This guide walks through all four paths with copyable commands, a pre-deploy check script, and the prompts to hand your AI coding agent.
Last updated: November 3, 2026. The commands below were run on a Linux test machine with a small sample script (plus one PyInstaller build on my own Windows PC), and the real output is shown. Store fees and review rules come from Apple’s App Review Guidelines (updated October 16, 2026), the Apple Developer Program page, and Google’s Play Console Help. I also read recent threads on r/vibecoding, r/learnpython and r/capacitor where people asked this exact question.
First, what “an app” means for your code
People who ask how to turn code into an app usually mean one of four things, and each one is a different job:
| You want… | Build this | Typical tools | Hardest part |
|---|---|---|---|
| Anyone with a link can use it | Web app | Streamlit, Flask/FastAPI, Next.js, Vite + a host | Secrets and a real database |
| A coworker can double-click it | Desktop executable | PyInstaller (Python), Electron or Tauri (JavaScript) | Building once per operating system |
| It installs on a phone home screen | Progressive web app (PWA) | A web app plus a manifest file | Offline behavior, iOS limits |
| It’s listed in the App Store / Google Play | Native wrapper or native app | Capacitor, React Native, Flutter | Store review and testing rules |
My opinion after reading a lot of these threads: most people jump straight to row four because “app” sounds like phone. Then they spend weeks on Xcode, signing certificates and store review before a single stranger has tried the idea. Start with row one. A URL you can send someone today beats an App Store listing you might get next month.
How difficult is it to make an app from code you already have?
Less difficult than it was, but the difficulty has moved. Writing features is now the easy part, because an AI agent can do most of it. The time goes into everything around the code: where it runs, where the data lives, how secrets stay secret, and (for mobile) what Apple and Google require.
A rough way to think about it, based on what builders report in recent r/vibecoding and r/apps threads:
- A script that works for you: you’re already done. Running it for yourself is fine.
- A web app other people can open: an afternoon to a weekend for a simple tool, if you keep it to one page and one job.
- A web app with accounts and saved data: a few weeks. Sign-in, a database and payments each add real work.
- A phone app in the stores: several weeks to a few months for a first one. Several people in those threads said wrapping the code took a day, and getting through store review and testing took weeks.
The pattern in those discussions is consistent: people shipping “an app in a day” are shipping a demo. That’s fine. Just know which one you’re building.
Step 0: Get the code out of the chat and into a project
If your code lives in a ChatGPT, Claude or Gemini conversation, it isn’t an app yet. It’s a set of snippets. Before any of the paths below:
- Make a folder and save every file with the exact name the AI used.
- Ask for the dependency file explicitly (
requirements.txtfor Python,package.jsonfor JavaScript). It’s the file people forget most, and without it no host can install anything. - Run it locally once. If it doesn’t run on your machine, it won’t run on a server.
- Put it in Git and push it to a private GitHub repo. Every host below deploys from GitHub.
Here’s a prompt that does most of step 0 in one go. Paste it into the chat that wrote the code:
List every file this project needs, with the full path and full contents of each.
Include the dependency file (requirements.txt or package.json) with pinned versions,
a .gitignore that excludes .env, node_modules and virtual environments,
and a README with the exact commands to install and run it locally.
Do not leave anything out or say "rest unchanged".
If you already use a coding agent like Codex, Claude Code or Cursor, open the folder in it instead and ask it to do the same thing. It can run the project and fix errors as they show up, which a chat window can’t.
Path 1: Turn code into a web app (the default)
A web app means your code runs on a server and people use it in their browser. Nothing to install, and when you fix a bug everyone gets the fix at once. That last point is why so many replies in the r/learnpython “how do I share my script” threads land on a web app: with desktop copies, people keep running last month’s version.
A Python script becomes a web app in about 15 lines
Here is a deliberately tiny example: a script that totals a CSV of expenses by category.
# csv_summary.py - the "script" stage: works for you, nobody else.
import csv, sys
from collections import defaultdict
def summarize(rows):
totals = defaultdict(float)
for r in rows:
totals[r["category"]] += float(r["amount"])
return dict(sorted(totals.items(), key=lambda kv: -kv[1]))
if __name__ == "__main__":
with open(sys.argv[1], newline="") as f:
for cat, total in summarize(csv.DictReader(f)).items():
print(f"{cat:<12} {total:>10.2f}")
To turn it into a web app, keep the logic and add a thin interface. Streamlit is the quickest option for Python because you write no HTML:
# app.py - the same logic as a web app anyone can open in a browser.
import csv, io
import streamlit as st
from csv_summary import summarize
st.title("Expense summary")
uploaded = st.file_uploader("Upload a CSV with category and amount columns", type="csv")
if uploaded:
rows = csv.DictReader(io.StringIO(uploaded.getvalue().decode("utf-8")))
totals = summarize(rows)
st.table([{"category": k, "total": round(v, 2)} for k, v in totals.items()])
st.download_button("Download summary", "\n".join(f"{k},{v:.2f}" for k, v in totals.items()), "summary.csv")
Notice the split: csv_summary.py still holds the logic, and app.py only handles upload, display and download. Keep that split when you ask an AI to “make it an app”. It stops the agent from rewriting working logic just to add buttons.
Here’s the real run on my Linux test machine (Streamlit 1.66.1, Python 3.13):
$ python csv_summary.py sample.csv
ai 30.00
hosting 25.50
domain 12.00
$ streamlit run app.py --server.headless true --server.port 8599
You can now view your Streamlit app in your browser.
Local URL: http://localhost:8599
$ curl -s http://localhost:8599/_stcore/health
ok
To put it online, push the folder (with requirements.txt listing streamlit) to GitHub and deploy it. Streamlit Community Cloud deploys straight from a GitHub repo for free. Its docs say apps go to sleep after 12 hours without traffic, so the first visitor after a quiet day waits for it to wake up. That’s fine for an internal tool or a demo, but not for something you charge for.
A JavaScript or AI-builder project becomes a web app
If your agent wrote a React, Vite or Next.js project, you already have a web app. You just need a host. Connect the GitHub repo to Vercel or Netlify and it builds on every push. I compared the two in Vercel vs Netlify. If the code came out of Lovable, Bolt or Replit, those tools can publish for you; Replit vs Lovable covers when to export the code instead.

Run this check before your first deploy
The same handful of problems breaks almost every AI-written project the first time it leaves your laptop: no dependency file, a hardcoded localhost URL, an API key pasted into the frontend, a .env file headed for GitHub, and browser localStorage pretending to be a database. I wrote a small script that flags all five. It prints file names only, never secret values:
#!/usr/bin/env bash
# ship-check.sh - quick pre-deploy sanity check for an AI-generated project.
# Usage: bash ship-check.sh [project-dir] (prints file names only, never secret values)
dir="${1:-.}"; cd "$dir" || exit 1
fail=0; ok(){ echo "OK $1"; }; bad(){ echo "FIX $1"; fail=1; }
skip='--exclude-dir=node_modules --exclude-dir=.venv --exclude-dir=.git --exclude-dir=dist --exclude-dir=build'
# 1. Dependency file
if [ -f package.json ] || [ -f requirements.txt ] || [ -f pyproject.toml ]; then ok "dependency file found"
else bad "no package.json / requirements.txt / pyproject.toml: the host won't know what to install"; fi
# 2. Start or build command
if [ -f package.json ] && grep -qE '"(build|start)"' package.json; then ok "package.json has a build/start script"
elif [ -f Procfile ] || [ -f Dockerfile ] || ls *.py >/dev/null 2>&1; then ok "start entry point present (check your host's start command)"
else bad "no obvious way to start the app"; fi
# 3. Hardcoded localhost
hits=$(grep -rlE 'https?://(localhost|127\.0\.0\.1)' $skip --include='*.js' --include='*.ts' --include='*.tsx' --include='*.jsx' --include='*.py' --include='*.html' . 2>/dev/null)
[ -z "$hits" ] && ok "no hardcoded localhost URLs" || bad "hardcoded localhost in: $(echo $hits)"
# 4. Secrets that look real, in source files
hits=$(grep -rlE '(sk-[A-Za-z0-9_-]{20,}|sk_live_[A-Za-z0-9]{10,}|AKIA[0-9A-Z]{16})' $skip . 2>/dev/null | grep -v '^./.env')
[ -z "$hits" ] && ok "no API-key-looking strings in source" || bad "possible secret in: $(echo $hits) (move it to an environment variable)"
# 5. .env kept out of git
if [ -f .env ]; then
if [ -f .gitignore ] && grep -qE '^\.env' .gitignore; then ok ".env is gitignored"; else bad ".env exists but is not in .gitignore"; fi
else ok "no .env file in the project root"; fi
# 6. Browser-only storage used as a database
hits=$(grep -rlE 'localStorage\.setItem' $skip --include='*.js' --include='*.ts' --include='*.tsx' --include='*.jsx' . 2>/dev/null)
[ -z "$hits" ] && ok "no localStorage writes" || echo "CHECK localStorage used in: $(echo $hits) (fine for settings, not for shared data)"
[ $fail -eq 0 ] && echo "Ready for a first deploy." || echo "Fix the FIX lines before you deploy."
exit $fail
On Windows, run it from Git Bash. Here is the output against a fake “ChatGPT-style” project I set up with every mistake on purpose (the key is fake), then again after fixing them:
$ bash ship-check.sh /tmp/demo
OK dependency file found
FIX no obvious way to start the app
FIX hardcoded localhost in: ./src/app.js
FIX possible secret in: ./src/app.js (move it to an environment variable)
FIX .env exists but is not in .gitignore
CHECK localStorage used in: ./src/app.js (fine for settings, not for shared data)
Fix the FIX lines before you deploy.
# after fixes
$ bash ship-check.sh /tmp/demo
OK dependency file found
OK package.json has a build/start script
OK no hardcoded localhost URLs
OK no API-key-looking strings in source
OK .env is gitignored
OK no localStorage writes
Ready for a first deploy.
It’s a quick filter, not a security audit. Before real users or payments, go through the vibe-coded app security checklist, and if you need shared data, pick a real database (Supabase vs Firebase is a good starting point).
Path 2: Turn code into a desktop app (an .exe or .app)
Choose this when the tool must work offline, touch local files, or run somewhere you can’t host a server. For Python, PyInstaller bundles your script and a Python interpreter into one file, so the other person doesn’t need Python installed.
pip install pyinstaller
# macOS / Linux
pyinstaller --onefile --name csv-summary csv_summary.py
./dist/csv-summary sample.csv
# Windows (PowerShell): call it through Python so PATH doesn't matter
python -m PyInstaller --onefile --name csv-summary csv_summary.py
.\dist\csv-summary.exe sample.csv
Two things I hit or confirmed while doing this:
1. You build once per operating system. PyInstaller’s own docs say it is not a cross-compiler: to make a Windows app you run it on Windows, and to make a Linux app you run it on Linux. My Linux build produced a 12 MB Linux binary, which is useless to a coworker on Windows. If you’re on Windows, run the Windows command there and you get dist\csv-summary.exe.
2. Some Python installs can’t be bundled. My first attempt on a Linux test machine failed with this real error:
ERROR: Python shared library ('libpython3.13.so.1.0') was not found!
The system Python on that Debian machine ships without the shared library PyInstaller needs, and the package manager was unavailable. A Python installed by uv worked first try:
$ uv venv --python 3.12 .venv-pyi && . .venv-pyi/bin/activate && uv pip install pyinstaller
$ pyinstaller --onefile --name csv-summary csv_summary.py
Building EXE from EXE-00.toc completed successfully.
$ ls -lh dist/
12M csv-summary
$ ./dist/csv-summary sample.csv
ai 30.00
hosting 25.50
domain 12.00
When I built it on Windows: “pyinstaller is not recognized”
On my Windows machine (Python 3.14, with pip installing packages into my user folder), the plain pyinstaller command failed in PowerShell. My PowerShell showed the message in Chinese; the English version is:
pyinstaller : The term 'pyinstaller' is not recognized as the name of a cmdlet, function, script file, or operable program.
+ FullyQualifiedErrorId : CommandNotFoundException
pip had put pyinstaller.exe in the user Scripts folder (under AppData\Roaming\Python\Python314), and that folder isn’t on PATH. You can add it to PATH, but the quicker fix is to run PyInstaller as a Python module. The module name is case-sensitive: PyInstaller, not pyinstaller. This is the command I ran on a small test script:
python -m PyInstaller --onefile --name csv-hello .\hello.py
The build took about 13 seconds and ended with “Build complete!” and the path to the dist folder:

Check dist before you send anything. It should hold one .exe:

A 9 to 12 MB file for a tiny script is normal (12 MB for my Linux build, about 9.3 MB for the Windows exe), since it carries Python inside it. A command-line tool also isn’t friendly for non-technical people, so if that’s who it’s for, ask your agent to add a small window first:
Add a minimal desktop GUI to csv_summary.py using tkinter (standard library only):
a "Choose CSV" button, a results table, and a "Save summary" button.
Keep summarize() unchanged and in its own module. Then give me the exact
PyInstaller command for Windows with --windowed so no console window appears.
For JavaScript projects, Electron and Tauri play the same role: they wrap a web frontend in a desktop window. Expect unsigned executables to trigger warnings on Windows and macOS. Code signing is its own small project, so for a handful of coworkers it’s often simpler to just tell them about the warning.
Path 3: Make it installable on a phone, without the stores
A progressive web app is a normal web app that phones and desktops can “install” to the home screen. No store, no review, no fee. MDN’s guide on making PWAs installable lists the basics: serve it over HTTPS and link a web app manifest with a name, a start URL, a display mode such as standalone, and icons (Chromium wants 192px and 512px). On iPhone, people install it from Safari’s Share menu with “Add to Home Screen.”
{
"name": "Expense Summary",
"short_name": "Expenses",
"start_url": "/",
"display": "standalone",
"background_color": "#0f172a",
"theme_color": "#0f172a",
"icons": [
{ "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" }
]
}
Save it as manifest.json in your public folder and add <link rel="manifest" href="/manifest.json"> to the page head. For a lot of solo-founder tools, this is the whole “mobile app” you need until people actually ask for a store listing.
Path 4: Put it in the App Store or Google Play
If you do need the stores, the usual shortcut for an existing web app is Capacitor. Its docs list three requirements: a package.json, a folder of built web assets (like dist), and an index.html at the root of that folder. Then:
npm i @capacitor/core
npm i -D @capacitor/cli
npx cap init
npm i @capacitor/android @capacitor/ios
npx cap add android
npx cap add ios
npm run build && npx cap sync
npx cap open android # or: npx cap open ios (needs a Mac with Xcode)
That part really is quick. The rest is where the time goes:
- Fees. The Apple Developer Program costs $99 per year. Google Play charges a one-time $25 registration fee.
- Apple’s minimum functionality rule. Guideline 4.2 says an app should offer features, content and UI that “elevate it beyond a repackaged website.” A full-screen view of your website is the case that gets rejected. Builders who got approved in the r/capacitor threads added things like push notifications, offline data, camera or location, and native-feeling navigation.
- Google’s testing rule for new accounts. Personal Play Console accounts created after November 13, 2023 must run a closed test with at least 12 testers opted in for 14 continuous days before they can apply for production access. Start recruiting testers early. One builder in r/apps said this was the step to start first.
- Store payment rules. If you sell digital features inside the app, read the stores’ in-app purchase rules before you design billing. One r/capacitor commenter said Apple’s pushback for them was about billing being reachable in the app, not the wrapper.
Here’s a prompt that keeps your agent honest about all of that before it writes code:
I have a working web app in this repo (built output in dist/). Plan, but do not
implement yet, how to ship it to the App Store and Google Play with Capacitor.
Include: which native features to add so it isn't "a repackaged website" under
Apple guideline 4.2, safe-area and navigation changes, how sign-in and account
deletion will work, how payments will comply with store rules, and a checklist
for Google Play's closed test (12 testers, 14 days). List risks and open questions.
The workflow I’d follow with an AI coding agent
Putting it together, this is the order I’d use for any “I have code, now make it an app” project:
- Decide the path with the table at the top. Default to a web app.
- Step 0: get every file into a folder, a dependency file, Git, and a private GitHub repo.
- Ask the agent for the thin interface only (“keep the logic module unchanged”). Run it locally.
- **Run
ship-check.sh** and fix every FIX line. - Deploy to a host that builds from GitHub, and set secrets as environment variables in the host’s dashboard.
- Send the URL to three real people before you add accounts, payments or a phone wrapper.
- Only then pick Path 2, 3 or 4 if those people actually need it.
If you’re starting from zero rather than from existing code, Claude Code for non-developers walks through building a first web app over a weekend, and What is vibe coding? covers the workflow and its risks. For what the hosting and tools cost each month, see the real monthly cost of an AI indie dev stack.
FAQ
Can I turn Python code into an app?
Yes. For other people to use it in a browser, wrap it with Streamlit, Flask or FastAPI and deploy it. For a downloadable program, package it with PyInstaller on each operating system you need. Python isn’t a good fit for native phone apps; for those, build a web frontend and wrap it, or use a mobile framework.
Can I turn code from ChatGPT into an app without knowing how to code?
You can get a simple web app live, yes. Save the files into a project, ask for the dependency file and run instructions, push to GitHub, and deploy. Where non-coders get stuck is secrets, databases and sign-in, so read the security checklist before anyone puts real data in it.
How much does it cost to turn code into an app?
A simple web app can run on free hosting tiers. A store listing costs $99 per year for Apple and a one-time $25 for Google Play, before any paid tools. Your AI subscription is usually the biggest monthly cost.
Do I need a Mac to make an iPhone app?
To build and submit an iOS app yourself with Capacitor’s normal workflow, you open the project in Xcode, which runs on macOS. A PWA needs no Mac at all, which is one more reason to start there.
What’s the fastest way to share my code as an app with one person?
Deploy it as a web app and send the link. If it must run on their machine, build an executable on their operating system and send that.