diff --git a/CLAUDE.md b/CLAUDE.md index 8a05b73..3867889 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -126,14 +126,16 @@ Three build shapes from one project (see the header comment in ## Content guardrails (from the brief) -- This is Quentin's **personal** site; it does not speak for any employer. Walmart is - named only as a biographical fact in body copy. No Walmart imagery, internal work, - confidential detail, or implied endorsement; keep case-study specifics generic - ("a Fortune 1 retailer"). Do not present him as an official representative in - metadata or structured data: machine-readable employer claims (`worksFor`, an - employer name inside ``) are out. `tools/seo_check.py` fails if a flagged - company name appears in any page ``, so keep such terms in body content only - (never in a `seo.*` field, since those render into ``). +- This is Quentin's **personal** site; it does not speak for any employer. Walmart may + be named in body copy, and public work Quentin himself has posted publicly (e.g. his + own NYC pop-up-shop video) may be shown and named at the owner's discretion. What + stays out regardless: internal, unreleased, or confidential work, and any implied + official endorsement. When describing enterprise engagements in the abstract, still + prefer generic framing ("a Fortune 1 retailer"). Do not present him as an official + representative in metadata or structured data: machine-readable employer claims + (`worksFor`, an employer name inside ``) are out. `tools/seo_check.py` fails if + a flagged company name appears in any page ``, so keep such terms in body + content only (never in a `seo.*` field, since those render into ``). - "Don't just wear clothes, wear confidence" survives only as a secondary tagline (the footer), not the headline. diff --git a/content/work.yaml b/content/work.yaml index f93855a..96e7ac5 100644 --- a/content/work.yaml +++ b/content/work.yaml @@ -143,6 +143,19 @@ archive: capTitle: "Editorial" capSub: "Color & movement" footnote: "A selection from a decade of work. Full archive available on request." +video: + eyebrow: "In motion" + heading: "On the floor" + intro: "The work moving, not just the finished frame. Tap to watch." + items: + - poster: + src: "assets/img/work-popup-shop.jpg" + alt: "Quentin Fears styling a New York City pop-up shop" + tag: "Video" + label: "YouTube Short" + caption: "Styling a New York City pop-up shop for Walmart. Brandon Maxwell gives the team a shout-out." + permalink: "https://youtube.com/shorts/PXC-BWog7-Q" + videoSrc: "" cta: heading: "I take on a few brand projects at a time." body: "Creative direction, visual strategy, and campaign work for brands and agencies." diff --git a/keystatic.config.ts b/keystatic.config.ts index 0cc01ad..ddba942 100644 --- a/keystatic.config.ts +++ b/keystatic.config.ts @@ -302,6 +302,30 @@ export default config({ }, { label: 'Styling archive' } ), + video: fields.object( + { + eyebrow: fields.text({ label: 'Eyebrow' }), + heading: fields.text({ label: 'Heading' }), + intro: fields.text({ label: 'Intro', multiline: true }), + items: fields.array( + fields.object({ + poster: photo('Poster still (vertical, ~1080x1920)'), + caption: fields.text({ label: 'Caption', multiline: true }), + permalink: fields.text({ + label: 'Video permalink', + description: 'YouTube or Instagram URL, used as the link when no self-hosted video is set', + }), + videoSrc: fields.text({ + label: 'Self-hosted video path (optional)', + description: + 'e.g. assets/video/clip-x.mp4 (produced by tools/prepare_reel.py). Blank = the poster links out to the permalink instead.', + }), + }), + { label: 'Videos', itemLabel: (p) => (p.fields.caption.value || 'Video').slice(0, 48) } + ), + }, + { label: 'Video' } + ), cta: cta(), }, }), diff --git a/public/assets/img/work-popup-shop-1080.avif b/public/assets/img/work-popup-shop-1080.avif new file mode 100644 index 0000000..7ba841d Binary files /dev/null and b/public/assets/img/work-popup-shop-1080.avif differ diff --git a/public/assets/img/work-popup-shop-1080.webp b/public/assets/img/work-popup-shop-1080.webp new file mode 100644 index 0000000..8ff132a Binary files /dev/null and b/public/assets/img/work-popup-shop-1080.webp differ diff --git a/public/assets/img/work-popup-shop-400.avif b/public/assets/img/work-popup-shop-400.avif new file mode 100644 index 0000000..195b7f8 Binary files /dev/null and b/public/assets/img/work-popup-shop-400.avif differ diff --git a/public/assets/img/work-popup-shop-400.webp b/public/assets/img/work-popup-shop-400.webp new file mode 100644 index 0000000..8024e54 Binary files /dev/null and b/public/assets/img/work-popup-shop-400.webp differ diff --git a/public/assets/img/work-popup-shop-800.avif b/public/assets/img/work-popup-shop-800.avif new file mode 100644 index 0000000..f94d62a Binary files /dev/null and b/public/assets/img/work-popup-shop-800.avif differ diff --git a/public/assets/img/work-popup-shop-800.webp b/public/assets/img/work-popup-shop-800.webp new file mode 100644 index 0000000..956c212 Binary files /dev/null and b/public/assets/img/work-popup-shop-800.webp differ diff --git a/public/assets/img/work-popup-shop.jpg b/public/assets/img/work-popup-shop.jpg new file mode 100644 index 0000000..e86588b Binary files /dev/null and b/public/assets/img/work-popup-shop.jpg differ diff --git a/src/data/img-variants.json b/src/data/img-variants.json index b2fa321..43064d4 100644 --- a/src/data/img-variants.json +++ b/src/data/img-variants.json @@ -215,6 +215,15 @@ 1080 ] }, + "assets/img/work-popup-shop.jpg": { + "height": 1920, + "width": 1080, + "widths": [ + 400, + 800, + 1080 + ] + }, "assets/img/work-time.jpg": { "height": 988, "width": 791, diff --git a/src/pages/work.astro b/src/pages/work.astro index fc1c889..0e98448 100644 --- a/src/pages/work.astro +++ b/src/pages/work.astro @@ -113,6 +113,44 @@ const jsonLd = { + + {work.video && work.video.items.length > 0 && ( + +
+
+
+
+

{work.video.eyebrow}

+

{work.video.heading}

+ {work.video.intro &&

{work.video.intro}

} +
+
+ {work.video.items.map((r) => { + const platform = r.permalink && /youtu\.?be/i.test(r.permalink) ? 'YouTube' : 'Instagram'; + return r.videoSrc ? ( +
+
+ + +
+
{r.caption}
+
+ ) : ( +
+ + + Watch on {platform} ↗ + +
{r.caption}
+
+ ); + })} +
+
+
+
+ )} +