Community subcategory tagging — two-layer system for user-contributed recipe categorization #118
Labels
No labels
accessibility
backlog
beta-feedback
bug
duplicate
enhancement
feature-request
help wanted
invalid
needs-design
needs-triage
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: Circuit-Forge/kiwi#118
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
FTS5 subcategory keyword matching fails for recipes where the corpus (food.com) does not use regional/technical terminology. Example:
"naples|neapolitan|pizza napoletana|ragù"returns 0 hits even though Neapolitan-style recipes exist — they just use generic titles.Solution: Two-Layer System
Layer A — Per-recipe community tags (immediate)
Users can tag individual recipes with a domain/category/subcategory from the existing taxonomy. Tags are stored in community PostgreSQL under a pseudonym. Browse counts for a subcategory merge FTS results + accepted community tags. Even a handful of community tags makes a zero-count subcategory browseable.
Flow: "Categorize this" button on recipe cards → pick subcategory from taxonomy picker → stored in community DB → reflected in browse counts on next refresh.
Schema (community Postgres):
Acceptance: Tag shows immediately on submitter's view; appears in public browse counts after reaching a vote threshold (e.g. 2 independent users).
Layer C — Taxonomy keyword proposals (power user, longer term)
Trusted users can propose new keyword strings to add to
browser_domains.pysubcategory lists. One accepted proposal fixes thousands of recipes in the next tag run rather than tagging one at a time.Flow: "These keywords are missing" → propose keyword additions → admin reviews → merged into browser_domains.py → infer_recipe_tags.py run → browse_counts refreshed.
Implementation Order
GET /api/v1/recipes/community-tags/{recipe_id}— fetch tags for a recipePOST /api/v1/recipes/community-tags— submit a tagPOST /api/v1/recipes/community-tags/{id}/upvote— vote on a tagNotes
recipe_id(integer corpus ID), not recipe titlePartial blocker: kiwi#119 (community recipe submission + dedup/clustering) blocks the "create if not exists" sub-feature only. Corpus-recipe tagging (the main feature) can ship independently.