Skip to content
LazyFrog

Make it real: from a chat prototype to a project

How to turn a prototype your AI made in the chat into a real LazyFrog project, with a database, a preview to share and a public address.

The user made something inside their AI app (a Claude artifact, a page ChatGPT previewed from a code block, a ChatGPT Site) and wants it to become a real app: its own address, data that is kept, visitors' accounts, their domain. There is no repository to import: you send its files, and the import lays them out as a project. The prototype stays as it is where it was made.

  1. Its source. In the chat where it was made you have it; otherwise ask the user to paste it, or to carry on in that chat. Don't change it yet: the import reads it as it is.
  2. The import. project import with source: {files: [{path, content}, …]} (or project create with the same source; name optional): paths as the prototype has them (index.html, App.tsx, styles.css), text as it is, an image or a font as encoding: "base64"; up to 100 files and 3 MB together (a binary file up to 1 MB). Bigger: import the page or component and what it needs, then fs_write the rest into the project (the refusal says so). It returns a job: follow it with job get. The import detects what the prototype is and lays it out:
    • one HTML page (its script and style inline or from a CDN): a static site, the page at workspace/site/index.html; a form on it works without a server (see Forms);
    • one React component that keeps nothing: a Vite React app served as a static service (workspace/src/<Name>.tsx, mounted by src/main.tsx and index.html, with allowedHosts set for the preview's address), its imports in package.json;
    • a component that calls the AI app (window.claude, window.openai), keeps data (an artifact's storage, localStorage) or reads another service: a Next.js app (workspace/components/<Name>.tsx shown by app/page.tsx, with lib/db.ts on DATABASE_URL, a first migration and the health route) so the server side has a place. Nothing in the prototype is rewritten except the entry point that mounts it. Dependencies are installed, the preview started and scanned, and the adaptation committed. preview_screenshot: it should look like the prototype before anything changes.
  3. The checklist. The job's result carries checklist, and the same words are the project's app info (project about), so the owner sees them too: what moved (file → place), what must change (each call the import found, with its file and lines, and what to do about it), what LazyFrog adds. Plan from it ("Before you build something new"): the prototype is most of the brief, so save what it does as mustHaves and the checklist's change items as doneWhen items, and ask only what it can't answer (the name, whose data it shows). The checklist lists facts found in the code; it doesn't see everything (a library that keeps state, an image from elsewhere), so read the code once yourself.
  4. What must change, each one a doneWhen item:
    • Kept data (localStorage, sessionStorage, IndexedDB, an artifact's own storage, a Site's D1 database, which is SQLite) lives in one browser or on the AI's platform. Move it to PostgreSQL through DATABASE_URL: a migration (migrations/0002_….sql) with a table for each kind of thing (not one table of keys and values), API routes in the app that read and write it, and the page calling them. SQLite's SQL mostly carries over (? becomes $1, AUTOINCREMENT an identity column). Data the user wants to keep: ask them to export it from the prototype (a JSON or CSV download it can offer), then load it with db_query.
    • Calls to the AI app (window.claude, window.openai) work only inside that app, on the viewer's own account. An AI feature becomes an API route of the app that calls the model through LazyFrog's AI gateway ($LAZYFROG_AI_URL, http://ai.local; see "Email, AI and PDFs for the app") with the owner's provider key and a monthly cap. Say plainly that the owner now pays for it, not each visitor.
    • Connected-app data (the user's mail, calendar, files or a business tool, read through their AI app's connectors): the app can't use those connections. Either the owner connects the source to the app itself (its API, with a key through secrets request), or they export the data and you import it into a table. Tell them which, in plain words.
    • Imports from a CDN (https://esm.sh/…, unpkg, jsdelivr): the package is in package.json already; import it by name and remove the address.
    • Sign-in (a Site's own, or none at all): the app's own accounts, see "Sign-in for the app's users".
    • Files (uploads, a Site's file storage): /data, see "Files and uploads". Images loaded from elsewhere: copy them into the project.
    • Links to the prototype's address: the project's own address. Keep the app info current as you go (project about with the whole record), so the owner's page says what is done.
  5. What LazyFrog adds, in a line or two for the user: a public address anyone can open without an account (https://<project>.lazyfrog.app, and their own domain on a paid plan), forms that reach them, email through their own provider, sign-in for their visitors, a preview to try changes on before they go live, snapshots, and an export whenever they want one.
  6. Publish when they say so (see Publishing).

For your AI: this page as Markdown · llms.txt