\n \n \n The iOS Development History Database: 856 Records That Automate Our Next App | SBB Dev Blog

The iOS Development History Database: 856 Records That Automate Our Next App

After building our first production iOS application—the Crown & Coil Booking app for a premium natural hair studio in Tacoma—we faced a question every engineering team eventually confronts: How do we make the second app faster, cheaper, and more reliable than the first?

Most teams write a retrospective, file it in Confluence, and forget it. We built a database.

A 17-table, 856-record SQLite database that captures every activity, task, requirement, tool, build run, error, dependency, design decision, and lesson learned from the entire iOS development lifecycle. The result isn't documentation—it's an automation blueprint.

17 Tables
856 Total Records
579 Requirements
105 Source Files
4 iOS Projects
11 Build Runs

Why a Database and Not a Document

Retrospective documents are write-once, read-never. They capture narrative but not structure. When you need to answer "What dependencies broke the build last time?" or "Which views are stubs that Apple will reject?", you need SQL—not prose.

Our ios_development_history.db is queryable. Every fact is a row. Every question is a SELECT.

-- What files do I need for a new booking app?
SELECT file_path, category, purpose
FROM source_files
WHERE project_id = 'crown_coil' AND is_stub = 0
ORDER BY category, file_path;
-- Returns 79 production-ready Swift files with exact purposes
-- What errors will I hit and how to prevent them?
SELECT error_message, root_cause, fix_description
FROM build_errors;
-- Returns 6 unique errors with root cause analysis

The Schema: 17 Tables That Capture Everything

The database isn't a flat list. It's a relational graph of the entire iOS development lifecycle.

Table Records What It Captures
projects4All iOS apps: Crown & Coil, SBB Companion, Aura, CEO Avatar
requirements579Every requirement across all projects, with status and traceability
source_files105Every Swift file: purpose, types, imports, stub status, generation method
build_runs11Every compilation attempt: status, error count, duration, simulator
build_errors6Every unique error with root cause analysis and fix description
dependencies5SPM packages: versions, products, known issues
automation_tools16Every script and tool: Ruby, Python, XcodeGen, Fastlane
design_decisions10Architecture choices with rationale and alternatives considered
api_endpoints10Backend routes from server.js mapped to iOS service files
data_models7Swift↔SQLite parity tracking for every model
timeline_events50Chronological history of every file creation, build, fix, milestone
appstore_compliance15Apple Review Guidelines checklist with evidence
brand_design_system13Color tokens, fonts, effects with CSS↔Swift mapping
testing_coverage4Test files, pass/fail status, known issues
performance_checks6TODO scans, accessibility label coverage over time
lessons_learned15What worked, what failed, and what to change

Anatomy of a Build Failure Timeline

One of the most valuable tables is build_runs. It tells the story of 11 consecutive failed builds—each one teaching us something different.

Build # 1 | FAILED | 0 errors | 61.7s  ← Dependency resolution timeout
Build # 2 | FAILED | 0 errors | 60.8s  ← Same timeout
Build # 3 | FAILED | 0 errors | 60.8s  ← Same timeout
Build # 4 | FAILED | 0 errors | 60.7s  ← Same timeout
Build # 5 | FAILED | 0 errors | 60.7s  ← Same timeout
Build # 6 | FAILED | 6 errors | 10.2s  ← First real compile errors!
Build # 7 | FAILED | 6 errors |  2.4s  ← Same 6 errors
Build # 8 | FAILED | 4 errors |  3.8s  ← Fixed 2, discovered 4 remaining
Build # 9 | FAILED | 3 errors |  3.3s  ← Fixed ApplePay delegate
Build #10 | FAILED | 3 errors |  2.6s  ← Persistent redeclaration
Build #11 | FAILED | 5 errors |  2.1s  ← Regression in ProfileView

Builds 1–5 all timed out at ~61 seconds during SPM dependency resolution. Firebase and GoogleSignIn are large SDKs. The lesson: always pre-resolve dependencies with swift package resolve before compiling.

Build 6 was the breakthrough—the first time we got past resolution into actual compilation. Six errors surfaced immediately. Each one is now cataloged with root cause analysis:

Error: invalid redeclaration of 'Appointment'
Root Cause: fix_all.py generated a stub Appointment.swift that conflicted with the real model in Models/Appointment.swift.
Prevention: Before generating stub files, always check if a real implementation already exists. Maintain a file registry.

The Design Decision Record

Every architectural choice is stored with its rationale and the alternatives we evaluated. This isn't about being right—it's about being reproducible.

SELECT title, rationale, alternatives_considered
FROM design_decisions WHERE project_id = 'crown_coil';

