Skip to content

Repository files navigation

AIArticleDigest

Swift Platform Xcode

📘 Overview

AIArticleDigest is a SwiftUI news reader portfolio app focused on practical app architecture:

  • clean repository-based data flow
  • SwiftData bookmarks
  • mock/live runtime switching
  • AI summary experience (mock and live-capable)
  • stable UI automation with accessibility identifiers

Features

  • Articles tab with:
    • search, pull-to-refresh, and recently viewed hint
    • navigation to article detail
    • stable row identifiers for UI testing
  • Article detail screen with:
    • hero thumbnail (when available)
    • bookmark toggle and share actions
    • in-app Safari for original article links
    • AI summary modes (3-Line / Detailed) with loading, error, retry, and cache
    • summary copy/share actions and toast feedback
  • Bookmarks tab with:
    • persisted bookmarks (SwiftData)
    • swipe-to-delete support
    • sort options (Newest / Oldest / Source A-Z)
    • navigation to article detail

Screenshots

Architecture

The app follows a lightweight layered architecture:

  • App/*: composition root (AppEnvironment) and runtime configuration
  • Core/*: cross-cutting modules (AI, networking, persistence, UI helpers)
  • Features/*: UI + ViewModels per feature

Key design points:

  • ArticleRepository and SummarizationService are protocol boundaries.
  • AppEnvironment builds concrete dependencies and injects them.
  • BookmarkStateStore (@MainActor, @Observable) provides immediate UI sync, while BookmarkRepository handles persistence.
  • Runtime behavior is centralized in RuntimeConfig (AIArticleDigestApp.swift).

Runtime Modes

The app supports mock/live switching via launch environment values.

Mode Articles Summary Required env vars
Mock (default) MockArticleRepository MockSummarizationService None
Live articles only RemoteArticleRepository (NewsAPI) MockSummarizationService USE_LIVE_API=1, NEWS_API_KEY
Live summary only MockArticleRepository LiveSummarizationService (OpenAI) USE_LIVE_SUMMARIZATION=1, OPENAI_API_KEY
Fully live RemoteArticleRepository (NewsAPI) LiveSummarizationService (OpenAI) USE_LIVE_API=1, NEWS_API_KEY, USE_LIVE_SUMMARIZATION=1, OPENAI_API_KEY

OPENAI_SUMMARY_MODEL is optional (default: gpt-4o-mini).

Debug helper

  • FAIL_ONCE_SUMMARY=1
    Forces the first summary request to fail once (DEBUG only), useful for retry verification.

Learn More

Environment Variables

Runtime configuration is read from Scheme Environment Variables.

  • Scheme environment variables are local developer settings and are not committed to this repository, so each developer must configure them manually.
    1. In Xcode, open Edit SchemeRunArgumentsEnvironment Variables.
    2. Add entries as needed (for example: Name USE_LIVE_API, Value 1).
    3. Ensure each variable is enabled (checked).
Name Purpose Example
USE_LIVE_API Enable live NewsAPI article fetching 1
NEWS_API_KEY NewsAPI key used by RemoteArticleRepository your_newsapi_key
USE_LIVE_SUMMARIZATION Enable live OpenAI-based summary generation 1
OPENAI_API_KEY OpenAI API key used by LiveSummarizationService your_openai_api_key
OPENAI_SUMMARY_MODEL Optional override for summary model gpt-4o-mini
FAIL_ONCE_SUMMARY DEBUG helper: fail the first summary request once 1

For UI tests, the launcher also uses:

Name Type Purpose
UITEST_IN_MEMORY_STORE Launch argument Runs SwiftData with an in-memory store

Secrets

Do not commit real keys.

  • Keep local secrets outside Git tracking (for example via Scheme Environment Variables).
  • Config/Secrets.xcconfig is ignored in .gitignore.
  • For public repos, never include real API keys in source/history.

Optional: Use .xcconfig with Scheme Environment Variables

If you prefer local key management with .xcconfig, you can wire it through your run scheme.

  1. Create a local Secrets.xcconfig (not committed), for example:
NEWS_API_KEY=your_newsapi_key
OPENAI_API_KEY=your_openai_api_key
  1. In Xcode, open Edit SchemeRunArgumentsEnvironment Variables.
  2. Add entries like:
    • Name: NEWS_API_KEY, Value: $(NEWS_API_KEY)
    • Name: OPENAI_API_KEY, Value: $(OPENAI_API_KEY)
  3. Ensure each variable is enabled (checked).

Testing

Unit tests (AIArticleDigestTests)

Covered areas include:

  • RemoteArticleRepository DTO mapping and filtering behavior
  • ArticleDetailViewModel summary state transitions
  • BookmarksViewModel sort behavior
  • RecentArticleStore persistence behavior
  • BookmarkStateStore state transitions
  • MockSummarizationService behavior

UI tests (AIArticleDigestUITests)

Main flow and empty bookmarks flow are covered.
UI tests use accessibilityIdentifier-based selectors to reduce brittle text matching.

The UI test launcher uses:

  • UITEST_IN_MEMORY_STORE launch argument
    to run with an in-memory SwiftData store.

Known Limitations

  • Live article data quality depends on the upstream NewsAPI response. Some items may not include image URLs or complete metadata.
  • Live summary requires a valid OpenAI API key and network connectivity.
  • API rate limits or provider errors can temporarily affect live article fetching or summary generation.
  • Mock mode is intended for development and demonstration; it does not represent real-time news updates.

Requirements

  • Xcode 26.x
  • iOS Simulator 26.x
  • Swift 6 (as configured by project settings)

License

MIT. See LICENSE.

About

A SwiftUI news reader portfolio app featuring AI summaries, SwiftData bookmarks, and mock/live modes.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages