App development

Building an app with AI

AI genuinely builds the screens of an app fast today, and those screens are the smallest part of the project; the rest, meaning permissions, money, error states and maintenance, is exactly where model output gets into trouble without a human pass. The right route is to change the order of the work: the specification in plain language first, then code generation, and last a security pass you read yourself.

  • Lesson 8 of 8
  • Intermediate
  • Free, no signup

What share of a real product are the screens?

Lines of code in rgb-freelance, counted on 8 September 202617,963 lines
  1. 3,231
  2. 11,597
  3. 3,135
  • The screens 3,231
  • Behind the screens 11,597
  • The look 3,135

This is a web product of ours rather than a mobile app; read the number as a proportion, not as a law.

Last checked: Facts and tool names in this lesson are re-checked against their sources on this date.

Which part of an app does AI actually build?

An answer that judges models fairly needs a number, and we took ours from one of our own products, because it is the only project we can count to its last line.

Our freelance marketplace plugin, rgb-freelance, has three folders. The screens folder is 3,231 lines, the logic behind the screens is 11,597 lines, and the look, meaning CSS and JavaScript, is 3,135 lines. That is 17,963 lines in total, in which the share of the screens is a little under a fifth. This is not a mobile app and we do not claim it is; it is a web product with users, projects, messages and files, and the shape of its division is the shape you see in a mobile app too.

Now lay the map over the models. That one fifth, the screens, is exactly what models genuinely build well today: forms, lists, empty states, responsive layout. Those middle two thirds, meaning who sees what, where the money is calculated and what happens when the server does not answer, are exactly where generated code usually looks complete and is not.

So the claim "build the app with AI" is neither a lie nor the whole story. More precisely: it makes the fastest part faster. If that is your expectation you get a real gain; if your expectation was a finished product, you discover the difference when you have real users.

A glass phone with screens painted red and green over hidden blue and white machinery that is still empty wireframe

Prototyping speed: what genuinely changed

Before the list of risks, an admission that gets made too rarely: something here genuinely changed, and belittling it is as careless as inflating it.

What used to be the hardest part of starting a product, getting an idea to something you can hold and show somebody, is now possible inside the same meeting. Three screens with fake data, a sign in flow, and a list that scrolls. For an app this matters even more than for the web, because people judge an idea differently on a phone than on paper.

The real value of that speed sits where it is least considered: the cost of throwing work away. When a first version takes half a day, abandoning it is easy too. Teams that spend months on the first version become attached to it in proportion, and let go of a bad idea later. This is the one place where cheap code is genuinely a strategic advantage rather than a saving.

And let us state the boundary plainly, because it gets blurred everywhere: a prototype is not a product. A prototype that works has still seen no real user, no weak network, and nobody deliberately sending wrong input. The distance between those two is the same two thirds from the previous section, and no model shortens it for you. If you have met this argument from the web side, vibe coding, its upside and its dangers takes the same position with more detail on the code.

What to hand a model and what to keep

Keep for yourself

  • The decision of who sees what
  • Anywhere money or stock is calculated
  • Keys, passwords and the real config file
  • The final acceptance of every piece entering the project

Hand to the model

  • Screens, forms, lists and empty states
  • Responsive layout and right to left adaptation
  • A first version that is meant to be thrown away
  • Rereading its own code, in a separate session

The right column does not mean a model cannot; it means a person has to accept or reject what it produces.

Four things that break in an app a model wrote

These four are not written from guesswork; each has a source, and each source is the word of the company selling the tool.

One, the key inside the app. A misunderstanding has to be cleared first: not every key inside an app is a danger. Google own page about Firebase keys writes that they are "public by design" and only identify your project and app, and that if your setup follows the guidelines they do not need to be treated as secrets and it is safe to include them in your code. But that same page carries an explicit exception which is exactly what shows up in generated apps: never include the Gemini Developer API in the allowlist for a publicly accessible key. Meaning a model that drops the AI key next to the Firebase key inside the app has apparently done the same thing and has actually left your account open.

Two, the permission nobody wrote. Generated code usually builds the optimistic path fully and the pessimistic path not at all. The OWASP Mobile Top 10 gives its first place to improper credential usage and rates its prevalence common, its detectability easy and its impact severe; meaning this class of mistake both happens often and is found easily, which is a bad combination. The first question to ask generated code is this: where was it checked that this user is allowed to do this?

