Skip to content

fix: take frontend config primarily from the backend#2290

Draft
sbliven wants to merge 1 commit intoSciCatProject:masterfrom
sbliven:backend-config
Draft

fix: take frontend config primarily from the backend#2290
sbliven wants to merge 1 commit intoSciCatProject:masterfrom
sbliven:backend-config

Conversation

@sbliven
Copy link
Copy Markdown
Member

@sbliven sbliven commented Mar 26, 2026

It is now recommended to serve frontend configuration settings from the backend. This has long been discussed (#1728) but the introduction of runtime configuration (SciCatProject/backend#2355) makes it more urgent. This PR introduces changes to the frontend configuration reflecting the expectation that in most scenarios only the URL to the backend must be configured in the frontend container.

Description

The recommended order of configs to load is now (later entries override earlier):

  1. app-config.defaults.ts (built into the container)
  2. /assets/config.json (fetched during loading; provides the backend url)
  3. [backendURL]/api/v3/admin/config (includes runtime configs and frontend.config.json from the backend container)

This is accomplished by adding a new additionalConfigs array to the configuration. Any URLs listed in this array will be fetched at runtime and merged over the existing settings. It can also be used to replicate the old config.override.json behavior if desired (which has been removed); just add /assets/config.override.json to the additionalConfigs list in config.json.

Motivation

Background on use case, changes needed

Fixes:

Please provide a list of the fixes implemented in this PR

Changes:

Please provide a list of the changes implemented by this PR

Changes requiring deployment changes:

  • [BREAKING CHANGE] config.override.json is not loaded by default.
    • Motivation: This was previously used to avoid modifying config.json, a common source of git conflicts. This is not a problem with the new minimal config.json, so we can avoid the extra http request.
    • Quick fix: Add /assets/config.override.json to the additionalConfigs list in config.json.
    • Better fix: Migrate any modified entries to the backend's frontend.config.json file
  • config.json defaults to looking for the backend config on the current domain. If this is not the case, include the domain name in the additionalConfigs URL. For instance, for scicatlive:
    {
      "additionalConfigs": ["http://backend.localhost/api/v3/admin/config"]
    }

Other changes:

  • Some default values didn't match the type annotations, and have been updated where necessary
  • the allowConfigOverrides setting has been removed

This PR is a draft pending tests and doc updates.

Tests included

  • Included for each change/fix?
  • Passing? (Merge will not be approved unless this is checked)

Documentation

  • swagger documentation updated [required]
  • official documentation updated [nice-to-have]

official documentation info

If you have updated the official documentation, please provide PR # and URL of the pages where the updates are included

Backend version

  • Does it require a specific version of the backend
  • which version of the backend is required:

Summary by Sourcery

Load frontend configuration from built-in defaults and additional runtime config URLs instead of relying on backend admin config and config.override.json.

New Features:

  • Introduce a default frontend configuration object embedded in the application image.
  • Add support for chaining and merging additional configuration files via an additionalConfigs list, with protection against circular references.

Bug Fixes:

  • Align configuration default values and types with their declared annotations.

Enhancements:

  • Simplify and harden app configuration loading logic, removing allowConfigOverrides and the special config.override.json mechanism.
  • Extend the app configuration schema with siteIcon and labelMaps options and tighten field customization typing.
  • Provide richer, opinionated defaults for UI layout, dataset/proposal lists, actions, and labels through the new default config file.

Deployment:

  • Change deployment expectations so that frontend config is primarily provided by backend-hosted configuration endpoints rather than per-environment override files.

…[BREAKING]

Replace config.override.json with a new `additionalConfigs` array. This is
indended to be the only item in the frontend config.json, and will point to the
backend config URL (although nothing prevents serving multiple static config
files from the frontend with the same mechanism). This enables use of the
runtime configuration without using the same domain name for frontend and
backend.

Config sources with the default setup (later entries override earlier):
1. app-config.defaults.ts (entries copied from old src/assets/config.json)
2. src/assets/config.json
3. [backendURL]/api/v3/admin/config. The backend merges files and
    runtime-config entries from the db.

Breaking changes:
- config.override.json is not loaded by default. Entries should be moved to the backend.
- config.json should be modified to include the backend URL (unless it shares a domain)

Other changes:
- Some default values didn't match the type annotations, and have been updated where necessary
- the `allowConfigOverrides` setting has been removed
Copy link
Copy Markdown
Member

@minottic minottic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this! It adds way more control on what to load, and would both allow changing the BE config URL and remove the 404 when the BE is not at api/v3/admin/config simply be overriding config.json with an empty additionalConfigs.

If I have to find a drawback (personal opinion, but happy anyway with this change!), it's maybe a bit over engineered, I believe we would have achieved the same by moving the BE config load from being the 1st loaded to the last, having prepended the lbBaseUrl living with the 404 or having refactored enableAdditionalConfig to additionalConfigs (as the change here), but without the recursion (essentially loading config.json, config.override.json and /v3/config only). The administrator would then be able not to touch the config.json (which had config.override.json in the additionalConfigs) and then have a config.override.json with the BE config in the additionalConfigs

if (this.mergedConfigUrls.has(url)) {
continue;
}
const additionalConfig = await this.loadConfigFromUrl(url);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the URL here I believe it needs to be relative to the FE base url, so it might need a change when passing an absolute BE config URL?

"samples": true
}
}
"additionalConfigs": ["/api/v3/admin/config"]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to keep backward compat with older version, can you plz add "/assets/config.override.json" as the 1st value of the list, so:

  "additionalConfigs": ["/assets/config.override.json", "/api/v3/admin/config"]

})
export class AppConfigService {
private appConfig: object = {};
private mergedConfigUrls = new Set<string>(); // Processed config URLs to prevent circular references
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since the size of mergedConfigUrls controls the number of HTTP calls to load configs, would it make sense to add a maximum size after which additional configs are skipped?

Comment on lines +201 to +206
private mergeObjects(config: AppConfigInterface, overrides: Partial<AppConfigInterface>): AppConfigInterface {
return mergeWith(
config,
overrides,
(objVal, srcVal) =>
Array.isArray(objVal) && Array.isArray(srcVal) ? srcVal : undefined,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a big fan of config merge concepts, considering the complex structure of frontend config and I think its very likely prone to the unexpected outcomes.

@Junjiequan
Copy link
Copy Markdown
Member

Junjiequan commented Mar 27, 2026

I’m not sure we really need to provide a fallback frontendConfig.json. The frontend is not going to function without a running backend anyway. If the frontend fails to fetch the config from the backend, we should investigate and fix the root cause.
I'm fine with having the frontendConfig either in the backend or the frontend, but I think we should have a single source of truth in one place, and avoid ovewritting it from multiple sources

@minottic
Copy link
Copy Markdown
Member

I'm fine with having the frontendConfig either in the backend or the frontend, but I think we should have a single source of truth in one place, and avoid ovewritting it from multiple sources

but how do you pass the BE url the config should be loaded from if it's on a different base URL than the FE?

@Junjiequan
Copy link
Copy Markdown
Member

Junjiequan commented Mar 27, 2026

but how do you pass the BE url the config should be loaded from if it's on a different base URL than the FE?

One solution could be that in the UI we provide an option to load config from external URL and saving it will overwritte the config saved in DB entirely.

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.

3 participants