Skip to content

Vocabulary

What feature, screen, view, service, model, route, and recipe each mean in swiftspawn.

A few words come up a lot in the CLI and in generated code. This page defines each one and shows where its files land.

TermWhat it isGenerated at
FeatureA folder grouping related screens and feature-local models.Features/<Name>/
ScreenA destination users navigate to. Always a View + ViewModel pair.Features/<Feature>/<Screen>/
ViewA standalone SwiftUI view, no ViewModel. For components and reusable UI.Features/<Feature>/ or Features/Components/
ServiceA protocol + impl + mock for one backend resource.Services/ (flat)
ModelA Codable struct. Can be feature-local or shared.Features/<Feature>/Models/ or top-level Models/
RouteA case in the Route enum, used for navigation.Infrastructure/Routing/Route.swift
RecipeMultiple commands chained together. For example, crud runs model + service + 3 screens at once.spans the project

Rule of thumb: screens get their own subfolder, views don’t. Screens carry state and need a clear home; views are presentational and live alongside their feature’s other files. Tests always mirror the source layout under Tests/<App>Tests/.

For a feature called Movies:

CommandFiles created
generate feature MoviesFeatures/Movies/, Features/Movies/Models/
generate screen MovieList on MoviesFeatures/Movies/MovieList/MovieListView.swift, Features/Movies/MovieList/MovieListViewModel.swift
generate screen MovieList on Movies --with-testsalso Tests/<App>Tests/Features/Movies/MovieList/MovieListViewModelTests.swift
generate view MoviePoster in MoviesFeatures/Movies/MoviePosterView.swift (no subfolder, no ViewModel)
generate service MovieServices/MovieService.swift, Services/MovieServiceImpl.swift, Services/MockMovieService.swift
generate model Genre --in MoviesFeatures/Movies/Models/Genre.swift
generate model Genre (no --in)Models/Genre.swift
recipe crud Movie --in Moviesmodel + 3-screen folder structure + service trio, all wired together

A feature is a grouping. It does not generate code on its own beyond the folder and Models/ subfolder; it’s a place for screens and shared models to live.

A screen is one destination in the navigation graph. Each screen is a pair: a View and a @MainActor @Observable ViewModel. The CLI creates a subfolder for each screen so the pair stays together.

Most features have a few screens. A Movies feature might own MovieList, MovieDetail, MovieEdit, and MovieSearch.

A screen owns state. Users navigate to it. It has a ViewModel.

A view is presentational. It takes inputs, renders UI, has no ViewModel. Use it for cards, posters, rows, headers, and reusable building blocks.

generate screen creates a subfolder; generate view does not.

A service is behavior. It declares what you can do with a resource (fetch, create, update) and has a real implementation that calls the API plus a mock for tests.

A model is data. It’s a Codable struct with no behavior of its own.

A typical resource has both: a Movie model and a MovieService that returns Movie values.

Every screen needs a route to be reachable. generate screen adds the route automatically. If you want to add a route by hand without creating a screen, use generate route.

Routes live in one enum (Route.swift). Adding a case there and adding a matching arm to RootView’s switch makes the destination navigable.

A recipe is a higher-level command that chains generators. recipe crud Movie is roughly:

  1. generate model Movie
  2. generate service Movie (with five CRUD methods instead of the default stub)
  3. generate screen MovieList, MovieDetail, MovieEdit
  4. Wires routes, DI, and navigation for all of them.

Recipes exist for patterns common enough that running each step manually feels wasteful. There’s only one recipe today (crud); more may follow.