fix(startup): kill the white flash on launch - #110
Merged
Conversation
Two flashes on every launch: 1. Blank white frame before styles load. The WebView paints its default white until styles.css applies the dark theme. Paint dark from frame zero: set the Tauri window backgroundColor (#1c1c20) and inline the dark bg + color-scheme in index.html, so the first paint is already dark. 2. Empty-state flash before tabs restore. hydrateTabsFromStorage() ran in an App useEffect (fires after paint), so the first render showed the empty state for a frame before the persisted tabs appeared. Hydrate in main.tsx BEFORE createRoot().render() so the initial paint already has the restored tabs. The background reconnect stays async; the rest of App's wiring stays in its effect.
Merged
oesukam
added a commit
that referenced
this pull request
Aug 6, 2026
Version bump for the **v0.4.0** release: `0.3.0 → 0.4.0` in `tauri.conf.json`, `Cargo.toml`, and `Cargo.lock`. ## What's in v0.4.0 (since v0.3.0) **Features** - MongoDB support: JS scripting, table-data browse/edit/insert/delete, connection URL, TLS handling (#101, #103, #105) - Engine registry — per-engine metadata drives the connection form, queries, display (#103) - Rail sessions behave like tabs: click selects, right-click to close, dim inactive, reconnect on click (#104) - Row count + query timer moved to a footer below the grid, for both table-data and SQL tabs (#108, #109) **Fixes** - Grid fills the pane for few-column tables; no open blink (#106) - Edit-connection opens the real connection; Mongo honors its pinned database (#107) - Startup white-flash eliminated (dark window bg + pre-render tab hydration) (#110) - Mongo defaults to TLS-off so a local Mongo connects (#105) - Actionable commitlint PR-title error (#102); release gated on lint/typecheck/tests (#100) ## Gate lint (0 errors), typecheck (CI-style clean), 321 unit tests, frontend build — all green locally. After merge, the Release workflow is triggered with `publish=false` to produce a **draft** release for review.
oesukam
added a commit
that referenced
this pull request
Aug 13, 2026
…link (#127) ## The blink The window opened **visible immediately**, so on launch you saw the dark-but-**empty** shell for a beat, then the rail + tabs popped in. This is a *content-render* blink — distinct from the white flash that #110 already fixed (dark background is correct from frame zero). ## Fix - **Create the window hidden** (`visible: false` in tauri.conf.json). - **Reveal it after the first paint** — the frontend calls `getCurrentWindow().show()` after two `requestAnimationFrame`s (so the populated frame has landed), Tauri-only. The OS then reveals an already-rendered window instead of a blank one that fills in. - **Rust safety net** — a background thread shows the window after 3s if the webview never loads (JS crash / blank bundle), so a broken frontend can't leave an invisible, un-closable window. ## Tests - Rust `cargo check` clean. - tsc clean, lint 0 errors, 321 unit tests pass. - e2e runs in the browser (`isTauri = false`), so `.show()` is skipped and the window config doesn't apply — verified a spec still passes. ## Note Best experienced on a fresh app build; the browser/dev path is unchanged.
oesukam
added a commit
that referenced
this pull request
Aug 22, 2026
The app flashed on every launch — two separate causes: ## 1. White frame before styles load The Tauri WebView paints its default **white** until `styles.css` applies the dark theme, so launch showed a bright flash that snapped to dark. **Fix:** paint dark from frame zero — - `tauri.conf.json`: set the window `backgroundColor` to `#1c1c20` (the native surface is dark before the WebView even paints); - `index.html`: inline `background: #1c1c20` + `color-scheme: dark` so the first HTML paint is dark before `styles.css` loads. ## 2. Empty-state flash before tabs restore `hydrateTabsFromStorage()` ran in an App `useEffect`, which fires **after** the first paint — so the initial render showed the empty state for a frame before the persisted tabs appeared. **Fix:** call it in `main.tsx` **before** `createRoot().render()`, so the first paint already has the restored tabs. The background reconnect stays async; the rest of App's wiring (menu handlers, accelerators, persistence subscription) stays in its effect. ## Tests tsc clean, 321 unit tests, 56 e2e pass.
oesukam
added a commit
that referenced
this pull request
Aug 22, 2026
Version bump for the **v0.4.0** release: `0.3.0 → 0.4.0` in `tauri.conf.json`, `Cargo.toml`, and `Cargo.lock`. ## What's in v0.4.0 (since v0.3.0) **Features** - MongoDB support: JS scripting, table-data browse/edit/insert/delete, connection URL, TLS handling (#101, #103, #105) - Engine registry — per-engine metadata drives the connection form, queries, display (#103) - Rail sessions behave like tabs: click selects, right-click to close, dim inactive, reconnect on click (#104) - Row count + query timer moved to a footer below the grid, for both table-data and SQL tabs (#108, #109) **Fixes** - Grid fills the pane for few-column tables; no open blink (#106) - Edit-connection opens the real connection; Mongo honors its pinned database (#107) - Startup white-flash eliminated (dark window bg + pre-render tab hydration) (#110) - Mongo defaults to TLS-off so a local Mongo connects (#105) - Actionable commitlint PR-title error (#102); release gated on lint/typecheck/tests (#100) ## Gate lint (0 errors), typecheck (CI-style clean), 321 unit tests, frontend build — all green locally. After merge, the Release workflow is triggered with `publish=false` to produce a **draft** release for review.
oesukam
added a commit
that referenced
this pull request
Aug 22, 2026
…link (#127) ## The blink The window opened **visible immediately**, so on launch you saw the dark-but-**empty** shell for a beat, then the rail + tabs popped in. This is a *content-render* blink — distinct from the white flash that #110 already fixed (dark background is correct from frame zero). ## Fix - **Create the window hidden** (`visible: false` in tauri.conf.json). - **Reveal it after the first paint** — the frontend calls `getCurrentWindow().show()` after two `requestAnimationFrame`s (so the populated frame has landed), Tauri-only. The OS then reveals an already-rendered window instead of a blank one that fills in. - **Rust safety net** — a background thread shows the window after 3s if the webview never loads (JS crash / blank bundle), so a broken frontend can't leave an invisible, un-closable window. ## Tests - Rust `cargo check` clean. - tsc clean, lint 0 errors, 321 unit tests pass. - e2e runs in the browser (`isTauri = false`), so `.show()` is skipped and the window config doesn't apply — verified a spec still passes. ## Note Best experienced on a fresh app build; the browser/dev path is unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The app flashed on every launch — two separate causes:
1. White frame before styles load
The Tauri WebView paints its default white until
styles.cssapplies the dark theme, so launch showed a bright flash that snapped to dark.Fix: paint dark from frame zero —
tauri.conf.json: set the windowbackgroundColorto#1c1c20(the native surface is dark before the WebView even paints);index.html: inlinebackground: #1c1c20+color-scheme: darkso the first HTML paint is dark beforestyles.cssloads.2. Empty-state flash before tabs restore
hydrateTabsFromStorage()ran in an AppuseEffect, which fires after the first paint — so the initial render showed the empty state for a frame before the persisted tabs appeared.Fix: call it in
main.tsxbeforecreateRoot().render(), so the first paint already has the restored tabs. The background reconnect stays async; the rest of App's wiring (menu handlers, accelerators, persistence subscription) stays in its effect.Tests
tsc clean, 321 unit tests, 56 e2e pass.