# Fine Jewellery Template

> A cold-luxury two page site for an independent jewellery house: a raking light you sweep across a single piece to move its exposure, its specular streak, its cast shadow and its colour temperature at once, plus a twelve piece shop page with a Flip-powered category filter, add to cart on every piece and a front-end selection drawer shared across both pages.

Canonical: https://gsapvault.com/templates/fine-jewellery-template
Live demo: https://gsapvault.com/demos/fine-jewellery-template/index.html

| Property | Value |
|----------|-------|
| Type | template |
| Tier | paid |
| Price | £10 |
| Difficulty | advanced |
| Plugins | ScrollTrigger, Flip |
| Techniques | pointer-tracking, css-mask-reveal, blend-mode, quickTo, ticker-loop, parallax, scrub, scroll-reveal, stagger, flip-filter, form-validation, keyboard-navigation, dialog-animation, click-toggle, value-transition, micro-interaction |
| Uses Lenis | Yes |

## Overview

A complete two page site for Halvard, a fictional independent fine jewellery house. It is deliberately cold: a silver-grey ground, smoke ink, a single malachite accent for the inverted sections, and a raised surface that is lighter than the ground rather than darker. There is no serif anywhere and no cream, beige, brass or gold in the CSS, so the only warm colour on the page is the metal inside the photographs.

The hero is a vitrine. One macro photograph of a ring runs at more than half the width of the window, cropped by the top and right edges, with a CSS cast shadow grounding it and the second line of the headline running underneath it. Below that, a section given over entirely to one interaction: a raking light you sweep across a single piece, which changes its exposure, throws a specular streak ahead of itself, swings a cast shadow the other way and warms the lit region as it passes.

The second page is a real shop: twelve pieces in a regular four column index with working category chips that reflow the grid with GSAP Flip, and every piece visible in the markup so the page is a complete product list before any script runs. The home page keeps a packed five-piece teaser that links through to it.

Both pages sell. Every piece carries an add line under its caption, the nav carries a live count, and the drawer that slides out is a jeweller's docket: name and line total on one baseline, spec, unit price and quantity under it, then a subtotal that counts to its new figure. One selection is shared between the two pages through localStorage. It is a front end cart and it says so: the checkout button is a marked stub that takes no payment, and the README documents where to wire your own provider.

The rest is an asymmetric five-piece collection grid at four different scales, an atelier section where the photograph runs to the edge of the window and lifts above the section seam, a commission enquiry on a committed malachite field with a real validated form, and a hairline footer.

Making it yours is a four-value edit. The token block at the top of style.css holds the ground, the ink, the accent and the raised surface with their RGB triples; every other colour on the page is one of those four at another opacity. Photographs are bundled optimised WebP derivatives you can swap file for file, and every section is independent, so any of them can be deleted without breaking the others.

## Features

- Complete deployable two page jewellery site: fixed nav, vitrine hero, signature light section, collection teaser, atelier, commission form and footer, plus a full shop page
- The rake light: a pointer-driven raking light with four channels answering one input, tuned from a single named constants block
- Fast pointer movement overshoots the cast shadow past its resting angle and smears the specular streak, then damps back into a slow idle drift
- Coarse pointers get the same interaction driven by scroll progress through the section, not a switched-off placeholder
- Arrow-key control of the light with a focus stop that only exists when the script has loaded
- Two stacked copies of one photograph do the exposure reveal, so the section needs a single image file
- Second page, collection.html, with a twelve piece shop grid, working category filter and a shared stylesheet and script
- Every product photograph blended into the ground with mix-blend-mode and a per-image lift, so no plate has a visible rectangle
- Asymmetric five-piece collection grid at four scales, with captions below the photographs and a wide piece breaking the frame
- Real commission form with inline validation, described errors, and every input, label, placeholder and focus ring measured against the malachite field
- Four-token palette with RGB triples behind every translucent value, and the measured contrast table recorded in the stylesheet
- Reduced-motion, no-JavaScript and blocked-CDN states that each leave a complete, designed, fully readable page
- Optional Lenis smooth scrolling on the same clock as ScrollTrigger, switchable per page or per URL
- A front-end selection drawer on both pages: add from any piece, change quantities, remove lines, read a counting subtotal, with the selection held in localStorage and shared between the two pages
- Honest about what it is: the checkout button is a marked stub that takes no payment and places no order, and the README documents exactly where to wire Shopify, Stripe Checkout or Snipcart
- The cart control, the add lines and the drawer are built by the script, so with JavaScript off both pages stay complete catalogues with no dead buying controls
- The drawer is a real dialog: focus moves in and is trapped, Escape closes it, focus returns to the control that opened it, and the rest of the page is inert while it is open

