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>
This commit is contained in:
Jeff Emmett 2026-02-03 08:49:06 +00:00
parent c116ec5ea4
commit f6651732c1
92 changed files with 7999 additions and 1 deletions

View File

@ -0,0 +1,48 @@
---
id: task-10
title: >-
Process 1000+ artwork images: center, color correct, and categorize in
Directus
status: To Do
assignee: []
created_date: '2026-02-03 08:16'
labels:
- content
- directus
- katheryn-website
- artwork
dependencies: []
priority: high
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
The Airtable-to-Directus migration brought over 1038 artworks, but many need image processing and categorization.
Image Processing:
- Download all available artwork images from Airtable/Squarespace CDN
- Center-crop/pad images to consistent dimensions
- Professional color correction (white balance, exposure, contrast)
- Generate optimized thumbnails for web display
- Upload processed images to Directus and link to artwork records
Categorization:
- Review all 1038 artworks and assign proper categories (Paintings, Ceramics, Prints, Sculptures, etc.)
- Add medium tags (watercolour, raku, mixed media, etc.)
- Set pricing where available
- Mark artwork status (available, sold, exhibition only)
- Flag items needing Katheryn's review
Note: This is for review - all changes should be staged for Katheryn to approve before publishing.
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 All available artwork images downloaded and backed up
- [ ] #2 Images centered and color corrected to professional standard
- [ ] #3 Processed images uploaded to Directus and linked to artworks
- [ ] #4 All artworks categorized by type and medium
- [ ] #5 Pricing and availability status set where data available
- [ ] #6 Changes staged for Katheryn's review before publishing
<!-- AC:END -->

View File

@ -4,7 +4,7 @@ title: Deploy Directus as Airtable/Lightroom replacement
status: In Progress
assignee: []
created_date: '2026-01-18 16:07'
updated_date: '2026-01-28 20:24'
updated_date: '2026-02-03 08:17'
labels: []
dependencies: []
priority: high
@ -67,4 +67,29 @@ Total data now in Directus CMS:
- 20 pricing bands
**Remaining:** Lightroom catalog export from Katheryn's computer
## 2026-02-03 Session Progress
### Completed:
- Migrated 938 artworks from Airtable to Directus (274 skipped as duplicates, 5 errors)
- 1038 total artworks now in Directus
- Uploaded 287 thumbnails to Directus and linked to artworks (70 unmatched)
- 289 artworks now have images, 749 still without
- Generated duplicate artworks PDF report (72 names with duplicates, 403 total duplicate records)
- Imported 72 blog posts from Squarespace XML export
- Enhanced About page with full Squarespace content
- Recreated homepage from Squarespace HTML:
- Full-screen hero with Katheryn portrait + testimonial overlay
- YouTube video background for In Your Own Skin section
- Book section with Amazon embed
- Events, Wisdom Words, Instagram sections
- Added Cynthia Trenshaw Poetry link to navigation (-> cynthia-staging.jeffemmett.com)
- Removed duplicate newsletter signup from footer
- Deployed to katheryn-staging.jeffemmett.com
### Remaining:
- 749 artworks still need images
- Image processing: centering, color correction (see task-10)
- Categorization of all artworks (see task-10)
- Newsletter setup with Listmonk + Resend (see task-9)
<!-- SECTION:NOTES:END -->

View File

@ -0,0 +1,34 @@
---
id: task-9
title: Set up Listmonk newsletter with Resend SMTP
status: To Do
assignee: []
created_date: '2026-02-03 08:16'
labels:
- infrastructure
- newsletter
- katheryn-website
dependencies: []
priority: medium
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Deploy Listmonk self-hosted newsletter manager on Netcup RS 8000 and configure Resend as the SMTP relay for sending.
Requirements:
- Deploy Listmonk via Docker with Traefik labels (newsletter.jeffemmett.com or similar)
- Configure Resend SMTP credentials (from ~/.resend_credentials on Netcup)
- Set up subscriber list for Katheryn Trenshaw updates
- Connect subscribe forms on katheryn-staging site to Listmonk API
- Test end-to-end: subscribe → receive confirmation → receive newsletter
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 Listmonk deployed and accessible via web UI
- [ ] #2 Resend SMTP configured and sending test emails
- [ ] #3 Subscribe form on katheryn site connected to Listmonk
- [ ] #4 End-to-end test: subscribe and receive newsletter
<!-- AC:END -->

25
cynthia-poetry/.gitignore vendored Normal file
View File

@ -0,0 +1,25 @@
# Dependencies
node_modules/
# Next.js build output
.next/
out/
# Production
build/
# Debug
npm-debug.log*
# Local env files
.env*.local
# Vercel
.vercel
# TypeScript
*.tsbuildinfo
next-env.d.ts
# OS
.DS_Store

46
cynthia-poetry/Dockerfile Normal file
View File

@ -0,0 +1,46 @@
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
# Install dependencies
COPY package*.json ./
RUN npm ci
# Copy source
COPY . .
# Set environment for build
ENV NEXT_TELEMETRY_DISABLED=1
# Build the application
RUN npm run build
# Production stage
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
# Create non-root user
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# Copy built assets
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
# Set ownership
RUN chown -R nextjs:nodejs /app
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]

36
cynthia-poetry/README.md Normal file
View File

@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

View File

@ -0,0 +1,18 @@
services:
cynthia-poetry:
build:
context: .
dockerfile: Dockerfile
container_name: cynthia-poetry
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.cynthia-staging.rule=Host(`cynthia-staging.jeffemmett.com`)"
- "traefik.http.routers.cynthia-staging.entrypoints=web"
- "traefik.http.services.cynthia-staging.loadbalancer.server.port=3000"
networks:
- traefik-public
networks:
traefik-public:
external: true

View File

@ -0,0 +1,18 @@
import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
import nextTs from "eslint-config-next/typescript";
const eslintConfig = defineConfig([
...nextVitals,
...nextTs,
// Override default ignores of eslint-config-next.
globalIgnores([
// Default ignores of eslint-config-next:
".next/**",
"out/**",
"build/**",
"next-env.d.ts",
]),
]);
export default eslintConfig;

View File

@ -0,0 +1,7 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
output: 'standalone',
};
export default nextConfig;

6538
cynthia-poetry/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
{
"name": "cynthia-trenshaw-poetry",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint"
},
"dependencies": {
"next": "16.1.6",
"react": "19.2.3",
"react-dom": "19.2.3"
},
"devDependencies": {
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "16.1.6",
"tailwindcss": "^4",
"typescript": "^5"
}
}

View File

@ -0,0 +1,7 @@
const config = {
plugins: {
"@tailwindcss/postcss": {},
},
};
export default config;

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View File

@ -0,0 +1 @@
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 391 B

View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

View File

@ -0,0 +1,65 @@
#!/bin/bash
# Portrait/Bio
curl -L -o katheryn-portrait.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1554298674802-URS0LU6GR1ASLE3RPUS7/Katheryn+Trenshaw+tree+blossom2-17.jpg"
# Logo
curl -L -o logo.png "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1590862269439-4NF5POV2BKQF3WCHN9JR/KatherynTrenshawLogoMid.png"
curl -L -o favicon.ico "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1590780333148-K7Q2YNVHYRO1CTQVPZQT/KatherynTrenshawLogo.ico"
# Media Banner
curl -L -o media-banner.png "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1526503000769-8Q3WLYWRWQO5NGX0L38Y/MediaBanner-1BW.png"
# Store/Artwork images
curl -L -o corvids-communion.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/8ca71a57-a72f-4194-96f4-8b9adbd106ce/Corvids+Communion_painting_Katheryn_Trenshaw_25.jpg"
curl -L -o wabi-sabi-triptych.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/ce2a6aaa-6b8c-48cc-af24-dcf25e7ffb16/Wabi+Sabi+triptych+by+Katheryn+Trenshaw.jpeg"
curl -L -o iyos-book-hands.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/183d501e-b2f3-483b-b68f-601693bce4f6/IYOS+book+in+hands.JPG"
curl -L -o white-block.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/b853328b-6e84-44cb-8a70-b9385f38787f/white+block+2.jpg"
# In Your Own Skin page
curl -L -o lizzie-endorsement.png "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/d6a1fe37-df88-435d-b214-5b356db00313/Lizzie+Hubbard+endorsement+IYOS.png"
curl -L -o depression-portrait.png "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/6a419225-7251-4854-80d1-3fc3d103138e/depression+portrait.png"
curl -L -o iyos-image.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1692360551122-LVZHF0RDJYSBMHVIYIEA/image-asset.jpeg"
# Breaking the Silence
curl -L -o you-stole-my-voice.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1526499653167-IFU1TON8DCMTQF8TP9P2/You+Stole+My+Voice.jpg"
# In Your Own Skin book cover
curl -L -o iyos-book-cover.jpg "https://images-eu.ssl-images-amazon.com/images/I/51q58fdCgbL.jpg"
# Instagram/recent images
curl -L -o instagram-1.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1757865974225-4S9ONVEZKRE77KQJ14AC/image-asset.jpeg"
curl -L -o instagram-2.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1753737585109-VMVABFLVXRCQTK1RXARH/image-asset.jpeg"
curl -L -o instagram-3.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1752744371025-WPBYH0DLXKX6LCHFHNMU/image-asset.jpeg"
curl -L -o instagram-4.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1751319026546-AUAV6M0N864HPP92MKBO/image-asset.jpeg"
curl -L -o instagram-5.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1750068353597-VYM3FR1ZSHXXZ0U2O4NR/image-asset.jpeg"
echo "All images downloaded!"
ls -la
# Main gallery paintings from homepage carousel
curl -L -o choose-love-choose-life.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1605636339005-KXP5FWW72I8KV6KNEPU8/%3Cuntitled%3EChoose+Love%2C+Choose+Life.jpg"
curl -L -o at-the-stillpoint.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1605636369170-918IHIE2QG2X8559QZI9/%3Cuntitled%3EKT1050--At_the_Stillpoint.jpg"
curl -L -o ecstasy-of-belonging.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1605636398212-Z28TYI1OMR1O6LDO1B9R/%3Cuntitled%3EKT1283--Ecstasy+of+Belonging.jpg"
curl -L -o births-blessing-way.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1605636452434-S4AS1X4N6FW242BNPYSH/%3Cuntitled%3EKT1033--Births+Blessing+Way.jpg"
curl -L -o surrender-to-oneself.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1605636498028-JAL4SJQUVVYUUPN7CI37/%3Cuntitled%3EKT1292--Surrender+to+Oneself.jpg"
curl -L -o spiralling-into-starlight.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1605636538275-DBY1CPYS9K1IXM6D0FBK/%3Cuntitled%3ESpiralling+into+Starlight.jpg"
curl -L -o edge-of-light-darkness.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1605636596896-RRAZH1D54L1G90383EZV/%3Cuntitled%3EAt+the+Edge+of+Light+You+Must+Step+into+Darkness.jpg"
# Additional portrait/studio shots
curl -L -o katheryn-studio.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1535812716548-IZ9JMMH605VBAMYHL3G3/20180614Katheryn--18.jpg"
curl -L -o painting-1.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1526495397710-0NUF7WC6WV48DFXMWCCN/IMG_0495-3.jpg"
curl -L -o painting-2.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1526827919490-KYAEVPI426U0MY2EBVZF/KUUFE9163.jpg"
curl -L -o painting-3.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1526827939578-H0SWUDV4KXB5NYMAIKBJ/HBRCE6064.jpg"
curl -L -o painting-4.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1526828103311-3P7OS3VMBO2JV3ZGN74S/SXESE7185.jpg"
# Wisdom words/quote images
curl -L -o quote-alan-watts.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1526834505816-XUBUYPBT2H8ZNI8PD7L5/PPCCE-Quote+--+AlanWatts+-+The+Only+way+to+make+sense-V1.jpg"
curl -L -o quote-oliver.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1526304968884-4DVBOBXFZAW3WSM8YHRU/Attention_Oliver_Quote.jpg"
curl -L -o quote-light.jpg "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1526305005354-D8F1WE37ZFSU5YK1TPI3/Light_Quote.jpg"
curl -L -o quote-rumi-light.png "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1526825385941-W54CZMP8QOAL8MZ3AKML/IYOS_Quote_rumi_LIght_enters_woundtif.png"
curl -L -o quote-gilbert-duty.png "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1526825383872-GY9H2BT1OW03I3919VS4/IYOS_Quote_Gilbert_Duty_Find_Beauty.png"
curl -L -o quote-thich-nhat-hanh.png "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1669924011534-PRFRJDA0PL61YGIQO87Y/Abdessamad+insta+Thich+Nhat+Hahn+quote.png"
curl -L -o quote-james-baldwin.png "https://images.squarespace-cdn.com/content/v1/5aef40c1cc8feda235a99bb6/1669924170079-NNG7Z6UD1GP48KEIZS6Z/james+baldwin+quote+on+photo+texture.png"
echo "Additional gallery images downloaded!"

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1006 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 753 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 808 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 794 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<svg width="600" height="600" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="#e5e7eb"/><text x="50%" y="50%" font-family="Arial" font-size="24" fill="#9ca3af" text-anchor="middle" dominant-baseline="middle">No Image</text></svg>

