Skip to content
taihengPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Steeped

A tea-steeping timer app built as a learning exercise for pointfreeco/swift-dependencies in a vanilla MVVM (@Observable) app — no TCA.

Requirements

  • Xcode 26+
  • iOS 17+
  • Swift 6.2
  • mise for tooling management

Tooling Setup

This project uses mise to manage tooling versions. After installing mise, run:

mise install
pre-commit install

mise.toml

Tool Version Purpose
pre-commit latest Git hook runner (format, lint, scan)
swiftlint latest Swift linter (also a build tool plugin)
trufflehog latest Secret / credential leak detection

Pre-commit Hooks

Pre-commit runs the following checks on every commit:

Hook Version Purpose
Sourcery 2.0.2 Code generation (AutoKind, AutomaticSettings)
SwiftFormat 0.52.8 Opinionated Swift code formatting
TruffleHog — Secret / credential leak detection (via mise)

Project Structure

Steeped/
├── mise.toml                     # Tooling versions (pre-commit, swiftlint, trufflehog)
├── .pre-commit-config.yaml       # Pre-commit hook definitions
├── .swiftlint.yml                # SwiftLint rule configuration
├── .swiftformat                  # SwiftFormat rule configuration
├── .sourcery.yml                 # Sourcery code generation config
├── .periphery.yml                # Periphery unused code detection config
├── AppFeature.xctestplan         # Test plan for AppFeature
├── docs/                         # Design documents and specs
└── Packages/                     # Swift Package (all feature code lives here)
    ├── Package.swift
    └── Sources/
        ├── AppFeature/           # Root app view, tab coordination
        ├── HomeFeature/          # Primary feature module
        ├── SettingsFeature/      # App settings and acknowledgements
        ├── SharedModels/         # Data models shared across features
        ├── SharedViews/          # Reusable UI components
        ├── PlaybookFeature/      # Playbook (UI storybook) scenarios
        └── TestExtensions/       # Shared test helpers (snapshots, diffs)

Package Dependencies

Package Purpose
Inject Hot reload in DEBUG builds
SwiftLint Linting via build tool plugin
Difference Human-readable test failure diffs
AcknowList Third-party acknowledgements screen
LifetimeTracker Memory leak detection in DEBUG builds
Roadmap In-app feature roadmap / voting
Playbook (playbook-ios) Component storybook for UI development
AutomaticSettings Settings screen code generation
swift-snapshot-testing Snapshot tests for SwiftUI views

Architecture

  • Modular SPM: All feature code is isolated into separate Swift Package targets under Packages/. The Xcode app target is a thin host.
  • Feature modules: Each feature (HomeFeature, SettingsFeature, etc.) owns its view and model. Shared types go in SharedModels or SharedViews.
  • Code generation: Sourcery generates boilerplate (AutoKind enums, AutomaticSettings) via pre-commit. Generated files are committed and have a // Generated header.
  • Swift 6: The package uses .swiftLanguageModes([.v6]) — all targets must be concurrency-safe.

Commit Conventions

This project follows Conventional Commits.

<type>(<scope>): <short summary>

[optional body]

[optional footer(s)]

Types

Type When to use
feat A new feature or user-visible behavior change
fix A bug fix
refactor Code change with no behavior change
test Adding or updating tests
chore Tooling, dependencies, build config
docs Documentation only
style Formatting, whitespace (no logic change)
perf Performance improvement
ci CI/CD configuration

Scopes (optional)

Use the module name as scope when the change is confined to one target: home, settings, shared-models, app, playbook.

Examples

feat(home): add undo support for the last action
fix(shared-models): correct calculation for edge case
chore: bump SwiftLint to 0.59.1
test(home): add snapshot for empty state
docs: update feature spec to v2

Breaking Changes

Append ! after the type or add BREAKING CHANGE: in the footer:

feat(shared-models)!: rename Item to DetailedItem

BREAKING CHANGE: All references to `Item` must be updated to `DetailedItem`.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages