Commit Graph

51 Commits

Author SHA1 Message Date
Jeff Emmett 9c82616d0f Deploy Listmonk newsletter at newsletter.jeffemmett.com
Wire subscribe forms to Listmonk API (token auth) with double opt-in,
falling back to email notifications when Listmonk is not configured.
SMTP via Mailcow (orders@katheryntrenshaw.com).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 13:05:19 -07:00
Jeff Emmett 7a295b183c chore: add backlog-notify onStatusChange hook
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:31:01 -07:00
Jeff Emmett 0e10b7482f Wire contact form, subscribe page, and footer newsletter to send emails
- Contact form POSTs to /api/contact → emails Katheryn with reply-to sender
- Subscribe page and footer form POST to /api/subscribe → welcome email
  to subscriber + notification to Katheryn
- Loading states, error handling, and disabled buttons while sending

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 00:34:04 +00:00
Jeff Emmett fadc3efc91 Migrate SMTP to mail.rmail.online for order emails
Updated SMTP_HOST from mx.jeffemmett.com to mail.rmail.online
using shared service credentials for orders@katheryntrenshaw.com.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 00:30:54 +00:00
Jeff Emmett a1038b72eb Redirect inyourownskin.org and passionatepresence.org to subpages
301 permanent redirects via Traefik middlewares:
- inyourownskin.org → katheryntrenshaw.com/in-your-own-skin
- passionatepresence.org → katheryntrenshaw.com/passionate-presence-centre

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 00:15:30 +00:00
Jeff Emmett 6a0ebc2d29 Consolidate header, add subscribe page, fix blog images, compress footer
- Merge two-bar header into single nav bar: remove social icons top bar,
  move search + cart icons next to hamburger menu
- Add /subscribe page with email signup form
- Fix blog images by restoring Squarespace CDN in next.config remotePatterns
- Compress footer into 4-column link layout, remove logo block
- Update Cynthia Trenshaw Poetry link to cynthiatrenshaw.com
- Add local images for homepage, about, IYOS, and artwork pages
- Add /wisdom-words page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 00:13:36 +00:00
Jeff Emmett 66454a4338 chore: migrate SMTP from mx.jeffemmett.com to mail.rmail.online
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:15:35 +00:00
Jeff Emmett 080268af22 Add KT monogram favicon for Katheryn Trenshaw site
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 14:54:21 -07:00
Jeff Emmett 6e74f4e360 Fix PayPal MULTI_CURRENCY_ORDER error by using consistent GBP
All store items are priced in GBP (filtered by price_gbp > 0).
Hardcode GBP currency throughout the checkout and order creation
flow to prevent currency mismatches between the PayPal SDK, order
items, and purchase unit amounts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 14:40:27 -07:00
Jeff Emmett e410bd1b0a Hardcode PayPal sandbox client ID as build arg
The env_file is only available at runtime, not during docker build.
Build args need explicit values in docker-compose.yml for NEXT_PUBLIC
vars to be inlined into the client bundle.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 14:35:50 -07:00
Jeff Emmett 518f08e8e6 Pass PayPal client ID as build arg for client-side bundle
NEXT_PUBLIC_* vars must be available at build time to be inlined
into the client JS bundle. Added NEXT_PUBLIC_PAYPAL_CLIENT_ID as
a Docker build arg so the PayPal checkout button works in the browser.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 14:34:38 -07:00
Jeff Emmett 09567cedad Fix store images: remove search restriction from localPatterns
The `search: ''` setting in localPatterns was blocking image URLs
that include query parameters (width, quality, format). Removing
this restriction allows the /api/assets proxy URLs to pass through
Next.js image optimization.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:41:46 -07:00
Jeff Emmett da7747610c Use GBP price as the store-readiness signal
Setting a GBP price in Directus is the intentional signal that an
artwork is for sale. USD-only items (264 with images) are imported
historical catalog data not meant for the store. The store now shows
the 19 artworks that have name + image + GBP price set.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:30:20 -07:00
Jeff Emmett 474470900f Automatic inventory management for the store
Artworks now automatically appear in the store when their required
fields are populated in Directus (name, image, and at least one price
in GBP or USD). Changing status to 'sold' moves them to the sold
section; 'draft' or 'archived' removes them entirely. No manual
"add to store" step needed — field completeness drives visibility.

