Overview
Recipe Room uses Supabase RPC (Remote Procedure Call) functions for operations that require multiple queries, atomic transactions, or complex joins. These are defined as PostgreSQL functions in supabase/migrations/.
Content Listing Functions
get_discover_content_list
Fetches mixed content (recipes + posts) for the discover feed.
get_discover_content_list(
p_limit integer DEFAULT 20,
p_offset integer DEFAULT 0,
p_sort text DEFAULT 'recent',
p_current_user_id uuid DEFAULT NULL
) → json
Sort options: recent, trending, popular. Returns interleaved recipes and posts with author info, favorite/repost status, and images.
get_follow_content_list
Fetches content from users the current user follows.
get_follow_content_list(
p_limit integer DEFAULT 20,
p_offset integer DEFAULT 0,
p_current_user_id uuid DEFAULT NULL
) → json
get_posts_list / get_collections_list
Dedicated listing functions for posts and collections with sorting and pagination.
get_posts_list(p_limit, p_offset, p_sort, p_current_user_id) → json
get_collections_list(p_limit, p_offset, p_current_user_id) → json
There is no get_recipes_list RPC function. Recipe listing is handled through get_discover_content_list (which returns mixed content) or via direct Supabase table queries. There are also no database views like recipe_with_stats or collection_with_stats — all stats are denormalized directly on the parent tables.
Detail Functions
get_recipe_detail
get_recipe_detail(
p_recipe_id uuid,
p_current_user_id uuid DEFAULT NULL
) → json
Returns complete recipe data: settings, images, tags, tagged users, lightroom settings, author info, favorite/repost status, and comments.
get_post_detail
get_post_detail(
p_post_id uuid,
p_current_user_id uuid DEFAULT NULL
) → json
Returns post with images, tags, linked recipe/collection, author info, and engagement status.
get_collection_detail
get_collection_detail(
p_collection_id uuid,
p_current_user_id uuid DEFAULT NULL,
p_item_limit integer DEFAULT 20,
p_item_offset integer DEFAULT 0
) → json
Returns collection with paginated saved items (enriched with content details), author info, and engagement status.
Profile Functions
get_user_profile_data
The main profile endpoint — replaces 5+ API calls with one database round-trip.
get_user_profile_data(
p_username text,
p_current_user_id uuid DEFAULT NULL,
p_limit integer DEFAULT 8,
p_offset integer DEFAULT 0
) → json
Returns: user profile, recipes, posts, collections, follow status, and engagement counts.
get_user_profile_data_by_id
Same as get_user_profile_data but accepts a UUID instead of username. Used when you have the user ID but not the username (e.g., from a notification or follow relationship).
get_user_profile_data_by_id(
p_user_id uuid,
p_current_user_id uuid DEFAULT NULL,
p_limit integer DEFAULT 8,
p_offset integer DEFAULT 0
) → json
get_user_profile_collections / get_user_profile_collections_by_id
Fetch just the collections for a user profile. Used for paginated collection loading on profile pages without re-fetching the full profile.
get_user_profile_collections(
p_username text,
p_limit integer DEFAULT 8,
p_offset integer DEFAULT 0
) → json
get_user_profile_collections_by_id(
p_user_id uuid,
p_limit integer DEFAULT 8,
p_offset integer DEFAULT 0
) → json
Social Functions
get_user_followers / get_user_following
get_user_followers(p_user_id, p_current_user_id, p_limit, p_offset) → json
get_user_following(p_user_id, p_current_user_id, p_limit, p_offset) → json
Returns follower/following lists with isFollowing status for the current user.
get_notifications
get_notifications(
p_user_id uuid,
p_limit integer DEFAULT 20,
p_offset integer DEFAULT 0
) → json
Returns notifications with actor info, grouped by type.
Atomic comment creation that returns the comment with author info.
create_post_comment(p_post_id uuid, p_user_id uuid, p_content text)
→ TABLE(out_comment_id, out_content, out_created_at, out_user_id, out_username, out_avatar_url)
Generic comment fetcher for any content type.
get_comments(
p_content_type text, -- 'post', 'recipe', or 'collection'
p_content_id uuid,
p_limit integer DEFAULT 20,
p_offset integer DEFAULT 0
) → TABLE(id, content, created_at, user_id, username, avatar_url, total_count)
Deletes a comment if the user is the author. Returns true on success.
delete_post_comment(p_comment_id uuid, p_user_id uuid) → boolean
delete_recipe_comment(p_comment_id uuid, p_user_id uuid) → boolean
CRUD Functions
create_recipe
Atomic recipe creation handling images, tags, tagged users, collection assignment, and optional Lightroom settings in a single transaction.
create_recipe(
p_user_id, p_title, p_description, p_camera_model,
p_images text[], p_cover_index, p_tags text[], p_tagged_user_ids uuid[],
p_collection_id, p_film_simulation, p_dynamic_range, p_grain_effect,
p_color_chrome_effect, p_color_chrome_effect_blue,
p_white_balance_mode, p_white_balance_kelvin, p_white_balance_red, p_white_balance_blue,
p_highlight, p_shadow, p_color, p_sharpness, p_noise_reduction, p_clarity,
p_include_lightroom, p_lr_exposure, p_lr_contrast, p_lr_highlights, ...
) → TABLE(id, title, description, ...)
update_recipe
Same parameter set as create, updates only provided fields.
create_post / update_post / delete_post / delete_recipe
create_post(
p_user_id uuid, p_title text, p_caption text,
p_camera_model text, p_film_simulation text,
p_images text[], p_cover_index integer,
p_tags text[], p_recipe_id uuid, p_collection_id uuid
) → TABLE(id, title, caption, camera_model, film_simulation, cover_image_url, cover_index, created_at, user_id, recipe_id, collection_id)
update_post(
p_post_id uuid, p_user_id uuid,
p_title text, p_caption text, p_camera_model text,
p_film_simulation text, p_tags text[],
p_recipe_id uuid, p_collection_id uuid
) → TABLE(id, title, caption, camera_model, film_simulation, recipe_id, collection_id, updated_at)
delete_post(p_post_id uuid, p_user_id uuid)
→ TABLE(id, deleted_at)
delete_recipe(p_recipe_id uuid, p_user_id uuid)
→ TABLE(id, image_urls text[], deleted_at)
create_post does NOT accept p_tagged_user_ids — unlike create_recipe, post tagging is handled separately. delete_recipe performs a hard delete (cascading deletion of all related data: images, tags, tagged users, comments, mentions, favorites, reposts, lightroom settings, saved items, notifications) and returns image_urls so the client can clean up storage. delete_post performs a soft delete (is_deleted = true).
delete_user_account
Cascading account deletion that removes all user data.
delete_user_account(p_user_id uuid) → void
Saved Items Functions
get_saved_page_data
Fetches the saved page overview for a user.
get_saved_page_data(p_user_id uuid) → json
get_uncategorized_saved_items
Gets saved items not in any collection, with pagination.
get_uncategorized_saved_items(
p_user_id uuid,
p_limit integer DEFAULT 12,
p_offset integer DEFAULT 0
) → json
get_user_collections_for_save_modal
Returns user’s collections with preview images and whether a specific saved item is in each collection.
get_user_collections_for_save_modal(
p_user_id uuid,
p_saved_item_id uuid DEFAULT NULL
) → TABLE(id, name, is_public, preview_image_url, item_count, is_in_collection)
Search
global_search
Full-text search across recipes, posts, collections, and users using pg_trgm.
global_search(
p_query text,
p_type_filter text DEFAULT NULL, -- 'recipe', 'post', 'collection', 'user'
p_limit integer DEFAULT 30
) → json
check_username_available
check_username_available(
p_username text,
p_exclude_user_id uuid DEFAULT NULL
) → boolean
Utility Functions
update_user_profile
Atomic profile update. Returns the updated profile row.
update_user_profile(
p_user_id uuid,
p_username text, p_first_name text, p_surname text,
p_location text, p_bio text, p_instagram_handle text,
p_avatar_url text, p_cover_photo_url text
) → SETOF profiles
validate_all_counters
Diagnostic function that compares denormalized counter values against actual counts. Returns mismatches.
validate_all_counters()
→ TABLE(table_name, record_id, counter_name, counter_value, actual_value)