Three, code that cannot be maintained next month. Unlike the previous two this risk is not a security one, and for that reason it surfaces later. The problem is not bad code, it is ownerless code: four pieces from four different answers, each with its own pattern, and nobody knowing why any of them is there. It has a simple fix that has nothing to do with AI: before accepting any piece of code, be able to say in one sentence what it does.

Four, licensing. Here too the reality is more moderate than either popular story. The GitHub documentation about Copilot writes that suggestions are checked against public code, and that when a match is found the URLs of the files and the name of the license that applies to that code are logged so you can decide yourself. The same page says these matches typically occur in less than one percent of suggestions, and two more important points: the check runs only for accepted inline suggestions, and code you wrote yourself or a suggestion you altered is not checked at all. So a measuring tool exists, but it is limited, and having it on is a setting rather than a universal default.

Four places model output looks complete and is not

  • A key in the wrong place

    A Firebase key inside the app is fine; an AI API key beside it is not.

  • An unchecked permission

    The optimistic path is complete and nowhere asks whether this user is allowed.

  • Ownerless code

    Several pieces from several answers, with no shared pattern and nobody knowing why.

  • An unclear license

    A tool to check matches against public code exists, but having it on is a setting.

None of these four is unique to AI; hand written code can carry all four. The difference is the speed at which they are produced.

The right order: specification first, then code

All four items above share one root and it is not technical: a model was asked to write code while nobody had made the decisions yet. A model does not decide, it fills the blank, and it fills the blank with the most conventional thing it has seen.

So change the order. Three passes, in this order, and skip none of them.

The first pass is the specification and contains no code: the feature list in plain language, the shape of the data, and who sees what and changes what. If you have read what an app backend is, this is that access table, and this is exactly its place, before generation.

The second pass is generation, and its input is the output of the first pass, not your verbal description. The difference between those two is large: with the feature list and the data shape in front of the model, there is nothing left to guess, and the code it produces can be compared against a document.

The third pass is review, and it should not be done in the same session that generated the code. A separate pass with one specific question: where does this code assume the user is telling the truth. That pass is what appears in the next section as a recipe.

One rule holds across all three and is the simplest of them: no generated code you cannot explain in one sentence enters the project. Not because it must be wrong, but because when it breaks nobody knows where to start. Coding with AI opens the same rule from the programming language side.

Generated code review sheetin a session separate from generation

Before the code enters the project

  • You can say in one sentence what this piece does
  • Wherever data changes, the user permission is checked
  • No key or password is in the code except those that are public
  • Every network request has an error state and a timeout

These mean do not accept it yet

  • An amount, a role or a stock number arrives from the client
  • The code uses a library whose name you have not even heard
  • The review was done by the same model in the same session
  • Nobody knows why this piece is here

The fast path, with AI

The recipe that genuinely makes a difference is not one prompt but three, and their order matters more than their wording. The first produces no code, the second feeds on the output of the first rather than on your words, and the third runs in a separate session so the model looks at its own code with fresh eyes.

  1. Pass one, the specification. Ask the model for the feature list and the data shape and tell it plainly to write no code. The output of this pass is a document you read and correct yourself.
  2. Pass two, generation. Put the corrected document in front of the model verbatim and say build only from this. Where something is not in the document, it must ask rather than build it.
  3. Pass three, the security review, in a fresh session. Hand over the code with no conversation history and ask only the questions of the third recipe. A model that wrote the code will defend it inside the same session.
  4. Use a strong model for passes one and three; a cheaper one is enough for pass two. Our current pick is on the AI section of the site and we deliberately do not write its version number here.

Copy-ready recipe

--- Pass 1: the specification, no code ---
I want to build this app:
{plain description of the app in ordinary language}

Write no code. Give me:
1) The list of screens, and for each screen one sentence on what is done with it.
2) The data shape: tables or collections, fields, and which user each row belongs to.
3) The access table: for every user role, what they see and what they change, each cell as one complete sentence.
4) A list called "questions I should ask" for every gap. Do not fill the gaps.

--- Pass 2: generation, from the document ---
This is the specification document and I have corrected it myself:
{corrected output of pass 1}

Write the app code based on this document alone, with these rules:
- Build nothing that is not in the document. If something is needed and missing, instead of building it leave a comment reading "not in the document, must be asked".
- Read every key and password from configuration and write no real value in the code, not even as a sample.
- Wherever data changes, check the user permission; and where the access table said nothing, do not write the missing check, leave a comment.
- Every network request must have a timeout and an error state, and sort errors by status code.
- At the end, list every external library you used with one sentence of reason for each.