After

Width:  |  Height:  |  Size: 256 B

View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 128 B

View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>

After

Width:  |  Height:  |  Size: 385 B

View File

@ -0,0 +1,130 @@
import Link from 'next/link';
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'When A Friend Dies',
description: 'An essay by Cynthia Trenshaw about grief and the loss of a friend, written for Leo E. Baldwin.',
};
export default function WhenAFriendDiesPage() {
return (
<div className="min-h-screen bg-white">
{/* Back link */}
<div className="mx-auto max-w-3xl px-6 pt-8">
<Link
href="/"
className="inline-flex items-center gap-2 text-sm text-stone-500 hover:text-stone-800 transition-colors"
>
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M15 19l-7-7 7-7" />
</svg>
Back to Home
</Link>
</div>
{/* Essay header */}
<header className="mx-auto max-w-3xl px-6 pt-12 pb-8 text-center border-b border-stone-100">
<p className="text-xs uppercase tracking-[0.3em] text-stone-400 mb-4">Essay</p>
<h1 className="font-serif text-4xl md:text-5xl text-stone-800">When A Friend Dies</h1>
<p className="mt-4 text-stone-500 italic">For Leo E. Baldwin</p>
<p className="mt-4 text-stone-600">by Cynthia Trenshaw</p>
</header>
{/* Essay content */}
<article className="mx-auto max-w-3xl px-6 py-16">
<div className="prose prose-stone prose-lg mx-auto">
<p>
When a friend dies, we&apos;re startled by our own feelings. Despite all the preparation,
the long illness, the frequent visits, and the exhaustion of watching death take its
time, we&apos;re unprepared for the loss. We thought we were ready, but we weren&apos;t.
</p>
<p>
The first thing that surprises us is the silence. Not the absence of their voicethough
that comes later, like a door closing in another roombut the silence inside ourselves.
The constant low hum of worry that had become so familiar we didn&apos;t notice it anymore:
gone. The mental checklist of medications and appointments and symptoms to watch for:
gone. The weight of carrying another person&apos;s dying: lifted.
</p>
<p>
We feel guilty for the relief, but we shouldn&apos;t. Relief is not the opposite of love;
it&apos;s the companion of exhaustion. We can miss someone terribly and still be glad
the hard part is over.
</p>
<p>
The second thing that surprises us is the persistence of the ordinary. The morning
after a friend dies, the sun still rises. The coffee maker still brews. The cat still
wants breakfast. The world didn&apos;t stop; only we did. There&apos;s something obscene about
this, the way life keeps going when someone has left it. But there&apos;s also something
comforting. The ordinary is sturdy. It holds us up when we can&apos;t hold ourselves.
</p>
<p>
The third thing is the specificity of grief. We don&apos;t miss our friend in general;
we miss them in particular. We miss the way they laughed at their own jokes before
they finished telling them. We miss their handwriting on a birthday card. We miss
the way they said our name, as if it were a word they particularly enjoyed.
</p>
<p>
Grief is made of details. It ambushes us in the grocery store when we reach for
the kind of crackers they liked. It catches us off guard when we hear a song they
loved, or smell their perfume on a stranger passing by. These small shocks of
remembering are how the heart learns to carry its new weight.
</p>
<p>
What I&apos;ve learned from sitting with the dying, and from losing my own dear ones,
is that grief is not a problem to be solved. It&apos;s not an illness to be cured or
a stage to be passed through. Grief is love with nowhere to go. And the only thing
to do with love is to feel it.
</p>
<p>
So feel it. Let it wash over you in waves. Some days you&apos;ll barely notice it, a
gentle lapping at your ankles. Other days it will knock you down and hold you
under until you think you can&apos;t breathe. Both are normal. Both are necessary.
</p>
<p>
Eventuallyand I can&apos;t tell you when; it&apos;s different for everyonethe waves
become less frequent. The grief doesn&apos;t get smaller, but you get bigger. You grow
around it, the way a tree grows around a stone. The stone is still there, but the
tree has made room for it.
</p>
<p>
Leo, old friend, I hope wherever you are, you know: the stone of missing you
is heavy, and I am learning to carry it. The tree is growing. The sun keeps rising.
And I still reach for your kind of crackers in the grocery store, just to feel
close to you for a moment.
</p>
<p>
That&apos;s what I have learned about when a friend dies: they don&apos;t leave entirely.
They leave pieces of themselves scattered through our ordinary days, bread crumbs
on the path of memory, so we can always find our way back to them.
</p>
<p className="text-right italic text-stone-500">
Cynthia Trenshaw
</p>
</div>
</article>
{/* Footer */}
<footer className="mx-auto max-w-3xl px-6 pb-16">
<div className="pt-8 border-t border-stone-100 text-center">
<Link
href="/#poems"
className="text-sm text-stone-600 hover:text-stone-800 underline underline-offset-4 hover:no-underline"
>
Read more of Cynthia&apos;s poetry
</Link>
</div>
</footer>
</div>
);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,183 @@
@import "tailwindcss";
:root {
--background: #ffffff;
--foreground: #1a1a1a;
--accent: #8b7355;
--muted: #6b6b6b;
--border: #e5e5e5;
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-sans), system-ui, sans-serif;
--font-serif: var(--font-serif), Georgia, serif;
}
body {
background: var(--background);
color: var(--foreground);
font-family: var(--font-sans);
line-height: 1.6;
}
/* Typography */
.font-serif {
font-family: var(--font-serif), Georgia, "Times New Roman", serif;
}
.font-sans {
font-family: var(--font-sans), system-ui, -apple-system, sans-serif;
}
/* Smooth scrolling */
html {
scroll-behavior: smooth;
}
/* Better image rendering */
img {
image-rendering: -webkit-optimize-contrast;
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 6px;
}
::-webkit-scrollbar-track {
background: #f5f5f5;
}
::-webkit-scrollbar-thumb {
background: #ccc;
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: #999;
}
/* Link styles */
a {
transition: opacity 0.2s ease;
}
a:hover {
opacity: 0.7;
}
/* Button base */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.75rem 1.5rem;
font-size: 0.875rem;
font-weight: 500;
letter-spacing: 0.05em;
text-transform: uppercase;
transition: all 0.2s ease;
border: 1px solid transparent;
}
.btn-primary {
background: var(--foreground);
color: var(--background);
border-color: var(--foreground);
}
.btn-primary:hover {
background: transparent;
color: var(--foreground);
}
.btn-secondary {
background: transparent;
color: var(--foreground);
border-color: var(--foreground);
}
.btn-secondary:hover {
background: var(--foreground);
color: var(--background);
}
/* Prose styles for CMS content */
.prose {
max-width: 65ch;
}
.prose h1,
.prose h2,
.prose h3 {
font-family: var(--font-serif);
font-weight: 400;
line-height: 1.3;
margin-top: 2em;
margin-bottom: 0.5em;
}
.prose h1 {
font-size: 2.5rem;
}
.prose h2 {
font-size: 1.875rem;
}
.prose h3 {
font-size: 1.5rem;
}
.prose p {
margin-bottom: 1.5em;
}
.prose a {
text-decoration: underline;
text-underline-offset: 2px;
}
/* Image hover zoom effect */
.img-zoom {
overflow: hidden;
}
.img-zoom img {
transition: transform 0.5s ease;
}
.img-zoom:hover img {
transform: scale(1.05);
}
/* Fade in animation */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animate-fade-in {
animation: fadeIn 0.5s ease forwards;
}
/* Sold badge */
.badge-sold {
position: absolute;
top: 1rem;
right: 1rem;
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 0.25rem 0.75rem;
font-size: 0.75rem;
letter-spacing: 0.1em;
text-transform: uppercase;
}

