# Epic 12: Mobile Experience Overhaul
Status: ready-for-dev
## Epic Overview
**Epic Goal:** Transform Keep's interface into a truly mobile-first experience while keeping the desktop interface unchanged.
**User Pain Points:**
- Interface overflows device screen (Galaxy S22 Ultra)
- Note cards too complex and large for mobile
- Masonry grid layout not suitable for small screens
- Too much visual information on mobile
- No mobile-specific UX patterns
**Success Criteria:**
- ✅ No horizontal/vertical overflow on any mobile device
- ✅ Simplified note cards optimized for mobile viewing
- ✅ Mobile-first layouts that adapt to screen size
- ✅ Smooth 60fps animations on mobile
- ✅ Touch-friendly interactions (44x44px min targets)
- ✅ Desktop interface completely unchanged
- ✅ Tested on Galaxy S22 Ultra and various mobile devices
---
## Story 12.1: Mobile Note Cards Simplification
**Status:** ready-for-dev
## Story
As a **mobile user**,
I want **simple, compact note cards**,
so that **I can see more notes and scan the interface quickly**.
## Acceptance Criteria
1. **Given** a user is viewing notes on a mobile device (< 768px),
2. **When** notes are displayed,
3. **Then** the system should:
- Display notes in a vertical list (NOT masonry grid)
- Show simple card with title + 2-3 lines of preview only
- Minimize badges and indicators (pin, labels, notebook)
- Hide image thumbnails on mobile
- Ensure touch targets are minimum 44x44px
- Implement swipe-to-delete or quick actions
## Tasks / Subtasks
- [ ] Create mobile variant of NoteCard component
- [ ] Create `MobileNoteCard.tsx` component
- [ ] Vertical card layout (not masonry)
- [ ] Simplified content: title + 2-3 lines preview
- [ ] Reduced badges (pin icon, label count only)
- [ ] No image thumbnails on mobile
- [ ] Implement mobile list layout
- [ ] Replace masonry grid with simple list on mobile
- [ ] 100% width cards on mobile
- [ ] Adequate spacing between cards
- [ ] Add mobile touch interactions
- [ ] Tap to open note (full screen)
- [ ] Long-press for actions menu
- [ ] Swipe gestures (left/right actions)
- [ ] Ensure responsive design
- [ ] Mobile cards: < 768px
- [ ] Desktop cards: >= 768px (UNCHANGED)
- [ ] Smooth transition between breakpoints
- [ ] Test on mobile devices
- [ ] Galaxy S22 Ultra (main target)
- [ ] iPhone SE (small screen)
- [ ] Android various sizes
- [ ] Portrait and landscape
## Dev Notes
### Mobile Card Design Requirements
**Layout:**
```
┌─────────────────────────────┐
│ [PIN] Title │ <- Title row with pin icon
│ Preview text... │ <- 2-3 lines max
│ [📎] [🏷️] • 2d ago │ <- Footer: indicators + time
└─────────────────────────────┘
```
**Typography (Mobile):**
- Title: 16-18px, semibold, 1 line clamp
- Preview: 14px, regular, 2-3 lines clamp
- Footer text: 12px, lighter color
**Spacing (Mobile):**
- Card padding: 12-16px
- Gap between cards: 8-12px
- Touch targets: 44x44px minimum
**Color & Contrast:**
- Light background on cards
- Good contrast for readability
- Subtle hover state
### Swipe Gestures Implementation
**Swipe Left → Archive**
```typescript
// Use react-swipeable or similar
handleArchive(note)}
onSwipeRight={() => handlePin(note)}
threshold={50}
>
```
**Swipe Right → Pin**
**Long Press → Action Menu**
### Responsive Logic
```typescript
// In page.tsx
const isMobile = useMediaQuery('(max-width: 768px)')
{isMobile ? (
{notes.map(note => )}
) : (
// Existing desktop behavior
)}
```
### Files to Create
- `keep-notes/components/mobile-note-card.tsx` - New mobile-specific component
- `keep-notes/components/swipeable-wrapper.tsx` - Swipe gesture wrapper
### Files to Modify
- `keep-notes/app/(main)/page.tsx` - Conditional rendering for mobile/desktop
- `keep-notes/components/note-card.tsx` - No changes (keep desktop version intact)
---
## Story 12.2: Mobile-First Layout
**Status:** ready-for-dev
## Story
As a **mobile user**,
I want **an interface optimized for my small screen**,
so that **everything is accessible without zooming or horizontal scrolling**.
## Acceptance Criteria
1. **Given** a user is using the app on a mobile device,
2. **When** viewing any page,
3. **Then** the system should:
- Use 100% width containers on mobile
- Reduce margins/padding on mobile
- Use compact header on mobile (60-80px vs 80px)
- Simplified note input on mobile
- Eliminate ALL horizontal overflow
- Prevent double scroll (menu + page)
- Maintain existing desktop layout unchanged
## Tasks / Subtasks
- [ ] Create responsive container layout
- [ ] Use `w-full` on mobile containers
- [ ] Reduce padding on mobile (px-4 vs px-6)
- [ ] Remove max-width constraints on mobile
- [ ] Optimize header for mobile
- [ ] Reduce header height on mobile (60px vs 80px)
- [ ] Compact search bar on mobile
- [ ] Hide non-essential controls on mobile
- [ ] Simplify note input on mobile
- [ ] Use minimal input on mobile
- [ ] Placeholder text: "Add a note..."
- [ ] Full FAB button for creating notes
- [ ] Fix horizontal overflow issues
- [ ] Use `overflow-x-hidden` on body
- [ ] Ensure no fixed widths on mobile
- [ ] Test on Galaxy S22 Ultra (main target)
- [ ] Test on various screen sizes
- [ ] Small phones: 320-375px
- [ ] Medium phones: 375-428px
- [ ] Large phones: 428px+ (Galaxy S22 Ultra)
- [ ] Tablets: 768-1024px
## Dev Notes
### Breakpoint Strategy
```css
/* Mobile First Approach */
/* Mobile: 0-767px */
.container {
width: 100%;
padding: 0.5rem 1rem;
}
/* Tablet: 768px+ */
@media (min-width: 768px) {
.container {
max-width: 1280px;
padding: 2rem 3rem;
}
}
```
### Header Optimization
**Desktop (current):**
- Height: 80px
- Padding: px-6 lg:px-12
- Search: max-w-2xl
**Mobile (new):**
- Height: 60px
- Padding: px-4
- Search: flex-1, shorter
### Note Input Simplification
**Desktop:** Full card with title, content, options
**Mobile:**
```typescript
```
### Files to Create
- `keep-notes/components/fab-button.tsx` - Floating Action Button
- `keep-notes/hooks/use-media-query.ts` - Hook for responsive queries
### Files to Modify
- `keep-notes/components/header.tsx` - Responsive header
- `keep-notes/components/note-input.tsx` - Mobile variant
- `keep-notes/app/(main)/page.tsx` - Container adjustments
- `keep-notes/app/globals.css` - Responsive utilities
---
## Story 12.3: Mobile Bottom Navigation
**Status:** ready-for-dev
## Story
As a **mobile user**,
I want **easy-to-access navigation tabs**,
so that **I can quickly switch between views**.
## Acceptance Criteria
1. **Given** a user is on a mobile device,
2. **When** navigating the app,
3. **Then** the system should:
- Display horizontal tabs at bottom of screen (Bottom Navigation)
- Show 3-4 tabs max (Notes, Favorites, Settings)
- Clearly indicate active tab
- Animate transitions between tabs
- NOT affect desktop interface (unchanged)
## Tasks / Subtasks
- [ ] Create Bottom Navigation component
- [ ] Create `MobileBottomNav.tsx` component
- [ ] 3 tabs: Notes, Favorites, Settings
- [ ] Icons for each tab
- [ ] Active state indicator
- [ ] Implement tab navigation logic
- [ ] Switch between views (Notes, Favorites, Settings)
- [ ] Maintain state on tab switch
- [ ] Animate transitions
- [ ] Style for mobile UX
- [ ] Fixed position at bottom
- [ ] Height: 56-64px (standard mobile nav)
- [ ] Safe area padding for iPhone notch
- [ ] Material Design / iOS Human Guidelines compliant
- [ ] Test on mobile devices
- [ ] Android (including Galaxy S22 Ultra)
- [ ] iOS (iPhone SE, 14 Pro)
- [ ] Different screen orientations
- [ ] Ensure desktop unchanged
- [ ] Only show on mobile (< 768px)
- [ ] No CSS conflicts with desktop layout
## Dev Notes
### Bottom Navigation Design
**Layout:**
```
┌─────────────────────────────────┐
│ [📝 Notes] [⭐ Favs] [⚙️] │
└─────────────────────────────────┘
^ Active (with underline/indicator)
```
**Material Design Spec:**
- Height: 56px minimum
- Icons: 24x24px
- Labels: 12-14px (can be hidden on very small screens)
- Active indicator: 4px height bar below icon
**Implementation:**
```typescript
// keep-notes/components/MobileBottomNav.tsx
'use client'
import { Home, Star, Settings } from 'lucide-react'
import Link from 'next/link'
import { usePathname } from 'next/navigation'
export function MobileBottomNav() {
const pathname = usePathname()
const tabs = [
{ icon: Home, label: 'Notes', href: '/' },
{ icon: Star, label: 'Favorites', href: '/favorites' },
{ icon: Settings, label: 'Settings', href: '/settings' },
]
return (
)
}
```
### Safe Area Padding
For iPhone notch (notch devices):
```css
padding-bottom: env(safe-area-inset-bottom, 0);
```
### Files to Create
- `keep-notes/components/mobile-bottom-nav.tsx` - Bottom navigation component
### Files to Modify
- `keep-notes/app/layout.tsx` - Add bottom nav to layout
- `keep-notes/app/(main)/page.tsx` - Adjust layout spacing
---
## Story 12.4: Full-Screen Mobile Note Editor
**Status:** ready-for-dev
## Story
As a **mobile user**,
I want **to create notes in full-screen mode**,
so that **I can focus on content without distractions**.
## Acceptance Criteria
1. **Given** a user is on a mobile device,
2. **When** they want to create a note,
3. **Then** the system should:
- Show a Floating Action Button (FAB) to create note
- Open full-screen note editor when tapped
- Display title and content fields optimized for mobile
- Place action buttons at bottom of screen
- Animate smoothly back to list view
- NOT affect desktop experience
## Tasks / Subtasks
- [ ] Create Floating Action Button (FAB)
- [ ] Create `fab-button.tsx` component
- [ ] Fixed position: bottom-right of screen
- [ ] Circle button: 56x56px
- [ ] Plus icon (+)
- [ ] Shadow and elevation
- [ ] Ripple effect on tap
- [ ] Create full-screen note editor
- [ ] Create `MobileNoteEditor.tsx` component
- [ ] Full viewport: `h-screen w-screen`
- [ ] Title field at top
- [ ] Content field takes remaining space
- [ - Action buttons at bottom (Save, Cancel)
- [ ] Optimize mobile keyboard handling
- [ ] Auto-focus on title when opened
- [ ] Keyboard-avoiding behavior
- [ ] Smooth keyboard transitions
- [ ] Implement save & close flow
- [ ] Save note on close
- [ ] Animated transition back to list
- [ ] Auto-scroll to new note in list
- [ ] Test on mobile devices
- [ ] Galaxy S22 Ultra
- [ ] iPhone
- [ ] Android various sizes
- [ ] Portrait and landscape
## Dev Notes
### FAB Design (Material Design)
```typescript
// keep-notes/components/fab-button.tsx
'use client'
import { Plus } from 'lucide-react'
interface FabButtonProps {
onClick: () => void
}
export function FabButton({ onClick }: FabButtonProps) {
return (
)
}
```
**Specs:**
- Size: 56x56px (standard FAB)
- Elevation: 6px (shadow-lg)
- Animation: 300ms
- Ripple effect on tap
### Full-Screen Editor Layout
```
┌─────────────────────────────┐
│ [X] │ <- Top bar: Close button
│ Title │ <- Title input
├─────────────────────────────┤
│ │
│ Content area │ <- Takes remaining space
│ (auto-expands) │
│ │
├─────────────────────────────┤
│ [Cancel] [Save] │ <- Bottom bar: Actions
└─────────────────────────────┘
```
### Keyboard Avoidance
```typescript
import { KeyboardAvoidingView } from 'react-native' // or web equivalent
// On web, use CSS:
.keyboard-avoiding {
padding-bottom: 200px; // Estimated keyboard height
transition: padding-bottom 0.3s;
}
.keyboard-visible {
padding-bottom: 0;
}
```
### Files to Create
- `keep-notes/components/fab-button.tsx` - Floating Action Button
- `keep-notes/components/mobile-note-editor.tsx` - Full-screen editor
### Files to Modify
- `keep-notes/app/(main)/page.tsx` - Add FAB to mobile layout
---
## Story 12.5: Mobile Quick Actions (Swipe Gestures)
**Status:** ready-for-dev
## Story
As a **mobile user**,
I want **quick swipe actions on notes**,
so that **I can manage notes efficiently**.
## Acceptance Criteria
1. **Given** a user is viewing notes on a mobile device,
2. **When** they swipe on a note card,
3. **Then** the system should:
- Swipe left: Archive the note
- Swipe right: Pin the note
- Long press: Show action menu
- Provide haptic feedback on swipe
- Show undo toast after action
- NOT affect desktop (no swipe on desktop)
## Tasks / Subtasks
- [ ] Implement swipe gesture library
- [ ] Integrate `react-swipeable` or `use-swipeable`
- [ ] Configure thresholds and velocities
- [ ] Handle touch events properly
- [ ] Add swipe actions
- [ ] Swipe left → Archive
- [ ] Swipe right → Pin/Unpin
- [ ] Long press → Action menu
- [ ] Add visual feedback
- [ ] Swipe indicator (icon appears)
- [ - Color change during swipe
- [ - Smooth animation
- [ - Snap back if not swiped enough
- [ ] Implement haptic feedback
- [ ] Vibrate on swipe (50-100ms)
- [ ] Vibrate on action complete
- [ ] Respect device haptic settings
- [ ] Add undo functionality
- [ ] Show toast after action
- [ ] Undo button in toast
- [ - Revert action on undo tap
- [ ] Test on mobile devices
- [ ] Android (various sensitivity)
- [ ] iOS (smooth swipes)
- [ - Different screen sizes
## Dev Notes
### Swipe Implementation
```typescript
// Using use-swipeable
import { useSwipeable } from 'react-swipeable'
export function SwipeableNoteCard({ note }: { note: Note }) {
const handlers = useSwipeable({
onSwipedLeft: () => handleArchive(note),
onSwipedRight: () => handlePin(note),
preventDefaultTouchmoveEvent: true,
trackMouse: false, // Touch only on mobile
})
return (
)
}
```
### Visual Feedback During Swipe
```css
/* Swipe left (archive) */
.swipe-left {
background: linear-gradient(90deg, #f59e0b 0%, transparent 100%);
}
/* Swipe right (pin) */
.swipe-right {
background: linear-gradient(-90deg, #fbbf24 0%, transparent 100%);
}
```
### Haptic Feedback
```typescript
// Web Vibration API
if ('vibrate' in navigator) {
navigator.vibrate(50) // 50ms vibration
}
```
### Undo Toast
```typescript
import { toast } from 'sonner'
const handleArchive = async (note: Note) => {
await toggleArchive(note.id)
toast.success('Note archived', {
action: {
label: 'Undo',
onClick: () => toggleArchive(note.id)
}
})
}
```
### Files to Create
- `keep-notes/components/swipeable-note-card.tsx` - Swipe wrapper
- `keep-notes/hooks/use-swipe-actions.ts` - Swipe logic hook
### Files to Modify
- `keep-notes/components/mobile-note-card.tsx` - Wrap in swipeable
---
## Story 12.6: Mobile Typography & Spacing
**Status:** ready-for-dev
## Story
As a **mobile user**,
I want **readable text and comfortable spacing**,
so that **the interface is pleasant to use**.
## Acceptance Criteria
1. **Given** a user is viewing the app on a mobile device,
2. **When** reading any text,
3. **Then** the system should:
- Use mobile-optimized font sizes (min 16px)
- Use generous line heights (1.5-1.6)
- Have comfortable padding for touch
- Maintain good contrast ratios
- NOT affect desktop typography
## Tasks / Subtasks
- [ ] Define mobile typography system
- [ ] Base font size: 16px (prevents iOS zoom)
- [ ] Headings: 18-24px
- [ ] Body text: 16px
- [ ] Small text: 14px
- [ ] Line heights: 1.5-1.6
- [ ] Optimize spacing for mobile
- [ ] Card padding: 12-16px
- [ ] Gap between elements: 8-12px
- [ - Touch targets: 44x44px minimum
- [ ] Ensure contrast compliance
- [ ] WCAG AA: 4.5:1 ratio
- [ ] Dark mode contrast
- [ - Test on mobile screens
- [ ] Create utility classes
- [ ] `text-mobile-base`: 16px
- [ - `text-mobile-sm`: 14px
- [ - `text-mobile-lg`: 18px
- [ ] Test on mobile devices
- [ ] Various screen sizes
- [ ] Different orientations
- [ - Accessibility check
## Dev Notes
### Typography Scale (Mobile)
```css
/* Mobile Typography */
:root {
--mobile-font-base: 16px;
--mobile-font-sm: 14px;
--mobile-font-lg: 18px;
--mobile-font-xl: 24px;
--line-height-relaxed: 1.6;
--line-height-normal: 1.5;
}
.text-mobile-base { font-size: var(--mobile-font-base); }
.text-mobile-sm { font-size: var(--mobile-font-sm); }
.text-mobile-lg { font-size: var(--mobile-font-lg); }
.text-mobile-xl { font-size: var(--mobile-font-xl); }
.leading-mobile { line-height: var(--line-height-relaxed); }
```
### Why 16px Minimum?
iOS Safari automatically zooms if font-size < 16px on input fields. Setting base font to 16px prevents this.
### Contrast Ratios (WCAG AA)
- Normal text: 4.5:1
- Large text (18pt+): 3:1
- UI components: 3:1
### Spacing System (Mobile)
```css
:root {
--spacing-mobile-xs: 4px;
--spacing-mobile-sm: 8px;
--spacing-mobile-md: 12px;
--spacing-mobile-lg: 16px;
--spacing-mobile-xl: 20px;
}
```
### Files to Modify
- `keep-notes/app/globals.css` - Typography and spacing utilities
- `keep-notes/components/mobile-note-card.tsx` - Apply mobile typography
- `keep-notes/components/mobile-bottom-nav.tsx` - Apply mobile spacing
---
## Story 12.7: Mobile Performance Optimization
**Status:** ready-for-dev
## Story
As a **mobile user**,
I want **fluid animations and fast performance**,
so that **the app is responsive and smooth**.
## Acceptance Criteria
1. **Given** a user is using the app on a mobile device,
2. **When** performing any action,
3. **Then** the system should:
- Animate at 60fps consistently
- Have no layout shifts
- Show loading skeletons on mobile
- Lazy load images
- Use optimized debounce for mobile
- Test and verify on Galaxy S22 Ultra
## Tasks / Subtasks
- [ ] Optimize animations for mobile
- [ ] Use CSS transforms (GPU-accelerated)
- [ ] Limit animation duration to 300ms max
- [ ] Respect `prefers-reduced-motion`
- [ ] Eliminate layout shifts
- [ ] Use skeleton loaders instead of empty states
- [ - Reserve space for content
- [ ] Use loading states
- [ ] Implement lazy loading
- [ ] Lazy load images
- [ ] Intersection Observer for off-screen content
- [ - Code splitting for mobile components
- [ ] Optimize event handlers
- [ ] Debounce search on mobile (150-200ms)
- [ - Passive event listeners where possible
- [ - Throttle scroll events
- [ ] Test on real devices
- [ ] Galaxy S22 Ultra (main target)
- [ ] iPhone SE, 14 Pro
- [ ] Android various models
- [ ] Measure FPS and performance
- [ ] Performance monitoring
- [ ] Add performance marks
- [ - Monitor Core Web Vitals
- [ - Log slow interactions
## Dev Notes
### GPU-Accelerated Animations
```css
/* Good: GPU-accelerated */
.element {
transform: translateX(0);
opacity: 1;
}
/* Bad: Triggers reflow */
.element {
left: 0;
width: 100%;
}
```
### Skeleton Loading
```typescript
// keep-notes/components/note-skeleton.tsx
export function NoteSkeleton() {
return (
```
### Debounce Optimization
```typescript
// Keep shorter debounce on mobile for responsiveness
const debounceTime = isMobile ? 150 : 300
const debouncedSearch = useDebounce(searchQuery, debounceTime)
```
### Performance Measurement
```typescript
// Performance API
performance.mark('render-start')
// ... component renders
performance.mark('render-end')
performance.measure('render', 'render-start', 'render-end')
// Log slow renders (> 16ms = < 60fps)
const measure = performance.getEntriesByName('render')[0]
if (measure.duration > 16) {
console.warn('Slow render:', measure.duration, 'ms')
}
```
### Files to Create
- `keep-notes/components/note-skeleton.tsx` - Skeleton loader
- `keep-notes/hooks/use-visibility.ts` - Intersection Observer hook
### Files to Modify
- `keep-notes/components/masonry-grid.tsx` - Performance optimizations
- `keep-notes/components/mobile-note-card.tsx` - GPU-accelerated animations
- `keep-notes/app/(main)/page.tsx` - Skeleton loading states
---
## Epic Summary
**Stories in Epic 12:**
1. 12-1: Mobile Note Cards Simplification
2. 12-2: Mobile-First Layout
3. 12-3: Mobile Bottom Navigation
4. 12-4: Full-Screen Mobile Note Editor
5. 12-5: Mobile Quick Actions (Swipe Gestures)
6. 12-6: Mobile Typography & Spacing
7. 12-7: Mobile Performance Optimization
**Total Stories:** 7
**Estimated Complexity:** High (comprehensive mobile overhaul)
**Priority:** High (critical UX issue on mobile)
**Dependencies:**
- Story 12-1 should be done first (foundational)
- Story 12-2 depends on 12-1
- Story 12-3, 12-4, 12-5 depend on 12-1
- Story 12-6 depends on 12-1
- Story 12-7 can be done in parallel
**Testing Requirements:**
- ✅ Test on Galaxy S22 Ultra (main target from user feedback)
- ✅ Test on iPhone SE (small screen)
- ✅ Test on iPhone 14 Pro (large screen)
- ✅ Test on Android various sizes
- ✅ Test in portrait and landscape
- ✅ Verify desktop unchanged (0 regression)
**Success Metrics:**
- Zero horizontal/vertical overflow on mobile
- 60fps animations on mobile devices
- Touch targets meet minimum 44x44px
- Desktop functionality 100% unchanged
- User satisfaction on mobile UX
---
## Dev Agent Record
### Agent Model Used
claude-sonnet-4-5-20250929
### Completion Notes List
- [x] Created Epic 12 with 7 comprehensive user stories
- [x] Documented mobile UX requirements
- [x] Detailed each story with tasks and dev notes
- [x] Created file list for implementation
- [ ] Epic pending implementation
### File List
**Epic Files:**
- `_bmad-output/implementation-artifacts/12-mobile-experience-overhaul.md` (this file)
**Files to Create (across all stories):**
- `keep-notes/components/mobile-note-card.tsx`
- `keep-notes/components/swipeable-note-card.tsx`
- `keep-notes/components/fab-button.tsx`
- `keep-notes/components/mobile-bottom-nav.tsx`
- `keep-notes/components/mobile-note-editor.tsx`
- `keep-notes/components/note-skeleton.tsx`
- `keep-notes/hooks/use-media-query.ts`
- `keep-notes/hooks/use-swipe-actions.ts`
- `keep-notes/hooks/use-visibility.ts`
**Files to Modify:**
- `keep-notes/app/(main)/page.tsx`
- `keep-notes/app/layout.tsx`
- `keep-notes/components/header.tsx`
- `keep-notes/components/note-input.tsx`
- `keep-notes/components/masonry-grid.tsx`
- `keep-notes/app/globals.css`
---
*Created: 2026-01-17*
*Based on user feedback from Galaxy S22 Ultra testing*
*Desktop Interface: NO CHANGES - Mobile Only*