advertise publish time, not create time, for published drafts
Created by: jedmund
Summary
A draft post held for two months and then published was advertising the February create time, not the May publish time, on the public site and in RSS. Two underlying bugs:
-
Posts — the draft → published handler had an
!existing.publishedAtguard that silently kept any stale value. There was also a footgun inPATCHwhere a request-bodypublishedAtcould override the status-driven assignment. -
Albums — no
publishedAttransition logic in the PUT handler at all. The universe feed and/rss+/rss/photoshard-codedcreatedAtas the public timestamp.
This PR brings everything in line with the existing Garden pattern: every draft → published transition stamps publishedAt = now; revert to draft clears it. Display side now reads publishedAt (with a createdAt fallback for legacy rows).
Changes
-
posts/[id]PUT + PATCH: drop the!existing.publishedAtguard, add clear-on-revert in PUT, remove thepublishedAtoverride in PATCH. -
albums/[id]PUT: add the missing publishedAt transition logic. -
/api/universe: select albumpublishedAt, usealbum.publishedAt ?? album.createdAt, order by[publishedAt, createdAt]. -
/rss+/rss/photos: same album fallback + order. - New migration
20260501000000_backfill_album_published_at: adds theAlbum.publishedAtcolumn (it was inschema.prismabut never had anADD COLUMNmigration) and backfillspublishedAt = createdAtfor existing published albums so they keep their currently-displayed date.
One thing to handle manually
The specific Feb-drafted post that triggered this still has the wrong publishedAt in the DB. Once this ships, easiest fix is to revert it to draft in admin and republish — the new logic will stamp a fresh time. Or run a one-off UPDATE "Post" SET "publishedAt" = ... WHERE id = ....
Test plan
-
npm run check— no new errors in touched files -
Draft a post, leave it for a moment, publish via StatusDropdown — publishedAtis now, distinct fromcreatedAt. Public page +/rssshow the publish time. -
Revert the post to draft — publishedAtclears in admin metadata. Republish — fresh timestamp (not the previous publish, not create). -
Edit a published post without changing status — updatedAtbumps,publishedAtunchanged. -
Same flow for an Album — universe card + /rss+/rss/photosreflect publish time. -
Run npx prisma migrate deployagainst a fresh DB to confirm the migration applies cleanly (column add + backfill).