Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MedsPlain

Turn dense medicine labels into plain, readable instruction cards — entirely on your iPhone.

Swift iOS Xcode Apple Intelligence License: MIT Privacy: On-Device

MedsPlain is a privacy-first iOS app that scans a medicine label, extracts dosage text locally using Vision OCR, and uses Apple Foundation Models to produce a structured instruction card — dose, timing, warnings, confidence — without ever sending your data off-device.

No backend. No cloud AI. No account. No analytics.


The Problem It Solves

Medicine labels are dense, full of jargon, and easy to misread. Critical information gets buried in small print.

Before After
"Adults and children 12 years and over: take 1 tablet every 4 to 6 hours while symptoms persist. Do not exceed 6 tablets in 24 hours unless directed by a doctor. Take with food or milk if stomach upset occurs." Dose: 1 tablet (200 mg) · Frequency: Every 4–6 hours · Timing: With food or milk · Warning: Max 6 tablets/day

MedsPlain reads the label so you don't have to squint.


Screenshots

Screenshots will be added here once the app is running on Apple Intelligence hardware.

Home Tutorial — Scan Tutorial — Review Tutorial — Result Tutorial — Share Saved Cards
Home Scan Review Result Share Saved
Scan or import a label Step 1 of 4 Step 2 of 4 Step 3 of 4 Step 4 of 4 Locally saved cards

Captured on iPhone 17 Pro Max · iOS 26.4 · Apple Intelligence enabled


Features

Feature Detail
Camera & Import Scan live or import from the photo library
On-Device OCR Vision VNRecognizeTextRequest — no cloud
User Review Step Edit extracted text before AI analysis
On-Device AI Apple Foundation Models with @Generable structured output
Plain Instruction Card Dose · Frequency · Route · Timing · Warnings
Confidence Display High / Medium / Low with reason and pharmacist prompt
Low-Confidence Safety Conservative refusal UI when dosage is unclear
Local Persistence SwiftData-backed saved cards with optional naming
Search & Share Search saved cards; share via native share sheet
Privacy Manifest PrivacyInfo.xcprivacy included for App Store compliance
Accessibility VoiceOver labels, Dynamic Type, haptic feedback
First-Launch Tutorial Step-by-step privacy intro with how-it-works walkthrough

Tech Stack

Layer Technology
UI SwiftUI
Architecture MVVM with protocol-oriented services
Concurrency Swift async/await, @MainActor
On-Device AI Apple Foundation Models — LanguageModelSession, @Generable
OCR Vision — VNRecognizeTextRequest
Storage SwiftData
Image Processing Core Image via ImagePreprocessor
Testing XCTest — unit tests for prompts, models, and VM cancellation
Minimum OS iOS 26.0 · Xcode 26+

Architecture

Views  ──▶  ViewModels  ──▶  Services  ──▶  Models
flowchart TD
    Photo[📷 Camera / Photo Library] --> OCR[Vision OCR\nVNRecognizeTextRequest]
    OCR --> Review[User Reviews & Edits Text]
    Review --> Availability{Foundation Models\nAvailability?}
    Availability -- Available --> AI[On-Device Structured Generation\nLanguageModelSession + @Generable]
    Availability -- Unavailable --> Banner[Availability Banner\nwith Reason]
    AI --> Card[Plain Instruction Card\nDose · Timing · Warnings · Confidence]
    Card --> Save[SwiftData — Local Save]
    Card --> Share[Native Share Sheet]
Loading

Key Components

Component Responsibility
ScanViewModel Camera/import flow, AI availability state, recent cards
OCRReviewViewModel Runs Vision OCR, exposes editable text
AnalysisViewModel Orchestrates structured generation, cancellation, error states
ResultViewModel Instruction card display and save/share actions
FoundationModelsMedicationService LanguageModelSession lifecycle, @Generable mapping
ModelAvailabilityService Maps SystemLanguageModel.availability to user-facing states
SwiftDataStorageService CRUD for persisted SavedMedicationCard
PromptBuilder Session instructions and per-request prompt construction
ImagePreprocessor Contrast/sharpness normalization before OCR

AI Workflow & Safety

Processing Pipeline

  1. Check SystemLanguageModel.default.availability
  2. Pre-warm a LanguageModelSession with strict medical safety instructions
  3. Build a structured prompt from the user-reviewed OCR text
  4. Generate typed GeneratedMedicationAnalysis output via @Generable
  5. Map to MedicationAnalysis model with confidence scoring
  6. Show pharmacist guidance when confidence.isLow or dose/frequency are empty

Safety Constraints (enforced in PromptBuilder)

  • Rephrase only what is supported by the user-reviewed label text
  • Never invent dosage amounts, timing, routes, or warnings
  • Never diagnose or recommend a medicine as appropriate
  • Always preserve original label text as sourceText
  • Surface questionsForPharmacist when the label is ambiguous
  • Conservative refusal UI (requiresPharmacistCheck) for low-confidence results

Project Structure

