feat: add inline loading shell to #root before React mounts - #4063
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe ChangesLoading Shell UI
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
f066b43 to
683b6eb
Compare
683b6eb to
e981faf
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ui/index.html`:
- Around line 17-24: The loading shell CSS is desktop-first and needs a
small-screen fallback: add a media query for narrow viewports that targets
`#bifrost-shell` to switch .sidebar to hidden or collapsed (e.g.,
width:0;display:none;or transform/aria-hidden) and adjust `#bifrost-shell` .main
to reduce padding and use column stacking for cards (lower gap, full-width
items) while scaling .logo and .nav-item heights; also ensure .bar and other
loading placeholders adapt (reduced height/opacity) so the initial loading,
empty, error, and mobile states render without overflow before React mounts.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: c0e52665-5a09-4a2f-9962-90b3fd51ccbb
📒 Files selected for processing (1)
ui/index.html
Confidence Score: 5/5Safe to merge — the change is additive HTML/CSS inside #root that is automatically discarded when React mounts, with no functional code paths altered. The addition is a purely presentational loading shell. Both logo assets are confirmed present, the shell is correctly marked aria-hidden, and React 18's createRoot will overwrite the container on first render. No existing behaviour, routes, data flows, or test IDs are affected. No files require special attention. Important Files Changed
Reviews (9): Last reviewed commit: "feat: add a skeleton to the root app whi..." | Re-trigger Greptile |
e981faf to
9e49084
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ui/index.html`:
- Line 16: The global CSS reset using the universal selector (*) causes brief
site-wide side effects during initial parse; scope the rule to the shell
container by replacing the selector with a scoped selector such as
"`#bifrost-shell` *" (or "`#root` *") so the reset only applies inside the shell
element and no longer affects the entire DOM before React hydrates.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: b5b009e2-08e9-4b90-8d63-15470a248b1e
📒 Files selected for processing (1)
ui/index.html
9e49084 to
8c43dd1
Compare
eada2eb to
257b83c
Compare
8c43dd1 to
52ec606
Compare
257b83c to
104ba11
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
ui/index.html (1)
17-24:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winMobile fallback is still missing.
The inline CSS has no responsive breakpoints for narrow viewports. On mobile devices, the 240px sidebar and 32px main padding can cause overflow or compression before React mounts. The past comment suggesting a
@media (max-width: 768px)rule to hide the sidebar and reduce padding remains unaddressed.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ui/index.html` around lines 17 - 24, Add a mobile fallback CSS media query to prevent overflow on narrow viewports: create a `@media` (max-width: 768px) rule targeting `#bifrost-shell` to collapse the sidebar and reduce main padding (e.g., set `#bifrost-shell` .sidebar to display:none or width:0 and adjust `#bifrost-shell` .main padding from 32px to a smaller value like 12px); ensure the rule also preserves layout (keep `#bifrost-shell` display:flex and .main flex:1) and include a dark-mode variant if needed by mirroring the existing `@media`(prefers-color-scheme:dark) structure.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ui/index.html`:
- Around line 25-26: The fade-in animation defined by `@keyframes` shell-fade and
applied to `#bifrost-shell` should respect users' motion preferences; add a CSS
media query for prefers-reduced-motion: reduce that disables the animation
(e.g., override `#bifrost-shell` to animation: none or animation-duration: 0s
!important) so the shell renders without the fade when the user has
reduced-motion enabled.
---
Duplicate comments:
In `@ui/index.html`:
- Around line 17-24: Add a mobile fallback CSS media query to prevent overflow
on narrow viewports: create a `@media` (max-width: 768px) rule targeting
`#bifrost-shell` to collapse the sidebar and reduce main padding (e.g., set
`#bifrost-shell` .sidebar to display:none or width:0 and adjust `#bifrost-shell`
.main padding from 32px to a smaller value like 12px); ensure the rule also
preserves layout (keep `#bifrost-shell` display:flex and .main flex:1) and include
a dark-mode variant if needed by mirroring the existing
`@media`(prefers-color-scheme:dark) structure.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: bfdd3292-1899-4294-a992-f264a0231fee
📒 Files selected for processing (1)
ui/index.html
104ba11 to
d649120
Compare
52ec606 to
2a46736
Compare
b954d74 to
6195969
Compare
75341fc to
63532b5
Compare
6195969 to
a2935d2
Compare
63532b5 to
fe4ec2b
Compare
Merge activity
|
## Summary Adds an inline loading shell to `index.html` that renders immediately while React is bootstrapping, eliminating the blank white/dark flash users see before the app mounts. ## Changes - Added a static HTML skeleton inside `#root` that mimics the app's layout — sidebar with logo and nav placeholders, and a main content area with placeholder bars - Included scoped inline styles with light/dark mode support via `prefers-color-scheme`, a subtle fade-in animation, and skeleton shapes that approximate the real UI structure - Used a `<picture>` element to serve the appropriate logo variant based on color scheme - The shell is automatically replaced when React mounts and takes over `#root` ## Type of change - [ ] Bug fix - [x] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [ ] Core (Go) - [ ] Transports (HTTP) - [ ] Providers/Integrations - [ ] Plugins - [x] UI (React) - [ ] Docs ## How to test ```sh cd ui pnpm i || npm i pnpm build || npm run build ``` Open the built app in a browser with network throttling enabled (e.g. Chrome DevTools → Slow 3G). Verify that the skeleton shell appears immediately on page load before React hydrates, and that it is cleanly replaced by the live UI without a flash or layout shift. Confirm both light and dark mode render the correct logo and color scheme. ## Screenshots/Recordings Before: blank screen until React bundle loads. After: sidebar + content skeleton visible immediately on first paint. ## Breaking changes - [ ] Yes - [x] No ## Related issues ## Security considerations No auth, secrets, or PII involved. All assets referenced (`/bifrost-logo.webp`, `/bifrost-logo-dark.webp`) are static public files. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [ ] I added/updated tests where appropriate - [ ] I updated documentation where needed - [ ] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Adds a pre-rendered loading shell that shows interface placeholders (sidebar/logo, navigation, and content bars) during startup. * Includes embedded styling with light/dark color adjustments for improved initial contrast and consistency. * Adds a subtle fade-in animation for a smoother initial presentation. * Marks the shell as non-interactive (aria-hidden) for accessibility during hydration. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
## ✨ Features - **OpenAI Compaction** — Added OpenAI conversation compaction support across core, framework, logging, and the API surface (#4053) - **Multi-Customer & Org Hierarchy** — Logs and usage tracking now support multiple customers, teams, and business units, including business unit CRUD, team assignment, and governance endpoints in the OpenAPI spec (#4066, #4041, #4082) - **Provider-Level Governance** — Budgets & limits are now scope-aware and can be applied at the virtual-key top level and per provider, wired from the model configs table, with UI filters for scope and providers (#3938, #3937, #3939, #3981, #3962) - **Customer Budgets** — Customers support multiple budgets and `calendar_aligned` budget windows (#3998, #3997) - **Virtual Key Attribution & Controls** — Added a `created_by` user attribution column and a `blacklisted_models` column for virtual key provider configs (#3672, #3653) - **Request Header Capture** — OTel and Maxim observability plugins capture `request_headers` by pattern, with wildcard support (e.g. `x-custom-*`); logging gained the same wildcard header capture (#4012, #3958) - **OTel Content Controls & Collectors** — New `disable_content_logging` option drops message/tool content from exported spans, plus support for multiple OTel collectors (#4064, #3894) - **xAI x_search** — Added xAI `x_search` tool support (#3976) - **URL Validation** — Added fetch URL validation with private-network configuration and link-local blocking (#3947, #3991) - **File Scheme Pricing URLs** — Pricing source URLs now accept the `file://` scheme for air-gapped and self-hosted deployments (#4045) - **Paginated Virtual Keys** — Virtual key fetching is paginated to handle deployments with very large numbers of keys (#3957) - **Client IP Resolution** — Resolve client IP from `X-Forwarded-For`/`X-Real-IP` headers - **SCIM Provisioning** — Added `attributeType`/`attributeValue` SCIM provisioning fields - **Helm/Config Schema** — Added `roles` RBAC governance config and `per_user_oauth` MCP auth to the Helm chart and config schema (#4004, #4009) - **Log Navigation UI** — Added a "View logs" menu item to customer, team, and virtual key tables, clickable links in log detail views, a customer detail sheet, and a reusable `BudgetDisplay` component (#4073, #4054, #4026, #4055) - **Faster First Paint** — Added an inline loading shell to `#root` before React mounts (#4063) - **Materialized View Alias** — Added an `alias` column to the materialized view with filter support (#4078) ## 🐞 Fixed - **Fetch URL IP Checks** — Hardened fetch URL IP checks against SSRF (#4092) - **Mantle Model Matching** — Broadened Mantle model matching to all `gpt` variants (#4091) - **Empty Thinking Blocks** — Strip thinking blocks when the signature is empty (#4079) - **OpenAI Stream Usage** — Removed usage from the `responses.created` event in the OpenAI stream (#4080) - **Prompt Cache Key** — Set the prompt cache key from the Anthropic integration (#4086) - **Upstream Failure Status** — Map upstream connection failures to 502 instead of 400 (#3929) (thanks [@chris-colinsky](https://github.com/chris-colinsky)!) - **Gemini Schema Constraints** — Accept numeric schema integer constraints for Gemini (#3994) (thanks [@yanhao98](https://github.com/yanhao98)!) - **Files Provider Param** — Accept the `?provider=` query param on `GET /v1/files` (#3971) (thanks [@alexef](https://github.com/alexef)!) - **Optional Batch Model** — Made the `model` field optional on `POST /v1/batches` (#3973) (thanks [@alexef](https://github.com/alexef)!) - **Helm Azure Config** — Added missing `azure_key_config` fields to the Helm schema (#3996) (thanks [@axelray-dev](https://github.com/axelray-dev)!) - **Text Completion Chunk Model** — Added the missing `Model` field to `TextCompletionChunkResponse` (#3970) (thanks [@kuishou68](https://github.com/kuishou68)!) - **MCP Inline stdio Env** — MCP stdio server configs accept inline environment variable assignments (#3861) (thanks [@Shushmitaaaa](https://github.com/Shushmitaaaa)!) - **Orphaned Tool Results** — Orphaned tool results in the OpenAI to Anthropic conversion flow are no longer rejected by the Anthropic API (#3919) - **Node Usage Reconciliation** — Added a monotonic `inc_number` log cursor so node usage reconciliation does not skip late async log writes (#3664) - **Bedrock Output Assessments** — Corrected the type of `outputAssessments` in Bedrock responses (#4028) - **Model Pool Pricing Reloads** — Preserve non-pricing model pool entries across pricing reloads (#3999) - **Ghost Node Reconciliation** — Replicate the VK hierarchy flow for ghost node reconciliation (#4088) - **VK Double Usage Counting** — Fixed double usage counting when creating a virtual key (#4070) - **Model Config Lifecycle** — Cascade deletes for model configs and removal of stale in-memory model configs (#4051, #4043) - **FTS Index Cap** — Reduced the FTS index `left()` cap from 800k to 250k chars to stay within the tsvector limit (#4057) - **Sync Worker Drift** — Reduced the sync worker ticker period to 5m to prevent threshold drift (#4023) - **Passthrough** — Fixed passthrough budgets, gated passthrough models per VK, model extraction for Azure passthrough, and restricted fallbacks/provider selection to the VK boundary (#3941, #3988, #3983, #3924) - **Provider Response Headers** — Strip provider response headers and add a content-type filter (#3955, #4024) - **Stream Handling** — Drain non-SSE stream readers and retry stale connections (#3956, #3967) - **Azure Claude** — Strip Azure diagnostic property for Claude models (#3925) - **Compat max_tokens** — Preserve chat `max_tokens` during param filtering (#3992) - **Raw Request Flag** — Removed the raw request flag from providers that don't support it (#4058) - **UI Fixes** — Standardized page container layout, virtual key model configs UI, and dashboard chart tooltips (#4046, #4052, #4044) ## 🔧 Maintenance - **Dependency Upgrades** — Bumped transitive `golang.org/x` dependencies (crypto, net, sys, text) for Docker Scout CVE remediation and `recharts` to 3.8.1; cascaded version bumps across all modules (#3900, #4003)

Summary
Adds an inline loading shell to
index.htmlthat renders immediately while React is bootstrapping, eliminating the blank white/dark flash users see before the app mounts.Changes
#rootthat mimics the app's layout — sidebar with logo and nav placeholders, and a main content area with placeholder barsprefers-color-scheme, a subtle fade-in animation, and skeleton shapes that approximate the real UI structure<picture>element to serve the appropriate logo variant based on color scheme#rootType of change
Affected areas
How to test
Open the built app in a browser with network throttling enabled (e.g. Chrome DevTools → Slow 3G). Verify that the skeleton shell appears immediately on page load before React hydrates, and that it is cleanly replaced by the live UI without a flash or layout shift. Confirm both light and dark mode render the correct logo and color scheme.
Screenshots/Recordings
Before: blank screen until React bundle loads.
After: sidebar + content skeleton visible immediately on first paint.
Breaking changes
Related issues
Security considerations
No auth, secrets, or PII involved. All assets referenced (
/bifrost-logo.webp,/bifrost-logo-dark.webp) are static public files.Checklist
docs/contributing/README.mdand followed the guidelinesSummary by CodeRabbit