Root layout overwrites every page title with the brand name — no route's <svelte:head><title> survives

Open Beginner friendly
#49 2 comments 0 reactions 0 assignees View on GitHub

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

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

bug

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from markramm/pyrite

All issues in markramm/pyrite

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.