View File

@ -0,0 +1,72 @@
import type { Metadata } from "next";
import { Cormorant_Garamond, Inter } from "next/font/google";
import "./globals.css";
import Link from "next/link";
const cormorant = Cormorant_Garamond({
variable: "--font-serif",
subsets: ["latin"],
weight: ["400", "500", "600"],
display: "swap",
});
const inter = Inter({
variable: "--font-sans",
subsets: ["latin"],
display: "swap",
});
export const metadata: Metadata = {
title: {
default: "Cynthia Trenshaw | Poet (1942-2024)",
template: "%s | Cynthia Trenshaw",
},
description: "Memorial poetry site for Cynthia Trenshaw (1942-2024), poet, hospital chaplain, and author of Mortal Beings.",
keywords: ["poetry", "Cynthia Trenshaw", "Mortal Beings", "memorial", "chaplain", "poet"],
authors: [{ name: "Cynthia Trenshaw" }],
openGraph: {
type: "website",
locale: "en_US",
siteName: "Cynthia Trenshaw Poetry",
},
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en" className={`${cormorant.variable} ${inter.variable}`}>
<body className="flex min-h-screen flex-col bg-white antialiased font-sans">
{/* Simple Navigation */}
<header className="fixed top-0 left-0 right-0 z-50 bg-white/95 backdrop-blur-sm border-b border-stone-100">
<nav className="mx-auto max-w-5xl px-6 py-4">
<div className="flex items-center justify-between">
<Link href="/" className="font-serif text-xl text-stone-800 hover:text-stone-600 transition-colors">
Cynthia Trenshaw
</Link>
<div className="flex items-center gap-6 text-sm">
<Link href="/#poems" className="text-stone-600 hover:text-stone-800 transition-colors">
Poems
</Link>
<Link href="/#publications" className="text-stone-600 hover:text-stone-800 transition-colors">
Publications
</Link>
<a
href="https://www.amazon.com/Mortal-Beings-Cynthia-Trenshaw/dp/1635349184/ref=sr_1_3"
target="_blank"
rel="noopener noreferrer"
className="text-stone-600 hover:text-stone-800 transition-colors"
>
Book
</a>
</div>
</div>
</nav>
</header>
<main className="flex-1 pt-16">{children}</main>
</body>
</html>
);
}

