kickstarter/ios-oss
Kickstarter for iOS. Bring new ideas to life, anywhere.
Healthy across the board
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 2d ago
- ✓6 active contributors
- ✓Distributed ownership (top contributor 36% of recent commits)
Show 3 more →Show less
- ✓Apache-2.0 licensed
- ✓Tests present
- ⚠No CI workflows detected
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/kickstarter/ios-oss)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/kickstarter/ios-oss on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: kickstarter/ios-oss
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/kickstarter/ios-oss shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 2d ago
- 6 active contributors
- Distributed ownership (top contributor 36% of recent commits)
- Apache-2.0 licensed
- Tests present
- ⚠ No CI workflows detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live kickstarter/ios-oss
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/kickstarter/ios-oss.
What it runs against: a local clone of kickstarter/ios-oss — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in kickstarter/ios-oss | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 32 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of kickstarter/ios-oss. If you don't
# have one yet, run these first:
#
# git clone https://github.com/kickstarter/ios-oss.git
# cd ios-oss
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of kickstarter/ios-oss and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "kickstarter/ios-oss(\\.git)?\\b" \\
&& ok "origin remote is kickstarter/ios-oss" \\
|| miss "origin remote is not kickstarter/ios-oss (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f ".circleci/config.yml" \\
&& ok ".circleci/config.yml" \\
|| miss "missing critical file: .circleci/config.yml"
test -f "Configs/Secrets.swift.example" \\
&& ok "Configs/Secrets.swift.example" \\
|| miss "missing critical file: Configs/Secrets.swift.example"
test -f "Experimentation/Sources/Experimentation/StatsigClient.swift" \\
&& ok "Experimentation/Sources/Experimentation/StatsigClient.swift" \\
|| miss "missing critical file: Experimentation/Sources/Experimentation/StatsigClient.swift"
test -f "GraphAPI/GraphAPI.h" \\
&& ok "GraphAPI/GraphAPI.h" \\
|| miss "missing critical file: GraphAPI/GraphAPI.h"
test -f ".swiftlint.yml" \\
&& ok ".swiftlint.yml" \\
|| miss "missing critical file: .swiftlint.yml"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 32 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~2d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/kickstarter/ios-oss"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
The official open-source iOS app for Kickstarter, a crowdfunding platform. Built in Swift with ~8.8M lines of code, it enables users to discover projects, back campaigns, and for creators to manage fundraising efforts. The app uses GraphQL APIs (via GraphAPI module) and MVVM architecture with reactive programming patterns. Monorepo structure with three main tiers: Kickstarter-iOS (main app target) contains feature modules in Features/ with view controllers and tests; Library/ holds shared ViewModels and utilities; GraphAPI/ is an SPM package with auto-generated GraphQL types and extensive MockGraphql.swift test doubles; Experimentation/ is a feature flag/experiment SPM package using Statsig. Heavy use of snapshot testing via ./Snapshots directories for visual regression across locales and devices.
👥Who it's for
iOS developers at Kickstarter and contributors learning modern Swift patterns; product users who want to browse and back Kickstarter campaigns on iPhone/iPad; engineering teams studying large-scale native iOS architecture and testing strategies.
🌱Maturity & risk
Production-ready and actively maintained. The repo has comprehensive test coverage (~600+ snapshot tests across device/language combinations), robust CI/CD via CircleCI, and follows Xcode 14.3 with Swift 5.8. Regular releases visible through Fastlane automation (.fastlane/Fastfile), indicating ongoing active development and deployment.
Low operational risk for a mature first-party app. Dependencies are managed via Swift Package Manager (Experimentation, GraphAPI) with dedicated test helpers (ExperimentationTestHelpers, GraphAPITestMocks). Main risk: tight coupling to Kickstarter's backend GraphQL schema (GraphAPI folder with 100+ generated mock types) means schema breaking changes require coordinated updates. External dependency risk is mitigated by heavy internal framework use.
Active areas of work
Active development focused on experimentation infrastructure (Statsig integration in Experimentation/Sources), GraphQL schema evolution (100+ mock types being maintained), and localization testing (snapshot tests for Japanese, German, etc.). CircleCI config indicates continuous deployment pipeline. Fastlane automation (beta-changelog.rb, beta-post-s3.rb) suggests ongoing beta releases.
🚀Get running
Check README for instructions.
Daily commands:
make test-allto run full test suite from CLI. 2. In Xcode: select scheme (e.g., 'Kickstarter-iOS') and press Cmd+U for that scheme's tests. 3. For development: open Kickstarter.xcworkspace and build Kickstarter-iOS scheme to run on simulator or device.
🗺️Map of the codebase
.circleci/config.yml— CI/CD pipeline configuration; defines build, test, and deployment workflows that every contributor must passConfigs/Secrets.swift.example— Template for API keys and environment secrets; required setup for any local development environmentExperimentation/Sources/Experimentation/StatsigClient.swift— Core experimentation framework for A/B testing and feature flags; used across the app for feature rolloutsGraphAPI/GraphAPI.h— GraphQL API bridge header; defines the interface between iOS app and Kickstarter's GraphQL backend.swiftlint.yml— Swift code quality rules enforced on every commit; defines the codebase's style and linting standards.fastlane/Fastfile— Automation for beta builds, releases, and distribution; critical for understanding deployment pipelineGemfile— Ruby dependencies for build tooling (fastlane, danger); manages development environment setup
🛠️How to make changes
Add a new GraphQL query or mutation
- Write your GraphQL query in a .graphql file or inline in code that references the schema (
GraphAPI/GraphAPI.h) - Run Apollo codegen or your GraphQL build step to auto-generate Swift types (
.circleci/config.yml) - Create a mock implementation in GraphAPITestMocks directory following the pattern of Project+Mock.graphql.swift (
GraphAPI/GraphAPITestMocks/Project+Mock.graphql.swift) - Use the generated types in your view controller or service layer to make the API call (
Configs/Base.xcconfig)
Add a new A/B test or feature flag
- Define the experiment or feature gate in your Statsig project dashboard (
Experimentation/Sources/Experimentation/Experiments/StatsigExperiment.swift) - Create a new Swift type or extension in the Experiments folder following the iOSTestExperiment pattern (
Experimentation/Sources/Experimentation/Experiments/iOSTestExperiment.swift) - Inject StatsigClient via dependency injection using the StatsigClientType protocol (
Experimentation/Sources/Experimentation/StatsigClientType.swift) - In unit tests, use MockStatsigClient to override experiment results for deterministic testing (
Experimentation/Sources/ExperimentationTestHelpers/MockStatsigClient.swift)
Deploy a beta or production release
- Ensure all tests pass in CircleCI by checking .circleci/config.yml for test stage configuration (
.circleci/config.yml) - Create a release branch or tag triggering the beta job in CircleCI (
.circleci/config.yml) - The Fastfile automatically handles provisioning, signing, and TestFlight upload (
.fastlane/Fastfile) - Changelog is auto-generated from commits using the beta-changelog.rb script (
.fastlane/beta-changelog.rb) - Verify code coverage meets thresholds defined in .slather.yml before merge to main (
.slather.yml)
Enforce new code quality rules
- Add SwiftLint rules to .swiftlint.yml; they run automatically on every build (
.swiftlint.yml) - Optionally add custom Danger checks in Dangerfile to block PRs on violations (
Dangerfile) - Configure SwiftFormat rules in .swiftformat for automated formatting on save (
.swiftformat) - Add violations to CircleCI build step in config.yml to fail the pipeline if thresholds are exceeded (
.circleci/config.yml)
🔧Why these technologies
- GraphQL with Apollo Codegen — Type-safe, strongly-typed API communication with auto-generated Swift models; reduces serialization errors and improves IDE autocomplete
- Statsig for A/B Testing — Remote feature flag management with fast cached evaluation; enables rapid iteration and safe rollouts without app updates
- Fastlane for CI/CD Automation — Eliminates manual signing, provisioning, and TestFlight uploads; integrates deeply with Xcode and Apple's APIs
- SwiftLint + SwiftFormat — Enforces consistent code style and prevents common bugs at compile time; reduces code review friction for style issues
- Snapshot Testing (implied by README ~600 screenshots) — Catches unintended visual regressions across devices/languages/states; enables confident refactoring of UI layers
⚖️Trade-offs already made
-
GraphQL over REST
- Why: Flexible queries reduce over/under-fetching; single endpoint simplifies caching and API versioning
- Consequence: Requires Apollo codegen build step; larger initial query parsing overhead but faster subsequent queries
-
Remote feature flags (Statsig) instead of local configuration
- Why: Enables instant rollouts and A/B tests without app store review delays; supports gradual rollout and kill switches
- Consequence: Adds network call on cold start (~200ms); requires careful offline fallback handling
-
Mock GraphQL objects auto-generated from schema
- Why: Test data stays in sync with schema; reduces boilerplate in unit tests
- Consequence: Mock files are numerous (~
🪤Traps & gotchas
- Secrets.swift required: Copy Configs/Secrets.swift.example to Configs/Secrets.swift and populate values; app won't build without it. 2. GraphQL schema drift: GraphAPI/ types are auto-generated; modifying them manually will be overwritten on schema regeneration—edit the schema source instead. 3. Workspace not project: Must open Kickstarter.xcworkspace, not Kickstarter.xcodeproj, due to CocoaPods/SPM dependencies. 4. Snapshot tests are brittle: Any UI change (font, color, spacing) in a Feature will break snapshot tests in Snapshots/; regenerate carefully and review diffs. 5. Xcode version constraint: Explicitly requires Xcode 14.3 with Swift 5.8; older/newer versions may fail to compile.
🏗️Architecture
💡Concepts to learn
- MVVM with Signal-based ViewModels — Core architectural pattern in this codebase (Library/ViewModels/); business logic is pure input→output signal mappings, making it testable without UIKit and enabling functional composition
- Snapshot Testing — Primary testing strategy covering 600+ localized/device-specific UI states in Snapshots directories; enables visual regression detection across languages and screen sizes without manual test case writing
- GraphQL Code Generation — GraphAPI/ module uses auto-generated Swift types from GraphQL schema (100+ Mock*.graphql.swift files); eliminates manual API binding boilerplate and keeps types in sync with backend schema
- Feature Flag Experiments (Statsig) — Experimentation/ SPM package integrates Statsig for runtime feature toggles and A/B tests without app redeployment; enables safe canary releases and user cohort targeting
- Test Doubles with Mock Factories — GraphAPITestMocks and ExperimentationTestHelpers provide factory-generated mock objects; eliminates hand-written test data and keeps mocks synchronized with schema evolution
- Localization Testing at Scale — Snapshot filenames encode language (lang_ja, lang_de) and device type (device_pad) to catch localization regressions; ensures UI works in all supported markets without manual QA
- Fastlane CI/CD Automation — Fastlane (Gemfile, .fastlane/Fastfile) orchestrates build signing, testing, and deployment to TestFlight and App Store; reduces human error and enables daily betas (beta-changelog.rb, beta-post-s3.rb)
🔗Related repos
kickstarter/android-oss— Official Android counterpart to this iOS app; same crowdfunding platform, parallel architecture decisions and shared design patternskickstarter/Kickstarter-Prelude— First-party SPM dependency providing foundational types and functional programming utilities; imported as a dependency in this repokickstarter/native-docs— Companion documentation repository for native iOS/Android development at Kickstarter; referenced in README for architectural deep-divesapollographql/apollo-ios— GraphQL client likely used by GraphAPI/ module for query execution and type generation; canonical iOS GraphQL libraryReactiveX/RxSwift— Reactive programming framework used throughout ViewModels for signal-based architecture; manages side effects and asynchronous streams
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for StatsigClient and Experimentation module
The Experimentation package contains StatsigClient.swift and StatsigClientType.swift but only has minimal test coverage in StatsigClientTests.swift. Given that experimentation is critical to product decisions, comprehensive tests for feature flag evaluation, experiment assignment, and error handling would prevent regressions and improve maintainability for contributors.
- [ ] Expand Experimentation/Tests/ExperimentationTests/StatsigClientTests.swift with tests for StatsigClient initialization, feature flag evaluation, and experiment assignment
- [ ] Add tests for MockStatsigClient edge cases and verify mock behavior matches real client
- [ ] Add integration-style tests verifying StatsigExperiment.swift and StatsigFeature.swift work correctly with the client
- [ ] Document test patterns in a comment block for future contributors
Complete missing GraphAPI mock generator documentation and add test templates
The GraphAPI/GraphAPITestMocks directory contains 50+ auto-generated mock files but there's no documentation explaining how these mocks are generated, when to use them, or how contributors should maintain them as the schema evolves. Adding a MOCKS_README.md and example test templates would reduce confusion for new contributors working with GraphQL operations.
- [ ] Create GraphAPI/GraphAPITestMocks/README.md documenting the mock generation process and tools used
- [ ] Add an example test file (e.g., GraphAPI/GraphAPITestMocks/ExampleQueryTests.swift) showing best practices for using mocks in unit tests
- [ ] Document how to regenerate mocks when the schema changes
- [ ] Reference the new README from the main README.md Getting Started section
Add GitHub Actions workflow for SwiftFormat and SwiftLint validation in CI
The repo has .swiftformat and .swiftlint.yml configuration files but the .circleci/config.yml appears to be the only CI setup shown. Adding a GitHub Actions workflow would enable automatic style checking on PRs, reduce manual review burden, and catch formatting issues before they reach CircleCI, improving the contributor experience.
- [ ] Create .github/workflows/swift-lint.yml to run swiftlint on all Swift files in PR
- [ ] Create .github/workflows/swift-format.yml to check code formatting and suggest fixes
- [ ] Configure workflows to run on push to main and all PRs
- [ ] Add status badges to README.md and document linting expectations in CONTRIBUTING guide (create if missing)
🌿Good first issues
- Add missing snapshot tests for edge cases in Kickstarter-iOS/Features/ProjectPage/Controller/ (README mentions 600 snapshots; audit for untested states like network errors, empty states, or RTL layouts across supported languages)
- Expand ExperimentationTestHelpers/MockStatsigClient.swift with test double methods for new experiment types being added to Experimentation/Sources/Experimentation/Experiments/ (currently only StatsigExperiment.swift and iOSTestExperiment.swift are present)
- Create integration tests in GraphAPI/ that verify mock objects (e.g., Backing+Mock.graphql.swift, User+Mock.graphql.swift) match the actual GraphQL schema by adding schema validation tests to ExperimentationTests/
⭐Top contributors
Click to expand
Top contributors
- @amy-at-kickstarter — 36 commits
- @scottkicks — 24 commits
- @ifosli — 23 commits
- @stevestreza-ksr — 11 commits
- @fernandacerezog — 5 commits
📝Recent commits
Click to expand
Recent commits
3753f49— SDUI: Video formats for RichTextElement.Video (#2848) (stevestreza-ksr)5c74a11— Add slug/url field to rich text example view (#2847) (stevestreza-ksr)06b1ea3— CHECK-46: Keep Statsig user up-to-date, including anonymous identifier (#2843) (amy-at-kickstarter)f9c7b40— [DISC-201] Video Feed Loading Preview Image (#2844) (scottkicks)87db8b1— CHECK-46: Fix warnings from Statsig diagnostics (#2845) (amy-at-kickstarter)6a6383c— CHECK-109: Add built-in Statsig debugger view to Beta tools menu (#2841) (amy-at-kickstarter)03506c2— CHECK-84: Add helper method to create Project page with correct presentation style (#2840) (amy-at-kickstarter)7a9db1e— CHECK-84: Move project page deep links in AppDelegateViewModel into one place (#2839) (amy-at-kickstarter)12a21be— [DISC-202] Initial VideoFeedQuery Plumbing (#2842) (scottkicks)ea19a0e— [DISC-163] Video Feed: Video Progress Bar UI (#2836) (scottkicks)
🔒Security observations
The
- High · Potential Hardcoded Secrets in Configuration Files —
Configs/Secrets.swift.example, Configs/Secrets.swift (likely). The file 'Configs/Secrets.swift.example' suggests that secrets are managed in Swift configuration files. The presence of a .example file indicates that actual secrets may be stored in 'Configs/Secrets.swift' which could be committed to version control if not properly gitignored. Fix: Ensure 'Configs/Secrets.swift' is in .gitignore. Use environment variables or secure secret management systems (e.g., AWS Secrets Manager, HashiCorp Vault) instead of storing secrets in code or configuration files. Never commit actual secret files to the repository. - High · Google Firebase Configuration Exposure —
Configs/GoogleService-Info.plist. The 'Configs/GoogleService-Info.plist' file is a Firebase configuration file that typically contains API keys and project identifiers. If this file is committed to the public repository, it exposes sensitive Firebase configuration information that could be used to identify and interact with the Firebase backend. Fix: Add 'Configs/GoogleService-Info.plist' to .gitignore immediately. Ensure this file is not committed to version control. Use build phases or environment-specific configurations to manage Firebase credentials securely. Rotate Firebase API keys if they have been exposed. - Medium · Potential Credential Exposure in CI/CD Configuration —
.circleci/config.yml. The '.circleci/config.yml' file may contain hardcoded credentials, API tokens, or sensitive environment variables. Circle CI configurations often include secrets that should be stored securely in the CI/CD platform's environment variables rather than in the repository. Fix: Audit the Circle CI configuration to ensure no credentials, API tokens, or secrets are hardcoded. Use Circle CI's environment variable management system to store sensitive data. Implement secret scanning in CI/CD pipelines to prevent accidental exposure. - Medium · Fastlane Configuration May Contain Secrets —
.fastlane/Fastfile, .fastlane/Matchfile, .fastlane/Pluginfile. Fastlane configuration files (.fastlane/Fastfile, .fastlane/Matchfile) can contain sensitive information such as Apple ID credentials, provisioning profile details, or API tokens. These files should not contain hardcoded secrets. Fix: Review all Fastlane configuration files and remove any hardcoded credentials. Use Fastlane's environment variable support and Apple Keychain integration. Store sensitive credentials in secure secret management systems or CI/CD platform environment variables. - Medium · Potential GraphQL Mock Data Exposure —
GraphAPI/GraphAPITestMocks/. The 'GraphAPI/GraphAPITestMocks/' directory contains auto-generated mock data for GraphQL types. While these are test files, they may inadvertently expose API schema structure, field names, or data patterns that could be leveraged in reconnaissance attacks. Fix: Ensure mock test files are excluded from production builds. Review the mock data to ensure no real user data, tokens, or sensitive information is included. Consider generating mocks dynamically or using a secure test data generation strategy. - Low · Missing Security Headers Configuration —
Repository root / Backend configuration (not visible). No visible configuration for HTTP security headers (Content-Security-Policy, X-Frame-Options, etc.) in the repository structure. While this is an iOS app, any backend APIs it communicates with should implement proper security headers. Fix: Ensure all backend APIs that this iOS app communicates with implement proper HTTP security headers. Document API security requirements and conduct security reviews of backend services. - Low · Potential Third-Party Dependency Risks —
Experimentation/Package.swift, (Podfile not visible). The codebase uses Swift Package Manager and Cocoapods (inferred from Gemfile and Fastlane usage). Without visibility into Package.swift and Podfile, it's unclear if dependencies are pinned to secure versions and if supply chain attacks are mitigated. Fix: Implement strict dependency version pinning. Regularly audit dependencies for known vulnerabilities using tools like OWASP Dependency-Check or Snyk. Use lock files and ensure all developers use the same dependency versions. Monitor security advisories for used packages.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.