Skip to main content

Browser the Cat

Browser the Cat is BookWish's friendly bookstore cat mascot who helps users discover features and provides contextual guidance throughout the app.

Character Overview

Browser is a helpful, warm, and friendly cat who lives in the BookWish bookstore. He appears at key moments to offer tips, celebrate achievements, and make the app experience more delightful and human.

Personality Traits:

  • Helpful but not intrusive
  • Warm and encouraging
  • Playful but professional
  • Book-loving and knowledgeable

Visual Design

Appearance

Browser appears as a Lottie animation positioned in the bottom-left corner of the screen, accompanied by a speech bubble containing his message.

Visual Properties:

  • Animation size: 80x80 pixels
  • Position: Bottom-left (100px from bottom, 16px padding)
  • Speech bubble: Dark blue (inkBlue) with white text
  • Speech bubble radius: 16px
  • Shadow: Subtle drop shadow for depth

Animation States

Browser has five distinct animation states that convey different moods and contexts:

AnimationUsageContext
idleDefault resting stateWhen no specific emotion needed
speakingProviding hints or informationDefault for most messages
thinkingLoading or processingError states, awaiting response
wavingGreeting usersOnboarding, first visits
sleepingPassive presenceUnused currently

Animation Files:

  • /app/assets/lottie/browser_idle.json
  • /app/assets/lottie/browser_speaking.json
  • /app/assets/lottie/browser_thinking.json
  • /app/assets/lottie/browser_waving.json
  • /app/assets/lottie/browser_sleeping.json

Implementation

Widget Structure

Browser is implemented as a persistent overlay widget (BrowserOverlay) that appears above the main content.

File: /app/lib/ui/widgets/browser_overlay.dart

// Browser appears when enabled, visible, and has a message
if (!browserState.isEnabled || !browserState.isVisible || browserState.message == null) {
return const SizedBox.shrink();
}

Browser State

File: /app/lib/state/browser_state.dart

class BrowserState {
final bool isVisible; // Currently showing
final bool isEnabled; // User preference (can be disabled)
final String? message; // Current message text
final BrowserAnimation animation; // Animation state
final BrowserContext context; // Usage context
final Duration? autoDismissAfter; // Auto-hide timer
}

Browser Properties

PropertyTypeDescription
isVisibleboolWhether Browser is currently displayed
isEnabledboolUser preference setting (persisted)
messageString?Text to display in speech bubble
animationBrowserAnimationCurrent animation state
contextBrowserContextUsage context for analytics
autoDismissAfterDuration?Optional auto-hide delay

Display Sizes

Size TypeDimensionsUsage
Standard80x80pxMain overlay appearance
Error State100x100pxLarger size in BwErrorState widget

Context Appearances

Onboarding

When: First launch of the app Animation: waving Message: "Hi, I'm Browser. I'm the BookWish bookstore cat." Duration: 5 seconds auto-dismiss

Implementation: /app/lib/ui/pages/auth/onboarding_page.dart

ref.read(browserNotifierProvider.notifier).show(
message: "Hi, I'm Browser. I'm the BookWish bookstore cat.",
context: BrowserContext.onboarding,
animation: BrowserAnimation.waving,
autoDismiss: const Duration(seconds: 5),
);

Tab Hints

Browser appears on first visit to major tabs to introduce functionality.

Contexts:

  • wish_tab_first - First visit to Wish tab
  • share_tab_first - First visit to Share tab
  • read_tab_first - First visit to Read tab

Animation: speaking Duration: 5 seconds auto-dismiss Behavior: Shows once per hint key, tracked in local storage

Empty States

Browser can appear in error states to provide a friendlier experience.

When: Data loading fails Animation: thinking Message: "Let me help you try that again!" Implementation: Optional in BwErrorState widget

BwErrorState(
title: 'Something went wrong',
subtitle: 'Check your connection',
onRetry: _handleRetry,
showBrowser: true,
)

Achievements & Celebrations

When: User completes significant actions Animation: speaking (could use waving for extra enthusiasm) Context: BrowserContext.celebration Example: "Great job adding your first book to your wishlist!"

Confirmations

When: Pre-purchase or important actions Animation: speaking Context: BrowserContext.confirmation Purpose: Provide helpful context before checkout

Loading States

When: Waiting for operations to complete Animation: thinking Context: BrowserContext.loading Purpose: Indicate processing with friendly presence

Settings Integration

Users can control Browser's appearance through the Preferences tab in Settings.

File: /app/lib/ui/overlays/settings_overlay.dart

SwitchListTile(
title: Text('Show Browser'),
subtitle: Text('Browser the cat helps you discover features'),
value: browserState.isEnabled,
onChanged: (value) {
ref.read(browserNotifierProvider.notifier).setEnabled(value);
},
)

