Skip to content

jh admin homepage: fetch/save the whole homepage layout as JSON #60

Description

@tanmaykm

Context

JuliaComputing/JuliaHub#24048 folded the custom landing page into the homepage layout editor: the landing page is no longer its own server-side object, it's the greeter widget's metadata.content inside the layout served by GET/POST /api/v1/ui/layout/homepage. #59 moves jh admin landing-page onto that endpoint to unbreak TestAdminLandingPageShow (#58), but keeps the old command surface — the CLI still presents the landing page as a first-class thing and does greeter-specific surgery on the layout to maintain that illusion.

Reviewing #59, @Hetarth02 pointed out that the CLI should follow the platform: stop special-casing the greeter and let admins fetch and save the layout itself as JSON.

Proposal

Add a jh admin homepage command pair that treats the layout as an opaque JSON document, mirroring what jh registry config already does for registries:

jh admin homepage show                      # GET the layout, pretty-print the JSON array
jh admin homepage update --file layout.json # POST the whole array back
cat layout.json | jh admin homepage update  # ... or via stdin

# get / edit / push back
jh admin homepage show > layout.json
jh admin homepage update --file layout.json

readRegistryPayload in registries.go is the precedent for the --file-or-stdin read; registryConfigAddCmd / registryConfigUpdateCmd in main.go are the precedent for the command shape.

Most of the plumbing already exists in landing.go from #59:

  • fetchHomepageLayout and saveHomepageLayout are exactly the two operations.
  • layoutWidget's Extra map[string]json.RawMessage passthrough already round-trips unknown fields byte-identically, so the CLI doesn't need to model widget types it doesn't understand.
  • layoutRequest already carries auth and the status+URL error messages.

What a raw-JSON path would let us drop, if we go the replace route: setGreeterContent, removeGreeter, the add-a-greeter-when-missing transform (geometry + order renumbering) and the "no saved layout" refusal in setLandingPage. It also dissolves the two semantics questions #59 flags — what remove should do when there's no separate "default landing text" any more, and whether update should synthesize a greeter card — because neither arises if the CLI doesn't model the greeter at all.

Open questions

@Hetarth02 — two calls to make here, in order.

First: is a CLI path wanted at all? If raw-JSON layout editing isn't an intended admin workflow — if the layout editor UI is meant to be the only supported way to author one — then this issue is a no-op and the CLI's footprint here should stay as small as it is. Everything below assumes the answer is yes.

Then: replace, or add alongside?

Replace. Drop jh admin landing-page entirely; jh admin homepage show/update is the only surface. Smallest CLI, matches the platform's model exactly, no greeter logic to maintain.

The cost: the case that actually broke is reading and setting the welcome text. jh admin landing-page update '# Welcome' becomes "fetch the array, find the greeter, hand-edit metadata.content, post it back" — awkward from a script, and TestAdminLandingPageShow in the platform's jh-cli-e2e-tests would need rewriting into something that parses the layout and digs out the greeter. It also removes the only path that handles a layout with no greeter yet.

Add alongside. Ship jh admin homepage show/update for the general case and keep landing-page as a thin convenience wrapper over the same two helpers. Two commands to document, but the common operation stays one line and the e2e test keeps working unchanged.

My inclination is add alongside, on the grounds that editing the welcome text is the overwhelmingly common admin task and the wrapper is ~40 lines over helpers we need anyway. But if we'd rather not carry both surfaces, replace is defensible and I'll do that instead.

Notes

  • Validation on update should stay minimal — reject non-array / unparseable JSON, otherwise forward as-is and let the server rule. The layout schema is a frontend concern and will grow widget types the CLI shouldn't have to track.
  • metadata.renderedContent is recomputed server-side from content and client values are ignored (per the JuliaHub code; not yet exercised with an authenticated write — worth confirming when implementing). It matters here because the raw-JSON path forwards renderedContent verbatim, where setGreeterContent strips it: if the server ever did honour a client value, editing content alone would leave a stale rendered card.
  • No DELETE endpoint exists; "remove a widget" is just POSTing a layout without it.

Out of scope

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions