Build the mental model
Every mobile framework has its own navigation API, but underneath sits the same handful of universal patterns. Knowing them lets you reason about navigation in any framework.
- Stack — Home -> Course -> Lesson, back pops last-in-first-out
- Tabs — parallel top-level sections like Home/Search/Downloads/Profile
- Drawer — a destination list behind a side menu, more common on Android
- Modal — a temporary focused overlay for confirmation/create-item tasks
- Deep Link — opening a specific screen directly from outside the app
Don't overuse modals
Using a modal for content that really deserves its own full screen is a common design mistake worth avoiding.
- Stack Navigation
- A navigation pattern where screens are pushed and popped last-in-first-out — the back button or gesture removes the topmost screen from the stack.
- Deep Link
- A mechanism that lets an external source — a notification, a link, another app — open a specific screen directly inside an app.
FOUR NAVIGATION PATTERNS
------------------------
FOUR NAVIGATION PATTERNS
-----
STACK (push/pop, LIFO) TABS (parallel sections)
Home -> Course -> Lesson [Home][Search][Downloads][Profile]
<- back pops top ^ tap switches instantly
DRAWER (side menu) MODAL (temporary overlay)
+------------------+ current screen
| = menu | +----------------+
| Home | | Confirm Delete |
| Settings | +----------------+
| Logout | dismiss -> back to screen
+------------------+Connect it to a real scenario
Most real apps combine several patterns rather than picking just one — a typical structure nests a stack navigator inside each top-level tab.
Switching tabs preserves each tab's stack independently in the background, and modals layer on top of this structure for short-lived, focused tasks.
Deep links tie it all together
A push notification about a new lesson can open the app directly to that lesson's screen inside the correct tab's stack, instead of dropping the user on a generic home screen.
Try the working example
function createNavigationStack(initialScreen) {
const stack = [initialScreen];
return {
push(screen) {
stack.push(screen);
return { currentScreen: screen, depth: stack.length };
},
pop() {
if (stack.length > 1) stack.pop();
return { currentScreen: stack[stack.length - 1], depth: stack.length };
}
};
}
const courseNav = createNavigationStack("Home");
console.log("push Course:", JSON.stringify(courseNav.push("Course")));
console.log("push Lesson:", JSON.stringify(courseNav.push("Lesson")));
console.log("pop (back):", JSON.stringify(courseNav.pop()));
console.log("pop (back):", JSON.stringify(courseNav.pop()));push Course: {"currentScreen":"Course","depth":2}
push Lesson: {"currentScreen":"Lesson","depth":3}
pop (back): {"currentScreen":"Course","depth":2}
pop (back): {"currentScreen":"Home","depth":1}
After two pushes from Home to Course to Lesson, two pops unwind the stack back to depth 1 (Home) in exact last-in-first-out order.5-minute try-it
Extend `createNavigationStack` with a `reset(screen)` method that clears the stack back to a single screen (useful for a 'log out and return to Home' flow), then verify it against a short sequence of pushes.
One important caution
Overusing modals for content that deserves its own full screen (long forms, browsing experiences)
Treating a deep link as a generic entry point without considering the correct tab's stack context
Navigation — Android Developers — How Mobile Apps Work