Also ensures related works on detail pages only show store-ready items.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:27:19 -07:00
Jeff Emmett 94894181ea Filter store to only show artworks with GBP prices set
The store was fetching all 2,324 artworks and filtering client-side,
resulting in 656 items shown (including imported catalog entries with
only USD prices and no images). Now filters at the Directus API level
for artworks with price_gbp set, showing only the 19 actual store items.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:23:28 -07:00
Jeff Emmett 2523a304cf Add localPatterns for /api/assets and writable cache dir
- Configure images.localPatterns to allow /api/assets/** with query strings
- Add /app/.next/cache as tmpfs for image optimization cache (read-only container)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:12:46 -07:00
Jeff Emmett 5f0d2eff16 Use API route proxy for Directus assets instead of direct internal URL
Next.js image optimizer blocks internal Docker URLs due to SSRF
protection (private IP resolution). Instead, proxy assets through
/api/assets/[id] which fetches from internal Directus URL server-side.

This bypasses both Cloudflare Access and SSRF protection since the
<Image> src is a same-origin path, not an external URL.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:11:13 -07:00
Jeff Emmett cd7c0200f3 Add NEXT_PUBLIC asset vars to runtime environment
NEXT_PUBLIC_ vars need to be set both at build time (client bundle)
AND at runtime (server-side rendering in standalone mode).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:06:44 -07:00
Jeff Emmett 41d784e92d Fix store images: bypass Cloudflare Access via internal Docker URL
Directus CMS is behind Cloudflare Access, which blocks the Next.js
image optimizer from fetching assets. Route image requests through the
internal Docker network (http://katheryn-cms:8055) instead.

- Add NEXT_PUBLIC_DIRECTUS_ASSET_URL/TOKEN env vars for client components
- Use DIRECTUS_INTERNAL_URL for server-side Directus API calls
- Convert store detail page from client to server component (data
  fetching now happens server-side, not in browser)
- Add internal Docker hostname to Next.js remotePatterns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:03:04 -07:00
Jeff Emmett 808b552b8e Mark task-5 (shop page) as Done with checkout/shipping/payment notes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 12:48:08 -07:00
Jeff Emmett 2966e3e003 Add PayPal/nodemailer deps and Order/OrderItem types
- Add @paypal/react-paypal-js, nodemailer, @types/nodemailer to package.json
- Add Order and OrderItem TypeScript interfaces to directus.ts
- These were part of the checkout implementation but missed in the initial commit

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 12:47:13 -07:00
Jeff Emmett f90b35d03a Update env_file path to /opt/secrets/katheryn-website/.env
Migrated from /root/.katheryn_credentials to the new organized
/opt/secrets/ directory structure. Symlinks ensure backward compat.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 12:43:24 -07:00
Jeff Emmett 2196cad129 Move secrets to env_file, add security hardening to docker-compose
- Use env_file referencing /root/.katheryn_credentials for all secrets
- Remove inline secrets from environment block (PayPal, SMTP, store token)
- Add directus_katheryn-internal network for internal CMS access
- Add container security: read_only, cap_drop ALL, no-new-privileges

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 12:34:12 -07:00
Jeff Emmett 2b5f2cf91d Add flat-rate shipping, PayPal checkout, and order confirmation emails
- Create shipping.ts with flat-rate tiers: UK £10, Europe £25, International £40
- Integrate shipping cost into PayPal order breakdown (item_total + shipping)
- Add server-side shipping calculation in order creation API (prevents tampering)
- Update checkout page to show real-time shipping cost based on country selection
- Add subtotal/shipping/total breakdown to order confirmation page
- Add order confirmation emails via SMTP (customer + Katheryn notification)
- Include shipping breakdown in email templates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 12:30:36 -07:00
Jeff Emmett 462b34f114 Add completed task-11: Fix blog post rendering issues
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 15:30:16 +00:00
Jeff Emmett da39ee7751 Remove duplicate featured images from blog content
- Add removeLeadingImage() to strip the first image from content when it matches
  the featured image, preventing duplication on blog post pages
- Handles figure wraps, linked images, and standalone img tags
- Featured image now appears only once (in the header), not repeated in content

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 14:54:31 +00:00
Jeff Emmett 64da557836 Convert WordPress [caption] shortcodes to proper HTML figures
- Add convertCaptionShortcodes() to transform [caption]...[/caption] into
  <figure class="wp-caption"> with <figcaption>
- Handle both plain images and linked images (wrapped in <a> tags)
- Add CSS styling for figure captions in prose content
- All 17 posts with captions now display properly

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 13:59:15 +00:00
Jeff Emmett 204679b740 Fix blog excerpt rendering: remove shortcodes and decode HTML entities
- Add decodeExcerptEntities() to handle &mdash;, &hellip;, smart quotes, etc.
- Add removeShortcodes() to strip [caption] and other WordPress shortcodes
- Regenerate blog-posts.json and pages.json with cleaned excerpts

Fixes issue where [caption] tags and raw HTML entities appeared in blog listings.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 13:46:20 +00:00
Jeff Emmett 9cc37beadb Update backlog tasks and add jsdom dependency
- Update task-5, task-8, task-10 with session progress
- Add jsdom for blog content cleanup

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 23:52:31 +00:00
Jeff Emmett aaea7c1b86 Clean up blog post HTML formatting
- Convert Squarespace [caption] shortcodes to proper figure elements
- Remove empty div wrappers
- Remove empty anchor tags
- Add consistent image classes
- Clean up blockquote formatting
- Remove empty paragraphs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 23:49:06 +00:00
Jeff Emmett cdae57d706 Add YouTube video to Breaking The Silence page
Embeds the Breaking The Silence film (https://youtu.be/hpzvEQs9vEk)
in a dedicated video section on the page.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 23:26:47 +00:00
Jeff Emmett 265af9b8fa Add Work With Me pages with content from original site
- Add Passionate Presence Centre page with Living Awake series
- Add Consulting page with approach and testimonials
- Add 1-to-1 Sessions page with session types and areas of focus
- Update navigation to link to new pages
- Add images for all three pages

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 23:22:26 +00:00
Jeff Emmett 586aa8de85 Force dynamic rendering for Directus pages
- Homepage, events, and store pages now use force-dynamic
- This ensures fresh data is fetched at runtime
- Fixes build-time Directus fetch failures

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 22:37:55 +00:00
Jeff Emmett fee96430ff Add event thumbnail images to homepage
- Import getAssetUrl function for Directus asset URLs
- Update homepage events section to display thumbnail images
- Images link to events page and show hover effect
- Fallback gracefully when no image is available

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 22:32:36 +00:00
Jeff Emmett 4002c2fe40 Move hero quote down to not cover face in photo 2026-02-04 22:22:53 +00:00
Jeff Emmett 0e13f60d14 Improve Directus integration and homepage dynamic events
- Add auth token to asset URLs for proper image access
- Map Directus artwork fields (name->title, price_gbp/usd->price, notes->description)
- Add currency field (GBP/USD) based on available price
- Fetch upcoming events dynamically on homepage
- Prefer artworks with images for featured display
- Add proper error handling for artwork lookups

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 22:02:17 +00:00
Jeff Emmett 5a477e31a2 Fix book covers: show full images without cropping
Switch from fill+object-cover (crops to aspect ratio) to explicit
width/height so book covers display at their natural proportions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 11:18:08 +00:00
Jeff Emmett a236963926 Replace book covers with full uncropped Amazon images
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 11:14:40 +00:00
Jeff Emmett aa588d8910 Update Meeting in the Margins Amazon link to paperback edition
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 11:12:22 +00:00
Jeff Emmett 26f4f97fec Update Amazon links for both books
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 11:11:30 +00:00
Jeff Emmett 5dedc87532 Add circular portrait to homepage hero, improve TOC link affordance
- Add Cynthia's portrait photo as a circular image above her name
- Restyle TOC entries with hover background, arrow reveal on hover,
  and subtle transition to make poems feel more clickable

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 11:07:59 +00:00
Jeff Emmett 11063b73cb Remove Hillsdale photo from above Second Chapter on about page
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 11:04:28 +00:00
Jeff Emmett f50cf2a58d Redesign cynthia-poetry as elegant digital chapbook with 87 poems
- Organize 87 poems into 3 thematic sections:
  I. At the Threshold (mortality, hospice, accompaniment)
  II. The Country of Memory (family, childhood, remembrance)
  III. Wild Things, Still Breathing (nature, prayer, presence)
- Create shared data module (src/data/poems.ts) with all poem content
- Add book-format table of contents on homepage
- Add sequential prev/next navigation between poems
- Add section breadcrumbs on poem pages
- Create About page with enriched biography and photos
- Reframe essay as Afterword with proper navigation
- Include both books: Meeting in the Margins + Mortal Beings
- Download 3 photos of Cynthia and Meeting in the Margins cover
- Add book-specific CSS (TOC entries, separators, poem nav)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 10:46:14 +00:00
Jeff Emmett f6651732c1 Add cynthia-poetry site to monorepo with Mortal Beings book cover
Moved cynthia-poetry-website into katheryn-website repo as sibling to
frontend. Added actual Mortal Beings book cover image replacing the
placeholder text. Also includes new backlog tasks for newsletter setup
and artwork processing.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 08:49:06 +00:00
Jeff Emmett c116ec5ea4 Remove duplicate newsletter signup from footer
Keep social links, logo, and copyright in footer.
Newsletter signup is already available in /subscribe page.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 02:09:37 +00:00
Jeff Emmett 94ec5ada95 Add Cynthia Trenshaw Poetry link to navigation
- Add external link to cynthia-staging.jeffemmett.com
- Support external links in both desktop and mobile nav
- Opens in new tab with proper rel attributes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 02:04:56 +00:00
Jeff Emmett 13500b3931 Fix build: add inline fallback images for artwork section 2026-02-03 02:00:24 +00:00
Jeff Emmett 80497fd4ed Update homepage with full-screen hero from Squarespace
- Add full-screen portrait hero with testimonial quote overlay
- Add social icons on hero section
- Add scroll indicator animation
- Add YouTube video background for In Your Own Skin section
- Add book section with Amazon embed
- Add Amazon images domain to Next.js config

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 01:59:11 +00:00
Jeff Emmett 7c9f222217 feat: Enhance About page with rich Squarespace content
- Add full biographical content from Squarespace export
- Include artist statement and teacher bio sections
- Add media banner and major projects showcase
- Use Squarespace CDN images for portraits

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 01:26:41 +00:00
Jeff Emmett 1d0dfc342e feat: Add blog system with 72 posts from Squarespace export
- Parse Squarespace WordPress XML export and extract all blog posts
- Create blog listing page with posts grouped by year
- Create individual blog post pages with full content
- Add social sharing, prev/next navigation, related posts
- Configure Next.js for Squarespace CDN images
- Add Tailwind typography plugin for prose styling
- Include 357 artwork thumbnails from Airtable

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 01:23:12 +00:00