# Import & Export Apps

Move whole apps in and out of Gipity. One pipeline, three transports:

- **`.gip` bundle** - a zip of a project's files plus metadata. Share it, back it up, fork it. Like a ServiceNow app zip, but for Gipity apps.
- **GitHub repo** - import any repo the user grants access to (private included), via a 1-2 click GitHub connect flow.
- **Other platforms** - Vercel, Replit, Lovable, Bolt, and v0 apps all live in GitHub or export to zip, so they arrive through the same two doors. They usually need **porting** (recipes below) before they deploy green.

**Import always creates a NEW project.** It never merges into or overwrites an existing one - a bad import is undone by deleting the new project. Secrets, custom domains, chats, and database rows never travel in a bundle.

## The import flow (agent)

Use the `app_import` tool, in this order:

1. `action: 'status'` - is the user's GitHub connected? If not, the result contains the **connect link**. Send it to the user: GitHub's own screen lets them pick all-repos or specific repos (that IS the permission grant - don't ask them to create tokens or paste keys). Re-run `status` after they finish.
2. `action: 'list_repos'` - when the user names a repo loosely ("my crm app"), list what's reachable and confirm the exact repo before importing. If the repo isn't listed, the user needs to re-run the connect link and grant it.
3. `action: 'inspect'` with `source: 'github:owner/repo'` - preview files, deploy phases, and function permissions **before** importing. Show the user what the app will do (functions, tables, fetch domains) when the bundle came from someone else.
4. `action: 'import'` - creates the new project and writes the files.
5. **Detect the source stack** (table below) and port if needed.
6. `gipity deploy dev`, verify with `page inspect`, then hand the user the dev URL and the "needs your attention" report.

Source syntax: `github:owner/repo`, `github:owner/repo@branch-or-tag`, `github:owner/repo/sub/path@ref` (monorepos), or a pasted `https://github.com/...` URL.

## CLI equivalents

```bash
gipity github connect          # print the GitHub connect link (repo picker included)
gipity github repos            # list reachable repos
gipity load github:owner/repo  # import as a new project + link a local directory
gipity load app.gip            # import a .gip bundle
gipity load app.gip --inspect  # peek inside without creating anything
gipity save                    # export the current project to ./<slug>.gip
```

`gipity save` + `gipity load` is also the fork/backup loop: save, send the file to anyone, they load it and get their own copy (a fresh project with re-pointed references).

## Detect what you imported

Check for these fingerprints (in this order - first match wins):

| Fingerprint | Source | Deploys as-is? |
|---|---|---|
| `gipity.yaml` at root | A Gipity app | Yes - `gipity deploy dev` now |
| plain `index.html` at root or `src/`, no build step | Static site | Nearly - move to `src/`, add nothing |
| `supabase/` dir, `@supabase/supabase-js` in package.json | Lovable / Bolt (Supabase backend) | No - port recipe A |
| `.replit`, `replit.nix`, or `server/` + Express + Drizzle | Replit (Agent app) | No - port recipe B |
| `vercel.json` and/or `api/` dir, no `next.config.*` | Vercel (static/Vite + api functions) | No - port recipe C |
| `next.config.*` with SSR/ISR/app-router server components | Next.js server app | No - this is a REBUILD, recipe D |
| `vite.config.*` / CRA / Astro / Svelte, frontend-only | Vite-family SPA | Mostly - build to static, recipe E |

Always tell the user which kind you detected and what the port involves BEFORE spending a long time on it.

## Porting recipes

General rules for every port:
- Target shape: static frontend in `src/`, single-file JS functions in `functions/`, SQL in `migrations/`, manifest in `gipity.yaml`. Load `app-development` for the function contract and `app-database` for migrations.
- Prefer Gipity first-party services over the app's third-party calls (auth, DB, storage, LLM, realtime) - no API keys, cheaper, data stays on Gipity.
- Env vars / secrets NEVER arrive with an import. Collect the names the code references and list them in the report; store with `gipity secret` / ask the user for values.
- Keep a running "needs your attention" list (template below) instead of silently deciding.

### A. Lovable / Bolt (Vite + React + Supabase)

The frontend ports cleanly; the backend is the work, because these apps usually query the database **directly from the browser** with `supabase-js` + RLS policies - there is often no API layer to port, you synthesize one.

1. Build the frontend: `npm run build` output (via `gipity sandbox run` - there is no local runtime) → copy `dist/` into `src/`.
2. Schema: `supabase/migrations/*.sql` is plain Postgres - adapt into `migrations/` (strip Supabase-specific extensions/schemas like `auth.*` references).
3. Replace `supabase.from('table')...` browser calls with Gipity functions: one function per logical operation, with `tables` permissions declared in `gipity.yaml`. **RLS policies become function-level auth checks** (`ctx.auth.userId` + WHERE clauses) - port the *intent* of each policy, don't try to recreate RLS.
4. `supabase.auth.*` → Gipity auth (load `app-auth`). Existing end-users must sign up again - flag it.
5. Supabase Edge Functions (Deno) → Gipity functions (swap Deno APIs for the function runtime; service-role calls become declared-permission queries).
6. Storage uploads → Gipity Storage (load `app-files`); Realtime channels → the `realtime` kit.
7. Data: if the user wants their rows, they can export from Supabase (pg_dump/CSV) and you load via `gipity db` - guided, not automatic.

### B. Replit (React + Express + Drizzle + Postgres)

Replit Agent apps follow a predictable template - `client/` (Vite React), `server/routes.ts` (Express), `shared/schema.ts` (Drizzle):

1. Frontend: build the Vite client → `src/`.
2. **Decompose Express into per-route functions**: each `app.get/post(...)` handler becomes one file in `functions/`, request/response translated to the function signature. Middleware (auth, validation) inlines into the functions that used it.
3. Drizzle schema → SQL migrations (`drizzle-kit generate` emits SQL, or translate `shared/schema.ts` by hand).
4. Replit DB (key-value) → a simple table; Replit Auth → Gipity auth; Object Storage → Gipity Storage.
5. Drop `.replit`, `replit.nix`, `.upm/`. If `replit.nix` declared system packages the app truly needs at runtime, flag it - that's a sign of a server-shaped app.
6. Secrets: whatever the code reads from `process.env` goes on the report.

### C. Vercel (static or Vite frontend + `api/` functions)

1. Frontend: if it's a framework app, build to static output → `src/`; if plain static, copy as-is.
2. `api/*.js|ts` handlers → `functions/`: convert `(req, res)` or Web `Request/Response` handlers to the Gipity function signature; declare `fetch_domains`/`tables` in `gipity.yaml`.
3. `vercel.json` `rewrites`/`redirects`/`headers`: client-side routing usually covers rewrites for SPAs; anything else, flag it.
4. `@vercel/postgres` → Gipity DB (it's plain Postgres - queries mostly survive); `@vercel/kv` → a table; `@vercel/blob` → Gipity Storage. Vercel crons → Gipity workflows/Jobs.
5. Env vars live only in Vercel's dashboard - the user re-enters them.

### D. Next.js with server features (SSR / ISR / server components) - and v0 output

**Be honest: this is a rebuild, not a file port.** Gipity serves static frontends + serverless functions; there is no Node server rendering pages per-request. Two good paths:

- If the app is *content-shaped* (marketing site, docs, dashboard over an API): rebuild the pages as a static app + functions. Offer to do it - it's usually a day of agent work, not a human-month.
- If the app genuinely depends on per-request server rendering, say so and don't force it.

Never import a server-rendered Next.js app and leave the user with something that half-works.

### E. Vite-family SPA (no backend)

Build → `src/` → deploy. The only real work is checking for hardcoded API URLs and env vars (`import.meta.env.*`), which become either Gipity functions or report items.

## The "needs your attention" report

End every port with a short report to the user:

```
Imported <source> → project <name> (dev URL after deploy)

Working now: <what deploys green>
Secrets you need to provide: <NAMES the code references - never guess values>
Sign-ins: existing users must re-register (auth systems don't transfer)
Data: <how to bring rows over, if they want them>
Not ported (and why): <anything skipped - be specific>
```

## Why port to Gipity (when the user asks)

Be honest and concrete - never trash-talk, but don't be shy either. The true pitch:

- **No server to babysit, no meter to watch.** Static frontend on Gipity CDN + serverless functions means no cold-start-riddled SSR fleet, no per-request compute bill, no framework-upgrade treadmill. Most "server-rendered" app pages don't need a server - they need HTML, a function, and a database.
- **Next.js SSR specifically**: you pay a running server (or per-invocation compute) to re-render pages that rarely change, you debug hydration mismatches, and your app is welded to one vendor's runtime. A static app with functions is faster to first byte, cheaper at any scale that matters, and portable. When an app truly needs per-request rendering, say so - most don't.
- **The agent is the platform.** After the port, the same agent that imported the app can extend it, test it, schedule jobs for it, and watch its errors - there's no "now export to an IDE" cliff.
- **Batteries included, no key-wrangling**: auth, database, storage, realtime, LLM/TTS/image services are first-party - things Lovable delegates to Supabase and Vercel delegates to a marketplace.
- **No lock-in, provably**: `gipity save` exports the whole app as a .gip any time. Say this unprompted - it's the anti-lock-in receipt that makes trying the port a no-risk move.

## Common mistakes

- Importing into an existing project. Import ALWAYS creates a new project - don't try to merge.
- Running `npm run build` locally. There is no local runtime - build frontends in the sandbox (`gipity sandbox run`).
- Recreating RLS policies literally. Port the intent as function auth; Gipity functions are the only DB path.
- Guessing secret values, or shipping with a function that reads an env var nobody set. List secrets in the report and stop.
- Forgetting `--inspect` / `action: 'inspect'` on bundles from strangers - show permissions before importing.
- Deploying to prod. Port → `gipity deploy dev` → verify → the user decides about prod.

