Skip to content

Guide

How This Site Was Built

A behind-the-scenes look at the stack, design decisions, and process behind the Unveiling Rarities memoir site — written so anyone (including a future editor of this repo) can pick up where this left off.

Tech Stack

Next.js 16 (App Router, TypeScript), Tailwind CSS v4 for styling with luxury theme tokens, Framer Motion for scroll-reveal and hero entrance animation, and GSAP + ScrollTrigger for the one place it earns its keep: subtle scroll-based image parallax. No Three.js / React Three Fiber — a 2D editorial site didn’t need it, and the brief was explicit about avoiding 3D for its own sake.

Design Direction

This is a book and legacy site first, jewelry-store site never. Every design decision was filtered through “does this feel like a museum-grade private archive and a sophisticated editorial publisher” rather than “does this look like an e-commerce storefront.” That ruled out product-grid layouts, sale-style CTAs, and anything that reads as SaaS-template.

Visual System

Deep black (obsidian) backgrounds throughout, with gold as the primary metallic accent, champagne and ivory for warm text and highlights, and platinum/silver introduced as a cooler secondary metallic tone. Ruby is used sparingly — a single soft glow in the generative backdrop, never a dominant color. Diamond-inspired details (a small rotated-square “facet” icon with a slow glint animation) mark each point on the journey timeline.

Typography Choices

Cormorant Garamond for all display/heading type — an elegant, high-contrast serif that reads as literary rather than corporate. Inter for body copy, chosen for clean legibility at small sizes on mobile. The pairing is intentionally restrained: one serif, one sans, used consistently everywhere rather than introducing a third display face.

Animation Approach

Motion is used to support the emotional pacing of a memoir, not to impress for its own sake: a staggered fade/rise on the hero, scroll-triggered reveals (fade + 28px rise, once per element) on every section, a real generated video behind both the hero and the quote section (see Higgsfield section below), and GSAP-driven parallax on the real photograph. A generative “cinematic backdrop” of drifting gold/platinum/ruby light (CinematicBackdrop.tsx) remains in the codebase as a fallback pattern but isn’t currently used on the page. Every animated component respects prefers-reduced-motion via Framer Motion’s useReducedMotion() hook, but deliberately only ever varies transition duration — never the shape of the animated target values. A global MotionConfig reducedMotion="user" was tried first and looked correct on a quick check, but a closer motion audit found it left content permanently invisible for reduced-motion users in some cases — see the iteration notes below.

Asset Workflow

Four real assets are in production use today: Jeff at a jeweler’s bench with a loupe (Author section and Gallery), the real book cover art (Book section and Gallery — its title/subtitle/byline are baked into the image itself, not overlaid text), a generated cinematic video of the actual cover coming to life — book opens, transitions into a chess king and ruby (Hero background, the first thing visitors see), and a second generated video of a chess knight and faceted ruby, book-cover-inspired (Quote section background — see the Higgsfield section below for how these were made). Everything else — five gallery slots and the journey timeline’s visual texture — renders as a deliberately designed placeholder (never a broken image or empty gray box) until real assets exist. Full generation prompts for every missing asset live in ASSET_PROMPTS.md at the repo root, each tied to its exact file/insertion point.

GPT Image 2 (or Equivalent) — Fallback Plan

No image-generation API was connected in the environment this site was built in, so this section documents the plan rather than a result. The book cover ended up being a real asset the user provided directly rather than something generated. If GPT Image 2 (or Midjourney/Flux/etc.) becomes available, the remaining highest-value targets are: macro gemstone photography for the five open gallery slots, and archival-style “New York Diamond District, 1970s–80s” atmosphere shots for the Journey section. Prompts for all of these are in ASSET_PROMPTS.md. Do not use Pinterest or copyrighted reference images directly — inspiration only, generate original work.

Higgsfield MCP — What Actually Happened

Higgsfield wasn’t connected for most of this build, so a comparable vidiq video-generation toolset was used instead — with explicit approval each time, since generation spends credits. Both cinematic videos on the page (Hero and Quote section, rendered by components/motion/VideoBackdrop.tsx) are genuine vidiq/Seedance output, not stock or hand-made.

