Navigation & Routing
Navigation & Routing
Section titled “Navigation & Routing”Overview
Section titled “Overview”Shaker uses Expo Router 6 for file-based navigation, providing a type-safe, intuitive routing system. The app features a tab-based navigation structure with nested stack navigators for each major section.
Navigation Structure
Section titled “Navigation Structure”Tab Navigation
Section titled “Tab Navigation”The app has 5 main tabs (plus a hidden Venues tab):
┌─────────────────────────────────────────────────────────┐│ Tab Bar │├──────────┬──────────┬──────────┬──────────┬─────────────┤│Dashboard │ Events │ Recipes │Inventory │ Settings │└──────────┴──────────┴──────────┴──────────┴─────────────┘Tab Configuration:
- Dashboard (
index.tsx) - Overview with quick actions and stats - Events (
events/) - Event planning and management - Recipes (
recipes/) - Recipe browsing and creation - Inventory (
inventory/) - Stock tracking and management - Settings (
settings/) - App configuration - Venues (
venues/) - Venue management (hidden from tab bar)
File Structure
Section titled “File Structure”app/├── _layout.tsx # Root layout – fonts, splash, keep-awake, hydration├── modal.tsx # Modal screen├── +not-found.tsx # 404 screen├── terms/│ ├── PrivacyPolicy.tsx # Privacy policy│ └── TermsOfService.tsx # Terms of service└── (tabs)/ # Tab navigator ├── _layout.tsx # Tab bar configuration ├── index.tsx # Dashboard tab ├── events/ # Events stack │ ├── _layout.tsx # Stack navigator │ ├── index.tsx # Events list │ ├── [id].tsx # Event detail │ ├── add-event.tsx # Create event │ ├── edit-event.tsx # Edit event │ ├── guests.tsx # Guest list │ ├── edit-guest.tsx # Edit guest details │ ├── menu.tsx # Event menu view │ ├── create-menu.tsx # Create/edit menu │ ├── bar-setup.tsx # Bar setup view │ ├── add-bar-setup.tsx # Add bar setup │ ├── edit-bar-setup.tsx # Edit bar setup │ └── batch-management.tsx # Event batch cocktail management ├── recipes/ # Recipes stack │ ├── _layout.tsx # Stack navigator │ ├── index.tsx # Recipe list │ ├── [id].tsx # Recipe detail │ ├── add-recipe.tsx # Create recipe │ ├── edit-recipe.tsx # Edit recipe │ ├── batch/ # Batch cocktails sub-stack │ │ ├── index.tsx # Batch cocktails list │ │ ├── create.tsx # Create batch │ │ └── [id].tsx # Batch detail / tracker │ └── make/ # Make-a-recipe guided flow │ └── [id]/ │ ├── index.tsx # Step 1 – ingredient availability check │ ├── select-instances.tsx # Step 2 – choose product instances │ ├── steps.tsx # Step 3 – guided step-by-step making │ └── complete.tsx # Step 4 – completion + inventory deduction ├── inventory/ # Inventory stack │ ├── _layout.tsx # Stack navigator │ ├── index.tsx # Inventory overview │ ├── [id].tsx # Inventory item detail │ ├── add-product.tsx # Add product (with barcode scan) │ ├── edit-item.tsx # Edit inventory item │ ├── inventory-items.tsx # All inventory items view │ ├── view-all.tsx # View all items (flattened) │ ├── quick-update.tsx # Quick level update screen │ ├── cost-analytics.tsx # Cost analytics dashboard │ ├── export.tsx # Export inventory data (JSON/CSV) │ ├── import.tsx # Import inventory data │ ├── products/ # Products sub-stack │ │ ├── _layout.tsx │ │ ├── index.tsx # Products list │ │ ├── [id].tsx # Product detail │ │ ├── edit-product.tsx # Edit product │ │ └── bulk-mapping.tsx # Bulk ingredient-to-product mapping │ ├── ingredients/ # Ingredients sub-stack │ │ ├── _layout.tsx │ │ ├── index.tsx # Ingredients list │ │ ├── [id].tsx # Ingredient detail │ │ ├── add-ingredient.tsx # Add ingredient │ │ └── edit-ingredient.tsx # Edit ingredient │ ├── equipment/ # Equipment sub-stack │ │ ├── _layout.tsx │ │ ├── index.tsx # Equipment list │ │ └── add-equipment.tsx # Add equipment │ ├── glassware/ # Glassware sub-stack │ │ ├── _layout.tsx │ │ ├── index.tsx # Glassware list │ │ └── add-glassware.tsx # Add glassware │ ├── tools/ # Tools sub-stack │ │ ├── _layout.tsx │ │ ├── index.tsx # Tools list │ │ └── add-tool.tsx # Add tool │ └── shopping/ # Shopping list sub-stack │ ├── _layout.tsx │ ├── index.tsx # Shopping list │ ├── add-item.tsx # Add shopping list item │ └── edit-item/[id].tsx # Edit shopping list item ├── settings/ # Settings stack │ ├── _layout.tsx # Stack navigator │ ├── index.tsx # Settings screen │ └── user-profile.tsx # User profile editor └── venues/ # Venues stack (hidden from tab bar) ├── _layout.tsx # Stack navigator ├── index.tsx # Venues list ├── [id].tsx # Venue detail └── add-venue.tsx # Create venueTab Bar Configuration
Section titled “Tab Bar Configuration”Tab Bar Styling (NeoBrutalism)
Section titled “Tab Bar Styling (NeoBrutalism)”The tab bar uses the RetroUI design system with bold, distinctive styling:
<augment_code_snippet path=“shaker/app/(tabs)/_layout.tsx” mode=“EXCERPT”>
screenOptions={{ // Tab bar colors - NeoBrutalism design tabBarActiveTintColor: designTokens.colors.gray[100], tabBarInactiveTintColor: designTokens.colors.black,
// Tab bar styling - RetroUI theme tabBarStyle: { backgroundColor: designTokens.colors.teal.DEFAULT, borderTopWidth: 6, borderTopColor: designTokens.colors.black, height: 100, }, // ...}}</augment_code_snippet>
Key Features:
- Teal background (
#14B8A6) - 6px black top border
- 100px height for comfortable touch targets
- Bold typography (11px, bold weight)
- Active state: White text
- Inactive state: Black text
Tab Icons
Section titled “Tab Icons”Each tab uses FontAwesome icons from the custom Icon component:
| Tab | Icon | Purpose |
|---|---|---|
| Dashboard | list | Overview and quick actions |
| Events | calendar | Event planning |
| Recipes | whiskey-glass | Recipe management |
| Inventory | box | Stock tracking |
| Settings | gear | App configuration |
Stack Navigators
Section titled “Stack Navigators”Each tab contains a stack navigator for hierarchical navigation within that section.
Header Configuration
Section titled “Header Configuration”All stack navigators use consistent NeoBrutalism header styling:
screenOptions={{ headerStyle: { backgroundColor: designTokens.colors.teal.DEFAULT, height: 116, borderBottomWidth: 6, borderBottomColor: designTokens.colors.black, }, headerTitleStyle: { fontWeight: designTokens.typography.fontWeight.bold, fontSize: designTokens.typography.fontSize.xl, color: designTokens.colors.black, }, headerTintColor: designTokens.colors.black, headerShadowVisible: false,}}Features:
- Teal background matching tab bar
- 116px height
- 6px black bottom border
- Bold black title text
- No shadow (solid design)
Navigation Patterns
Section titled “Navigation Patterns”Programmatic Navigation
Section titled “Programmatic Navigation”import { router } from 'expo-router';
// Navigate to a screenrouter.push('/recipes/add-recipe');
// Navigate with parametersrouter.push(`/recipes/${recipeId}`);
// Go backrouter.back();
// Replace current screenrouter.replace('/inventory');Type-Safe Routes
Section titled “Type-Safe Routes”Expo Router provides type-safe navigation with TypeScript:
import { Href } from 'expo-router';
const recipeDetailRoute: Href = `/recipes/${recipeId}`;router.push(recipeDetailRoute);Modal Presentation
Section titled “Modal Presentation”Modal screens are defined at the root level:
export default function Modal() { return ( <View> <Text>Modal Content</Text> </View> );}
// Navigate to modalrouter.push('/modal');Deep Linking
Section titled “Deep Linking”URL Scheme
Section titled “URL Scheme”The app uses the shaker:// URL scheme for deep linking:
shaker://recipes/123 # Open recipe detailshaker://inventory/products # Open products listshaker://events/add-event # Open create event screenConfiguration
Section titled “Configuration”Deep linking is configured in app.json:
{ "expo": { "scheme": "shaker" }}Navigation Best Practices
Section titled “Navigation Best Practices”1. Use Typed Routes
Section titled “1. Use Typed Routes”Always use TypeScript for route parameters:
import { useLocalSearchParams } from 'expo-router';
export default function RecipeDetail() { const { id } = useLocalSearchParams<{ id: string }>(); // ...}2. Handle Navigation State
Section titled “2. Handle Navigation State”Use navigation state for conditional rendering:
import { useNavigation } from 'expo-router';
const navigation = useNavigation();const canGoBack = navigation.canGoBack();3. Optimize Screen Transitions
Section titled “3. Optimize Screen Transitions”Use headerShown: false for tabs with stack navigators to avoid double headers.
4. Implement Back Button Handling
Section titled “4. Implement Back Button Handling”Handle Android back button appropriately:
import { useRouter } from 'expo-router';import { BackHandler } from 'react-native';
useEffect(() => { const backHandler = BackHandler.addEventListener( 'hardwareBackPress', () => { router.back(); return true; } ); return () => backHandler.remove();}, []);Feature-Specific Navigation Flows
Section titled “Feature-Specific Navigation Flows”Make a Recipe Flow
Section titled “Make a Recipe Flow”The “Make a Recipe” feature is a guided 4-step flow under recipes/make/[id]/. It walks the user through checking inventory, selecting product instances, following instructions step by step, and recording consumption.
recipes/make/[id]/├── index.tsx # Step 1: Ingredient availability check│ # Shows in-stock / low / missing per ingredient│ # Option to add missing items to shopping list├── select-instances.tsx # Step 2: Choose product instances│ # For ingredients with multiple products, user picks which bottle├── steps.tsx # Step 3: Guided step-by-step making mode│ # Alternates between ingredient steps and instruction steps│ # Timer support for timed instructions│ # Check-off for each ingredient as poured└── complete.tsx # Step 4: Completion summary # Shows what was deducted from inventory # Highlights any products now low/emptyNavigation entry point:
router.push(`/recipes/make/${recipeId}`);State between steps:
Step 3 → Step 4 passes completion state via store/makeCompletionStore.ts (an in-memory store) to avoid URL length limits:
import { setMakeCompletion, getMakeCompletion } from '@/store/makeCompletionStore';
// In steps.tsx – after applying consumptionsetMakeCompletion({ recipeId, recipeName, deductions, lowStockAfter });router.replace(`/recipes/make/${id}/complete`);
// In complete.tsxconst completion = getMakeCompletion();Batch Cocktails Flow
Section titled “Batch Cocktails Flow”Batch cocktails are pre-made, large-quantity preparations tracked across events. The flow lives at recipes/batch/.
recipes/batch/├── index.tsx # List of all batched cocktails with summary stats and low-stock alerts├── create.tsx # Create a new batch (select recipe, set serving count, storage location)└── [id].tsx # Batch detail – status, servings tracker, storage infoBatch status values: preparing → ready → serving → depleted / expired
Event-specific batch management is accessible from the Events tab at events/batch-management.tsx.
Inventory Sub-sections
Section titled “Inventory Sub-sections”The Inventory tab contains five independently navigable sub-sections, each with their own stack layout:
| Sub-section | Route prefix | Description |
|---|---|---|
| Products | /inventory/products/ | Physical bar products with barcode/UPC support |
| Ingredients | /inventory/ingredients/ | Abstract ingredient management |
| Equipment | /inventory/equipment/ | Bar equipment (shakers, strainers, etc.) |
| Glassware | /inventory/glassware/ | Glassware collection |
| Tools | /inventory/tools/ | Bar tools (jiggers, muddlers, etc.) |
Shopping lists are embedded in the inventory section at /inventory/shopping/.
Inventory Utility Screens
Section titled “Inventory Utility Screens”| Screen | Route | Description |
|---|---|---|
| Quick Update | /inventory/quick-update | Rapidly update product levels |
| Cost Analytics | /inventory/cost-analytics | Total value, spending, price trends |
| Export Data | /inventory/export | Export products/ingredients/shopping as JSON or CSV |
| Import Data | /inventory/import | Import inventory from exported files |
| View All | /inventory/view-all | Flat view of all inventory items |
Settings Screens
Section titled “Settings Screens”The Settings tab has two screens:
settings/├── index.tsx # App settings (preferences, data management, legal links)└── user-profile.tsx # User profile editor (name, email, phone with validation)Root Layout Startup Sequence
Section titled “Root Layout Startup Sequence”app/_layout.tsx orchestrates the startup sequence before the tab navigator mounts:
- Font loading – SpaceMono + FontAwesome icon fonts
- Local storage hydration – Calls
hydrateFromLocalStorage()which migrates AsyncStorage → MMKV on first run, then loads all domain data into memory - Splash screen – Hidden after hydration completes
- Keep-awake – Activates
expo-keep-awakeon native platforms (screen stays on during events/bar service)
Last Modified
Section titled “Last Modified”2026-03-06