fix(about): wrap bio richText in collapsible so Lexical editor renders in admin
Some checks failed
ci/woodpecker/push/web Pipeline failed

The bare richText field was silently not rendering in the Payload admin UI.
Wrapping in a collapsible preserves the data path while giving the editor
a proper container. Also renames image assets and adds media management scripts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-15 21:11:10 -05:00
parent b47c5e420a
commit 936a98f955
13 changed files with 261 additions and 1 deletions

74
scripts/rename-media.ts Normal file
View File

@@ -0,0 +1,74 @@
/**
* Rename media — re-uploads each file under its new filename.
* Payload replaces the old file + regenerates thumbnails while keeping the same ID.
*/
import { getPayload } from 'payload'
import config from '@payload-config'
import path from 'node:path'
import fs from 'node:fs'
const imagesDir = path.resolve(process.cwd(), 'images')
const renames: Array<{ alt: string; newFile: string }> = [
{ alt: 'Jason Woltje portrait', newFile: 'jason-portrait.jpg' },
{ alt: 'Stylized portrait — thought leader', newFile: 'thought-leader-city.jpg' },
{ alt: 'Stylized portrait — social', newFile: 'social-neon.jpg' },
{ alt: 'Jason Woltje — tech founder portrait, dark background', newFile: 'tech-founder-dark.jpg' },
{ alt: 'Jason Woltje — social media profile, neon gradient', newFile: 'social-neon.jpg' },
{ alt: 'Jason Woltje — at the desk, documentary style', newFile: 'at-the-desk.jpg' },
{ alt: 'Jason Woltje — illustrated portrait', newFile: 'illustrated-portrait.jpg' },
{ alt: 'Jason Woltje — thought leader portrait, city backdrop', newFile: 'thought-leader-city.jpg' },
{ alt: 'Jason Woltje — fashion editorial portrait', newFile: 'editorial-blazer.jpg' },
]
async function main() {
const payload = await getPayload({ config })
const seen = new Set<number>()
for (const r of renames) {
const { docs } = await payload.find({
collection: 'media',
where: { alt: { equals: r.alt } },
limit: 1,
depth: 0,
})
if (docs.length === 0) {
console.log(` skip — no media with alt "${r.alt}"`)
continue
}
const doc = docs[0]!
if (seen.has(doc.id as number)) continue
seen.add(doc.id as number)
const currentFilename = (doc as any).filename as string
if (currentFilename === r.newFile) {
console.log(` ↷ id=${doc.id} already named ${r.newFile}`)
continue
}
const filePath = path.join(imagesDir, r.newFile)
if (!fs.existsSync(filePath)) {
console.log(` ⚠ file missing: ${r.newFile}`)
continue
}
await payload.update({
collection: 'media',
id: doc.id,
filePath,
data: {},
})
console.log(` ✓ id=${doc.id}: ${currentFilename}${r.newFile}`)
}
console.log('\nDone.')
process.exit(0)
}
main().catch((err) => {
console.error('Fatal:', err)
process.exit(1)
})