Skip to content

generate screen

Create a screen (View + ViewModel) and auto-wire its route + navigation.

Creates a paired SwiftUI View and @MainActor @Observable ViewModel, registers a route for it, and wires the navigation switch.

Terminal window
swiftspawn generate screen <Name> [--on <feature>] [--uses <services>] [--with-tests] [--no-route] [--dry-run] [--force] [--quiet] [--verbose]

A screen is a destination users navigate to. It always comes as a pair: a SwiftUI view and a ViewModel. The ViewModel holds the screen’s state (idle / loading / loaded(value) / failed(error) is a common shape) and calls services.

The View suffix is appended automatically: generate screen MovieList produces MovieListView.swift.

--uses <services> tells the generator which services the ViewModel depends on. They become @Injected properties on the ViewModel and are registered in DIContainer.swift between the auto-managed markers.

--no-route skips the route entry, useful for screens that need parameters in the route case (you’ll add the case manually).

--on <feature> (or the bare on Movies form) places the screen under Features/<Feature>/. Without it, the screen lives directly under Features/.

Terminal window
swiftspawn generate screen Home
swiftspawn generate screen MovieList on Movies --uses MovieService
swiftspawn generate screen Profile --uses UserService,SettingsService --with-tests
Features/<Feature>/<Name>/<Name>View.swift
Features/<Feature>/<Name>/<Name>ViewModel.swift

With --with-tests:

Tests/<App>Tests/Features/<Feature>/<Name>/<Name>ViewModelTests.swift
  • Adds case <name> to Route.swift between // MARK: - Cases (auto-generated) markers (unless --no-route).
  • Adds case .<name>: <Name>View() to RootView.swift’s switch route between its markers.
  • Registers each service in --uses in DIContainer.swift between its markers.

If those marker comments don’t exist (legacy projects), the generator prints the snippet to paste in instead of editing.

FlagDescription
--on <feature>Feature folder to nest the screen under. Bare on <feature> also works.
--uses <services>Comma-separated services the ViewModel depends on.
--with-testsAlso emit a ViewModel test file.
--no-routeSkip the Route.swift case (write screen files only).
--dry-runPreview without writing.
--forceOverwrite existing files.
CodeMeaning
2Invalid name.
5Not in a swiftspawn project.
7Route.swift is missing the markers.
12Route case already exists.