A real problem from my own life, broken down the way a systems-engineering textbook would: need, measures of effectiveness, boundary, operations, and traceable requirements. Then the SysML model of what I built, and the scheduling theory behind 150 hours of solo iOS development.
I'm a student, first in high school and now in college, and my schedule rarely lets up. I often end the week burnt out and tired, and my screen time makes it worse. Scrolling social media turns into comparison, and the hours I'm supposed to be off, actually resting, stop feeling like rest.
I also want to practice my faith better: to pray without ceasing and to live more peacefully. When I look at Jesus's life, I see someone who set boundaries and made time to rest, and who still served thousands of people. I want to pursue what I care about with more tenacity and vigor, and I want that work to bear fruit. Resting well is how I get there.
But it's 2026, and my phone is always in my pocket. I don't always remember to bring a book. The damage happens in the small moments, like riding in a car or waiting for class to start, when I pull out my phone without thinking and undo my dopamine patterns.
A busy student needs a way to turn the unplanned, idle moments of the day into real rest and prayer instead of comparison-driven scrolling. It has to work with a phone that is always present and can't depend on willpower or on remembering to bring anything.
Systems-engineering texts (Blanchard & Fabrycky, the INCOSE handbook) start by separating the need from any solution. Then they ask how you'd know it was met (measures of effectiveness) and what limits the answer (constraints). Here is that breakdown, and every requirement in section 05 traces back to it.
| ID | Stakeholder need | Root cause it addresses |
|---|---|---|
| N1 | Rest that feels like rest during time that's already "off" | Feeds fill downtime with comparison, not recovery |
| N2 | Cover the micro-moments (car rides, the minutes before class) | The phone is the only thing always in reach, and it defaults to a feed |
| N3 | A steady rhythm of prayer and Scripture across a full schedule | Faith practice gets pushed out when there's no set time or trigger for it |
| N4 | Rest with other people, not in isolation | Boundaries are easier to keep when your circle keeps them too |
| N5 | Low friction: no willpower, no cost, nothing extra to carry | Plans that depend on discipline fail on exactly the tired days |
| MOE | Measure of effectiveness |
|---|---|
| MOE-1 | Idle moments spent resting or praying instead of scrolling |
| MOE-2 | Consistency: consecutive days rested (streak) |
| MOE-3 | Exposure to comparison: no public metrics, no endless feed |
| MOE-4 | Adoption: whether people keep opening it (rating, retention) |
| C | Constraint |
|---|---|
| C1 | The phone stays in the pocket, so the design must work with it |
| C2 | One developer, ~150 hours, alongside a full course load |
| C3 | iOS platform rules and App Store review |
| C4 | Free: a paywall would defeat the point |
Before designing what's inside the box, define what's outside it. NoRush doesn't control the schedule, the social apps, or the phone. It can only change what happens at the interfaces between them.
flowchart LR
U(["Student\n(primary user)"])
CI(["Circle\n(friends & family)"])
SCH(["Daily schedule\ncar rides · class gaps"])
SM(["Social media apps\ncompeting for attention"])
IOS(["iPhone / iOS\nnotifications · Live Activities"])
SYS["NoRush\n— system of interest —\nRest Call · verse · prayer · games"]
SCH -->|idle moment| U
SM -.->|pull to scroll| U
U -->|opens instead| SYS
SYS -->|scheduled push| IOS
IOS -->|surprise prompt| U
SYS -->|shared rest| CI
style SYS fill:#141b26,stroke:#5fc3d4,stroke-width:2px
A ConOps describes the system through a real scenario from the user's point of view. Below is the same five minutes, as-is and to-be.
Each "shall" statement traces back to a need and forward to the feature that meets it, plus a verification method (Inspection, Analysis, Demonstration, or Test). If a feature traces to no need, it's scope creep.
| Req | The system shall… | Traces to | Design element | Verify |
|---|---|---|---|---|
| R1 | prompt a rest once per day, at an unpredictable time, from one global schedule, never user-initiated | N1 N5 | Rest Call; timezone-aware scheduled Cloud Function | Test |
| R2 | bound each rest to seven minutes and one photo | N1 MOE-3 | Capture window (state machine, §07) | Demonstration |
| R3 | present no algorithmic or endless feed | N1 MOE-3 | Circle-only feed | Inspection |
| R4 | fit any gap in the day: either spend 30 seconds or 30 minutes on the app | N2 N3 | Daily verse & quote, prayers, 60-sec meditation, daily games | Demonstration |
| R5 | share rest only within a user-chosen circle | N4 | Circles; Firestore security rules | Test |
| R6 | track consecutive days rested | N3 MOE-2 | Streaks & friend leaderboard | Demonstration |
| R7 | provide every feature at no cost | N5 C4 | No paywall, no subscription tier | Inspection |
After NoRush shipped, I modeled it as a SysML block model: a digital twin of the real system in diagram form, so I could reason about its architecture and see how the pieces actually fit. I used the notation from Magic Systems of Systems Architect, the MBSE tool from my coursework, applied to a product that was already live.
Package Diagram — organization
%%{init: {'theme':'base', 'themeVariables': {
'background':'#10151f','primaryColor':'#141b26','primaryTextColor':'#e8eef5',
'primaryBorderColor':'#a98af0','lineColor':'#a98af0','secondaryColor':'#141b26',
'tertiaryColor':'#141b26','fontFamily':'Space Mono, monospace','fontSize':'12px'
}}}%%
flowchart TB
subgraph CLIENT["«package» Client"]
direction TB
V["SwiftUI Views"] --> VM["MVVM ViewModels"]
end
subgraph SOCIAL["«package» Social Platform"]
direction TB
CI["Circle"] --> FR["Friends"]
FR --> FE["Feed"]
end
subgraph ENGINE["«package» Rest Engine"]
direction TB
SC["Scheduling"] --> NO["Notifications"]
NO --> LA["Live Activities"]
end
subgraph DATA["«package» Data & Identity"]
direction TB
AU["Auth"] --> FS["Firestore"]
FS --> ST["Cloud Storage"]
end
CLIENT -->|depends on| SOCIAL
CLIENT -->|depends on| ENGINE
SOCIAL -->|depends on| DATA
ENGINE -->|depends on| DATA
style CLIENT fill:#141b26,stroke:#a98af0,stroke-width:2px
style SOCIAL fill:#141b26,stroke:#5fc3d4,stroke-width:2px
style ENGINE fill:#141b26,stroke:#e2a33d,stroke-width:2px
style DATA fill:#141b26,stroke:#5fd88f,stroke-width:2px
%%{init: {'theme':'base', 'themeVariables': {
'background':'#10151f','primaryColor':'#141b26','primaryTextColor':'#e8eef5',
'primaryBorderColor':'#5fc3d4','lineColor':'#5fc3d4','secondaryColor':'#141b26',
'tertiaryColor':'#141b26','fontFamily':'Space Mono, monospace','fontSize':'12px'
}}}%%
classDiagram
class NoRushApp {
<<block>>
+version : Build
+startSession()
}
class RestEngine {
<<block>>
+scheduledTime : Time
+fireNotification()
+startLiveActivity()
}
class SocialPlatform {
<<block>>
+circleId : String
+postToFeed()
+listenRealtime()
}
class BackendServices {
<<block>>
+schemaVersion : SchemaVariant
+runCloudFunction()
}
NoRushApp *-- RestEngine : composes
NoRushApp *-- SocialPlatform : composes
RestEngine o-- BackendServices : uses
SocialPlatform o-- BackendServices : uses
The structure above only says what the system is made of. Below is its behavior counterpart — one RestSession, modeled from scheduled trigger to archived record.
%%{init: {'theme':'base', 'themeVariables': {
'background':'#10151f','primaryColor':'#141b26','primaryTextColor':'#e8eef5',
'primaryBorderColor':'#5fd88f','lineColor':'#5fd88f','secondaryColor':'#141b26',
'tertiaryColor':'#141b26','fontFamily':'Space Mono, monospace','fontSize':'12px'
}}}%%
stateDiagram-v2
[*] --> Idle
Idle --> Scheduled : daily timer set
Scheduled --> Notified : surprise trigger fires
Notified --> Capturing : user opens app
Capturing --> Shared : photo taken [circle confirms]
Capturing --> Notified : timeout, no action
Shared --> Archived : 7-minute window closes
Archived --> [*]
I'm an Industrial & Systems Engineering student at Virginia Tech. Here are the two things a classroom never really teaches you: real requirements are discovered, not given — and an hour of work is worth a different amount depending on when you spend it. Both showed up while I was building this, and I had to engineer around them, not just survive them.
All models are wrong, some are useful.— George Box
%%{init: {'theme':'base', 'themeVariables': {
'background':'#10151f','primaryColor':'#141b26','primaryTextColor':'#e8eef5',
'primaryBorderColor':'#1f2a38','lineColor':'#5fc3d4','secondaryColor':'#141b26',
'tertiaryColor':'#141b26','fontFamily':'Space Mono, monospace','fontSize':'12px'
}}}%%
flowchart TB
subgraph CLASSROOM["CLASSROOM PROBLEM"]
direction TB
C1["Given: complete, stated inputs"] --> C2["Exactly one correct answer"]
C2 --> C3["Time bounded by the exam clock"]
C3 --> C4["Graded on correctness"]
end
subgraph REAL["REAL-WORLD PROBLEM: NoRush"]
direction TB
R1["Given: incomplete — name and scope\nonly revealed through real usage"] --> R2["No single correct answer —\nrebranded twice in 16 days"]
R2 --> R3["Time bounded by App Store review\nand my own finals calendar"]
R3 --> R4["Graded on whether anyone\nkeeps opening it"]
end
%%{init: {'theme':'base', 'themeVariables': {
'background':'#10151f','primaryColor':'#141b26','primaryTextColor':'#e8eef5',
'primaryBorderColor':'#1f2a38','lineColor':'#5fc3d4','secondaryColor':'#141b26',
'tertiaryColor':'#141b26','fontFamily':'Space Mono, monospace','fontSize':'12px'
}}}%%
flowchart LR
N["Need identified\nJun 2024"] -->|"18 mo self-taught\nWIP=1, no deadline"| P["Low-fidelity prototyping\nLovable + Claude-assisted"]
P -->|"Finals end —\nhard deadline appears"| B["Build sprint\n~150 hrs total"]
B -->|"Self-imposed buffer:\n'get submission 90% right today'"| S["Submit + TestFlight\nV&V gate"]
S -->|"Live usage surfaces\nunknown requirements"| Ch["Requirements churn:\n2 renames in 16 days"]
Ch -->|"MTTR cut by\ndaily dogfooding"| Op["Operate & sustain\nongoing"]
Op -.->|"feedback loop"| Ch
I was the whole system, so WIP and cycle time moved together for me: holding three half-built features open at once (higher L) stretches every one of their finish times (W), even though my throughput (λ) hadn't changed. Finishing the circle/rest-call feature before starting trivia — rather than running both half-open — was a deliberate choice I made to limit WIP, not a coincidence of order.
Queueing theory says wait time explodes as you push utilization toward 100% — a system running flat-out has no slack left to absorb anything unexpected. I lived that curve: my highest-output hour wasn't the one where I'd crammed the most work around it — it was the one where I actually had room to think.
Instead of padding every task, I put a single project buffer in front of the real deadline: an in-app checklist item I wrote on June 24, 2026 literally read "review and get the next App Store submission 90% right today" — six days ahead of the actual rebrand ship date. That's a project buffer I built into my own product before I'd even studied the term for it.
Sabbath → Linger → NoRush in 16 days wasn't scope creep — it was the requirement ("what should this be called and feel like") becoming knowable only once real people in my circle used it daily. Treating that churn as expected and schedulable, instead of a sign something went wrong, is what kept me from blowing the launch date.
Human-factors research consistently finds a real re-orientation cost every time your attention switches tasks. Building solo alongside a full course load for a year and a half meant every time I came back to the codebase, I paid that tax first — I learned the hard way why the May 2026 sprint needed to be one protected, single-purpose block instead of scattered sessions.
Internally, my Xcode project, bundle identifiers, and folder structure are still literally named for the app's first name — I renamed the product twice, but never touched the substrate underneath. That's a maintenance cost I deferred on purpose: safe to postpone, expensive to fix mid-sprint, the same tradeoff any engineer makes under a live deadline.
Sabbath, Linger, and NoRush are really the same underlying system wearing three different names — what a systems engineer would call a variant. But my backend evolved on its own version axis too: I ran a Firestore schema migration alongside one of the rebrands, so I needed a real constraint holding the two together: { clientBuild ≥ 2.7.1 ⇒ backendSchema = v3 }. If I'd shipped a client without honoring that constraint, I'd have broken every circle already live on the old schema — which is exactly why I ran the migration before the client update, not after.
Independently designed, built, and shipped a native iOS app over 150 hours, applying a full systems-engineering lifecycle — needs identification, low-fidelity prototyping, TestFlight-based verification, and phased deployment — to take a solo concept to a live, 5.0-rated App Store launch.
Modeled the shipped system in SysML — package, block definition, and state-machine diagrams built in Magic Systems of Systems Architect — to formally capture structure and behavior for a product that already existed in production, not as pre-build documentation.
Diagnosed requirements volatility from live usage data and responded by executing two full product rebrands within 16 days, rather than treating the churn as project failure — kept the original launch timeline intact.
Applied WIP-limiting (Little's Law) to a single-person development pipeline, sequencing feature delivery to hold cycle time flat as scope grew across three shipped engagement features.
Built a self-imposed critical-chain buffer ahead of a hard external deadline (App Store review), scheduling internal readiness checkpoints days before the real delivery date to absorb schedule risk proactively.
Ran continuous dogfooding as a production feedback loop, personally using the app daily to surface and resolve a live reliability bug the same day it appeared.
Made an explicit cost-of-delay tradeoff to defer non-critical technical debt (legacy internal naming) in favor of shipping velocity — a deferral, not an oversight, made under real resource constraints.