The Quote section’s video (chess knight + faceted ruby) took four attempts to land on: (1) sora-2 was blocked by content moderation for unclear reasons (credits auto-refunded); (2) seedance-2-fast succeeded but the gem read as a ruby rather than a diamond; (3) explicit “brilliant round-cut facets” wording produced an actual faceted red diamond, matching the timeline’s 2021 Fancy Red diamond beat, and briefly shipped; (4) the user then supplied their own prompt explicitly calling for a ruby — i.e. reverting by design — which produced a different piece style entirely (a knight with a crown finial, dark gunmetal, gold-dust bokeh). The user reviewed this one directly and preferred it, so it shipped. All four of these were purely text-prompted — none referenced the real book cover’s pixels, because vidiq only accepts reference images as base64 in the tool call itself, and even a heavily downscaled ~10KB JPEG cost tens of thousands of tokens to transmit that way.

Partway through the build, a Higgsfield MCP connection did appear, and it changes the calculus completely for anything that needs to reference a real image: its media_import_url tool imports a live HTTPS URL server-side and returns a reusable media_id — no base64, no token cost at all. Its seedance_2_0 model is explicitly built for “reference-driven video ... consistent identity,” which is exactly what reproducing a real book cover in video needs. A cost preflight (get_cost: true) quoted only 35 credits for the Hero’s 10-second sequence — but the connected Higgsfield account only had ~24 credits available, so the job couldn’t run there.

The Hero’s video — the book cover opening into the chess king/ruby scene, the first thing a visitor sees — ended up generated via vidiq after all, but this time paying the base64 token cost deliberately: a downscaled ~14KB JPEG of the real cover was passed as a vidiq ingredients reference. It worked far better than expected — the model rendered “UNVEILING RARITIES,” “My Fifty Years in the World of Diamonds,” and “JEFF PANCIS” accurately and legibly on a photorealistic 3D book mockup, because it had real text to copy rather than needing to invent it. Lesson for next time: if Higgsfield has enough credits, prefer it for anything referencing a real image — media_import_url removes the token-cost problem entirely, and its identity-preserving model is purpose-built for this; vidiq’s base64-only path is a viable but expensive fallback.

One thing deliberately left out of every generation: the original brief for the Hero video also asked for archival and family photos of Jeff Pancis to appear within the book’s pages. Video models can’t accurately reproduce a specific real person’s likeness, and fabricating a fake face to represent a real, living person would misrepresent him — so that part was skipped rather than attempted. If wanted, the honest way to do it is compositing his real photos into the finished video afterward, not generating them.

Deployment Process

Production build verified locally (npm run build) after lint and typecheck passed clean, then linked and deployed via the Vercel CLI (vercel link --project unveiling-rarities vercel deploy --prod), which also auto-connected the project’s GitHub repo for future git-triggered deploys. Live at unveiling-rarities.vercel.app. One Windows-only development quirk is worth noting for future contributors: Next.js 16’s Turbopack dev server currently panics on Windows when the project path contains a space (this repo lives in “Unveiling Rarities”), so local dev runs with next dev --webpack as a workaround. Production builds are unaffected either way.

Three Iteration Passes

Pass 1 — Design audit: reviewed every section for spacing, hierarchy, and whether it still read as a generic template versus a considered memoir site; tightened section rhythm and made sure the Author section’s Holocaust-survivor-parents line was treated with the same quiet weight as the rest of the copy rather than singled out for dramatic emphasis.

Pass 2 — Motion and interaction audit: switched off a global MotionConfig reducedMotion="user" in favor of per-component handling that only varies transitionduration, never the animated target values — the target-value approach is what caused an earlier hydration mismatch in this project’s history, and duration-only branching avoids it by keeping the server-rendered markup identical either way. Also gave the cinematic backdrop’s infinite drifting-light loop an explicit reduced-motion resting state (auto-playing motion past five seconds should be reducible per WCAG 2.2.2), and confirmed the journey timeline’s diamond-glint detail reads as texture, not a distraction.

