This is a modular Swift iOS application with a Vapor backend server, using Tuist for project generation and mise for tool management.
# Weather Alerts App - Development Guidelines ## Project Overview This is a modular Swift iOS application with a Vapor backend server, using Tuist for project generation and mise for tool management. ## Tooling Stack ### Required Tools - **mise** (v2.x+): Tool version manager - manages Tuist and Trunk versions - **Tuist** (v4.104.6): Xcode project generator and dependency manager - **Trunk** (v1.3.4+): Universal linter for code quality - **Xcode**: iOS development IDE - **swift-openapi-generator**: OpenAPI code generation (located in `bin/`) ### Tool Installation ```bash # Install mise first (if not installed) curl https://mise.run | sh # Then install project tools via mise mise install ``` ## Project Structure ``` weather-alerts-app/ ├── Apps/ │ ├── WeatherAlertsApp/ # Main iOS app │ │ ├── Sources/ # App source code │ │ ├── Resources/ # Assets, storyboards, etc. │ │ └── Tests/ # App tests │ ├── WeatherAlertsServer/ # Vapor backend server │ │ ├── Sources/ │ │ └── Tests/ │ └── TestApp/ # Test harness app ├── Modules/ # Modular feature components │ └── <ModuleName>/ │ ├── Project.swift # Tuist project definition │ ├── Sources/ # Module source code │ │ └── <ModuleName>/ │ └── Tests/ # Module tests │ └── <ModuleName>Tests/ ├── Tuist/ # Tuist configuration │ ├── Package.swift # SPM dependencies │ ├── ProjectDescriptionHelpers/ # Shared Tuist helpers │ └── Templates/ # Module scaffolding templates └── Workspace.swift # Root workspace definition ``` ## Commands for Agent Development ### Project Generation ```bash # Generate main app Xcode workspace (opens in Xcode) make app # Generate without opening Xcode make app-no-open # Generate specific module workspace (opens in Xcode) make module name=<ModuleName> # Generate module without opening Xcode make module-no-open name=<ModuleName> # Scaffold and generate new module make new-module name=<ModuleName> # Install/update dependencies tuist install # Regenerate all projects after dependency changes tuist generate ``` ### Building Code ```bash # Build main app (fast, recommended) make build-app # Build specific module make build-module name=<ModuleName> # Or build via command line with xcodebuild xcodebuild -workspace WeatherAlertsApp.xcworkspace \ -scheme WeatherAlertsApp \ -destination 'platform=iOS Simulator,name=iPhone 16 Pro' \ build ``` ### Linting ```bash # Lint changed files only (fast, recommended for development) trunk check --ci # Lint all files trunk check --all --ci # Auto-fix issues where possible trunk check --fix --ci # Lint specific files or directories trunk check --ci path/to/file.swift # Lint with specific linters only trunk check --ci --filter=swiftlint,swiftformat ``` ### Testing ```bash # Test main app (fast, recommended) make test-app # Test specific module make test-module name=<ModuleName> # Or use xcodebuild directly xcodebuild test \ -workspace WeatherAlertsApp.xcworkspace \ -scheme WeatherAlertsApp \ -destination 'platform=iOS Simulator,name=iPhone 16 Pro' # Or use Xcode UI: Cmd+U to run tests ``` ### Running the Server ```bash # Run server via SPM (recommended) make spm-server name=WeatherAlertsServer # Run server via Tuist make tuist-server name=WeatherAlertsServer # Set log level make spm-server name=WeatherAlertsServer LOG_LEVEL=info ``` ### Docker (Server) ```bash # Build server image docker compose build # Start server with Postgres database docker compose up app # Stop all services docker compose down ``` ### Code Generation ```bash # Regenerate WeatherAPI from OpenAPI spec cd Modules/WeatherAPI ./generate_code.sh # Generate Cuckoo mocks make mocks ``` ### Cleanup ```bash # Clean Tuist cache and derived data make clean tuist clean # Nuclear clean (WARNING: removes all untracked files except Tuist build cache) make very-clean ``` ## Development Workflow ### Creating a New Module 1. Scaffold the module: `make new-module name=MyModule` 2. Implement features in `Modules/MyModule/Sources/MyModule/` 3. Add tests in `Modules/MyModule/Tests/MyModuleTests/` 4. Add module dependency to main app in `Apps/WeatherAlertsApp/Project.swift` if needed 5. Regenerate main app: `make app` ### Making Changes to Existing Code 1. Ensure workspace is generated: `make app` or `make module name=<ModuleName>` 2. Open the appropriate `.xcworkspace` file in Xcode (or use `make app-no-open` to skip opening) 3. Make changes to Swift files 4. Lint changes: `trunk check --ci` 5. Build: `make build-app` or `make build-module name=<ModuleName>` 6. Run tests: `make test-app` or `make test-module name=<ModuleName>` 7. Fix any linter errors: `trunk check --fix --ci` ### Adding Dependencies 1. Add package to `Tuist/Package.swift` for SPM dependencies 2. Or add to `Tuist/ProjectDescriptionHelpers/PackageDependencies.swift` for Tuist-managed packages 3. Update module's `Project.swift` to include the dependency 4. Run `tuist install` to fetch dependencies 5. Regenerate projects: `tuist generate` or `make app` ### Before Committing 1. Run linter: `trunk check --all --fix --ci` 2. Build: `make build-app` (or `make build-module name=<ModuleName>` for modules) 3. Run tests: `make test-app` (or `make test-module name=<ModuleName>` for modules) 4. Ensure no build errors or warnings 5. Clean up any generated files not meant for version control ## Code Style Guidelines ### Swift Best Practices - Use declarative and composable patterns - Avoid inheritance; prefer protocols and composition - Avoid mutable patterns; prefer immutability - Use Swift concurrency (async/await, actors) over legacy GCD - No trailing whitespace at end of lines ### Project Conventions - Each module should be focused and have a single responsibility - Keep module dependencies minimal and explicit - Use dependency injection - Place shared utilities in dedicated modules (e.g., LoggingService, RESTService) - Test coverage expected for all modules ## Key Dependencies ### iOS App (in Tuist/Package.swift) - `swift-openapi-runtime`: OpenAPI client support - `swift-openapi-urlsession`: URLSession transport for OpenAPI - `ViewInspector`: SwiftUI testing - `swift-snapshot-testing`: Snapshot tests - `swift-concurrency-extras`: Concurrency utilities - `Cuckoo`: Mock generation ### Server - `Vapor`: Web framework - `swift-nio`: Networking ## Troubleshooting ### "No such workspace" errors - Run `make app` to generate the workspace first - Workspaces are not checked into git and must be generated locally ### Xcode build errors after pulling changes - Run `tuist clean && tuist install && make app` - Kill Xcode and regenerate: `make app` (includes kill-xcode step) ### Linter not found - Ensure mise is installed: `mise --version` - Install tools: `mise install` ### Module not found in main app - Add module to dependencies in `Apps/WeatherAlertsApp/Project.swift` - Regenerate app workspace: `make app` ## Important Notes for Agents 1. **Always generate projects before building**: Run `make app` or `make module name=<ModuleName>` before attempting to build 2. **Never commit generated files**: `.xcworkspace` and `.xcodeproj` files are generated by Tuist, not source 3. **Lint before testing**: Run `trunk check` to catch issues early 4. **Use Make targets**: Prefer `make` commands over direct `tuist` calls for common operations 5. **Module isolation**: Each module should be independently testable and buildable 6. **Tool versions matter**: Use mise-managed tool versions specified in `mise.toml`
Workflows from the Neura Market marketplace related to this Cursor resource