## Use Cases

- Independent jewellers and goldsmiths selling made-to-order and commission work
- Watchmakers and other single-object luxury brands where the product photograph carries the sale
- Ceramics, glass and metalwork studios wanting a cold, gallery-like presentation
- Perfume, eyewear and small-batch accessory houses with a short numbered collection
- Any brand-and-commerce landing page that needs one memorable interaction rather than a page of them

## Vibe-Code Ready Setup

This template includes `START-HERE-AI.md`, a product-specific copy-paste setup prompt for Cursor, Claude Code, ChatGPT, GitHub Copilot, Windsurf, and other coding assistants. It tells the assistant to inspect the existing stack, integrate the supplied files, preserve the design, scope selectors, retain accessibility and responsive behaviour, add framework-appropriate GSAP cleanup, and report what it tested.

[How AI-assisted setup works](https://gsapvault.com/vibe-coding)

## How It Works

### The vitrine hero

The hero has no container and no card. The photograph is positioned against a frame that stops growing past 108rem, so the crop and the overlap hold the same proportions on a large monitor as on a laptop. Because the piece is square, its height is restated once as a custom property that both the image and its CSS cast shadow read. The shadow deliberately sits behind the headline rather than across it: a shadow falling over the type looks good and costs the headline four points of contrast.

### The rake light

One photograph is stacked twice. The lower copy is graded down to near darkness and the upper copy is graded up, then revealed through a soft linear band whose position is a single custom property. Because both layers are the same picture, a wide feather reads as light falloff rather than as two images averaging into mush, but the band keeps a solid core so the lit region still has an edge.

### Four channels, one input

Pointer x drives a gsap.quickTo onto the light position, and a ticker derives everything else from it: a smoothed signed speed, a shadow that lerps along behind rather than tracking, and a smear that relaxes on its own. Speed throws the shadow past its resting angle and elongates the streak; distance from the middle lengthens the shadow and cools the lit region. Every number is in one constants block at the top of the script.

### Touch, keyboard and rest

A coarse pointer drives the same light from scroll progress through the section, with the smear channel dropped because there is no whip gesture to smear. Arrow keys step the light and get a focus stop that the script adds and removes, so it never appears on a page whose JavaScript failed. When the pointer leaves, the light eases out of where it was left and into a slow idle drift over about a second and a half rather than snapping home.

### The shop page

collection.html reuses the same stylesheet, script and head gate as the home page, and every initialiser returns early when its markup is missing, so one script serves both. The category chips hide and show cards, set aria-pressed, and reflow the grid with Flip. The grid's height is pinned and eased during that reflow, because Flip lifts the surviving cards out of normal flow and the page below would otherwise lurch on every press.

### The cart drawer

Add lines under every piece on both pages write to one selection in localStorage, so a piece added on the home page teaser and the same piece on the collection page are one line item rather than two. The drawer lists each line as a jeweller's docket, name and total on one baseline with the spec, unit price and quantity under it, and the subtotal counts to its new figure instead of cutting to it. Prices are read out of the card's own caption and held as whole pence, so the drawer cannot disagree with the card and a subtotal never picks up a rounding error. It is front end only: the checkout button is a stub that says so, on the panel and again when pressed, and the README documents where to put your own provider.

### Without JavaScript

The gating class is added synchronously in the head so reveal start states apply before first paint, and the script removes it when GSAP is missing, so a blocked CDN degrades to the plain document rather than hiding content forever. The light position and warmth are ordinary CSS custom properties with sensible initial values, so with scripting off the piece is already lit from the right. Under prefers-reduced-motion the same section freezes at a flattering angle with the shadow at rest, and the form falls back to the browser's own validation. The cart is built the same way round: the control, the add lines and the whole drawer are created by the script rather than written into the pages, so a visitor with scripting off gets a complete catalogue with no buying chrome instead of buttons that cannot work.

## Integration Preview

How this effect integrates into a page. The full documentation (examples, events, programmatic API, customization guide) ships with the download.

### Quick Start

**1. Upload the folder.** It is static: `index.html`, `collection.html`,
`assets/style.css`, `assets/script.js`, `assets/img/`. No build step, no
dependencies to install. Both pages share one stylesheet and one script, and
every section initialiser returns early when its markup is absent, so each
page silently skips what it does not have.

**2. The three script tags at the bottom of `index.html`** load GSAP,
ScrollTrigger and Lenis from a CDN. Leave them as they are, or self-host the
files and change the paths.

```html
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/ScrollTrigger.min.js"></script>
<script src="https://unpkg.com/lenis@1.3.17/dist/lenis.min.js"></script>
<script src="assets/script.js"></script>
```

**3. Keep this line in `<head>`, above the stylesheet:**

```html
<script data-cfasync="false">document.documentElement.classList.add('has-js')</script>
```

It runs before the first paint so that reveal start states apply without a
flash. `assets/script.js` removes the class again if GSAP fails to load, which
is what makes a blocked CDN degrade to a plain readable document instead of a
page of hidden content. Moving this into the body reintroduces the flash.

**4. Replace the copy and the photographs.** Every section is independent: the
script skips any section whose markup is not there, so you can delete whole
sections without touching the JavaScript.

### Accessibility

- **Contrast.** Every pair on the page was measured as used, composited, at
  the size it is used, and the results are in the `:root` header comment in
  `assets/style.css`. Nothing relies on the 3:1 large-text allowance.
- **Reduced motion.** Under `prefers-reduced-motion` the page is a designed
  static document, not the animated one with the motion switched off. The rake
  light freezes at a flattering angle with the piece lit and the shadow at
  rest, and every reveal target is restored by CSS independently of the script.
- **Keyboard.** The rake light takes Arrow Left and Arrow Right. Its focus stop
  is added by the script and removed on teardown, so it never appears on a page
  whose JavaScript did not load. Focus outlines are visible on every ground and
  switch colour on the two dark sections.
- **Touch.** A coarse pointer gets the rake light driven by scroll progress
  through the section rather than nothing, with the smear channel dropped
  because there is no whip gesture to smear.
- **No JavaScript.** Every piece of content is readable with scripting off. The
  light position and the warmth are ordinary CSS custom properties with
  sensible initial values, so the piece in the rake section is already lit.
- **Forms.** Labels sit above inputs, errors sit below them and are wired with
  `aria-describedby`, and no placeholder is used as a label.
- **The cart.** A real dialog: focus moves in, is trapped, and returns to the
  control that opened it; Escape closes it; the rest of the page is `inert`
  while it is open. One live region announces every count change. The whole
  of it is built by the script, so with scripting off there is no cart
  control anywhere and nothing on either page is unreachable. Full detail in
  the Cart section above.

### Dependencies

| Library | Version | Required |
|---|---|---|
| GSAP | 3.14.2 | Yes |
| ScrollTrigger | 3.14.2 | Yes |
| Lenis | 1.3.17 | Optional |

Smooth scroll is opt-out. Add `data-smooth="off"` to the `<html>` tag to ship
without it, or append `?smooth=off` to the URL to compare a page both ways
without editing anything. It is also off automatically under
`prefers-reduced-motion`, which Lenis does not honour by itself.

If you remove Lenis, delete the whole `initLenis` block at the bottom of
`assets/script.js` rather than part of it. The shared-clock wiring, the opt-out
check, the refresh listener and the teardown each fix a different bug, and half
of that block reads as correct while still being broken.

## What You Get

- `index.html`: working demo page
- `assets/script.js`: commented, readable source
- `assets/style.css`: effect styles
- `README.md`: full documentation with examples and framework integration notes
- `START-HERE-AI.md`: product-specific copy-paste prompt for AI-assisted setup
- `LICENSE.txt`: standard license terms
- Lifetime updates: re-download anytime from your library

## Get the Code

This is a premium template. The standard license costs £10 one-time and covers unlimited personal and commercial projects with no attribution required. The only restrictions: no redistribution of the code itself and no competing effect libraries.

- [Buy Fine Jewellery Template](https://gsapvault.com/templates/fine-jewellery-template)
- [Effects & Templates Vault (£39 one-time, best value): every current and future effect and template](https://gsapvault.com/effects)

---

From [GSAP Vault](https://gsapvault.com): production-ready GSAP animation effects. Full catalog for agents: https://gsapvault.com/llms-full.txt
