Claude-skill-registry-data menu-verification
Use this skill to verify whether restaurants actually have Planted products on their current menu. Crawls restaurant websites, parses PDF menus, and updates venue verification status in Firestore.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry-data
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry-data "$T" && mkdir -p ~/.claude/skills && cp -r "$T/data/menu-verification" ~/.claude/skills/majiayu000-claude-skill-registry-data-menu-verification && rm -rf "$T"
manifest:
data/menu-verification/SKILL.mdsource content
Menu Verification Skill
This skill verifies whether discovered venues actually have Planted products on their current menus. It's essential for maintaining data quality - press releases and discovery don't guarantee ongoing availability.
When This Skill Activates
Triggers on:
- Verifying newly discovered venues
- Re-checking venues marked as
unverified - Validating venues from press releases
- Auditing existing venue data quality
Quick Start
Run the Verification Agent
cd planted-availability-db/packages/scrapers # Verify all unverified venues with websites node verify-menu-agent.cjs # Verify a specific venue by ID node verify-menu-agent.cjs --venue-id=VENUE_ID_HERE
What the Agent Does
- Finds unverified venues with websites in Firestore
- Crawls the website including subpages (/restaurant, /en, /de, etc.)
- Discovers PDF links on the pages
- Tries common PDF paths directly (/media/menu.pdf, /speisekarte.pdf, etc.)
- Parses PDF content using pdf-parse library
- Searches for Planted keywords (planted, plant-based, geschnetzeltes, etc.)
- Updates Firestore with verification status and any dishes found
Verification Statuses
| Status | Meaning |
|---|---|
| Planted products confirmed on current menu |
| No Planted products found after thorough check |
| Not yet checked |
| Website couldn't be crawled, needs human verification |
Manual Verification Workflow
For venues the agent can't verify automatically:
1. Check the Website Directly
# Get venue details node -e " const admin = require('firebase-admin'); admin.initializeApp({ credential: admin.credential.cert('../../service-account.json') }); const db = admin.firestore(); db.collection('venues').doc('VENUE_ID').get().then(d => console.log(JSON.stringify(d.data(), null, 2))); "
2. Look for PDF Menus
Common PDF locations to check:
,/media/menu.pdf/media/speisekarte.pdf/downloads/menu.pdf/restaurant/menu.pdf- Language variants:
,_en.pdf
,_de.pdf_d.pdf
3. Search for Planted Keywords
In PDFs or HTML, search for:
(brand name)planted
,plant-based
,plant basedpflanzenbasiert
(common planted dish)geschnetzeltes
,planted chicken
,planted kebabplanted steak
4. Update the Venue
# Mark as verified with planted products node -e " const admin = require('firebase-admin'); admin.initializeApp({ credential: admin.credential.cert('../../service-account.json') }); const db = admin.firestore(); db.collection('venues').doc('VENUE_ID').update({ status: 'active', verification_status: 'verified_on_menu', verification_date: new Date(), verification_method: 'manual', verification_note: 'Found X planted dishes on menu PDF', updated_at: new Date() }); " # Or mark as not found node -e " const admin = require('firebase-admin'); admin.initializeApp({ credential: admin.credential.cert('../../service-account.json') }); const db = admin.firestore(); db.collection('venues').doc('VENUE_ID').update({ status: 'unverified', verification_status: 'not_found_on_menu', verification_date: new Date(), verification_method: 'manual', verification_note: 'No planted products found on menu', updated_at: new Date() }); "
Adding Dishes from Verified Menus
When planted products are found:
node -e " const admin = require('firebase-admin'); admin.initializeApp({ credential: admin.credential.cert('../../service-account.json') }); const db = admin.firestore(); const dish = { venue_id: 'VENUE_ID', name: 'Planted Geschnetzeltes mit Rösti', description: 'Swiss-style planted strips with hash browns', price: { amount: 32.00, currency: 'CHF' }, planted_products: ['planted.geschnetzeltes'], status: 'active', source: 'menu_verification', created_at: new Date(), updated_at: new Date() }; db.collection('dishes').add(dish).then(ref => console.log('Added dish:', ref.id)); "
Planted Product SKUs
Common product identifiers:
- Planted Chickenplanted.chicken
- Planted Geschnetzeltes (strips)planted.geschnetzeltes
- Planted Kebabplanted.kebab
- Planted Steakplanted.steak
- Planted Pulledplanted.pulled
- Planted Schnitzelplanted.schnitzel
Removing Invalid Venues
If a venue doesn't have planted products and was added in error:
# Delete venue (and its dishes) node -e " const admin = require('firebase-admin'); admin.initializeApp({ credential: admin.credential.cert('../../service-account.json') }); const db = admin.firestore(); const venueId = 'VENUE_ID'; // Delete dishes first db.collection('dishes').where('venue_id', '==', venueId).get() .then(snap => { const batch = db.batch(); snap.docs.forEach(doc => batch.delete(doc.ref)); return batch.commit(); }) .then(() => db.collection('venues').doc(venueId).delete()) .then(() => console.log('Deleted venue and dishes')); "
Agent Configuration
The verify-menu-agent.cjs searches for these patterns:
Subpages Crawled
const SUBPAGE_PATTERNS = [ '/restaurant', '/en', '/de', '/bar', '/cuisine', '/kulinarik' ];
PDF Paths Tried
const COMMON_PDF_PATHS = [ '/media/menu.pdf', '/media/speisekarte.pdf', '/media/restaurant_mo_-_fr_d.pdf', // Kronenhalle pattern '/downloads/menu.pdf', '/menu.pdf' ];
Keywords Searched
const PLANTED_KEYWORDS = [ 'planted', 'plant-based', 'plant based', 'pflanzenbasiert', 'planted chicken', 'planted kebab', 'planted geschnetzeltes' ];
Dependencies
The agent requires:
npm install pdf-parse # For PDF text extraction
Example Session
$ node verify-menu-agent.cjs === Menu Verification Agent === Found 3 unverified venues with websites Checking: Kronenhalle (https://www.kronenhalle.com) Crawling homepage... Found 2 PDF links Parsing: restaurant_mo_-_fr_d.pdf (12 pages) FOUND: "Planted Geschnetzeltes «Kronenhalle» mit Rösti" FOUND: "Planted Steak mit Sanddorn" Status: verified_on_menu (2 dishes added) Checking: Lindenhofkeller (https://www.lindenhofkeller.ch) Crawling homepage + subpages... Found 3 PDF links Parsing: drinks.pdf (31 pages) - no planted Parsing: lunch.pdf (4 pages) - no planted Parsing: dinner.pdf (6 pages) - no planted Status: not_found_on_menu === Summary === Verified: 1 Not found: 1 Errors: 0
Troubleshooting
PDF Not Parsing
- Check if pdf-parse is installed:
npm ls pdf-parse - Some PDFs are image-based (scanned) - need manual check
- Compressed PDFs may fail - try downloading manually
Website Blocking
- Some sites block automated crawlers
- Try with different User-Agent
- May need manual verification
No Menu Found
- Check if restaurant uses third-party menu systems
- Look for iframe embeds
- Check delivery platform listings instead