User Control:

  • Users can disable Browser entirely
  • Preference is persisted in local storage (Hive)
  • When disabled, Browser never appears
  • Setting is accessible under Settings > Preferences > Helper

Animation Guidelines

When to Use Each Animation

  1. Waving - First impressions, warm welcomes

    • Onboarding
    • After long absence
    • Special celebrations
  2. Speaking - Default for communication

    • Feature hints
    • Confirmations
    • General guidance
    • Celebrations
  3. Thinking - Processing or uncertainty

    • Error states
    • Loading operations
    • Complex decisions
  4. Idle - Passive presence

    • Default fallback
    • Minimal distraction needed
  5. Sleeping - Reserved for future use

    • Night mode?
    • Inactive periods?

Animation Best Practices

  • Keep animations smooth and brief (under 3 seconds loop)
  • Ensure animations work well at 80x80px size
  • Test animations on various devices and screen densities
  • Maintain consistent character design across all animations
  • Ensure animations don't interfere with touch targets

Writing Browser's Voice

Tone Guidelines

Browser speaks in first person and maintains a consistent, helpful tone:

  • Friendly but professional - "Hi, I'm Browser" not "Hey there!"
  • Brief and clear - Short sentences, under 20 words when possible
  • Action-oriented - Focus on what users can do
  • Encouraging not demanding - Suggest, don't command
  • Bookish references welcome - Cat and book puns are on-brand

Example Phrases

Good Examples:

  • "Hi, I'm Browser. I'm the BookWish bookstore cat."
  • "Tap here to add books to your wishlist."
  • "Great job adding your first book!"
  • "This is where you'll find your reading communities."
  • "Let me help you try that again!"

Avoid:

  • "YOU MUST DO THIS NOW!" (Too demanding)
  • "This is the wishlist tab where you can add books..." (Too verbose)
  • "OMG AMAZING!!!" (Too informal)
  • Technical jargon or complex language
  • Negative or discouraging language

Message Length

  • Optimal: 10-15 words
  • Maximum: 25 words
  • Longer messages should be split or simplified

Hint Best Practices

  1. Show once - Use showOnceHint() for feature introductions
  2. Time wisely - 5 seconds auto-dismiss for hints
  3. Context matters - Show hints when users need them, not randomly
  4. Allow dismissal - Always let users tap to dismiss
  5. Respect preferences - Honor the disabled setting

Technical Implementation

Showing Browser

// Simple show
ref.read(browserNotifierProvider.notifier).show(
message: 'Your message here',
context: BrowserContext.tabHint,
animation: BrowserAnimation.speaking,
autoDismiss: const Duration(seconds: 5),
);

// Show once (tracked hint)
await ref.read(browserNotifierProvider.notifier).showOnceHint(
hintKey: BrowserHints.wishTabFirstVisit,
message: 'Create wishlists for books you want to read!',
context: BrowserContext.tabHint,
animation: BrowserAnimation.speaking,
);

Hiding Browser

// Manual hide
ref.read(browserNotifierProvider.notifier).hide();

// Auto-dismiss (specify when showing)
autoDismiss: const Duration(seconds: 5)

Hint Tracking

Hints are tracked in local storage to prevent repeat displays.

File: /app/lib/utils/browser_hints.dart

Predefined Hint Keys:

  • wish_tab_first - Wish tab introduction
  • share_tab_first - Share tab introduction
  • read_tab_first - Read tab introduction
  • first_wishlist_add - First wishlist item added
  • pre_purchase - Pre-checkout confirmation

Error Handling

Browser includes fallback UI if Lottie animations fail to load:

errorBuilder: (context, error, stackTrace) {
return Container(
width: 80,
height: 80,
decoration: BoxDecoration(
color: AppColors.tealEdge,
borderRadius: BorderRadius.circular(40),
),
child: const Icon(
CupertinoIcons.paw,
color: Colors.white,
size: 40,
),
);
}

Displays a paw icon in a teal circle if animation files are missing or corrupt.

Accessibility Considerations

Browser is primarily a visual enhancement and should not be required for app functionality.

  • Browser can be disabled entirely by users
  • All information conveyed by Browser should also be available through standard UI
  • Browser messages are readable text (not embedded in animations)
  • Tappable to dismiss (meets minimum touch target size)
  • Consider adding semantic labels for screen readers in future updates

Future Enhancements

Potential improvements to the Browser system:

  1. Sleeping animation usage - Activate during inactive periods or night mode
  2. More animations - Reading, jumping, playing for more contexts
  3. Screen reader support - Add semantic labels and announcements
  4. Customization - Allow users to choose different mascots
  5. Context awareness - More intelligent hint timing based on user behavior
  6. Achievement system - Special Browser appearances for milestones
  7. Accessibility improvements - Reduced motion alternative animations