Building an Admin Portal and Launching on RapidAPI in One Session
Building an Admin Portal and Launching on RapidAPI in One Session
Today was one of those marathon sessions where you start with "the strain data is too thin" and end with a live marketplace listing. Here's what happened.
The Problem: Skeleton Data
My cannabis strain API has 43,000+ strains, but most of them looked like this:
{
"name": "Triple Stack",
"type": "indica",
"thc_content": 0.0,
"cbd_content": 0.0
}
No effects, no flavors, no terpenes. Just names and types. The data came from 5 different scrapers, but most only grabbed listing pages — not the detail pages where the good stuff lives.
Enriching the Data
First attempt: backfill from Leafly. Wrote an enrichment script that takes each thin strain, constructs a Leafly URL from the name, and scrapes the detail page. Result: 6% hit rate. Most of these strains don't exist on Leafly.
Second attempt: go back to the original sources. AllBud and SeedFinder already had the strain names — so the match rate would be near 100%. Wrote enrich_from_sources.py that:
- Finds strains with SeedFinder source URLs → fetches their detail pages
- Remaining thin strains → tries AllBud by constructing URLs from name + type
Hit rate jumped to 21%. Not perfect, but 2,600+ strains enriched and climbing. Also enriched the list endpoint itself — it now returns effects, flavors, and terpenes instead of bare skeletons.
Building the Admin Portal
I needed a way to see what's happening with the API — who's using it, which keys are active, what the error rate looks like. So I built a full admin section into the existing Next.js developer portal.
Backend:
request_logstable with async fire-and-forget middleware- Admin endpoints for API key management across all users
- Analytics endpoints: daily request volume, popular endpoints, error breakdown
Portal:
- 4 new admin pages (overview, keys, users, analytics)
- Amber accent color to distinguish admin from regular dashboard
- Only visible to admin users
The analytics page turned out to be the most useful — seeing a bar chart of daily requests with error portions highlighted in red made it immediately obvious that 37% of my traffic was errors. All from my own debugging session with expired tokens.
The CI Gauntlet
The test suite was a disaster — 65 failures. Every test file had mismatches:
hashed_passwordvspassword_hash(model field name changed)strain_typevstype(same thing)settings.JWT_SECRET_KEYvssettings.secret_key- Cache service tests calling static methods on an instance-based class
- Rate limiter crashing when Redis returns
None(comparingNone > 60)
Fixed them all in waves. 65 → 23 → 7 → 2 → 0. Also fixed the CI config itself — pinned black version, made mypy non-blocking, fixed the Docker build for Trivy scanning.
Deploying to Cloudflare Pages
This was more painful than expected. The portal was set up as "Direct Upload" on Cloudflare Pages (not Git-connected), so every deploy is manual. Learned the hard way:
output: "export"in Next.js config breaks everything — Cloudflare Pages needs@cloudflare/next-on-pagesto handle the build properlybasePath: "/bud"meanswindow.location.hrefneeds the/budprefix, but Next.jsrouter.pushdoes not- CDN caching means you won't see changes immediately — cache busters (
?v=2) are your friend
The correct deploy command ended up being:
npm run build && npx @cloudflare/next-on-pages && npx wrangler pages deploy .vercel/output/static --project-name=all-the-bud-portal --commit-dirty=true
RapidAPI Listing
Got the API listed on RapidAPI for passive discovery. The OpenAPI spec auto-imported all endpoints, which saved a ton of manual work. Set up three tiers (Basic free, Pro $29/mo, Ultra $199/mo) with request quotas.
Added X-RapidAPI-Proxy-Secret verification to the API so RapidAPI can proxy requests without needing individual API keys.
What's Next
- The enrichment script is still running — should hit ~7,500 enriched strains by the time it finishes
- Product Hunt launch is prepped but not submitted yet
- Reddit post drafted for r/SideProject
- Need to set up Cloudflare Pages Git integration so deploys are automatic
The whole session was probably 8 hours. Not bad for going from "the data sucks" to "we're on a marketplace."