Skip to content

fix(app): five UX papercuts in app list / app view discovery - #179

Merged
ZacxDev merged 1 commit into
mainfrom
zach/app-discovery-ux-fixes
Jul 26, 2026
Merged

fix(app): five UX papercuts in app list / app view discovery#179
ZacxDev merged 1 commit into
mainfrom
zach/app-discovery-ux-fixes

Conversation

@ZacxDev

@ZacxDev ZacxDev commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Why

A blind dogfood of the new App-discovery commands (civitai app list / app view, added in #178) surfaced five UX papercuts. This PR fixes all five, with tests.

The five papercuts & fixes

1. (biggest) Top-level help hid app-browsing. The app group's Short was authoring-only ("Author and ship Civitai Apps"), so a user who wanted to browse the store never learned app list / app view existed from civitai --help.

  • ShortBrowse, author, and ship Civitai Apps; the group Long now opens with the browse commands.
  • Added a "Browse the App store" block to the root Examples (root.go) so civitai --help surfaces civitai app list / civitai app view <slug>.

2. Broken help example. app list's Example used --category productivitynot a valid category, returns HTTP 400.

  • Replaced with --category generation (a real category).
  • The --category flag help now lists the valid set (generation, games, utility, discovery, moderation, analytics, other), mirroring the backend MARKETPLACE_CATEGORIES enum.

3. app view printed rating: twice. Both the star rating and the content rating were labeled rating: (rating: - (0 review(s)) then rating: content g).

  • The content-rating line is now labeled content:content: g.

4. Enum flags 400'd with an unhelpful generic message. A bad --kind/--sort/--category round-tripped to a bare invalid request parameter (400).

  • Server-error surfacing (primary): the store endpoint returns zod's flattened shape {"error":{"formErrors":[...],"fieldErrors":{"<field>":["<msg>"]}}}, which the SDK's badRequestDetail didn't parse. Added flattenedZodDetail so a 400 now surfaces the field-specific message (naming the bad field + constraint) — e.g. invalid request parameter (400): category — Invalid enum value. Expected 'generation' | 'games', received 'productivity'. This stays in sync with the backend enum (no client-side drift). fieldErrors is decoded in document order so the reported field is deterministic.
  • Client-side (secondary): the fixed enums --kind (all/onsite/offsite) and --sort (top-rated/popular/newest/name) are validated locally for a fast, offline allowed-values error — no HTTP call. --category is deliberately not hardcoded client-side (its allowlist grows as the backend adds categories); it relies on the improved 400 handling above. --limit's existing local validation is unchanged.

5. Empty list gave a bare header. For a non-mod user (the common case — the catalog is identity/flag-gated) app list printed only the table header, unexplained.

  • Now prints a hint matching the --help gating wording: No apps visible for your account — until the store opens publicly you only see apps if your account is a moderator or app-dev-tester, or nothing matches your filters. + a login/relax-filters follow-up.

Tests

Verification

go build ./... && go vet ./... && go test ./... all green (16 packages ok); gofmt -l pkg/civitai internal/cmd clean. Built the binary and eyeballed app --help, app list --help, and app view (shows content: g, not a second rating:).

🤖 Generated with Claude Code

A blind dogfood of the new App-discovery commands surfaced five papercuts:

1. Top-level help hid app-browsing. The `app` group's Short was authoring-only,
   so `civitai --help` never advertised `app list` / `app view`. Short is now
   "Browse, author, and ship Civitai Apps"; the group Long + the root Examples
   surface `civitai app list` / `civitai app view <slug>`.
2. Broken help example. `app list`'s Example used `--category productivity`, an
   invalid enum that 400s. Replaced with `--category generation`, and the
   --category flag help now lists the valid marketplace categories.
3. `app view` printed `rating:` twice. The content-rating line reused the
   `rating:` label; it is now `content:`.
4. Enum flags gave an unhelpful generic 400. The SDK's badRequestDetail now
   parses zod's FLATTENED error shape ({formErrors, fieldErrors}) — what the
   store endpoint returns — and surfaces the field-specific message (naming the
   bad field + constraint), instead of the bare "invalid request parameter
   (400)". Additionally, the FIXED enums --kind/--sort are validated
   client-side (fast, offline, allowed-values message); --category is left to
   the improved 400 handling so its allowlist can't drift from the backend.
5. Empty list gave a bare header. `app list` with zero items now prints a hint
   explaining the mod/tester gating (matching the --help wording) + the filters.

Tests: server-400 field-error surfacing (cmd + SDK unit), local enum
validation (no HTTP), content: label / no double rating:, empty-list hint, and
regression guards on the Short/root Examples + the invalid-category example.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ZacxDev
ZacxDev merged commit 06361f3 into main Jul 26, 2026
10 checks passed
@ZacxDev
ZacxDev deleted the zach/app-discovery-ux-fixes branch July 26, 2026 18:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant