Skip to content

kitlangton/Void

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Void — Meditation

Void — Meditation Timer

This is Void, a simple meditation timer built with SwiftUI and the Composable Architecture (TCA). This repository demonstrates how to structure a small-to-medium app using the composable architecture.

This is by no means a perfect codebase, but I hope open-sourcing it might help others learn to use these wonderful tools. Feel free to open up an issue with any questions or comments you may have. Have fun and enjoy! 🙇‍♂️

Oh, and download the app! — And review it if you like it!

Download on the App Store

Overview

  • SwiftUI + TCA: We organize the app into features, each with its own @Reducer, State, Action, and SwiftUI views.
  • Dependency Injection: External services (e.g. HealthKit, Audio) are encapsulated as “clients” using TCA’s DependencyKey.
  • Feature Folders: Each major app section (like Onboarding, Settings, Timer, etc.) lives in its own folder under Features.
  • Reusable Components: Shared logic and helpers (e.g. SoundManager, HealthKitClient) live in Clients and Utilities.

Below is a quick tour of the major directories and files.


Project Structure

Features

Each feature folder contains:

  1. A Reducer (FeatureNameFeature.swift) defining State, Action, and any side effects.
  2. A View file (FeatureNameView.swift) binding to the reducer’s state.

Highlights:

The app’s root reducer is HomeFeature.swift. It ties all child features together (onboarding, settings, stats, meditation timer) and manages global app state.

Clients

Dependencies for external or system services are in Clients. Each client is implemented as a TCA DependencyKey:

Models

We store plain data models in the Models folder:

Views and Utilities


How It Works

  1. App Launch
    • The root HomeFeature checks if HealthKit is authorized. If not, it presents the onboarding flow (OnboardingFeature).
  2. Meditation Flow
    • The user sets their timer, intervals, and ambient sound in the Settings feature.
    • Tapping Begin starts MeditationTimerFeature, which counts elapsed time and plays interval/finish bells.
    • When the user stops, the session is saved to HealthKit (if over 10 seconds).
  3. Stats & Quotes
    • StatsFeature queries HealthKit daily to display total minutes meditated and keeps track of your daily streak.
    • QuotesView shows random mindfulness quotes on the home screen.

Patterns & Best Practices

  • Composable Architecture: Each feature has:
    • A @Reducer struct with State, Action, and body.
  • Dependency Clients:
    • Wrapped in @DependencyClient, with liveValue (real implementation) and testValue (fake or mock).
    • Each client is registered in DependencyValues for easy access in reducers.
  • State Persistence:
    • We use TCA’s @Shared storage for persisting state across app launches (e.g. VoidSettings, MeditationState).

Contributing

I'm more than happy to accept contributions, but I also want to keep this app simple and functional. So perhaps open up an issue before coding up too much 😜