Pass 3 — Production audit: ran lint, typecheck, and a production build to a clean exit code; checked for console errors and broken internal links across every anchor section and the /guide route; removed dead code left over from the site’s earlier jewelry-store iteration; verified accessibility basics (focus states, semantic landmarks, form labels) before deployment.

Pre-Launch Refinement Pass

A final pass ahead of the unveilingrarities.com launch, working from a client feedback list rather than an internal audit. Added the book’s subtitle (“My Fifty Years in the World of Diamonds”) to the Hero and Book section, renamed the Hero’s secondary button to “Contact Jeff,” and layered a soft ruby glow behind the book cover in the Hero to round out the gold-and-ruby luxury palette the brief called for. Switched the Hero video backdrop’s poster/fallback image from the generated cinematic frame to the real book cover file, so a slow or failed video load still shows authentic cover art rather than an AI mockup.

Added a new “A Life in Diamonds” section (components/home/LegacySection.tsx) between the Author and Journey sections — deliberately styled as matted, slightly rotated keepsake photos rather than reusing the Gallery grid, so it reads as personal memory rather than stock photography. Two of its three photo slots (a young photo of Jeff, and a current photo of Jeff with his wife) are intentionally left as elegant placeholders rather than AI-generated: image and video models can’t reliably reproduce a specific real person’s likeness, and fabricating one would misrepresent real, living people — the same call made earlier in this project when video generation was in play. They’re ready for real family photos to be dropped in via lib/data.ts.

Rewrote the Author bio to the client-supplied copy while preserving the two real, previously-verified biographical facts already on the site (the Cowboys Super Bowl starcut diamond credit and the Holocaust-survivor-parents legacy line) rather than dropping them for the new draft. Renamed the contact form’s inquiry options to match the requested set (Book Inquiry, Speaking / Interview Request, Press / Media, Family / Legacy Inquiry, General Contact) and relabeled the field “Reason for Inquiry.”

Updated metadata for launch: page title now reads exactly “Unveiling Rarities by Jeff Pancis,” the description matches the requested copy, and Open Graph/Twitter cards now include the real book cover as the social share image. Added a proper favicon (app/icon.svg, a gold diamond-facet monogram on obsidian) and a brand-styled 404 page. The README now documents the exact DNS/SSL steps for connecting unveilingrarities.com in Vercel, including the www ↔ apex redirect.

One deliberate non-change: the client feedback suggested per-section page titles (Home, The Book, About Jeff Pancis, Journey, Contact). This site is intentionally a single scrolling page with anchor navigation rather than five separate routes — splitting it into multiple pages would be a real architectural change, not a refinement, and would work against the “don’t overcomplicate the design” instruction in the same brief. The single home-page title (“Unveiling Rarities by Jeff Pancis”) and the section anchor ids used by the nav (Book, Jeff Pancis, Legacy, Journey, Contact) are the single-page equivalent.

Two follow-ups after this pass shipped. First, the real “Jeff & Audrey Pancis, Today” photo replaced the placeholder in the Legacy section — the caption now names her, and the original full-resolution file lives in the gitignored brand-reference/ folder, with only an optimized web copy shipped in public/images/brand/. Second, the Gallery section (“A Private Archive”) was pulled from the page: with four of its seven slots still generic placeholder icons, it read as unfinished next to the new memoir-styled Legacy section covering similar ground with real photos. The component and its data in lib/data.ts are untouched — it’s a one-line re-add in app/page.tsx once more real photography is available.

Third: this very page’s footer link (“How this site was built”) was removed. A behind-the-scenes build log is useful for whoever maintains this repo next, but it isn’t something a memoir site’s visitors need to see, and surfacing it worked against the polished, editorial feel the rest of the site aims for. The route itself is left in place rather than deleted — set to robots: { index: false, follow: false } and dropped from app/sitemap.ts, so it’s unlinked and unindexed but still readable at /guide for anyone who has the repo open.