The Problem
NBA jersey prices are all over the place. The same Mitchell & Ness jersey can be $250 on one site and $180 on another. Resale prices on eBay fluctuate daily. If you're a collector, you're constantly checking multiple platforms to find fair prices.
I wanted a single tool that shows real-time market pricing across retailers — so I built one.
The Stack
- Next.js 16 (App Router, static generation)
- MDX for content (each jersey has its own article with structured pricing data)
- Tailwind CSS 4 for UI
- TypeScript end-to-end
- Vercel for deployment + analytics
- Custom scraping pipeline for price updates
Architecture
The site has 270+ pages across 5 locales (EN, ZH, JA, KO, ES). Every jersey article contains structured pricing data in its MDX frontmatter:
pricing:
fanatics:
price: 129.99
url: "https://..."
mitchellNess:
price: 299.99
url: "https://..."
ebayAvg: 185
trend: "rising"
A scheduled agent script scrapes current prices and updates the frontmatter. On build, Next.js generates static pages with Product JSON-LD schema — so Google sees structured pricing data.
The Valuation Tool
The most interesting part is the Jersey Valuation Tool. Users select a player + jersey, and it shows:
- Current retail prices (Fanatics, Mitchell & Ness)
- eBay average sold price (last 30 days)
- Price trend (rising/stable/declining)
- Estimated collector value based on era, condition, and rarity
All computed client-side from the static pricing data — no API calls needed at runtime.
SEO Strategy That Actually Works
This is a content site, so organic traffic is everything. Some things that worked:
1. Structured Data on Every Page
Every jersey page has Article + Product + FAQ + BreadcrumbList schemas. Google Rich Results are the goal — showing prices directly in search results.
2. Multi-locale with Proper Hreflang
Using next-intl with 5 locales. Every page has full hreflang alternates in both the HTML <head> and sitemap. This opens up non-English search traffic (huge for basketball content in Asia).
3. Programmatic Content at Scale
Each player hub page is auto-generated from their jersey collection. Team pages aggregate by franchise. Number pages group by jersey number. This creates a dense internal linking structure without manual work.
4. Active Indexing
Passive sitemap submission is too slow for new sites. I built a script that pushes URLs directly to Google's Indexing API and Bing's URL Submission API on every deploy. 98 URLs indexed within days instead of weeks.
Challenges
- Affiliate compliance: Every pricing link needs FTC disclosure. Built a component that auto-injects disclaimers.
- Stale prices: Prices change daily. The scraping pipeline runs on a schedule, but I still need to handle the "price was X when we checked" transparency.
- Image generation: Needed unique hero images for 45+ jerseys. Used AI image generation with careful prompts to avoid trademark issues.
Results So Far
- 270+ pages indexed
- 5 language variants
- Sub-1s LCP on all pages (static generation FTW)
- Structured data validated on 100% of product pages
Still early on traffic — the site is only a few weeks old — but the technical foundation is solid.
Open Source?
Not yet, but thinking about it. The content pipeline (MDX + frontmatter pricing + automated scraping + multi-locale) is pretty reusable for any product comparison site.
If you're building something similar, happy to answer questions about the architecture.
Check it out: JerseyToMe — NBA Jersey Encyclopedia & Price Guide
The valuation tool: Jersey Valuation Tool
Top comments (0)