Skip to main content

What It Does

Global search across all content types using PostgreSQL’s pg_trgm extension for fuzzy trigram matching.

User Flow

1

Open Search

Tap Search tab → app/(tabs)/search.tsx
2

Type Query

Search input with typewriter placeholder animation cycling through phrases (“Classic Chrome recipes”, “Portrait photography”, “Street photography”, “Fujifilm X-T5”, etc.). Minimum 2 characters to trigger search. Debounced via useDebouncesupabase.rpc('global_search', { p_query, p_type_filter, p_limit }).
3

Filter by Type

Icon-only filter tabs appear once query ≥ 2 characters. Active tab has 2px bottom border.
4

View Results

Content tabs (post/recipe/collection) show results in VirtualizedMasonryGrid with variant="imageOnly" cards. Creator tab shows CreatorCardList (horizontal layout with avatar, name, follow button) in a FlatList.

Search Scopes

Four filter tabs, icon-only (matching profile tab style):
TabIconContentView
PostsImageIconPosts onlyMasonry grid
RecipesFilmRecipes onlyMasonry grid
CollectionsLibraryBigCollections onlyMasonry grid
CreatorsUsersUser profilesList view (CreatorCardList)
Default tab is Posts. The typeFilter parameter is passed to the global_search RPC so it only scans the relevant table(s).

Empty & Loading States

  • Before typing: centered Search icon (48px) + “Search for recipes, posts, collections, or creators”
  • Loading: MasonryGridSkeleton with 6 items
  • No results: EmptyState with “No results found” / “We couldn’t find anything for [query]”
  • No results for specific tab: EmptyState with “No [type]s match [query]“

Components

ComponentPurpose
ContentCardRecipe/post/collection results (masonry grid, variant="imageOnly")
CreatorCardCreator result in masonry grid
CreatorCardListCreator result in list view (avatar, name, follow button)
VirtualizedMasonryGridMasonry layout for content results
MasonryGridSkeletonLoading skeleton
EmptyStateNo results state

Context

SearchProvider (src/context/SearchContext.tsx) — manages search query state, results, filters. Also exposes openSearch(query) used by MetadataPills to navigate to search with a pre-filled query.

Hooks

  • useSearch (src/hooks/useSearch.ts) — search logic
  • useDebounce (src/hooks/useDebounce.ts) — debounces search input

Data Access Pattern

The mobile app calls Supabase directly — supabase.rpc('global_search'). The web API route exists for the web client (Phase 2).

Web API Route (Phase 2)

GET /api/search
  • Query params: q (search term), type (optional filter: ‘recipe’, ‘post’, ‘collection’, ‘user’)
  • Calls global_search RPC

RPC Functions

FunctionParametersReturns
global_searchp_query (text), p_type_filter (optional), p_limit (30)JSON — results across all content types
check_username_availablep_username (text), p_exclude_user_id (optional)boolean — used for registration and profile edit

Database Extension

pg_trgm (installed in public schema) — provides trigram-based similarity matching for fuzzy search. Used by global_search RPC for % LIKE matching and similarity scoring.