-- "XcodeGen for Project File Management"
-- Rationale: .pbxproj is notoriously difficult to merge. YAML is
-- human-readable and git-friendly. Enables regenerating project.
-- Alternatives: ["Manual Xcode", "Tuist", "Bazel"]

-- "Firebase for Backend"  
-- Rationale: Rapid development, no server management, real-time
-- sync, built-in auth providers.
-- Alternatives: ["Custom Node.js", "Supabase", "AWS Amplify"]

-- "Glassmorphism Visual Effects"
-- Rationale: Matches web CSS (rgba(255,255,255,0.03) + blur(20px)).
-- Alternatives: ["Flat design", "Neumorphism", "Material Design"]

Web→iOS Feature Parity Tracking

The requirements table holds 579 items across 26 categories. For the Crown & Coil app alone, we decomposed the entire web platform—book.html, server.js, db.js, styles.css—into 543 specific, queryable requirements.

Category Count What They Cover
UI Components110Every SwiftUI view mapped to its web HTML counterpart
App Store Compliance105Apple Review Guidelines 1.x–5.x + metadata
Data Layer105CoreData schema, sync, migration, caching
Developer Practices100Testing, CI/CD, documentation, code quality
Feature Modules48Booking, referral, waitlist, loyalty, live stream, etc.
Booking Flow105-step wizard: tier→pricing→intake→calendar→confirm
Models6Designer, Customer, CrownPass, Appointment, Wallet, PromoCode
+ 19 more categories95Services, security, analytics, localization, accessibility…

Brand Design System as Data

We didn't just screenshot the CSS—we stored every design token as a row with its web value and its Swift equivalent. This means the next app can programmatically inherit the entire visual identity.

SELECT token_name, css_value, swift_value, usage_context
FROM brand_design_system WHERE token_type = 'color';

-- crownGold | #C9973A        | Color(hex:"C9973A") | Buttons, highlights
-- crownDark | #0A0D14        | Color(hex:"0A0D14") | Backgrounds
-- crownCream | #FAF5EC       | Color(hex:"FAF5EC") | Text on dark
-- glassBg   | rgba(…,0.03)   | .ultraThinMaterial  | Card backgrounds

Fonts, animations, spacing, effects—all stored the same way. When spinning up Aura Bookings (our white-label booking app), we query this table, swap the color palette, and the design system is bootstrapped in seconds.

Lessons Learned: The Highest-Impact Table

The lessons_learned table is arguably the most valuable. Each row has a lesson_type (success, failure, recommendation), an impact rating, and a concrete action_item for next time.

Stripe SDK Missing from SPM

StripeService.swift was generated with import Stripe but the SDK was never added to Package.swift. This blocked every single build.

Duplicate Type Declarations

fix_all.py generated stub files that conflicted with real implementations. The "invalid redeclaration" error persisted across 6+ builds.

36 Feature Stubs

36 feature modules were generated as single-line Text("Feature") views. Apple Guideline 2.1 rejects apps with inactive screens.

XcodeGen for Project Files

Using project.yml + xcodegen eliminated .pbxproj merge conflicts entirely. Clean regeneration from YAML is invaluable.

SQLite Requirements Database

Tracking 543 requirements in SQLite enabled automated gap analysis and in-app compliance views. Far superior to markdown checklists.

💡

Build Early, Build Often

First build attempt was late in development. All 11 failed. Run xcodebuild after every batch of file generation.

How This Powers the Next App

When we start Aura Bookings—our white-label booking platform—the database becomes the factory specification:

  1. Query source_files to generate the exact directory structure and file manifest
  2. Query dependencies to write Package.swift with all required packages on day one
  3. Query data_models to scaffold Swift models with correct Codable conformance
  4. Query build_errors to pre-check generated code against known failure patterns
  5. Query brand_design_system to bootstrap the theme with swapped color tokens
  6. Query automation_tools to know which Ruby scripts to run and in what order
  7. Query appstore_compliance to build the pre-submission checklist from the start
  8. Query lessons_learned to avoid every mistake that cost us 11 failed builds

The database is the institutional memory of the engineering team. It doesn't forget, it doesn't paraphrase, and it answers in milliseconds. Every future app inherits the full weight of every decision, every failure, and every fix that came before it.

Technical Implementation

The system is three files:

The entire database can be regenerated from scratch in under 2 seconds. It's idempotent, deterministic, and version-controlled alongside the source code.

cd databases/
python3 ios_development_history_db.py   # Create + seed 17 tables
python3 migrate_requirements.py          # Import 579 requirements
# Done. 856 records. 320 KB. Ready to query.

We don't build apps from memory. We build them from data. And now, every app we ship makes the next one better—automatically.

← Back to Engineering Narratives