Skip to content

feat(settings): add a URL Base field to General settings - #907

Open
m4bard wants to merge 1 commit into
Listenarrs:canaryfrom
m4bard:feat/urlbase-settings-field
Open

feat(settings): add a URL Base field to General settings#907
m4bard wants to merge 1 commit into
Listenarrs:canaryfrom
m4bard:feat/urlbase-settings-field

Conversation

@m4bard

@m4bard m4bard commented Aug 28, 2026

Copy link
Copy Markdown

Companion to #880, and independent of it. #880 makes the backend serve under a sub-path; this adds the field that lets someone set it.

Why

UrlBase can only be set today by editing config.json in the config volume or by posting to /api/v1/configuration/startupconfig. Unless an operator already knows the file exists, the reverse-proxy support is invisible. Sonarr, Radarr and Readarr all put it in Settings, General, under Host, next to Bind Address and Port.

What this adds

A Host section on the General tab with a single URL Base input, carrying Sonarr's wording: "For reverse proxy support, default is empty", plus the restart warning, since UrlBase is read at startup.

The field warns when the value is an absolute URL rather than a path. NormalizeUrlBase treats a full URL as unusable and serves at the site root, so accepting one silently would save a value that does nothing. This mirrors the *arr ValidUrlBase rule, which rejects anything starting with a scheme.

It needs nothing from #880

All the plumbing already exists on canary. StartupConfig.urlBase is in the frontend type, GeneralSettingsTab already receives startupConfig and declares the update event, and SettingsView already spreads the whole startup config into saveStartupConfig. Only the field was missing. So this can land whether or not #880 does, and it is useful either way: it makes the existing value settable.

Not the same thing as #690

Different feature with an unfortunately similar name. #690 asks for a URL Base field on the qBittorrent download client configuration, for reaching a qBittorrent that is itself behind a proxy at a path prefix. That is a real open request and this does not address it. This one is Listenarr's own URL base.

On the styling

Scoped styles do not cascade between sibling settings sections, so every section restates the heading and card rules rather than inheriting them. The heading, the .form-body card and the input all carry explicit rules here, matching FileManagementSection, which renders directly below this on the same tab. A first pass at this omitted them and rendered as an unstyled block with a browser-default input, which is worth mentioning only because it is not obvious from the diff why the rules are repeated.

Tests

One test covers the wiring rather than the component, because a section that renders correctly and swallows its own emit would look right and save nothing. The component tests pass either way by design; the wiring test is the one that fails when the emit is dropped.

A further test asserts the input carries the class its styling hangs off. That one is a weak guard and I would rather say so: it catches an unclassed input, not rules that are present and wrong. Whether it actually looks right still needs eyes on it.

Frontend suite: 606 passed.

UrlBase can only be set today by editing config.json in the config
volume or by posting to /api/v1/configuration/startupconfig, so unless
an operator already knows the file exists the reverse-proxy support is
invisible. Sonarr, Radarr and Readarr all put it in Settings, General,
under Host, next to Bind Address and Port.

Adds a Host section to the General tab with a single URL Base input,
carrying Sonarr's wording: "For reverse proxy support, default is
empty", plus the restart warning, since UrlBase is read at startup.

All the plumbing already existed. StartupConfig.urlBase is in the
frontend type, GeneralSettingsTab already receives startupConfig and
declares the update event, and SettingsView already spreads the whole
startup config into saveStartupConfig. Only the field was missing.

The field warns when the value is an absolute URL rather than a path.
NormalizeUrlBase treats a full URL as unusable and serves at the site
root, so accepting one silently would save a value that does nothing.
This mirrors the *arr ValidUrlBase rule, which rejects anything starting
with a scheme.

On the styling: scoped styles do not cascade between sibling sections,
so every settings section restates the h3 and card rules rather than
inheriting them. The heading, the .form-body card and the input itself
therefore carry explicit rules here, matching FileManagementSection,
which renders directly below this one on the same tab. Without them the
section renders as an unstyled block with a browser-default input, which
is what a first pass at this shipped.

One test covers the wiring rather than the component, because a section
that renders correctly and swallows its own emit would look right and
save nothing. The component tests pass either way, by design; the wiring
test is the one that fails when the emit is dropped. A further test
asserts the input carries the class its styling hangs off, which is a
weak guard: it catches an unclassed input, not rules that are present
and wrong. Whether it actually looks right still needs eyes on it.
@m4bard
m4bard requested a review from a team August 28, 2026 21:23
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