| 9 | Mar 2026 | Ironclad rebrand, demo content seed, font fix (Oswald/Raleway/Space Grotesk/Playfair), About rewrite, PestFlow Pro footer badge, review_text column fix, Pexels portraits for team |
Resources
17Install
npx skillscat add ironwoodoperations/pestflow-pro Install via the SkillsCat registry.
PestFlow Pro — Claude Code Autonomous Dev Skill
Session 1+
HOW TO USE
- Read this file fully
- Read TASKS.md
- Execute first unchecked [ ] task
- git add . && git commit -m "..." && git push after each task
- Mark [x] and proceed automatically
PROJECT IDENTITY
- Product: PestFlow Pro (white-label SaaS for pest control)
- GitHub: https://github.com/ironwoodoperations/pestflow-pro
- Stack: React 18 + TypeScript + Vite + Tailwind + Supabase + Vercel
- Demo admin: admin@pestflowpro.com / pf123demo
- Demo company: Ironclad Pest Solutions (Tyler, TX — seeded in Supabase)
- Model: claude-sonnet-4-6 (ALWAYS — never anything else)
SUPABASE
- Project ID: biezzykcgzkrwdgqpsar
- URL: https://biezzykcgzkrwdgqpsar.supabase.co
- Auth: has_role() RPC checks user_roles table (NOT profiles)
- New admin users: insert into BOTH profiles AND user_roles
- Demo Tenant ID: e5d34055-2a35-4e48-8864-d9449cb9da43
TABLES
profiles, user_roles, tenants, page_content, seo_meta, blog_posts,
location_data, testimonials, leads, settings, keyword_tracker,
keyword_placements, page_snapshots, social_posts
SETTINGS KEYS (JSONB in settings table)
- business_info: {name, phone, email, address, hours, tagline, license}
- branding: {logo_url, favicon_url, primary_color, accent_color, template}
- hero_media: {youtube_id, thumbnail_url}
- social_links: {facebook, instagram, google}
- notifications: {lead_email, cc_email, monthly_report_email}
- integrations: {facebook_access_token, facebook_page_id, google_place_id, google_api_key}
- onboarding_complete: {complete: true/false}
DESIGN TEMPLATES
branding.template values: bold | clean | modern
All page components read this and apply the correct variant.
ANTHROPIC API PATTERN (browser)
fetch('https://api.anthropic.com/v1/messages', {
method: 'POST',
headers: {
'x-api-key': import.meta.env.VITE_ANTHROPIC_API_KEY,
'anthropic-version': '2023-06-01',
'anthropic-dangerous-direct-browser-access': 'true',
'content-type': 'application/json',
},
body: JSON.stringify({
model: 'claude-sonnet-4-6',
max_tokens: 1000,
messages: [{ role: 'user', content: prompt }]
})
})
const text = data.content[0].text
RULES (NEVER VIOLATE)
- Routes in App.tsx MUST appear BEFORE /:slug catch-all
- Model is always claude-sonnet-4-6 — never anything else
- has_role() checks user_roles — always insert there for new admins
- New admin users: insert into BOTH profiles AND user_roles
- Tenant ID resolved dynamically — never hardcode beyond DEMO_TENANT_ID fallback
- Template stored in branding.template: bold | clean | modern
- After every task: git add . && git commit -m "..." && git push
- Read files before editing them
- Single useState object for forms — never per-field state (prevents focus bug)
- exec_sql RPC does NOT exist — use Supabase MCP directly for raw SQL
- vercel.json rewrites rule is required — all routes must return index.html for SPA routing
- Template stored in settings branding.template: bold | clean | modern — always read via useTemplate()
- Location pages use ORANGE CTA — never yellow diagonal (that is pest service pages only)
- /quote route must appear before /:slug in App.tsx — quotes are not a location
- /blog/:slug route MUST appear before /:slug in App.tsx
- StructuredData injects JSON-LD via useEffect script tag, not Helmet
- ContentTab uses left sidebar (page list) + right panel (edit form) pattern
- Pest pages: YELLOW diagonal East Texas CTA | Location pages: dark navy CTA. NEVER swap.
- THEME: Hero bg = dark navy #0a0f1e | Primary accent = emerald #10b981 | East Texas CTA = yellow #f5c518 — NO orange in PestFlow Pro templates
- HolidayBanner goes ABOVE on all public pages — add to every new public page
- AI keyword research uses claude-sonnet-4-6 — prompt must request JSON-only response, strip backticks before JSON.parse
- Blog slugs are auto-generated from title (kebab-case) — always editable before save
- CSV export uses browser-side Blob + URL.createObjectURL — no backend needed
- Leads table status updates are auto-save on dropdown change — no Save button
- QuotePage is a 4-step wizard — single useState object, never lose state between steps
- /sitemap.xml route MUST appear before /:slug in App.tsx
- /pricing route MUST appear before /:slug in App.tsx
- Edge function env vars: RESEND_API_KEY, SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY — set in Supabase dashboard
- Social posting requires facebook_page_id + facebook_access_token in settings.integrations
- Google Reviews import requires VITE_GOOGLE_PLACES_API_KEY env var + google_place_id in settings
- NotFound.tsx is the * catch-all — always import in App.tsx, never use inline div
- PWA icons needed: replace public/icon-192.png + icon-512.png with real branded assets before client launch
- seed-page-content.mjs — run once per new tenant: TENANT_ID=xxx node scripts/seed-page-content.mjs
- Hero video: set youtube_id in Settings → Hero Media — falls back to gradient if not set
- Location pages fetch otherLocations for We Also Serve — needs 2+ live locations to render
- Demo company name is "Ironclad Pest Solutions" — never Dang or Apex in this repo
- Hero video uses HeroVideoPlayer.tsx component with youtube-nocookie embed + overlay
- Footer always shows "Powered by PestFlow Pro" badge — never remove
- Testimonials DB column is review_text (NOT content) — all frontend queries must use review_text
KEY FILE PATHS
src/lib/supabase.ts
src/lib/tenant.ts
src/hooks/useTenant.ts
src/components/ProtectedRoute.tsx
src/pages/admin/Login.tsx
src/pages/admin/Dashboard.tsx
src/pages/admin/Onboarding.tsx
src/components/admin/ (all tab components)
src/App.tsx
src/pages/Index.tsx # Public home page
src/pages/QuotePage.tsx # Quote form + lead submission
src/pages/ContactPage.tsx # Contact page
src/pages/SlugRouter.tsx # Routes /:slug to LocationPage
src/pages/LocationPage.tsx # Dynamic location pages
src/components/Navbar.tsx # Template-aware nav (mobile hamburger)
src/components/Footer.tsx # Template-aware footer
src/lib/templates.ts # Template token definitions
src/hooks/useTemplate.ts # Template-aware hook
src/pages/SpiderControl.tsx # MASTER pest page template
src/pages/MosquitoControl.tsx
src/pages/AntControl.tsx
src/pages/WaspHornetControl.tsx
src/pages/RoachControl.tsx
src/pages/FleaTickControl.tsx
src/pages/RodentControl.tsx
src/pages/ScorpionControl.tsx
src/pages/BedBugControl.tsx
src/pages/PestControlPage.tsx
src/pages/TermiteControl.tsx
src/pages/TermiteInspections.tsx
src/pages/About.tsx
src/pages/FAQPage.tsx
src/pages/ReviewsPage.tsx
src/pages/ServiceArea.tsx
src/pages/BlogPage.tsx
src/pages/BlogPostPage.tsx
src/components/PestPageTemplate.tsx # Shared pest page layout
src/components/StructuredData.tsx # JSON-LD injection
src/components/HolidayBanner.tsx # Holiday hours banner (reads settings)
src/pages/QuotePage.tsx # 4-step quote wizard
src/pages/Pricing.tsx # Public pricing page
src/pages/Sitemap.tsx # /sitemap.xml route
public/robots.txt # Search engine directives
supabase/functions/notify-new-lead/index.ts # Resend email edge function
src/pages/NotFound.tsx # Branded 404 page
src/pages/Pricing.tsx # Public pricing page
scripts/create-admin-user.mjs
scripts/create-demo-tenant.mjs # Multi-tenant seeding script
scripts/seed-page-content.mjs # Seed default page copy
public/manifest.json # PWA manifest
SKILL.md
TASKS.md
MULTI-TENANCY
Tenant resolution (src/lib/tenant.ts):
- Check localStorage for 'pf_tenant_id' (set during onboarding via setTenantId())
- Fallback to VITE_TENANT_ID env var (demo mode / single-tenant deploy)
- Every Supabase query filters by tenant_id — RLS enforces isolation at DB level
To add a new tenant:
- Run scripts/create-demo-tenant.mjs (seeds tenants + settings + location_data)
- Set VITE_TENANT_ID to the new UUID in .env (or use setTenantId() in browser)
- Create admin user: scripts/create-admin-user.mjs (assigns user to tenant)
SESSION LOG
| Session | Date | Completions |
|---|---|---|
| 1 | Mar 2026 | Scaffold, Supabase migrations, auth, admin shell, onboarding wizard |
| 2 | Mar 2026 | Vercel config, template system, Navbar, Footer, Home page, QuotePage, ContactPage, SlugRouter, LocationPage, Settings Business Info + Branding |
| 3 | Mar 2026 | Theme overhaul (orange→dark navy+emerald), all 12 pest pages, About/FAQ/Reviews/ServiceArea/Blog, StructuredData, ContentTab, SocialLinks, Notifications, Navbar dropdown |
| 4 | Mar 2026 | SEO tab + SERP preview, Testimonials CRUD, Leads tab + CSV export, Blog CRUD, Locations CRUD, AI keyword research, Integrations settings, Hero Media settings, StructuredData all pages, HolidayBanner, Reports + Social stubs |
| 5 | Mar 2026 | 4-step quote wizard, lead email notifications, Google Reviews import, Facebook social posting, sitemap.xml, robots.txt, PageSpeed optimizations, Pricing page, multi-tenant docs |
| 6 | Mar 2026 | Domain setup guide, page content seeding script, Maps embed, We Also Serve, AI content writer, hero video player, PWA manifest, 404 page, accessibility fixes |
| 6.1 | Mar 2026 | Merged PR, PESTFLOW-SKILL.md created, TASKS.md updated |
| 7 | Mar 2026 | HeroVideoPlayer (youtube-nocookie background embed), branded 404 page (full chrome), PWA manifest + icons, bulk keyword sync (keyword_tracker → seo_meta) |
| 8 | Mar 2026 | Remove Pricing page, rustic template (4th option), Pexels stock images script + introImage on all pest pages, Apex Pest Solutions About page, polished onboarding wizard, OnboardingLive screen-share mode |
| 9 | Mar 2026 | Ironclad rebrand, demo content seed, font fix (Oswald/Raleway/Space Grotesk/Playfair), About rewrite, PestFlow Pro footer badge, review_text column fix, Pexels portraits for team |