Skip to content

A format added to formats.py is not offered until the frontend lists it #2002

Closed

Description

@MODSetter

The gap

docs/architecture/studio.md lists this under Known gaps:

The format picker's list of keys is hard-coded in studio-formats.ts. The API's catalog fills in each listed format's details and availability, so a format added to formats.py is not offered until the frontend lists it too.

Why it matters

GET /workspaces/{id}/studio/formats is the server's answer to what Studio can make, and the panel throws away anything in that answer it does not already know about. Adding a format is meant to be a folder with a render, a case in job_router.py and a row in formats.py; in practice it is silently not offered until someone also edits a file in the frontend. That is a trap for exactly the contributor most likely to hit it, and nothing fails to warn them — the tile is simply absent.

Where

The fallbacks you need are already written, which is what makes this small:

  • formatLabel(entry) returns the translated label for a known key and falls back to entry.label, the API's English one.
  • formatHint(entry) reads FORMAT_HINTS for the tooltip and already falls back for an unknown key, and shows the API's unavailable_reason when a format is not available.
  • FORMAT_ICONS[entry.key] ?? FileIcon in FormatCard already covers an unknown key, as does viewers/registry.tsx, which falls back to the plain DocumentViewer so a new format renders as raw content instead of breaking the panel.

So the change is in catalogFormats(): once the API has answered, its list decides which formats exist, and studioCatalog() stays what it says it is — the placeholder before the answer arrives.

What done looks like

  • A format present in the API's catalog and absent from studio-formats.ts appears in the picker, with the API's label, the fallback icon, and its real available and unavailable_reason.
  • The tiles painted before the API answers are unchanged, and the panel does not flicker or reorder as the real catalog lands.
  • A format the frontend knows and the API does not send is no longer offered. That is the intended direction — the server decides — but say in the PR that you checked it, because it is the half of this change that removes a tile rather than adding one.
  • Delete the Known gaps line from docs/architecture/studio.md in the same PR, and check the Layout of worker/studio/ section, which tells a contributor that adding a format means "plus the frontend entries below" — that sentence gets narrower once this is fixed.

How to verify

surfsense_local/frontend/src/features/studio/studio-panel.test.tsx drives the panel. Write the failing test first: render with an API catalog containing a key studio-formats.ts has never heard of, and assert the tile is there with the server's label.

cd surfsense_local/frontend
pnpm test
cd ../.. && python scripts/check_docs.py

Before you start

Read CONTRIBUTING.md and the Studio doc. React and UI work in surfsense_local/frontend follows the frontend-workflow skill described in AGENTS.md. You should not need to add any interface strings — the point of the change is that an unknown format uses the server's label — so if you find yourself adding one, that is a sign to stop and ask here. This is a frontend-only change and touches no contract. Open your PR against dev, not main. Comment here to claim this.

Activity

  1. fukalous commented on Sep 29, 2026

    @fukalous
    Contributor

    I am taking this. I will keep studioCatalog() as the pre-load fallback, switch to the API catalog as the authoritative list once it arrives, and add a panel-level regression test for an unknown server format plus the documented removal of frontend-only formats. I will also update the Studio architecture doc. This work is AI-assisted; no independent human review is claimed.

  2. MODSetter commented on Sep 29, 2026

    @MODSetter
    OwnerAuthor

    Fixed by #2038, fix(studio): trust the server format catalog, by @fukalous. Merged into dev.

    Closing by hand rather than by keyword: Fixes #2002 only auto-closes on a merge to the default branch, and this repo merges through dev (CONTRIBUTING), so this would have stayed open and claimable while the work was already done. It reaches main with the next release.

    Nothing left to pick up here.

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions