Root layout overwrites every page title with the brand name — no route's <svelte:head><title> survives
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 86/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- javascript, playwright
- Domain
- frontend, testing-qa
Research direction
Start with web/src/routes/+layout.svelte and web/src/routes/+layout.ts, then compare the layout behavior with the route-level svelte:head<title> declarations such as web/src/routes/search/+page.svelte. Run the title assertions in settings.spec.ts, search.spec.ts, qa.spec.ts, and daily.spec.ts; done means route-specific titles survive branding loads while the default remains available.
Written by the indexing model from the issue text.
Description
Found while building the deterministic Playwright world (Package A of the playwright-e2e-suite-non-deterministic-failures-* ticket).
What happens
web/src/routes/+layout.svelte sets document.title from the branding store:
// Push branding into the DOM as it loads:
// --brand-primary — accent color referenced by chrome components
// document.title — replace app.html's static "Pyrite"
$effect(() => {
if (typeof document === 'undefined') return;
document.documentElement.style.setProperty('--brand-primary', brandStore.primary_color);
if (brandStore.loaded) {
document.title = brandStore.name;
}
});
Every route also declares its own title, e.g. web/src/routes/search/+page.svelte:
<svelte:head><title>Search — Pyrite</title></svelte:head>
The layout effect runs once brandStore.loaded flips and clobbers whatever the page set. SSR is off (+layout.ts: export const ssr = false), so the page title is only ever applied client-side — after which the layout overwrites it.
Evidence
Probe navigating to every top-level route with a 1.5 s settle, reading page.title():
ROUTE / -> "Pyrite"
ROUTE /entries -> "Pyrite" (page declares "Entries — Pyrite")
ROUTE /search -> "Pyrite" (page declares "Search — Pyrite")
ROUTE /settings -> "Pyrite" (page declares "Settings — Pyrite")
ROUTE /qa -> "Pyrite" (page declares "QA Dashboard — Pyrite")
ROUTE /daily -> "Pyrite" (page declares "Daily Notes — Pyrite")
ROUTE /timeline -> "Pyrite"
ROUTE /graph -> "Pyrite"
ROUTE /collections -> "Pyrite"
ROUTE /login -> "Pyrite"
No route wins. This is a user-visible bug, not only a test one: every browser tab, every bookmark and every window-switcher entry reads "Pyrite" regardless of where you are in the app.
It is also a source of moving e2e failures, because it is a race: settings.spec.ts:4 and search.spec.ts:4 failed their toHaveTitle in all five of five consecutive runs, while qa.spec.ts:4 and daily.spec.ts:4 — the same assertion, same cause — failed in four of five. Whether the page title or the branding effect lands last depends on when /config/branding returns.
Suggested fix
The layout should supply a default, not an override — e.g. put the brand name in <svelte:head><title> in the layout (SvelteKit lets a page's head override a layout's) instead of assigning document.title in an effect. If a branded suffix is wanted on every page, compose it where the page title is set rather than replacing it wholesale.
Why not fixed here
Out of scope for Package A (the e2e environment); the pages and their specs belong to packages B/G of that ticket, and this is a product bug in the layout rather than a test-harness one. Filed per ADR-0033.
- Dominant language
- Python
- Stars
- 6
- Forks
- 10
- PR merge metrics
- No merged PRs in 30d
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from markramm/pyrite
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
bug web
Difficulty 2/5 Half a day Newbie friendliness 85/100
-
bug
Difficulty 2/5 Half a day Newbie friendliness 78/100
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
-
bug web
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100