$ cat system.md
For the curious. The full technical colophon.
dependencies
framework
- next14.2App Router, server components
- react18.2Static server pages by default
- typescript5.6Strict mode
- tailwindcssv4Utility-first, PostCSS plugin
data
- postgresqlNeonServerless, branching
- prisma5.106 models, typed queries
ai
- gemma3:12bplutoNames gear in a video description
- gemma3:4bplutoClassifies a search result as a review
revenue
- amazon associatestagged linksSearch, product, and cart URLs carry the partner tag
external
- youtube data v3APIFinds and titles review videos
- amazon pa-api 5.0not approved yetSigV4 client exists in lib/amazon/, unused in production
hosting
- vercel—Deploys on every push to master
testing
- vitest4.x151 tests across 17 files
architecture
cache: search=1h, price=24h, video=24hCache-through on every external call: check the database first, hit Amazon or YouTube only on a miss, then store the result. Price TTL is 24 hours because that is the Amazon TOS maximum.
asin: parsed by code, never generatedThe kit extraction schema (lib/kits/extract.ts) has no ASIN field. The model names an item and points it at a link number; code resolves that number back to an ASIN it already parsed. The model cannot write an ASIN even if a description names one.
shortlink: HEAD once, redirect: 'manual'lib/kits/resolve.ts sends one HEAD request per amzn.to/a.co link and reads the Location header without following it, because requesting amazon.com directly can return a CAPTCHA page at HTTP 200 instead of an error.
catalog: CATALOG_WHERE = { source: 'curated' }An allowlist, not a denylist, in lib/products/visibility.ts. A new source value stays invisible in search, category pages, and featured products until someone adds it here on purpose.
affiliateTag: built once, .trim()'dlib/amazon/affiliate-links.ts is the only place the partner tag is read. A trailing newline in a Vercel env var once passed through URLSearchParams silently and cost affiliate credit on search links while product links kept working — found in production on 2026-09-12.
kits.build()
A kit is a curated gear list tied to one YouTube video. It is built from that video's description, not from the video itself — dino.place has no transcript, only title, channel, and description text.
lib/kits/links.ts finds every URL and classifies it as an Amazon link, a short link, or neither, before anything touches a model.
Up to 40 HEAD lookups, a 2-second gap between them, and the run stops after two failures in a row or a bad-failure ratio — so a batch of dead links fails fast instead of hammering Amazon.
The prompt gives the model numbered links and asks which item goes with which number. It never sees a field called ASIN and can't produce one.
A creator's own shop link, an unresolved shortener, or a non-Amazon store is allowed. That item renders as a plain line on the kit page with no buy button.
A kit with zero valid ASINs across all its items cannot publish. Kits with at least one ASIN still need each pairing confirmed before the item is live.
principles
- #Every response goes through jsonOk() or jsonErr() from lib/http.ts. No raw Response.json().
- #Every input is validated with a Zod schema from lib/domain/dtos.ts before it is used.
- #Every API route is wrapped with withErrorHandling().
- #A Prisma Decimal arrives as a string. Convert it with Number() before doing math on it.
- #FTC affiliate disclosure appears on every page that carries an affiliate link.
- #Amazon prices are cached at most 24 hours — the TOS maximum, not a target.
- #Migration order follows the change direction: add a column before the code that reads it deploys; drop a column only after the code that read it is already gone.
$ dino-place --version
Built by one developer, revived from a 2016 MEAN-stack project called Watchville.
Product discovery backed by real video reviews, not sponsored placement.
$ _
Want to see it work?
All this disappears behind a simple search box. Look up a product and see what real reviewers actually said about it.
as an amazon associate, dino.place earns from qualifying purchases