Skip to main content
There are six ways to bring something you already have onto InstaPods. Each one tells you what it will and will not carry across before it runs, in the dashboard, in the CLI, and here. Start at Import in the dashboard sidebar (or /dashboard/import).

The one thing to read first

No import path moves any of this, on any platform: An importer that quietly skipped one of these would be worse than no importer, so every path prints the list and the dashboard shows it beside the deploy button.

1. A GitHub repository

The main path, and the one that keeps you portable: your repository stays the source of truth and InstaPods deploys from it. You can point another host at the same repo at the same time.
  1. Paste the repository URL into the GitHub repo tab and press Check.
  2. We read the repo’s root files and tell you the runtime we detected.
  3. Read the transfer summary, then Continue in the deploy wizard, where you set the branch, environment variables, and the install/build/start commands (all editable).
Private repositories work: the wizard connects GitHub and clones with a scoped token. Comes across: everything committed to the branch, the detected build, the environment variables you enter, and push-to-deploy via a webhook. Doesn’t: anything in .gitignore (which is where the real .env almost always is), and any process beyond the single service a pod runs.

2. From Railway

The GitHub-repo path, plus a paste box for the service’s variables. We never ask for a Railway token and never read anything from Railway.
Railway disclosed on 2026-10-21 that customer environment variables were accessed. Treat every secret that lived there as exposed: this tab leaves secret values blank and asks for a newly issued one. Revoke the old value at its provider.
  1. Open the From Railway tab (or /dashboard/import?tab=railway). Paste the GitHub repository the service builds from (the service’s Settings, under Source) and press Check.
  2. Paste the service’s variables. Any of these works:
    • the Variables tab’s Raw Editor (.env or JSON view)
    • railway variables --kv in the linked project
    • the table railway variable list prints
  3. Every variable is sorted before anything is created:
  4. If the service uses Postgres (DATABASE_URL, PG*, a postgres:// value), you can tick Add PostgreSQL (Build plan and up). The pod gets an empty managed database and its DATABASE_URL is written for you; the Railway DATABASE_URL/PG*/POSTGRES_* values are left out. Moving the data is a pg_dump and restore you run yourself: see Migrate from Railway. The pod runs PostgreSQL 16; check yours with SELECT version();, because a dump from 17 or newer may need edits before it restores.
  5. Continue in the deploy wizard, pick the plan, and deploy. The variables reach the wizard in memory, not in the URL; a page reload drops them and you start again from the tab.
One Railway service per import. A project with several web services needs one import each. Doesn’t come across: secret values (by default), database data, volumes, cron and other services in the project, your domain, and Dockerfile builds (we build from source with a detected runtime), on top of the list above. If the Railway service runs a published Docker image rather than building a repo, use the Deploy the image link at the top of the tab: it opens the Docker image tab below and keeps the Railway tag on the pod. Pods created this way are tagged source: railway.

3. A published Docker image

Already push an image to ghcr.io, Docker Hub, Quay or ECR Public? Run it as it is: open the Docker image tab (or /dashboard/import?tab=image), or instapods deploy --image <image>. The image is checked against its registry before anything is created, so a wrong tag, a private image or an arm64-only build is refused up front. Its command, port, VOLUMEs and ENV are used as Docker would use them; your variables override the image’s. Full details: Deploy a Docker image. Doesn’t come across: private images (registry login), docker-compose setups with several services, HEALTHCHECK, and building from a Dockerfile, on top of the list above. Files the app writes outside its volumes are replaced on every redeploy. Pods created this way are tagged source: image.

4. A live URL (static snapshot)

For a site whose hosting costs more than the site earns — a brochure site, a small WordPress install nobody edits any more. We fetch the pages a visitor can reach from the URL you give us, download the images, CSS, JavaScript and fonts on the same domain, rewrite those references to point at the pod, and serve the result as static files.
  1. Put the homepage URL into the Live URL tab.
  2. Set how many pages to save (25 by default, 1 for a single page, 100 maximum).
  3. Preview — it lists exactly which pages and assets were saved, and how big they are.
  4. Deploy.
Comes across: the HTML your server returns, and same-domain assets. Your URLs stay the same. Links between pages keep the addresses they have today (/about/, not /about/index.html), and <link rel="canonical"> and og:url keep naming your own domain - for a WordPress site they come out exactly as they were. An address without a trailing slash (/about) redirects to /about/. When you import the home page, your robots.txt comes across unchanged and a sitemap of the pages we saved is written at the address it points to (or /sitemap.xml, added to robots.txt, if it names none), so a sitemap you already submitted to Google keeps resolving. Doesn’t:
  • Anything that runs on the server — forms, search, comments, logins, carts, the admin area. There is no PHP and no database behind a snapshot.
  • Your CMS. This copies the output, not the system that produced it; to change content you edit the files or re-run the import.
  • Pages behind a login, and pages nothing links to.
  • Content JavaScript builds after the page loads — we save what the server sends.
  • Assets on other domains. A CDN or third-party script keeps pointing at that domain.
  • Your RSS feed (/feed/). Feed readers stop updating once the old site is down.
  • Addresses ending in .php or carrying a ?query. They are saved under a new .html name - links inside the snapshot follow, but search engines see a new address.
Only snapshot a site you own or have permission to copy. We identify ourselves as InstaPods and respect the site’s robots.txt; a site that disallows us is not copied.
If the crawl hits the page, size or time limit, it stops and says so — and every link to a page it didn’t save keeps pointing at your original site, so nothing 404s while you check the result. The output is a plain folder of files. You can download it from the pod’s backups and host it anywhere.

4b. WordPress to Astro

For a WordPress blog or content site you want to keep editing, without WordPress. Instead of saving pages as HTML, this reads your published posts and pages through the WordPress REST API (on by default on every WordPress site) and builds a small Astro project:
  • every post and page as a Markdown file, with title, date, last update, slug, categories, tags, excerpt and featured image in the frontmatter
  • your images, downloaded from your site and saved at the same /wp-content/uploads/... path
  • the same URLs: each post and page is built at the path it has today, and category and tag archives at theirs. If a path can’t be kept (sites on plain ?p=123 links), the old URL gets a 301 redirect to the new one
  • an RSS feed and a sitemap (the old /feed/ and sitemap addresses redirect to them)
  • a plain, readable layout and a README explaining how to edit, build and deploy
  1. Put your site’s address into the WordPress to Astro tab and click Preview. You see how many posts and pages we can read, one post converted to Markdown, and what won’t come across.
  2. Download Astro project for a zip you can host anywhere, or Deploy on InstaPods to build it on a Launch pod and serve it with your redirects applied.
The --astro flag needs a CLI release newer than v1.16.0. Until one ships, use the WordPress to Astro tab in the dashboard.
Blocks that don’t convert cleanly to Markdown (tables, embeds, galleries, page-builder layouts) are kept as HTML inside the Markdown file, so nothing is dropped. Up to 500 posts are converted by default (newest first, up to 1,000 on request), plus up to 200 pages and 40 MB of images; anything past a limit is listed in the project’s MIGRATION-NOTES.md. Doesn’t come across: comments, drafts and private or password-protected posts (we only read what’s public), forms, search, shops and logins (the result is static), shortcodes from inactive plugins (they show up as text), your theme, menus and widgets, content types other than posts and pages (products, events), and your WordPress settings and users. Your WordPress install and its database are not touched. If the site’s REST API is turned off (some security plugins do this), the converter says so and offers the static snapshot above instead. Pods created this way are tagged source: wordpress-astro.
Running EmDash? Its 1-Click app has its own WordPress import, so you don’t need this converter.

5. A project ZIP

For anything you can download as a folder but haven’t put in a repository - a Google AI Studio export, a Replit download, a v0 or Bolt project, a Vite app you built locally.
  1. Open Create pod and pick Upload ZIP.
  2. Drop your project .zip in. We read the top level, work out the runtime, and name the pod after the file.
  3. If your app calls the Gemini API, expand Does your app call the Gemini API? and paste the key
    • it’s stored as an environment variable on the pod, not baked into your files.
  4. Deploy. The pod is created immediately; dependency install and the production build run on the pod straight afterwards, and the detail page narrates it. You end up on a live HTTPS URL without running npm install yourself.
Zip up the project folder itself - the archive needs a package.json or an index.html at its top level (one wrapper folder is fine). The limit is 128MB; leave node_modules out of it.

Updating an uploaded app

A pod created this way keeps an Update from ZIP card on its detail page. Upload a new .zip and it replaces the app’s files and rebuilds in place - same URL, same plan, same environment variables. There’s no need to redeploy from scratch to publish a change. The new ZIP has to be the same kind of project as the pod: a Node archive can’t be uploaded onto a PHP pod. Create a new pod if the runtime changed.
A ZIP is a snapshot, not a connection - nothing updates when you edit the original project. If you’ll be iterating, push the project to GitHub and deploy it from there instead, so every push redeploys.

Claude Design exports

A Claude Design export is a set of .dc.html artboards and their support files, with no index.html - the canvas names each file after the design. Uploaded as-is anywhere else, / returns a 404 and the site looks broken even though every file arrived. InstaPods recognises the export and writes the missing entry point for you. A single-artboard design is served at / directly; a design with several artboards gets an index page linking to each one by name. This works on every path in: the ZIP upload, a repo deploy, instapods deploy, and the Claude connector.

6. Lovable, Replit, Vercel and friends

None of these expose your project to a URL a server can fetch — the source sits behind an authenticated API — so pasting a project link imports nothing anywhere, including here. Each one does have an export. Open the Another platform tab for the steps, or read them below.

Lovable

Connect the project to a GitHub repository you own (Lovable pushes the whole generated project and keeps pushing as you keep editing), then deploy that repository from the GitHub tab. Your Supabase project does not move — database, auth, storage and edge functions stay in Supabase. That’s usually what you want, but it means your data still lives with a second provider and you still need your own backups of it. Re-enter the Supabase URL and anon key as environment variables or the deployed app can’t reach it.

Replit

Push the Repl to GitHub from the Git pane (or use ⋮ → Download as zip and the wizard’s Upload ZIP step). Copy your Replit Secrets out before you leave — they’re in neither the repository nor the zip, and if you lose access to the Repl you lose the values. Export anything in Replit DB or an attached database for the same reason. Your .replit run config doesn’t transfer either; check the start command we detect matches what the Repl actually ran. This is the “GitHub plus a database you control” setup people recommend for exactly this situation: the repository and the database are both yours, independent of where the app runs.

Vercel

A Vercel project already builds from a Git repository, so there’s nothing to export — copy the repo URL from Settings → Git and deploy the same repository here. Copy Settings → Environment Variables too (Vercel hides existing values, so you may need the originals). A pod runs one long-lived server. A Next.js app runs with next build + next start and its API routes keep working. Standalone serverless and edge functions, Vercel KV/Blob/Postgres/Cron, ISR and edge-caching behaviour, preview deployments and Vercel-managed domains do not have an equivalent — plan for each of those before you switch DNS. Deploying here doesn’t disconnect Vercel. Run both while you check the pod behaves the same.

Netlify, Bolt, v0

Same shape: Netlify and Bolt go through GitHub (Netlify Functions, Forms, Identity and _redirects rules don’t transfer); a single v0 component goes through the Paste tab, and a whole v0 project through GitHub.

From the CLI

Without --dry-run, the CLI prints the same summary and asks you to confirm before creating a pod. Pass -y to skip the prompt in a script; the prompt is skipped automatically when stdin isn’t a terminal.

The WordPress to Astro preview API

The preview behind the WordPress to Astro tab is public, so a page outside the dashboard can use it without a login:
It returns report (site name, found counts of posts, pages, categories, tags and comments, whether permalinks are kept, a sample post as frontmatter plus Markdown, and notes), transfer (what will and won’t come across), limits, and next.continue_url (the dashboard tab with the URL filled in). A site without a readable REST API answers 422 with code rest_api_blocked or no_rest_api and fallback: "url". It downloads no images and makes about a dozen small requests to the site. It is limited to 5 requests a minute and 30 an hour per IP, answers for the same site are cached for 10 minutes, and it only fetches public addresses. Downloading the full project or deploying it needs an account.

The catalog as data

GET /api/imports/sources returns every route in, every guided platform, and the transfer summary for each. Pass ?url= and it also tells you what it would do with that URL. The dashboard, the CLI and this page all read from it, so they can’t disagree about what an import carries.