Fix datetime round-trip in page properties (#133), shared news cards, shown fields per page type #151
Labels
No labels
bug
enhancement
needs-triage
ready-for-agent
ready-for-human
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/deckle#151
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Four follow-ups from the news-workflow analysis, in one pull request:
(List pagination was part of this issue until the List module was dropped; paging now lives in #153's module screen.)
Current behavior
Dates (#133)
The settings read (
fieldValueininternal/pageops/settings.go) stringifies every string-shaped value withcast.ToStringE,datetimefields included.Reproduced in triage on
main(after #155), with adatetimefielddate(asnews-itemdeclares it). The read hands over these values, and saving them untouched fails on the server with "must be a valid RFC3339 datetime" (element.ValidateValues). The form's own check ("Must be a valid date and time") mirrors that rule, so the browser blocks the save first:date = 2026-07-10T09:00:00Ztime.Time2026-07-10 09:00:00 +0000 UTCdate = 2026-07-10T11:00:00+02:00time.Time2026-07-10 11:00:00 +0200 +0200date = 2026-07-10T09:00:00LocalDateTime2026-07-10T09:00:00date = 2026-07-10LocalDate2026-07-10date: 2026-07-10, JSON"date": "2026-07-10"2026-07-10date: 2026-07-10 09:00:002026-07-10 09:00:00Exact RFC3339 strings work: quoted TOML, YAML (Hugo's YAML decoder hands timestamps over as strings, never
time.Time) and JSON. Editor-created pages are unaffected, because the editor writes quoted RFC3339 strings.#153 added
content.DateRFC3339(internal/content/meta.go), "the one wire format every datetime the editor serves uses". The page tree and the module entries endpoint go through it. Triage checked it on every spelling above: each comes out as RFC3339 (offset-less values read in UTC), and an unreadable value reports not-ok.News cards
news-listshortcode (scaffold/features/news/layouts/shortcodes/news-list.html) has its own copy of the teaser card markup, without image or categories.layouts/news/list.html) and the category term page (layouts/term.html) render through the sharedpartials/news-teasers.html, which exists so that their cards cannot drift. The partial draws its own<section class="ce-teasers ce-news-list">wrapper and renders nothing for an empty list.partials/ce/attrs.html:id="c-<uid>"always,data-ce-*underhugo server).ce/attrs.htmlreads the shortcode context (.Get "uid",.Name,.Page, the ordinal path). The root renders even when the section has no items or doesn't resolve; a theme test pins that.Fields in page properties
titlefield, else an implicit one), every field the type declares, and, on a site that declares backend layouts, two implicit pickers (settingsFieldsandlayoutPickersininternal/pageops/settings.go): "Backend layout" (front-matterbackendLayout) and "Backend layout for sub-pages" (backendLayoutNextLevel). A page type has no say in which of them show.children: [], e.g.news-item). The scaffold shipsone-colandtwo-col, so every new site with news shows it there.Type label
PageSettings(web/src/components/PageSettings.tsx), both in the page module and on the News module's Properties tab.Desired behavior
Dates
datetimefield's value reaches the properties form as RFC3339 whatever front-matter spelling Hugo reads: every row of the table above.T00:00:00Z.Cards
news-listrenders its cards throughnews-teasers.html, so "Latest news" and the archive show identical cards for the same item, image and categories included.news-listgains aboolparamallNewsLink(labelShow "All news" link, defaultfalse). When it is on and the section resolves, the element ends with an "All news →" link to the section's URL. It is off by default, so existing elements render as before, apart from the cards.Fields shown per page type
shownFields, lists which fields the type's properties form shows. A name is either a field the type declares infields:, or one of the two implicit layout pickers, named by the front-matter keys they write:backendLayoutandbackendLayoutNextLevel.backendLayoutNextLevelon a type withchildren: []. With[], only the title shows. With a list, the title and exactly the listed fields show; a listedbackendLayoutNextLevelshows even on a childless type.titlefield or the implicit one.fields:order, own layout, sub-pages layout.create:), and editor modules may still list, sort and filter by a field the form doesn't show.type: linkfield's<name>Targetcompanion included. The value keeps working: templates, modules and layout resolution read front matter, not the form.Type label
Docs
scaffold/site/AGENTS.mdand the README (CLAUDE.md rule):shownFieldsin the page-type schema: the names it takes, the default, the title and required-field rules, and the untouched stored values;datetimeparagraph and "Editing content by hand").Decisions
ValidateValuesrejects anything else, and the client mirrors Go'stime.RFC3339.content.DateRFC3339, as the page tree and the module entries endpoint already do, so every datetime the editor serves comes from one function. #158 extends the same standard to every other datetime read.content.Setalways rewrites a set key) and have no time value type. Keeping the original spelling would need one, with no visible gain.fieldValue's contract: settings reads never fail on odd data).ce/attrs.htmlneeds the shortcode context. The theme'steasers.htmlpartial andpage-teaserselement are the precedent: the partial draws the list, each caller owns its wrapper.versiongoes up by one (to 3), because its vendored files change;versionis what tells bundle revisions apart. No migration or upgrade path: there are no existing sites (maintainer, 2026-10-06).children: []rule becomes the default.shownFieldslists what shows (maintainer, in triage). It works like deckle's other lists (children,elements,allowedAt): no key means everything,[]means nothing, a list means exactly those. TYPO3's per-doktypeshowitemis the same idea. The accepted cost: once a type uses the key, a field added tofields:later stays hidden until it is listed. A hide-list (hiddenFields: [backendLayoutNextLevel]) was rejected: shorter for one hidden field, but a second kind of list.create:on a required field is already a load error: a required field is always asked for.create:), and module columns, sorts and filters name the fields they use.news-listelement.Key interfaces
fieldValue/ReadSettings(internal/pageops/settings.go) andcontent.DateRFC3339(internal/content/meta.go). Its other callers arepagetreeandentryValue(internal/server/modules.go).element.ValidateValuesand the client'sisRFC3339(web/src/components/fields.tsx) stay as they are.settingsFields,layoutPickersandreconcileLayoutOptions(internal/pageops/settings.go) build the form's fields.SaveSettingssets or deletes only those, so a field left out keeps its stored value.pagetype.Schema, its strict loader (rawSchema) and the package doc (internal/pagetype) get the key and its load errors.PageSettings(web/src/components/PageSettings.tsx), used byPagePaneandEntryEditor. Labels already reach the client through/api/pagetypes;pageTypeLabel(web/src/pagemanage.ts) is the existing lookup.scaffold/features/news/):layouts/shortcodes/news-list.html,layouts/partials/news-teasers.htmland its callerslayouts/news/list.htmlandlayouts/term.html,editor/elements/news-list.yaml,feature.yaml. The theme'spartials/ce/attrs.html,partials/teasers.htmlandshortcodes/page-teasers.htmlare the precedent. Theme tests:internal/theme/news_test.go.Acceptance criteria
datetimefielddatespelled as each row of the table (TOML offset and local datetimes, TOML local date, YAML and JSON date-only strings, YAML2026-07-10 09:00:00) reads as RFC3339 and saves without touching the date; the saved value is the same instant. The regression test fails before the fix and passes after it.news-listroot keepsid="c-<uid>"and, underhugo server, itsdata-ce-*markers, and still renders with no items or a stale section.allNewsLinkis on, and points to the section's URL.shownFields, anews-itemshows "Backend layout" but not "Backend layout for sub-pages", and anewspage shows both.shownFieldsshows the title and exactly the listed fields, in the usual order;[]shows only the title.shownFieldsare each a load error naming the file.create: truefield thatshownFieldsleaves out.versionis 3.shownFields, and AGENTS.md says how a properties save stores front-matter dates.How to verify
make test. It buildsweb/distfirst, whichweb/embed.goneeds; a barego test ./...fails in a fresh worktree. At triage,go test ./internal/...was green andcd web && npm testpassed 65 files, 1818 tests.hugoon PATH. CI installs extended 0.163.3; run the card tests with it installed.shownFields, settings tests for shown and hidden fields, and theme tests for the shared cards and the link.harness serve, on a site withharness add news:date = 2026-07-10T09:00:00Z(unquoted TOML), open its properties and save without touching the date. The save succeeds, and the file holds the same instant;shownFieldsto a page type and check its properties and its create dialog;/news/in the preview, and turn the "All news" link on and off.Assumptions to check
timeZone(the scaffold'shugo.tomlsets none), which matches howcontent.DateRFC3339reads it.Out of scope
timeZonefor offset-less dates.showitemalso does that);shownFieldsonly filters.allowedAtstays the filter.categoryparam and the duplicated category option lists (#152 replaces them)./api/treepayload: route repair and the link pickers read them.Blocked by
None - can start immediately
Fix datetime round-trip in page properties (#133), shared news cards, layout pickers per page type, List paginationto Fix datetime round-trip in page properties (#133), shared news cards, layout pickers per page typeFix datetime round-trip in page properties (#133), shared news cards, layout pickers per page typeto Fix datetime round-trip in page properties (#133), shared news cards, shown fields per page type