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>
|
|
@ -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 -->
|
||||
|
|
@ -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 -->
|
||||
|
|
|
|||
|
|
@ -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 -->
|
||||
|
|
@ -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
|
||||
|
|
@ -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"]
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import type { NextConfig } from "next";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
output: 'standalone',
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
const config = {
|
||||
plugins: {
|
||||
"@tailwindcss/postcss": {},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
After Width: | Height: | Size: 65 KiB |
|
|
@ -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 |
|
|
@ -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 |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 114 KiB |
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 395 KiB |
|
|
@ -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!"
|
||||
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 369 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 314 KiB |
|
After Width: | Height: | Size: 229 KiB |
|
After Width: | Height: | Size: 327 KiB |
|
After Width: | Height: | Size: 310 KiB |
|
After Width: | Height: | Size: 395 KiB |
|
After Width: | Height: | Size: 314 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 1006 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 403 KiB |
|
After Width: | Height: | Size: 403 KiB |
|
After Width: | Height: | Size: 370 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 310 KiB |
|
After Width: | Height: | Size: 447 KiB |
|
After Width: | Height: | Size: 352 KiB |
|
After Width: | Height: | Size: 344 KiB |
|
After Width: | Height: | Size: 179 KiB |
|
After Width: | Height: | Size: 327 KiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 194 KiB |
|
After Width: | Height: | Size: 314 KiB |
|
After Width: | Height: | Size: 515 KiB |
|
After Width: | Height: | Size: 645 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 175 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 310 KiB |
|
After Width: | Height: | Size: 447 KiB |
|
After Width: | Height: | Size: 352 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 486 KiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 344 KiB |
|
After Width: | Height: | Size: 395 KiB |
|
After Width: | Height: | Size: 349 KiB |
|
After Width: | Height: | Size: 522 KiB |
|
After Width: | Height: | Size: 467 KiB |
|
After Width: | Height: | Size: 753 KiB |
|
After Width: | Height: | Size: 808 KiB |
|
After Width: | Height: | Size: 169 KiB |
|
After Width: | Height: | Size: 171 KiB |
|
After Width: | Height: | Size: 176 KiB |
|
After Width: | Height: | Size: 794 KiB |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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'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. We thought we were ready, but we weren't.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The first thing that surprises us is the silence. Not the absence of their voice—though
|
||||
that comes later, like a door closing in another room—but the silence inside ourselves.
|
||||
The constant low hum of worry that had become so familiar we didn't notice it anymore:
|
||||
gone. The mental checklist of medications and appointments and symptoms to watch for:
|
||||
gone. The weight of carrying another person's dying: lifted.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
We feel guilty for the relief, but we shouldn't. Relief is not the opposite of love;
|
||||
it'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't stop; only we did. There's something obscene about
|
||||
this, the way life keeps going when someone has left it. But there's also something
|
||||
comforting. The ordinary is sturdy. It holds us up when we can't hold ourselves.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The third thing is the specificity of grief. We don'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'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'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'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't breathe. Both are normal. Both are necessary.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Eventually—and I can't tell you when; it's different for everyone—the waves
|
||||
become less frequent. The grief doesn'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's what I have learned about when a friend dies: they don'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's poetry
|
||||
</Link>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
After Width: | Height: | Size: 25 KiB |
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
@ -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 (1942–2024) 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>
|
||||
);
|
||||
}
|
||||
|
|
@ -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 them—they 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 it—I 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 goes—not 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>
|
||||
);
|
||||
}
|
||||
|
|
@ -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"]
|
||||
}
|
||||