Tire Implementation Audit & Improvement Plan
This audit reviews the K&M Tire integration across the CROP ecosystem. The implementation is functional but has several issues that need addressing for...
Tire Implementation Audit & Improvement Plan
Executive Summary
This audit reviews the K&M Tire integration across the CROP ecosystem. The implementation is functional but has several issues that need addressing for production readiness.
Critical Issues
Issue #1: Old Slug URLs Return 404 (CRITICAL)
Problem: URLs with old slug format (/tires/kmt-04493560000) return 404.
The slug format was changed from kmt-{partNumber} to ct-kmt-{partNumber} but:
- Old bookmarked URLs break
- Search engines have indexed old URLs
- No redirect mechanism exists
Solution: Add redirect logic in tire detail page to handle old format.
// In app/tires/[slug]/page.tsx
if (slug.startsWith('kmt-') && !slug.startsWith('ct-kmt-')) {
const newSlug = `ct-${slug}`;
redirect(`/tires/${newSlug}`);
}Status: To be implemented
Issue #2: Elasticsearch Index Not Rebuilt
Problem: MongoDB has updated slugs (ct-kmt-*) but Elasticsearch tires_current index may still have old slugs or no data on dev environment.
Solution:
- Deploy new search service version
- Run GCP rebuild script:
bash services/search/scripts/gcp-rebuild-tires-index.sh
Status: Pending deployment
Code Quality Issues
Issue #3: Real-Time Inventory Uses Raw fetch Instead of React Query
Current Implementation (real-time-inventory.tsx):
const [data, setData] = useState<RealTimeInventoryData | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchInventory = useCallback(async () => {
setIsLoading(true);
// manual fetch...
}, [partNumber]);Best Practice (React Query):
const { data, isLoading, error, refetch } = useQuery({
queryKey: ['tire-inventory', partNumber],
queryFn: () => fetchTireInventory(partNumber),
staleTime: 30 * 1000, // 30 seconds
retry: 2,
});Benefits:
- Automatic caching and deduplication
- Built-in loading/error states
- Automatic background refetching
- Better DevTools integration
Status: Recommended improvement
Issue #4: Hardcoded Manufacturer Code
Location: app/tires/(catalog)/page.tsx:53
manufacturer: "KMT",Risk: If manufacturer code changes, catalog breaks.
Solution: Extract to constant or config.
// lib/constants/manufacturers.ts
export const TIRE_MANUFACTURER = {
code: 'KMT',
name: 'K&M Tire',
} as const;Status: Recommended improvement
Issue #5: No generateStaticParams for Popular Tires
Current: All tire detail pages are dynamically rendered.
Best Practice (Next.js): Pre-generate popular tire pages for better performance.
export async function generateStaticParams() {
// Fetch top 100 popular tires
const tires = await getPopularTires(100);
return tires.map((tire) => ({ slug: tire.slug }));
}
export const dynamicParams = true; // Allow dynamic for non-pregeneratedStatus: Optional improvement
Issue #6: Missing Error Boundary with Retry
Current: Error shows generic message without retry option.
Best Practice: Add retry button in error state.
Status: Recommended improvement
Backend Issues (CROP-parts-services)
Issue #7: Search Zero-Results Fallback Ignores Target Index
Location: services/search/src/routes/search.ts:569, 591
// Uses env.SEARCH_INDEX_NAME instead of targetIndex
const spellingSuggestion = await getSpellingSuggestions(client, {
indexName: env.SEARCH_INDEX_NAME, // Should be targetIndex
});Impact: Tire searches with zero results get suggestions from parts index.
Status: Identified, needs fix
Issue #8: Equipment Route Hardcoded to Parts Index
Location: services/search/src/routes/equipment.ts:174, 376, 652
Impact: Equipment searches cannot find tires if they have fitment data.
Status: Identified, needs fix
Issue #9: Unused isTiresRequest Function
Location: services/search/src/utils/index-resolver.ts
export function isTiresRequest(params: IndexResolverParams): boolean {
return resolveSearchIndex(params) === env.TIRES_INDEX_NAME;
}Status: Remove or mark as @internal
Best Practices Comparison
Next.js Data Fetching
| Pattern | Current | Best Practice |
|---|---|---|
| Server Components | Yes | Yes |
| Revalidate | 60s | OK |
| Error Handling | Basic | Should add retry |
| generateStaticParams | No | Should add for top tires |
| Redirect for old URLs | No | MUST add |
React Query (TanStack Query v5)
| Pattern | Current | Best Practice |
|---|---|---|
| Data fetching | Raw useState | useQuery |
| Caching | Manual | Automatic staleTime |
| Error handling | Manual try/catch | Built-in error state |
| Refetching | Manual button | Automatic + manual |
| Loading state | Manual useState | Built-in isLoading |
Caching Strategy
| Endpoint | Current Cache | Recommended |
|---|---|---|
| Tire catalog | 60s | 60s (OK) |
| Tire detail | 60s | 60s (OK) |
| Real-time inventory | 0s (no-store) | 30s staleTime in React Query |
| K&M API (backend) | 5min | 5min (OK) |
Implementation Priority
P0 - Critical (Must Fix Now)
- Add redirect for old slug format (
kmt-*→ct-kmt-*) - DONE - Add fallback for old slugs during ES migration - DONE
- Deploy search service (has multi-index fix but not deployed)
- Rebuild tires ES index (has old slugs)
Deployment Commands
# Step 1: Deploy search service
cd /Users/vova/Code/CROP/CROP-parts-services
gcloud run deploy search-service --source . --region us-east1 --project noted-bliss-466410-q6
# Step 2: Rebuild tires index
bash services/search/scripts/gcp-rebuild-tires-index.sh
# Step 3: Verify
curl 'https://api.crop-dev.app/api/parts/ct-kmt-04493560000' | jq '.part.slug'P1 - High (Should Fix Soon)
- Fix search zero-results fallback to use targetIndex - ALREADY DONE
- Extract manufacturer code to constant - DONE
- Add error retry button to tire pages
P2 - Medium (Nice to Have)
- Migrate real-time inventory to React Query
- Add generateStaticParams for popular tires
- Fix equipment route multi-index support - ALREADY DONE
P3 - Low (Future)
- Remove unused isTiresRequest function
- Add admin route index parameter
Files to Modify
Frontend (CROP-front)
| File | Change | Priority |
|---|---|---|
app/tires/[slug]/page.tsx | Add redirect for old slugs | P0 |
lib/constants/manufacturers.ts | Create file | P1 |
app/tires/(catalog)/page.tsx | Use constant | P1 |
app/tires/_components/real-time-inventory.tsx | Migrate to useQuery | P2 |
Backend (CROP-parts-services)
| File | Change | Priority |
|---|---|---|
services/search/src/routes/search.ts | Use targetIndex | P1 |
services/search/src/routes/equipment.ts | Use getAllSearchIndices | P2 |
services/search/src/utils/index-resolver.ts | Remove isTiresRequest | P3 |
Verification Checklist
After implementing fixes:
# 1. Test old slug redirect
curl -I http://localhost:3000/tires/kmt-04493560000
# Expected: 308 redirect to /tires/ct-kmt-04493560000
# 2. Test new slug works
curl http://localhost:3000/tires/ct-kmt-04493560000
# Expected: 200 OK with tire page
# 3. Test catalog page
curl http://localhost:3000/tires/
# Expected: 200 OK with tire list
# 4. Test real-time inventory
# Open tire detail page, check "Live" badge appearsSummary
| Category | Status |
|---|---|
| Slug format change | Done (code) |
| MongoDB migration | Done (7091 docs) |
| ES index rebuild | Pending deployment |
| Old URL redirect | To implement |
| React Query migration | Recommended |
| Backend index fixes | Identified |
Tire Implementation: Critical Review & Improvement Plan
Overall Assessment: The tire implementation is functionally complete but has significant gaps in: - Performance optimization (no React.memo, unoptimized...
Testing Strategy - CROP Frontend Platform
Last Updated: 2025-11-08 Status: Active Coverage Target: >90% for critical paths