MedsPlain/
├── MedsPlain.xcodeproj/
├── MedsPlain/
│   ├── App/                    # Entry point, router, environment
│   ├── Models/                 # MedicationAnalysis, SavedMedicationCard, AppSettings
│   ├── Services/
│   │   ├── AI/                 # FoundationModelsMedicationService, PromptBuilder
│   │   ├── OCR/                # VisionOCRService
│   │   ├── Imaging/            # ImagePreprocessor, ImageStore
│   │   └── Storage/            # SwiftDataStorageService
│   ├── ViewModels/             # ScanVM, OCRReviewVM, AnalysisVM, ResultVM, SavedCardsVM
│   ├── Views/
│   │   ├── Scan/               # ScanView, CameraPicker
│   │   ├── Analysis/           # AnalysisView
│   │   ├── Result/             # ResultView, InstructionCardView, ConfidenceView
│   │   ├── Saved/              # SavedCardsView, SavedCardRow
│   │   ├── Settings/           # SettingsView
│   │   └── Components/         # ShareSheet, reusable UI
│   ├── DesignSystem/           # MPButtonStyle, MPCardStyle, MPTypography, Haptics
│   ├── Utilities/              # Logger, ErrorState, DateFormatting, SampleData
│   └── Resources/
│       └── PrivacyInfo.xcprivacy
├── MedsPlainTests/             # PromptBuilder, AnalysisViewModel, MedicationAnalysis, Settings tests
├── docs/
│   ├── DEVELOPMENT.md
│   ├── APP_STORE.md
│   └── PRIVACY.md
├── screenshots/
└── LICENSE

Requirements

  • Xcode 26+ on macOS
  • iOS 26+ on device or simulator
  • Apple Intelligence-capable device for on-device AI (iPhone 15 Pro / iPhone 16 series or later)
  • Apple Intelligence enabled under Settings → Apple Intelligence & Siri

Getting Started

1. Clone

git clone https://github.com/your-username/MedsPlain.git
cd MedsPlain

2. Open

open MedsPlain.xcodeproj

3. Configure Signing

  1. Select the MedsPlain target → Signing & Capabilities
  2. Choose your development team
  3. Update the bundle identifier if needed

4. Run

Select an Apple Intelligence-compatible simulator or device and press ⌘R.

On first launch, the app walks you through a privacy intro and tutorial. Scan or import a label, review extracted text, then tap Simplify Dosage.

5. Test AI Availability States

Edit the scheme (⌘<) and use Foundation Models Availability to simulate:

State Simulates
Available Normal on-device AI flow
Device not eligible Older device banner
Apple Intelligence disabled Settings prompt
Model not ready Preparing state

Running Tests

xcodebuild test \
  -project MedsPlain.xcodeproj \
  -scheme MedsPlain \
  -destination 'platform=iOS Simulator,name=iPhone 16 Pro'

Test coverage includes:

  • PromptBuilderTests — prompt content and instruction constraints
  • AnalysisViewModelTests — cancellation and error propagation
  • MedicationAnalysisTests — model computed properties
  • SettingsServiceTests — UserDefaults persistence

Privacy

Concern Answer
Label photos Stay on device, never uploaded
OCR text Processed locally by Vision framework
AI analysis Runs entirely via Apple Foundation Models on-device
Analytics / telemetry None
Network requests Zero for label processing
Account required No

Privacy manifest: MedsPlain/Resources/PrivacyInfo.xcprivacy
Full policy: docs/PRIVACY.md


Production Readiness

  • SwiftUI MVVM with protocol-oriented, injectable services
  • On-device OCR via Vision framework
  • On-device AI via Apple Foundation Models (@Generable)
  • User review step before any AI generation
  • Medical safety boundaries enforced in prompt and UI
  • Conservative low-confidence and pharmacist-check states
  • SwiftData local persistence with search and delete
  • Share sheet export
  • Privacy manifest for App Store
  • Unit tests for prompts, models, and cancellation
  • VoiceOver labels and Dynamic Type support
  • App Store screenshots on physical Apple Intelligence device
  • Physical device QA on iPhone 15 Pro / iPhone 16

Limitations

MedsPlain is a label readability tool, not a medical advisor. It does not:

  • Diagnose conditions or recommend whether a medicine is appropriate
  • Adjust dosage based on age, weight, symptoms, or conditions
  • Replace guidance from a pharmacist, clinician, or manufacturer

When the model is uncertain, the app surfaces a conservative state and directs you to check with your pharmacist.


Roadmap

  • App Store screenshots and submission
  • Physical device QA with Apple Intelligence
  • Multi-language label support (locale-aware prompts already scaffolded)
  • Medication interaction awareness (pharmacist Q&A prompts)
  • Accessibility audit — full VoiceOver navigation pass
  • iPad and Mac Catalyst layout

Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/your-feature
  3. Follow the existing MVVM + protocol-service pattern
  4. Add unit tests for new business logic
  5. Verify PromptBuilder safety constraints are preserved
  6. Open a pull request with a clear description

Read docs/DEVELOPMENT.md for the implementation task breakdown and manual QA checklist.


Disclaimer

MedsPlain interprets visible medicine label text. It is not a substitute for advice from a pharmacist, clinician, or the manufacturer's official instructions. When in doubt, ask your pharmacist.


License

MIT — see LICENSE.


Built with SwiftUI · Apple Foundation Models · Vision · SwiftData

No cloud. No account. Just your label, made readable.

About

Privacy-first iOS app that turns dense medicine label dosage text into plain instruction cards using Vision OCR and Apple Foundation Models — entirely on-device.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages