# Create your first app

`smf create` generates an app in a new directory. In a terminal it asks what it needs to know, and with the answers given as options it asks nothing.

## Answer the questions

Run `smf create` in the directory where the app's own directory should go:

```bash
smf create
```

This is what a run looks like when you keep the start screen `home`, which is selected already, and pick tabs at the bottom, a settings screen, the onboarding, the localization, the theme, get_it, the event bus, the app icon and the splash screen:

```text
👋 Hello! Let's create a Flutter app with Say My Frame.
? App name my_app
? Organization (reverse domain) com.example
? Features: which do you want? home — Start screen with a welcome and the next steps
? Infrastructure: which do you want? none
? Layout: which module provides it? bottom_tabs — Tabs in a bar at the bottom of the app
? Settings screen: which module provides it? settings — Settings screen with the settings of the modules
? Onboarding screen: which module provides it? onboarding — Onboarding on the first launch of the app
? Localization: which module provides it? gen_l10n — Texts in ARB files with gen-l10n of Flutter
? Theme: which module provides it? material_theme — Light and dark Material 3 themes with a palette and a bundled font
? Push messages: which module provides it? None
? Notifications: which module provides it? None
? Dependency injection: which module provides it? get_it — Service locator with get_it
? State management: which module provides it? None
? Events: which module provides it? event_bus — Events between parts of the app with event_bus
? Authentication: which module provides it? None
? REST API: which module provides it? None
? Purchases: which module provides it? None
? Values in .env: which module provides it? None
? Crash reporting: which module provides it? none
? Analytics: which module provides it? none
? App icon: which module provides it? launcher_icons — App icon from assets/branding with flutter_launcher_icons
? Splash screen: which module provides it? native_splash — Light and dark splash screen from assets/branding with flutter_native_splash
? CI: which module provides it? None
✓ Checking the machine (5ms)
Adding flutter_core: the only provider of the app entry role, which every app needs.
Adding go_router: the only provider of the router role, which home requires.
Adding shared_preferences: the only provider of the preferences role, which onboarding requires.
✓ Rendering the app (0.2s)
✓ Getting the packages of the app (1.3s)
? Making the app icon from assets/branding (dart tool/update_app_icon.dart), for launcher_icons. Run it now? Yes
✓ Making the app icon from assets/branding (1.3s)
? Making the splash screen from assets/branding (dart run flutter_native_splash:create), for native_splash. Run it now? Yes
✓ Making the splash screen from assets/branding (1.3s)
✓ Cleaning up the imports (1.8s)
✓ Applying dart fix (0.8s)
✓ Formatting the code (0.2s)
✓ Getting the packages of the app in its directory (1.0s)
Created my_app in /Users/you/projects/my_app.
Run it:
  cd /Users/you/projects/my_app
  flutter run
```

A short note with links to the community follows.

### The questions