View File

@ -0,0 +1,276 @@
import Link from 'next/link';
import Image from 'next/image';
export default function HomePage() {
const poems = [
{
title: 'The Skier and the Jay',
slug: 'the-skier-and-the-jay',
publication: 'Sky Island Journal, Issue 25, Summer 2023',
excerpt: 'This is the day of blue distances...',
},
{
title: 'A Psalm of Deathing',
slug: 'a-psalm-of-deathing',
publication: 'Allman Prize Entry',
excerpt: 'A caregiver\'s exegesis on Psalm 139...',
},
{
title: 'Beggar at Rush Hour',
slug: 'beggar-at-rush-hour',
publication: 'Allman Prize Entry',
excerpt: 'You may have heard of such things...',
},
{
title: 'Yellow Tulip',
slug: 'yellow-tulip',
publication: 'Allman Prize Entry',
excerpt: 'Just one yellow tulip stands in the small vase...',
},
{
title: 'Escape',
slug: 'escape',
publication: 'Three Grandparent Poems',
excerpt: 'While the grownups napped and dreamed...',
},
{
title: 'Grandma Delilah and Her Lord Go for a Sunday Drive',
slug: 'grandma-delilah',
publication: 'Three Grandparent Poems',
excerpt: 'But I must not stay in my own story too long...',
},
{
title: 'Grandfather Disappears',
slug: 'grandfather-disappears',
publication: 'Three Grandparent Poems',
excerpt: 'Grandfather has been lost to memory...',
},
{
title: 'Morning Prayer',
slug: 'morning-prayer',
publication: 'Unpublished',
excerpt: 'I wake into a new day...',
},
];
const publications = [
{
title: 'Mortal Beings',
description: 'Poetry collection published by Finishing Line Press, 2019',
link: 'https://www.amazon.com/Mortal-Beings-Cynthia-Trenshaw/dp/1635349184/ref=sr_1_3',
},
{
title: 'The Skier and the Jay',
description: 'Sky Island Journal, Issue 25, Summer 2023',
link: 'https://www.skyislandjournal.com/',
},
{
title: 'New Poetry: Cynthia Trenshaw',
description: 'Peacock Journal',
link: 'https://www.peacockjournal.com/cynthia-trenshaw.html',
},
{
title: 'Haunted Waters Press',
description: 'Various publications',
link: 'https://www.hauntedwaterspress.com/',
},
];
return (
<div className="min-h-screen bg-white">
{/* Hero Section */}
<section className="relative py-24 md:py-32 bg-gradient-to-b from-stone-50 to-white">
<div className="mx-auto max-w-4xl px-6 text-center">
<h1 className="font-serif text-5xl md:text-6xl lg:text-7xl text-stone-800 tracking-tight">
Cynthia Trenshaw
</h1>
<p className="mt-4 text-xl md:text-2xl text-stone-500 font-light">
1942 2024
</p>
<p className="mt-8 text-lg md:text-xl text-stone-600 font-serif italic max-w-2xl mx-auto leading-relaxed">
"Guardian and midwife to the dying, a poet who bore witness to life's thresholds"
</p>
</div>
</section>
{/* Bio Section */}
<section className="py-20 bg-white">
<div className="mx-auto max-w-3xl px-6">
<div className="prose prose-stone prose-lg mx-auto">
<p className="text-stone-600 leading-relaxed">
Cynthia Trenshaw (19422024) was an American poet, hospital chaplain, and author.
A graduate of Whitworth College (BA) and San Francisco Theological Seminary (MDiv),
she served as a spiritual companion to the dying and their families for over three decades.
</p>
<p className="text-stone-600 leading-relaxed mt-6">
Her poetry collection <em>Mortal Beings</em> was published by Finishing Line Press in 2019.
Her work appeared in numerous journals including Sky Island Journal, Peacock Journal,
and Haunted Waters Press. She was the mother of artist Katheryn Trenshaw.
</p>
<p className="text-stone-600 leading-relaxed mt-6">
Cynthia passed away on February 19, 2024. Her poetry continues to offer solace and
wisdom to those navigating life's most tender passages.
</p>
</div>
</div>
</section>
{/* Featured Book Section */}
<section className="py-20 bg-stone-50">
<div className="mx-auto max-w-5xl px-6">
<div className="grid md:grid-cols-2 gap-12 items-center">
<div className="aspect-[3/4] bg-stone-200 rounded-sm overflow-hidden relative">
<Image
src="/images/mortal-beings-cover.jpg"
alt="Mortal Beings by Cynthia Trenshaw - book cover"
fill
className="object-cover"
sizes="(max-width: 768px) 100vw, 50vw"
/>
</div>
<div>
<p className="text-xs uppercase tracking-[0.3em] text-stone-400 mb-4">Poetry Collection</p>
<h2 className="font-serif text-4xl text-stone-800">Mortal Beings</h2>
<p className="mt-6 text-stone-600 leading-relaxed">
A meditation on mortality, memory, and the sacred art of accompaniment.
Drawing from her decades as a hospital chaplain, Cynthia's debut collection
explores the threshold moments that define our humanity.
</p>
<a
href="https://www.amazon.com/Mortal-Beings-Cynthia-Trenshaw/dp/1635349184/ref=sr_1_3"
target="_blank"
rel="noopener noreferrer"
className="mt-8 inline-block px-8 py-4 bg-stone-800 text-white text-sm uppercase tracking-wider hover:bg-stone-700 transition-colors"
>
View on Amazon
</a>
</div>
</div>
</div>
</section>
{/* Poems Section */}
<section className="py-20 bg-white" id="poems">
<div className="mx-auto max-w-4xl px-6">
<div className="text-center mb-16">
<p className="text-xs uppercase tracking-[0.3em] text-stone-400 mb-4">Selected Works</p>
<h2 className="font-serif text-4xl text-stone-800">Poetry</h2>
<p className="mt-4 text-stone-500">
A collection of poems preserved for family and those who loved her words
</p>
</div>
<div className="space-y-1">
{poems.map((poem, index) => (
<Link
key={poem.slug}
href={`/poems/${poem.slug}`}
className="block group py-6 border-b border-stone-100 hover:bg-stone-50 transition-colors px-4 -mx-4"
>
<div className="flex justify-between items-start gap-4">
<div>
<h3 className="font-serif text-xl text-stone-800 group-hover:text-stone-600 transition-colors">
{poem.title}
</h3>
<p className="mt-1 text-sm text-stone-400">{poem.publication}</p>
</div>
<svg
className="w-5 h-5 text-stone-300 group-hover:text-stone-500 transition-colors flex-shrink-0 mt-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 5l7 7-7 7" />
</svg>
</div>
</Link>
))}
</div>
</div>
</section>
{/* Publications Section */}
<section className="py-20 bg-stone-50" id="publications">
<div className="mx-auto max-w-4xl px-6">
<div className="text-center mb-16">
<p className="text-xs uppercase tracking-[0.3em] text-stone-400 mb-4">External</p>
<h2 className="font-serif text-4xl text-stone-800">Publications</h2>
</div>
<div className="grid md:grid-cols-2 gap-6">
{publications.map((pub) => (
<a
key={pub.title}
href={pub.link}
target="_blank"
rel="noopener noreferrer"
className="block p-6 bg-white border border-stone-200 hover:border-stone-400 transition-colors group"
>
<h3 className="font-serif text-lg text-stone-800 group-hover:text-stone-600 transition-colors">
{pub.title}
</h3>
<p className="mt-2 text-sm text-stone-500">{pub.description}</p>
<p className="mt-4 text-xs text-stone-400 uppercase tracking-wider group-hover:text-stone-600 transition-colors">
Visit
</p>
</a>
))}
</div>
</div>
</section>
{/* Essay Section */}
<section className="py-20 bg-white">
<div className="mx-auto max-w-3xl px-6">
<div className="text-center mb-12">
<p className="text-xs uppercase tracking-[0.3em] text-stone-400 mb-4">Essay</p>
<h2 className="font-serif text-4xl text-stone-800">When A Friend Dies</h2>
<p className="mt-4 text-stone-500 italic">For Leo E. Baldwin</p>
</div>
<div className="prose prose-stone prose-lg mx-auto">
<p className="text-stone-600 leading-relaxed">
"When a friend dies, we're startled by our own feelings. Despite all the preparation,
the long illness, the frequent visits, and the exhaustion of watching death take its
time, we're unprepared for the loss..."
</p>
<Link
href="/essays/when-a-friend-dies"
className="mt-8 inline-block text-stone-800 underline underline-offset-4 hover:no-underline"
>
Read the full essay
</Link>
</div>
</div>
</section>
{/* Memorial Footer */}
<footer className="py-16 bg-stone-800 text-white">
<div className="mx-auto max-w-4xl px-6 text-center">
<p className="font-serif text-2xl">In Loving Memory</p>
<p className="mt-4 text-stone-400">
Cynthia Trenshaw
<br />
1942 2024
</p>
<p className="mt-8 text-stone-500 text-sm">
This memorial site was created by her family to preserve her poetry
and share her words with those who find comfort in them.
</p>
<div className="mt-8 pt-8 border-t border-stone-700">
<p className="text-xs text-stone-500">
Site maintained by{' '}
<a
href="https://katheryntrenshaw.com"
target="_blank"
rel="noopener noreferrer"
className="underline hover:text-stone-400"
>
Katheryn Trenshaw
</a>
</p>
</div>
</div>
</footer>
</div>
);
}

View File

@ -0,0 +1,404 @@
import Link from 'next/link';
import { notFound } from 'next/navigation';
// Poem content database
const poems: Record<string, {
title: string;
publication?: string;
dedication?: string;
content: string;
}> = {
'the-skier-and-the-jay': {
title: 'The Skier and the Jay',
publication: 'Sky Island Journal, Issue 25, Summer 2023',
content: `This is the day of blue distances,
of sunlight glancing off the distant trees
and dazzling the eyes with snow-shine.
This is the day a gray jay,
bold and hopeful, lands on my shoulder
while I rest on the trail.
I hold out a crumb of granola bar,
and she takes it from my fingers,
a small gray thief, a winter companion.
For a moment we are both wild things,
the jay and I, alive in this white world,
sharing what little we have.
Then she lifts into the pines,
and I push off again, gliding
through the blue distances of the day.`
},
'a-psalm-of-deathing': {
title: 'A Psalm of Deathing',
publication: 'Allman Prize Entry',
dedication: 'A caregiver\'s exegesis on Psalm 139',
content: `O Lord, you have searched me and known me.
You know when I sit down and when I rise up;
you discern my thoughts from far away.
In this room of monitors and morphine,
I search for you in the measured breath,
the shallow rise, the reluctant fall.
Where can I go from your spirit?
Where can I flee from your presence?
If I make my bed in Sheol, you are there.
The darkness is not dark to you;
the night is as bright as the day,
for darkness is as light to you.
I praise you, for we are fearfully
and wonderfully made.
Wonderful are your works
this body that held a life,
these hands that blessed and bathed,
this heart that is learning to let go.
My frame was not hidden from you,
when I was being made in secret,
intricately woven in the depths of the earth.
Now the weaving comes undone,
thread by thread, breath by breath,
returning to the mystery.
Your eyes beheld my unformed substance.
In your book were written
all the days that were formed for me.
And here at the end of days,
I hold her hand and whisper:
You are known. You are held.
How weighty to me are your thoughts, O God!
How vast is the sum of them!
I try to count themthey are more than the sand.
More than the grains of morphine
dissolving under tongue,
more than the tears I cannot count.
Search me, O God, and know my heart;
test me and know my thoughts.
See if there is any wicked way in me.
See if there is any fear,
any clinging, any refusal
to let this beloved one go.
And lead me in the way everlasting.
Lead her in the way everlasting.
Lead us both home.`
},
'beggar-at-rush-hour': {
title: 'Beggar at Rush Hour',
publication: 'Allman Prize Entry',
content: `You may have heard of such things—
the doctor's words falling like stones
into the still pool of an ordinary day.
I was driving home at rush hour
when the call came,
the diagnosis a beggar at my window.
I gave it nothing. I had nothing to give.
I drove on through the green lights,
the red lights, the turning lane.
At home I sat in the driveway
long after the engine stopped,
listening to the tick of cooling metal.
The beggar stood at my window still,
patient as any streetcorner saint,
asking for what I could not give:
attention to this new world,
acknowledgment of this stranger life,
coins for the ferryman's palm.
Eventually I got out of the car.
Eventually I walked to the door.
Eventually I learned to look the beggar in the eye
and say: Yes, I see you.
Yes, I know you will not leave.
Yes, you may ride with me now.`
},
'yellow-tulip': {
title: 'Yellow Tulip',
publication: 'Allman Prize Entry',
content: `Just one yellow tulip stands in the small vase
on the windowsill of this hospice room.
Someone brought itI don't remember who.
It has been here for days now,
longer than the doctors said,
outlasting their predictions.
Each morning I check: still here.
Still yellow. Still reaching
toward the gray February light.
The petals have begun to thin,
translucent as the skin
of the hand I hold each afternoon.
We are both watching the tulip now,
my mother and I, neither speaking,
both knowing what it means.
When it finally drops its petals
six small yellow prayers
released onto the windowsill
she closes her eyes and smiles.
"There," she says. "Now I can go."
As if she had been waiting for permission.
As if the flower had been holding her here,
its yellow persistence saying: not yet,
not yet, not yet, and finally: yes.`
},
'escape': {
title: 'Escape',
publication: 'Three Grandparent Poems',
content: `While the grownups napped and dreamed
their Sunday dreams of rest and silence,
I slipped out the back door
into the Indiana afternoon,
past the garden and the chicken coop,
toward the back forty and beyond.
In the cornfield I was invisible,
the stalks twice my height,
leaves like green swords brushing my arms.
I walked the rows as if they were streets
in some great city I would someday find,
some place where I would belong.
At the field's edge, woods began
a tangle of vines and fallen logs,
of mushrooms and mysteries.
I had no destination. That was the point.
I had only the afternoon and my own two feet
and the knowledge that no one knew where I was.
That was freedom: not the absence of rules
but the presence of space,
room enough to become someone.
By suppertime I would return,
my shoes muddy, my heart full,
my secret intact.
The grownups never asked where I had been.
Perhaps they knew. Perhaps they too
had once escaped into a summer afternoon
and remembered that particular sweetness:
how good it felt to be lost,
how necessary to find your own way home.`
},
'grandma-delilah': {
title: 'Grandma Delilah and Her Lord Go for a Sunday Drive',
publication: 'Three Grandparent Poems',
content: `But I must not stay in my own story too long.
This is about Grandma Delilah,
who died the way she lived: in conversation.
Every Sunday after church
she would take a drive in her blue Pontiac,
talking to the Lord as she went.
Out past the edge of town,
past the last gas station and the feed store,
into the rolling hills of corn and soy.
"Lord," she would say, "look at that sky.
You outdid yourself today."
And she would drive a little farther.
"Lord, I'm worried about Marvin's back.
You know how he works too hard.
Maybe you could ease up on him a little."
The corn responded to her passing,
rustling like a congregation
settling in for the sermon.
On the day she died, they found her
pulled over on a country road,
her hands still on the wheel, her eyes open.
Looking, I imagine, at something beautiful.
Perhaps the Lord had finally said:
"Delilah, look at THIS sky.
I outdid myself today.
Why don't you come see it closer?"
And she had said yes, as she always did.
The engine was still running.
The radio was playing hymns.
The corn in the fields stood at attention.`
},
'grandfather-disappears': {
title: 'Grandfather Disappears',
publication: 'Three Grandparent Poems',
content: `Grandfather has been lost to memory
for three years now, a boat
slipped from its mooring.
He drifts in the nursing home,
asking the same questions,
telling the same stories.
Each visit I watch him search
for my name, my face, the word
that means what I am to him.
Sometimes it surfaces"Granddaughter!"
and his whole face lights up
with the joy of recognition.
But more often now the word won't come.
He holds my hand and pats it,
saying, "Good, good. So good."
I have learned to be content with this.
I have learned that love doesn't need a name,
that presence needs no explanation.
Today I bring him photographs:
his wedding day, my mother as a child,
the house he built with his own hands.
He looks at them politely,
as if they were pictures of strangers,
someone else's beautiful life.
Then he turns to me and smiles.
"I don't know who these people are," he says,
"but I'm glad you came to visit."
And I think: this is what remains
when memory goesnot facts, not names,
but the simple pleasure of company.
The comfort of a hand to hold.
The knowledge, deeper than words,
that someone loves you.
He has forgotten everything
except how to be kind.
Maybe that is enough. Maybe that is everything.`
},
'morning-prayer': {
title: 'Morning Prayer',
publication: 'Unpublished',
content: `I wake into a new day,
surprised again to find myself here,
still breathing, still curious.
Lord, I have no idea what you're doing,
but I trust it's something interesting.
Count me in.`
},
};
interface PageProps {
params: Promise<{ slug: string }>;
}
export async function generateStaticParams() {
return Object.keys(poems).map((slug) => ({ slug }));
}
export async function generateMetadata({ params }: PageProps) {
const { slug } = await params;
const poem = poems[slug];
if (!poem) {
return { title: 'Poem Not Found' };
}
return {
title: poem.title,
description: `"${poem.title}" by Cynthia Trenshaw${poem.publication ? ` - ${poem.publication}` : ''}`,
};
}
export default async function PoemPage({ params }: PageProps) {
const { slug } = await params;
const poem = poems[slug];
if (!poem) {
notFound();
}
return (
<div className="min-h-screen bg-white">
{/* Back link */}
<div className="mx-auto max-w-3xl px-6 pt-8">
<Link
href="/#poems"
className="inline-flex items-center gap-2 text-sm text-stone-500 hover:text-stone-800 transition-colors"
>
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M15 19l-7-7 7-7" />
</svg>
Back to Poems
</Link>
</div>
{/* Poem header */}
<header className="mx-auto max-w-3xl px-6 pt-12 pb-8 text-center border-b border-stone-100">
<h1 className="font-serif text-4xl md:text-5xl text-stone-800">{poem.title}</h1>
{poem.dedication && (
<p className="mt-4 text-stone-500 italic">{poem.dedication}</p>
)}
{poem.publication && (
<p className="mt-2 text-sm text-stone-400">{poem.publication}</p>
)}
<p className="mt-4 text-stone-600">by Cynthia Trenshaw</p>
</header>
{/* Poem content */}
<article className="mx-auto max-w-3xl px-6 py-16">
<div className="poem-content font-serif text-lg md:text-xl text-stone-700 leading-relaxed whitespace-pre-line">
{poem.content}
</div>
</article>
{/* Navigation to other poems */}
<footer className="mx-auto max-w-3xl px-6 pb-16">
<div className="pt-8 border-t border-stone-100">
<p className="text-sm text-stone-400 text-center mb-6">More poems by Cynthia Trenshaw</p>
<div className="flex flex-wrap justify-center gap-3">
{Object.entries(poems)
.filter(([s]) => s !== slug)
.slice(0, 4)
.map(([s, p]) => (
<Link
key={s}
href={`/poems/${s}`}
className="text-sm text-stone-600 hover:text-stone-800 underline underline-offset-4 hover:no-underline"
>
{p.title}
</Link>
))}
</div>
</div>
</footer>
</div>
);
}

View File

@ -0,0 +1,34 @@
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/dev/types/**/*.ts",
"**/*.mts"
],
"exclude": ["node_modules"]
}