Follow-up from #371, which named this but deliberately left it standing.
The remaining magic string
#371 framed the problem as a pair:
This retires a cross-repo magic string: today the ui recognises the name sublime, paired with getDefaultStylesheetName's ?? 'sublime' fallback here. Same shape that drifted on the seeded-avatar sentinel.
#371 retired the delivery half — Sublime's row now carries cssUrl = null, so the injector can branch on data instead of on a name (that's stellar-ui #196). The api-side half is untouched:
// src/modules/stylesheet.ts
export const getDefaultStylesheetName = async (tx?: Tx): Promise<string> => {
const row = await db.stylesheet.findFirst({ where: { isDefault: true }, select: { name: true } });
return row?.name ?? 'sublime';
};
Why it was left
It returns a name, written to UserSettings.siteAppearance at user creation (modules/user.ts, modules/auth.ts, routes/api/install.ts). That is a different axis from cssUrl delivery, and retiring it is not a rename — it forces a decision about what siteAppearance is when no row is marked default:
- Return
null → siteAppearance becomes nullable, rippling through three creation paths, the settings read/write surface, and the ui's theme resolution.
- Throw → user creation now fails on a registry with no default. Arguably correct, but it turns a soft fallback into a hard dependency on seed order.
- Keep a fallback but source it from the schema default →
user_settings.siteAppearance already has DEFAULT 'sublime' at the DB level (20260524181515_add_stylesheets), so the literal exists there too. Retiring one copy while the other stands may not be worth the churn.
Note the string is load-bearing in more than these two places, which is part of why it wasn't a quick fix — the DB column default, this fallback, and the fixture/registry naming all say sublime independently.
Worth checking first
Whether this is a real drift risk or a benign default. The seeded-avatar precedent (api SEEDED_AVATAR ↔ ui SEEDED_AVATAR_SENTINEL) drifted because two repos independently encoded the same sentinel. Here, after #371 + ui#196, the ui no longer reads the name at all — so the cross-repo half is already gone and what remains is api-internal. That may downgrade this to cleanup rather than risk.
Related
Update 2026-07-20 — re-scoped from risk to cleanup
The "worth checking first" question above has been checked, and it resolves to cleanup, not drift risk.
stellar-ui #196 (PR #200) merged and deleted the name comparison outright — the ui no longer reads the stylesheet name on any path. That removes the second independent encoding, which is the only thing that made the seeded-avatar precedent apply. What remains is a single api-internal default with no cross-repo counterpart to drift against.
Verified still accurate as of 4b29528:
src/modules/stylesheet.ts:13 — the fallback itself, unchanged.
- Three creation paths confirmed:
modules/user.ts:136, modules/auth.ts:181, routes/api/install.ts:199.
user_settings.siteAppearance still carries DEFAULT 'sublime' at the DB level (20260524181515_add_stylesheets).
That last point is the reason to be sceptical this is worth doing at all: retiring the code copy leaves the DB copy standing, so the churn buys a partial cleanup rather than the elimination of the literal. Decide whether it's worth doing before designing it — and if it is, the DB default should go in the same pass or the issue isn't actually closed.
Priority accordingly: low. Not a correctness or drift hazard.
Follow-up from #371, which named this but deliberately left it standing.
The remaining magic string
#371 framed the problem as a pair:
#371 retired the delivery half — Sublime's row now carries
cssUrl = null, so the injector can branch on data instead of on a name (that's stellar-ui #196). The api-side half is untouched:Why it was left
It returns a name, written to
UserSettings.siteAppearanceat user creation (modules/user.ts,modules/auth.ts,routes/api/install.ts). That is a different axis fromcssUrldelivery, and retiring it is not a rename — it forces a decision about whatsiteAppearanceis when no row is marked default:null→siteAppearancebecomes nullable, rippling through three creation paths, the settings read/write surface, and the ui's theme resolution.user_settings.siteAppearancealready hasDEFAULT 'sublime'at the DB level (20260524181515_add_stylesheets), so the literal exists there too. Retiring one copy while the other stands may not be worth the churn.Note the string is load-bearing in more than these two places, which is part of why it wasn't a quick fix — the DB column default, this fallback, and the fixture/registry naming all say
sublimeindependently.Worth checking first
Whether this is a real drift risk or a benign default. The seeded-avatar precedent (api
SEEDED_AVATAR↔ uiSEEDED_AVATAR_SENTINEL) drifted because two repos independently encoded the same sentinel. Here, after #371 + ui#196, the ui no longer reads the name at all — so the cross-repo half is already gone and what remains is api-internal. That may downgrade this to cleanup rather than risk.Related
Update 2026-07-20 — re-scoped from risk to cleanup
The "worth checking first" question above has been checked, and it resolves to cleanup, not drift risk.
stellar-ui #196 (PR #200) merged and deleted the name comparison outright — the ui no longer reads the stylesheet name on any path. That removes the second independent encoding, which is the only thing that made the seeded-avatar precedent apply. What remains is a single api-internal default with no cross-repo counterpart to drift against.
Verified still accurate as of
4b29528:src/modules/stylesheet.ts:13— the fallback itself, unchanged.modules/user.ts:136,modules/auth.ts:181,routes/api/install.ts:199.user_settings.siteAppearancestill carriesDEFAULT 'sublime'at the DB level (20260524181515_add_stylesheets).That last point is the reason to be sceptical this is worth doing at all: retiring the code copy leaves the DB copy standing, so the churn buys a partial cleanup rather than the elimination of the literal. Decide whether it's worth doing before designing it — and if it is, the DB default should go in the same pass or the issue isn't actually closed.
Priority accordingly: low. Not a correctness or drift hazard.