| Question | What the answer does |
| --- | --- |
| App name | The default is `my_app`. The name becomes the Dart package name of the app in snake_case, so `My App` becomes `my_app`, and it names the app's directory. |
| Organization | Reverse domain notation, `com.example` by default. It starts the identifiers of the app: `com.example.my_app` on Android and `com.example.my-app` on iOS, where bundle identifiers take no underscores. |
| Features, Infrastructure | These list the modules that provide no role, grouped by their kind. Select any number of them, or none. `home` is selected already, so Enter takes it, and the app starts on it. |
| One question per role | Each lists the modules that provide the role, such as the layout, the onboarding screen or dependency injection. A role that an app has at most one of also offers None, and Enter takes its first module. For crash reporting and analytics you can select several modules, or none. The roles come in an [order](https://doc.saymyframe.com/guides/smf-create.md#the-order-of-the-roles) that goes from what the user of the app sees to what gets the app released. |

A role may ask one more question once the modules are known. With the feature `sign_in`, or another module that brings the authentication, `smf create` asks who may use the app without an account: nobody, everyone, or everyone as an anonymous user. See [Sign-in](https://doc.saymyframe.com/guides/sign-in.md#the-mode).

A role that the modules you picked require offers no None. When only one module provides it, SMF adds that module without asking and tells you why. Here the start screen requires a router, so SMF adds `go_router`. The layout, the settings screen and the onboarding screen require the router too, which is why SMF asks about them first. The onboarding, the theme and the localization require the preferences, which remember what the user chose. Only `shared_preferences` provides them, so SMF adds it without a question here. Push messages require the notifications, so the question of push messages comes before the one of the notifications.

Use the arrow keys to move, the space bar to select in a list that takes several answers, and Enter to confirm. Ctrl-C cancels the run at any question and leaves nothing behind.

### What happens next

After the questions, SMF renders the app in memory and writes it to a temporary directory. There it gets the packages with `flutter pub get`, runs the setup steps of the modules, cleans up the imports, applies `dart fix` and formats the code. Then it moves the app to its directory and gets the packages again, because Flutter writes the path of the app into some files. If `flutter pub get` or a step that the app cannot do without fails, the app stays in the temporary directory, and the error says where. A step that the app can do without, such as the tool that makes the app icon or the configuration of Firebase, is left for later with its command instead, and a failure of `dart fix` or `dart format` is only a warning.

## Pass everything as options

You can give every answer on the command line instead. This command generates the same app without asking anything:

```bash
smf create my_app --org com.example -m home,bottom_tabs,settings,onboarding,gen_l10n,material_theme,get_it,event_bus,launcher_icons,native_splash --no-input
```

- `-m` lists the modules, separated by commas, in the order of the answers above. SMF adds what they need, such as the router for `home`.
- `--org` sets the organization. Without it, the organization is `com.example`.
- `--no-input` turns the questions off. A run that would have to ask stops with an error that names the option to add. Such a run takes only the modules that it was given, so `home` is in the list too.

A run without a terminal, as in a script or in CI, asks nothing either. See the [`smf create` reference](https://doc.saymyframe.com/guides/smf-create.md) for every option.

## Run the app

```bash
cd my_app
flutter run
```

On its first launch, the app shows the [onboarding](https://doc.saymyframe.com/modules/onboarding.md): two pages, with Skip above them and Next below. Skip, or Get started on the last page, ends it, and the app opens on the [start screen](https://doc.saymyframe.com/modules/home.md). That screen greets you, names the app and lists three next steps, the first of which is to replace it with a screen of your own. At the bottom are two tabs, Home and Settings. Under Settings, the user chooses the language, English or Ukrainian, and the theme mode, and the app remembers both. The next launch opens on the start screen right away.

`flutter run` builds the flavor `dev`, which installs as My App Dev under the id `com.example.my_app.dev`, next to the other two [flavors](https://doc.saymyframe.com/guides/flavors.md). The icon and the splash screen show the mark of Say My Frame until you [replace them](https://doc.saymyframe.com/guides/app-icon-and-splash.md).

[Video: A walk through a generated app on an iPhone: the three pages of the onboarding, the second of which asks to turn on notifications and is passed with Not now, the start screen with its next steps, the settings screen with the entries Theme, Language and Notifications, a tap on Dark that puts the app into the dark theme, and the sheet of the languages, where a tap on Українська puts the app into Ukrainian](https://doc.saymyframe.com/demo/0.8/app_tour.mp4)

A walk through an app with these screens and with [`local_notifications`](https://doc.saymyframe.com/modules/local-notifications.md), recorded on an iPhone simulator. So its onboarding has three pages, with a page between the two of this app that asks to turn on notifications, and its settings screen has the row Notifications too. Its modules were chosen in another order, so its settings screen has Theme above Language.

An app with no screen to start on, such as an app without a feature, opens on the [fallback start screen](https://doc.saymyframe.com/modules/flutter-core.md#the-fallback-start-screen), which names the app and tells you where its first screen goes. With `gen_l10n`, such an app is in English and in Ukrainian too.

For iOS builds with Xcode 27 and Flutter 3.44, see [troubleshooting](https://doc.saymyframe.com/guides/troubleshooting.md#ios-builds-with-xcode-27).

## Next

- [Take a tour of the app](https://doc.saymyframe.com/getting-started/generated-app.md) to see what each module added.
- To give the app sign-in, add `sign_in` and a state manager to `-m`, as in `-m home,sign_in,bloc,bottom_tabs`, and `google_sign_in` and `apple_sign_in` for sign-in with Google and Apple. Such an app signs in with Firebase Authentication, so it needs a Firebase project before it runs; see [Sign-in](https://doc.saymyframe.com/guides/sign-in.md).
- To give the app notifications, add `local_notifications`, and `firebase_messaging` for push messages; see [Notifications and push messages](https://doc.saymyframe.com/guides/notifications.md).
- To make requests to your API, add `dio`, and fill in its address in `.env`; see [REST API](https://doc.saymyframe.com/guides/rest.md).
- To run the checks on each push and build an APK on request, add `github_actions`; see [CI](https://doc.saymyframe.com/guides/ci.md).
- To sell premium access, add `paywall` and a state manager, as in `-m home,paywall,bloc,bottom_tabs`. The app sells the plans of a RevenueCat project, and a debug build buys in the Test Store of RevenueCat once its API key is in `.env`; see [Purchases](https://doc.saymyframe.com/guides/purchases.md).
