Repository-only instructions. Do not copy this guide, manifests, credentials,
production files, or review evidence into public/, posts, or generated feeds.
This GitHub repository is public: confidential information stays outside Git.
https://www.randalolson.com/store/; checkout: https://store.randalolson.com/.randy-olson-data-art, shop ID sh_725f3983-738f-4e68-8878-210ff8185a5a. Separate shop from Optimal Road Trips, same login.support.store.randalolson.com is a mail subdomain, not the recipient address.randal.s.olson@gmail.com.main deploy through Railway. The Name Age Calculator frontend deploys from its own repository. Ship destination routes before calculator links.https://www.randalolson.com with permanent redirect.| File or repository | Owns |
|---|---|
src/data/store-catalog.json |
Website designs, offers, prices, preview paths, post mapping, purchase URLs |
scripts/store/fourthwall-manifest.json |
Shop identity, remote IDs/URLs, master hashes, costs, verification, checkout evidence |
src/lib/store.ts |
Grouping, allowed referrals, detail and purchase links |
src/components/store-{catalog,product,offers,link,callout}.tsx |
Catalog, selectors, checkout links, referral persistence, post callouts |
src/app/store/page.tsx, src/app/store/[slug]/page.tsx |
Routes and artwork-specific Open Graph/Twitter metadata |
scripts/store/ |
Rendering, source data, provider adaptations, draft creation, synchronization, tests |
name-age-calculator repository |
Result-page handoff in apps/frontend/src/components/NamePrintLink.tsx; matching in apps/frontend/src/lib/name-prints.ts |
/store/: category filters and pagination (9 designs/page). Each artwork has a detail page; all names share /store/name-prints/?print=NAME_ID. Legacy catalog hash links resolve to details.node scripts/store/sync-products.mjs --write only after hosted verification. Null URLs hide purchase links. --check detects drift and wrong-shop links.| Offering | Sizes (inches) | USD prices |
|---|---|---|
| 3 artworks: hurricane tracks, Kyoto, Roman reigns | 18 x 24; 24 x 36 | Matte $39/$55; black-framed $99/$149; download $9 |
| 10 name-age portraits | 12 x 16; 18 x 24 | Matte $29/$39; download $9 |
| Hurricane desk mat | 31.5 x 15.5 | $39 |
build/store/: 300 ppi sRGB PNG masters, exact-size raster PDFs, deterministic ZIPs, checksums, provider assets, upload cache, review evidence. Never deploy this directory.public/assets/store/: reduced JPEG previews only. Artwork and physical quality are different checks; never claim a physical inspection without a sample.DATA.csv, printing instructions, source credits, usage terms, and checksums. Full-resolution delivery is through Fourthwall after purchase.scripts/store/data/roman-emperors.csv; approximate ranges use midpoints. Keep disputed assassination color distinct but include it in violent-death counts. Callouts are computed from the same data: 35 reigns under 5 years, 27 of those deaths violent. No redundant Years column or repeated death text; definitions belong in download credits.#0072B2), not bars or mosaics. Balanced age summaries precede the legend, then the chart. Footer combines SSA source/category and estimate year; keep model details in download credits.build_name_age.py uses name-history.csv and pct_alive_2026.csv to generate name-age-2026.csv: 1900-2025 cohorts, interpolated SSA survival anchors, rounded survivors, weighted birth-year percentiles. Approximate age is 2026 minus birth year. Missing counts remain gaps; count axes start at 0, scales vary by name.From this repository or its linked worktree:
python3 scripts/store/fourthwall_api.py --check
python3 scripts/store/fourthwall_api.py --request GET /shops/current
Client.for_project() resolves the Git common directory through private ~/.config/fourthwall/projects.json. Each repository has its own credential file and expected shop ID; unrelated repositories have no default shop.python3 ~/.config/fourthwall/client.py --check uses the same binding. Credential files are mode 600 in a mode-700 directory outside Git. Never print secrets or pass them in command arguments.--request METHOD /relative-path --body-file /private/request.json. Confirm the expected personal-shop ID above before any write.From the repository root, with dependencies installed:
python3 -m venv .venv
.venv/bin/python -m pip install -r scripts/store/requirements.txt
.venv/bin/python scripts/store/build_name_age.py
.venv/bin/python scripts/store/prepare.py --only WORK_ID
.venv/bin/python scripts/store/prepare.py --check
.venv/bin/python scripts/store/prepare_provider_assets.py
.venv/bin/python -m unittest discover -s scripts/store -p 'test_*.py'
node --test scripts/store/tests/*.test.mjs src/lib/store.test.mjs
node scripts/store/sync-products.mjs --check
npm run typecheck
npm run lint
npm run build
--only WORK_ID for targeted rendering; omit it only to regenerate the whole collection. Regeneration retains remote IDs but clears verification on changed artwork/listing details. Run sync --write to close affected links until re-verified.create_physical_products.py uploads checked assets and creates missing hidden drafts (publishOnCreate: false); it uses build/store/uploaded-media.json. Inspect unknown outcomes before rerunning to avoid duplicates. Digital uploads and missing controls use the dashboard. Keep new products Private for review.name-prints.ts after the product is verified. Keep its exact SSA category and work ID consistent with this catalog.verification.status: public-verified, then sync --write, build, and review the website links. Verify mobile selectors, name matching/history, cross-links, and downloads before shipping.dist/. Confirm docs, scripts, manifests, full-resolution masters, and ZIPs are absent there and absent from generated llms*.txt/feeds. Restore timestamp-only generated-file churn when unrelated to the change.G-4R2NWZM0C4: website, calculator, and Fourthwall Analytics > Tracking pixels. Native tag loading was verified at launch; do not promise paid purchase reporting until tested.store_browse; outbound Fourthwall purchase links emit store_click with product_id, product_type, source_page, and UTMs.storeReferralQuery accepts only known post paths and the calculator source. useStoreReferral preserves them in tab session storage; a fresh recognized referral replaces the old source. Never persist/forward arbitrary queries or searched names.docs/store-promotion-drafts.md, not posted. No paid promotion or recurring automation. After 8 weeks of sales availability, compare visits, orders, contribution after fees/refunds, and owner hours; separate browsing from checkout clicks. Low traffic alone does not establish poor demand.