--- Pass 3: the review, in a fresh session ---
This is the code of an app. You did not write it and you have no history about it.
{code}

Answer only these four questions, each with line numbers:
1) Where is it assumed that the user input is correct?
2) Where does data change without the user permission being checked?
3) What is in the code that should be in configuration?
4) Which network request has no timeout or no error state?

If you find no case for a question, write "no case found". Add nothing else and write no corrected code.

Before you trust the output: The output of the third pass is a list of accusations, not a list of facts. Open every item it returns at that line number and look yourself; models both miss cases and invent them. And one thing no pass catches: a model does not know which data is sensitive in your product. Which table holds personal information and which does not is your decision, and it has to be written in that first pass document, otherwise all three passes run on neutral assumptions.

AI in this kind of work

Our position is this: for an app, use the models, and from day one make one person responsible for accepting each piece of code. The three tools below are for three different jobs, and the point that matters most is that the review tool must not be the same session that wrote the code.

Tools that actually help

  • Claude Code Useful for the second and third passes on the project itself, because it sees the files and can give line numbers. It runs on the same Anthropic account, and Iran is not on the supported-countries list.
  • Claude Suited to the specification pass and to reviewing code in a fresh session. Iran is on neither of Anthropic two supported-countries lists. We read that on Anthropic own page rather than measuring it.
  • Gemini Cost effective for the second pass and for repetitive work on the screens. Google own page says the Gemini web app runs in over 230 countries and territories, and Iran is not on that list.

Where it backfires

The main risk of this lesson is not a bug, it is a habit: accepting code nobody read. Three of the four items in the third section are all found by one person reviewing and none of them by an automated test. So the rule we propose is not a coding rule, it is a team rule: every piece of code has one person who accepted it and can explain it, even if they did not write it.
The more specific risk is the key, and its source is Google own page: a Firebase key is public and it is safe to include in code, but that same page says explicitly that the Gemini Developer API must never be in the allowlist of a publicly accessible key. A model blindly executing "put the keys in the app config file" sees those two as the same thing. Every time model output places a key somewhere, ask yourself what that key gives access to and what a stranger holding it could do.

Sources: Firebase: learn about using and managing API keys GitHub Docs: Copilot code referencing OWASP Mobile Top 10: M1 improper credential usage Anthropic: supported countries Google: where Gemini Apps are available

Where this advice stops

We have not published a mobile app that a model wrote end to end, and the number in the first section comes from a web product of ours rather than a mobile app. So read that ratio as a proportion, not as a law that holds on every project. Three more things are deliberately absent: any claim that model written code is identifiable, any percentage of how much of today code models write, and any comparison of tools by output quality. None of the three can be said without measuring, and we have not measured them.

From our own work

The numbers in the first section were counted on our own plugin today and repeat with three commands. Inside the rgb-freelance folder: the PHP files of templates come to 3,231 lines together, the PHP files of includes to 11,597 lines, and the CSS file plus six JavaScript files to 3,135 lines. What that count made clear to us is this: the part everybody talks about in a product demo is under a fifth of the code that was written. And a parallel from this Learn section that reached the same conclusion: the validator of these very lessons, the function rgbl_validate_lesson, carries twenty three rules, and one of them rejects any lesson without a limit block or a first hand proof block. We made those two mandatory from the start for exactly this reason: they are precisely the two things a generated text lacks by default.

Real follow-up questions

Can you build an app with AI without knowing how to program?

A prototype that works, yes, and it has been done many times. A product holding real money and real people data, no, because three of the four risks in this lesson are found only by reading the code. The middle route is to build the prototype yourself and get somebody who reads code to do the review pass.

Does AI generated code have an ownership problem?

The situation is more moderate than either popular story and depends on the tool and its settings. The GitHub documentation says suggestions are checked against public code and that on a match the name of the license is logged so you can decide yourself, and that such matches typically occur in less than one percent of suggestions. For any other tool you have to read its own terms, and we speak for none of them here.

Is it better for models to write the whole app or only pieces?

It depends on what happens afterwards. For something meant to be thrown away, hand over the whole app and do not read it at all; speed is the point. For something meant to last, hand it over piece by piece and accept each piece before the next, because ownerless code is made exactly when five pieces arrive together.