Skip to main content

From Idea to App — Practical Techniques


Introduction

Modaal is an AI system for building native iOS apps. You describe an idea or a task, and the AI agent generates code, builds the project, analyzes errors, and iterates with you. The quality of the result depends directly on how you phrase your request and whether you ask for a plan first. There’s a single control for that — the Plan toggle in the composer:
  • Plan off (the default) — the agent works directly: it writes code, builds the project, debugs, fixes, and iterates with you.
  • Plan on — the agent produces a structured implementation plan (a feature spec) without writing code. On a brand-new project, its first prompt runs Refine: it turns your idea into a PRD and scaffolds the project.
Both share the same project context, constitution, knowledge base, and tooling — toggle Plan on or off at any point.

The Plan toggle

You control planning with the Plan button next to the composer. Leave it off for most work; turn it on when you want a thorough plan before any code is written.
Composer with the Plan toggle off

Plan off (default): the agent executes tasks directly — best for simple tasks and fast iteration.

Composer with the Plan toggle on

Plan on: describe your feature and get a structured implementation plan — for deep research, complex tasks, and feature planning.

The two produce different deliverables. With Plan on, the deliverable is the plan itself — a feature spec at specs/<feature>/spec.md — and no code is written yet. With Plan off, the deliverable is working code: the agent implements your request directly. If a spec already exists from a Plan-on session, the agent reads it and builds from it.

How it fits together

Starting a brand-new project? Turn Plan on. On your very first prompt it automatically runs Refine — it captures your idea into a PRD, confirms key decisions (like architecture), scaffolds the project, and writes the first feature spec. (You don’t pick Refine separately; with Plan on, the agent detects the project has no code yet and adapts.) Already have a project? Two typical workflows: Structured: Plan on → Plan off → repeat
Use Plan on to research the codebase and produce a detailed feature spec, then turn Plan off to implement it. Repeat for each feature. Exploratory: keep Plan off
Keep Plan off for continuous building and iteration, turning Plan on when a feature is complex enough to warrant a thorough spec first. The agent picks up all context automatically when you toggle — active feature, constitution, knowledge base, attached files.

With Plan on — Planning

What it does

With Plan on, the agent produces a thorough written plan before any code is written. It:
  • Does not edit, create, or modify any source code
  • Reads any file in the codebase for research
  • Produces a single output: spec.md inside the feature directory
  • Can continue or update an existing feature spec
Planning has two flavors, and the agent auto-detects which applies — you don’t pick:
  • Brand-new project (no code yet) → the Refine flow (below)
  • Existing project → researches your codebase and writes a feature spec referencing real files and patterns to reuse

Refine: the first prompt on a new project

When you start from scratch with Plan on, your first prompt is the Refine step. You come in with an idea — anything from a single sentence to a multi-page description with Figma links — and the agent turns it into a structured project. Refine has two phases:
  • Phase A — Understand the idea → confirm key decisions (architecture, platforms) → write the PRD → scaffold the project
  • Phase B — select the first feature from the PRD → create the feature directory → write its spec.md
Phase A involves direct interaction: the agent asks you to confirm irreversible decisions like architecture choice (MVVM vs RIBs) before proceeding. What the agent does:
  1. Reads your description (text, images, Figma links — whatever you provide)
  2. Researches the knowledge base for architecture guidance and platform patterns
  3. Confirms key decisions with you (architecture, platforms, scope)
  4. Writes a structured PRD to PRD.md
  5. Scaffolds the project (creates the Xcode project structure)
  6. Plans the first implementable feature and writes spec.md
After Refine completes, turn Plan off to start implementing the first feature. Prompt examples (new project): A brief idea:
A guitar tuner app. It listens to the microphone, detects the pitch, and shows whether the string is in tune.
The agent expands this into a PRD: the main tuner screen, tuning selection (standard, drop-D, open-G), visual feedback (needle + color), session history (as a provisional suggestion). It notes that microphone access and audio analysis are core, while cloud sync is deferred. Then it scaffolds the project and writes a feature spec for the first iteration. A detailed description:
I’m building a local services marketplace. Here’s what I need: User side: Browse services by category, view provider profiles with ratings, book appointments with date/time picker, in-app chat with provider, pay via Stripe, rate after service. Provider side: Create/edit profile, manage availability calendar, accept/reject bookings, view earnings dashboard. Target: iOS 18+, iPhone only. Need to support Ukrainian and English.
Here the agent preserves everything as-is, adds structure (user flows, acceptance criteria, technical considerations), and doesn’t invent extra features. Figma-based:
Here’s my Figma design: [link]. Build this app exactly as designed. The first tab is a feed, the second is search, the third is profile.
The agent uses Figma MCP to pull design context and screenshots, then generates a PRD based on the UI structure. Just an attachment: You can attach a PRD, design doc, or screenshot with no text at all. The agent reads the attachment and works from its content.

Planning on an existing project

For an existing app, Plan on makes the agent research the codebase thoroughly, understand existing patterns, and produce a detailed feature spec — without writing any code. How it works:
  1. Parse User Input — reads your feature description and checks for existing feature context
  2. Determine Feature Context — decides whether to continue an existing feature or create a new one:
    • If the request refines/extends the current feature → updates the existing spec
    • If it describes a clearly different feature → creates a new feature directory
    • If ambiguous → asks you to choose
  3. Research the Codebase — reads source files, identifies patterns, finds reusable code, checks the knowledge base
  4. Write the Spec — creates or updates spec.md with: Overview, User Scenarios, Technical Approach (Architecture, Key Design Decisions, Existing Code to Reuse), Implementation Steps (phased), Files to Create/Modify, Risks & Open Questions, Testing Strategy
  5. Report Completion — summarizes findings and flags open questions
Prompt examples (existing project): New feature for an existing app:
Add push notification support. Users should be able to opt in/out per category (promotions, reminders, social). Store preferences locally and sync with the backend. Show an onboarding prompt on first launch.
The agent explores the existing codebase, understands the current architecture and patterns, and produces a detailed spec referencing actual files and functions to reuse. Updating an existing feature plan:
The notification spec needs to also handle silent push for background data sync. Add a section covering the background modes capability and how it integrates with the existing sync service.
The agent reads the existing spec.md, incorporates the new requirement, and overwrites with the revised version — preserving sections that are still valid. After the plan is ready, turn Plan off to implement.

With Plan off — building directly

This is the default. The agent executes your request directly — it writes code, builds the project, and iterates with you. Use it for anything that produces code: continuous feature-building, fast prototyping, and short, specific one-off tasks. You and the agent co-create: there’s an idea, there’s momentum, there’s a result. With Plan off, the agent:
  • Generates code, builds the project, and iterates with you
  • Verifies its work (runs the project after changing Swift sources)
  • Suggests alternatives and improvements
  • Can ask you clarifying questions via structured prompts
  • Commits after completing a logical unit of work (asking you first)
If a feature was already planned with Plan on, the agent reads that spec.md for context and implements from it. On its own, Plan off doesn’t write a spec — it goes straight to the code. Working directly isn’t “sloppy.” The agent still follows the project’s architectural rules (RIBs or MVVM), uses semantic design tokens, and structures modules correctly. It just doesn’t write a formal plan before it starts.

How it works

Plan off handles two kinds of request, and the agent picks the right shape per turn:
  • Execute — an imperative request (“build the project”, “fix the crash in ProfileViewModel.swift:42”, “extract this into a helper”). The agent does the work, verifies it (runs the project if Swift sources changed), and reports what changed with file/line citations.
  • Answer — a question (“why is the build failing?”, “what does this function do?”, “where is the device list populated?”). The agent reads the relevant files and answers directly, with citations — it doesn’t start editing code just to answer.
It does what was asked and stops — no unrelated cleanups, no speculative next steps. When a change adds up to a logical unit of work, it asks whether to commit. If a feature was already planned with Plan on, the agent reads that spec.md and implements from it — you get the best of both worlds: thorough planning followed by fast execution.

When to use it

  • You’re validating an idea and want to see results fast
  • You want a clickable prototype quickly
  • Requirements aren’t fully clear yet — you want to iterate
  • You’re implementing a feature that was already planned with Plan on
  • You need a one-off action: a build, a debug session, a specific fix, a refactor
Want a quick clickable prototype? There’s no separate “prototype” mode — just say so. Describe what you want with Plan off and iterate, or turn Plan on for a prototype-focused plan first (UI + realistic mock data, integrations deferred), then build it.

Prompt Examples

Starting from scratch:
I want to build a habit tracker. The main screen shows today’s habits as a checklist. Tapping a habit marks it done with a satisfying animation. There’s a stats screen showing streaks.
The agent starts with the main screen, then adds navigation and the statistics screen. After each step — build, verify, next step. Implementing a planned feature:
Let’s implement this. Start with the notification preferences screen.
The agent reads the spec from your Plan-on session, picks up the first implementation step, and starts building. Iterating on what exists:
The habit list looks too plain. Let’s add a card-based layout — each habit is a rounded card with the habit icon on the left, name in the center, and a circular progress indicator on the right.
The agent understands the context (which view to change), updates the layout, builds, and shows the result. Changing direction:
Actually, let’s pivot. Instead of a checklist, make it a ring-based UI like Apple’s Activity rings. Each habit is a ring, and filling it gives visual feedback.
The agent handles pivots smoothly — generates the new UI and preserves what didn’t change (models, services). Technical request:
Add CloudKit sync. When a habit is completed on one device, it should appear on other devices within a few seconds. Use CKSubscription for real-time updates.
You can give precise technical instructions. The agent doesn’t simplify — it follows your level of detail. Build:
Build the project.
or
Build only the watchOS target.
Build debugging:
The build is failing with “Cannot find type ‘ThemeProviding’ in scope” in TunerView.swift. Fix it.
Give the agent the full error. It analyzes imports, module dependencies, and suggests a fix. Runtime debugging:
The app crashes on launch. The crash log shows EXC_BAD_ACCESS in SceneDelegate.swift line 14.
The agent checks crash context, runtime logs, and suggests a fix. Precise edit:
In MainView.swift, change the navigation title from “Home” to use the localized string .mainScreenTitle instead.
Refactoring:
Extract the booking flow (BookingDateView, BookingConfirmView, BookingPaymentView) into a separate SPM module called BookingFeature under Libraries/.

Feature Artifacts

Turning Plan on produces a written artifact — a feature spec — that Plan off then implements:
What the spec contains depends on how you planned it: Plan off doesn’t create a spec of its own — it builds directly. But when a spec from a Plan-on session exists, Plan off reads it and implements from it. That’s the structured workflow: plan with Plan on, build with Plan off, against the same feature directory.

Case Studies

Case 1. “Build Me an App” — From One Sentence to a Prototype

Situation: You have an idea and want to see results as fast as possible. No specs, no requirements — just a sentence. Approach: Plan on (Refine) → Plan off Step 1 (Plan on / Refine):
A meal planning app. You pick recipes for the week, and it generates a shopping list.
The agent generates a PRD: weekly planner screen (calendar grid), recipe catalog (with mock data), auto-generated shopping list grouped by category. Immediately marks as deferred: backend, auth, sharing. Then scaffolds the project and writes a feature spec for the first iteration. Step 2 (Plan off):
Let’s build this. Start with the weekly planner screen — a horizontal scroll of 7 day cards. Tapping a day opens a sheet to add recipes.
Then you iterate:
The day cards are too small on iPhone SE. Make them fill the width and stack vertically instead — a scrollable list of 7 rows.
Add a “Generate Shopping List” button at the bottom of the planner. It should aggregate all ingredients from selected recipes, merge duplicates (2 onions + 1 onion = 3 onions), and group by supermarket aisle.
The shopping list looks good but needs a “check off” feature — tapping an item strikes it through.
From one sentence to a working prototype — a few hours.

Case 2. Complex UI from Figma

Situation: A designer created a detailed mockup in Figma. You need to translate it to code pixel-perfect. Multiple screens, custom components, animations. Approach: Plan off (with Figma MCP)
Here’s the Figma design for the onboarding flow: https://figma.com/design/abc123/Onboarding?node-id=1-2 Build all 4 onboarding screens exactly as designed. Each screen has a full-bleed illustration, title, subtitle, and a “Continue” button. The last screen has “Get Started” instead. Add a page indicator at the bottom. Swipe gesture between screens.
The agent pulls design context via Figma MCP (colors, fonts, spacing, layout), generates SwiftUI views with the closest matching semantic tokens, and builds the project. Iteration:
The illustration on screen 2 is clipped at the bottom on smaller devices. Make it aspect-fit instead of aspect-fill, and add 16pt bottom padding before the title.
Add a subtle parallax effect to the illustrations — as the user swipes, the illustration on the next screen should slide in slightly faster than the text.

Case 3. Adding a Feature to an Existing App

Situation: You have a working app and want to add a complex feature. You want the agent to understand the existing code before proposing changes. Approach: Plan on → Plan off Step 1 (Plan on):
Add push notification support. Users should be able to opt in/out per category (promotions, reminders, social). Store preferences locally and sync with the backend. Show an onboarding prompt on first launch.
The agent researches the codebase, identifies the existing architecture and patterns, and produces a detailed spec.md referencing actual files, functions, and modules to reuse. Step 2 (Plan off):
Let’s implement this. Start with the notification preferences screen.
The agent reads the spec it just wrote, picks up the first implementation step, and starts building.

Case 4. Technical Feature: Camera + CoreML

Situation: You need to add object detection via the camera using CoreML. This is a UIKit-heavy feature (AVCaptureSession) that integrates into a SwiftUI wrapper. Approach: Plan off, with technical detail
Add a camera scanner feature to the app. Requirements:
  1. Use AVCaptureSession with the back camera, preview in a full-screen layer
  2. Run a CoreML model (YOLOv8 — I’ll add the .mlmodel file later, use a placeholder for now) on every nth frame
  3. Overlay bounding boxes on detected objects with labels and confidence scores
  4. In RIBs: create a ScannerRIB under Main. The interactor manages the capture session lifecycle. The view is a UIViewController with AVCaptureVideoPreviewLayer, not a SwiftUI view.
  5. Add a “Scan” button on the main screen that attaches the ScannerRIB.
Notice: the prompt tells the agent which architecture to use (RIBs), which system frameworks (AVFoundation, CoreML, Vision), and where to place the code. The more technical detail you give, the more precise the result. Iteration:
The bounding box overlay flickers. The issue is likely that we’re updating UI on a background thread. Dispatch the overlay updates to the main queue. Also, add a confidence threshold — only show boxes with confidence > 0.7.

Case 5. “Fix My Build” — A Debug Session

Situation: After a refactoring, the project stopped building. Lots of errors, and you don’t want to dig through them yourself. Approach: Plan off (build + debug) Step 1:
Build the project.
The agent runs the build, gets the error log, analyzes it. Step 2 (the agent responds with analysis, you provide context):
Fix all the build errors. The refactoring was moving SettingsInteractor from the Main module to a new SettingsFeature module — some imports and dependency wiring are probably broken.
Context about what you refactored helps the agent understand the root cause instead of just patching symptoms. Step 3 (if there are still errors after the fix):
Build again. If there are still errors, fix them too.
An iterative build-fix cycle is a normal pattern. The agent keeps context between iterations.

Case 6. Prototype Evolution: From Quick Builds to Structure

Situation: You started with Plan off, built a prototype, and it grew to 12 screens. Now you want to add a complex feature (subscription with paywall, trial period, purchase restoration) and feel you need more structure. Approach: Plan on → Plan off (or a detailed Plan-off prompt) You can turn Plan on to get a thorough spec first, or give a spec-level prompt directly with Plan off:
Add a subscription system with these requirements:
  1. Paywall screen: Shown when user tries to access premium features. Two plans: Monthly (4.99)andAnnual(4.99) and Annual (39.99). Highlight annual as “Best Value”. Show feature comparison table.
  2. Purchase flow: Use StoreKit 2. Handle: successful purchase, cancelled, failed, pending (Ask to Buy). Show appropriate UI for each state.
  3. Trial: 7-day free trial for annual plan. Show trial badge on paywall. When trial ends, auto-convert to paid (standard StoreKit behavior).
  4. Restore: “Restore Purchases” button on paywall and in Settings. Verify receipt server-side (mock the server call for now, return success).
  5. Premium gate: Create a PremiumAccessService that checks subscription status. Inject via @Environment. Premium features: unlimited habits (free = 5), custom icons, stats export.
  6. Entitlement check: On launch, verify current entitlements via StoreKit 2 Transaction.currentEntitlements. Cache status locally for offline access.
This is a Plan-off prompt, but with planning-level detail. The agent implements step by step, building after each step.

Prompting Tips

Detail Level Drives the Result

All three are valid prompts. The difference is how much you control the result.

Structure Complex Requests

For features with multiple components, use numbered lists. The agent treats them as checklists — implements item by item and marks them done.

Attach Files for Context

You can attach files (images, documents, PDFs) to any prompt. The agent reads and incorporates them — useful for design references, PRDs from other tools, or API documentation. You can even send just an attachment with no text, and the agent will interpret it.

Give Context When Debugging

Bad:
“The app crashes.”
Good:
“The app crashes when I tap the ‘Save’ button on the edit profile screen. Console shows: ‘Fatal error: Unexpectedly found nil while unwrapping an Optional value’ in ProfileViewModel.swift.”

Reference Specific Files

“In BookingView.swift, the date picker is showing dates in the past. Add a minimumDate constraint set to today.”
Specific file + specific UI element + specific change = the agent doesn’t waste time searching.

Pivoting Is Normal

With Plan off you can change direction at any time. The agent adapts on the spot. You don’t need to start a new project — just say:
“Scrap the tab-based navigation. Let’s switch to a sidebar layout — the sidebar shows categories, and the main area shows the selected category’s content.”

Toggling Plan Is Free

Plan on and Plan off share the same project context. The agent picks up all context automatically — active feature, constitution, knowledge base.

Summary: Plan on or Plan off?

Turn Plan on to plan before building — it bootstraps new projects with Refine and specs out features on existing ones. Leave Plan off (the default) to build, iterate, and handle one-off actions. Toggle freely — the context follows you.
Modaal uses the same knowledge base, constitution, and architectural templates either way. The difference isn’t in code quality — it’s in how much planning happens before the code gets written.