Skip to content

feat(start): add inline CSS runtime controls and asset URL templates#7380

Open
schiller-manuel wants to merge 3 commits into
mainfrom
css-inline-runtime
Open

feat(start): add inline CSS runtime controls and asset URL templates#7380
schiller-manuel wants to merge 3 commits into
mainfrom
css-inline-runtime

Conversation

@schiller-manuel
Copy link
Copy Markdown
Collaborator

@schiller-manuel schiller-manuel commented May 11, 2026

Summary by CodeRabbit

  • New Features

    • Runtime-configurable inline CSS with opt-in URL-template support; asset transforms can rewrite URLs inside inlined stylesheets and be toggled per request.
  • Documentation

    • Added CSS Styling guides for React and Solid; CDN/asset URL docs updated with inlined-CSS URL handling and examples.
  • Chores

    • Patched core packages and removed deprecated asset-URL API.
  • Tests

    • Expanded E2E and unit tests and test scripts to cover inline-CSS and transform-assets scenarios.

Review Change Stack

@nx-cloud
Copy link
Copy Markdown
Contributor

nx-cloud Bot commented May 11, 2026

View your CI Pipeline Execution ↗ for commit 1263b50

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ❌ Failed 7m 2s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 45s View ↗

☁️ Nx Cloud last updated this comment at 2026-05-11 19:05:02 UTC

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 11, 2026

🚀 Changeset Version Preview

5 package(s) bumped directly, 19 bumped as dependents.

🟨 Minor bumps

Package Version Reason
@tanstack/start-client-core 1.168.2 → 1.169.0 Changeset

🟩 Patch bumps

Package Version Reason
@tanstack/router-core 1.169.2 → 1.169.3 Changeset
@tanstack/start-fn-stubs 1.161.6 → 1.161.7 Changeset
@tanstack/start-plugin-core 1.169.20 → 1.169.21 Changeset
@tanstack/start-server-core 1.167.30 → 1.167.31 Changeset
@tanstack/react-router 1.169.2 → 1.169.3 Dependent
@tanstack/react-start 1.167.65 → 1.167.66 Dependent
@tanstack/react-start-client 1.166.48 → 1.166.49 Dependent
@tanstack/react-start-rsc 0.0.44 → 0.0.45 Dependent
@tanstack/react-start-server 1.166.52 → 1.166.53 Dependent
@tanstack/router-cli 1.166.43 → 1.166.44 Dependent
@tanstack/router-generator 1.166.42 → 1.166.43 Dependent
@tanstack/router-plugin 1.167.35 → 1.167.36 Dependent
@tanstack/router-vite-plugin 1.166.50 → 1.166.51 Dependent
@tanstack/solid-router 1.169.2 → 1.169.3 Dependent
@tanstack/solid-start 1.167.62 → 1.167.63 Dependent
@tanstack/solid-start-client 1.166.47 → 1.166.48 Dependent
@tanstack/solid-start-server 1.166.51 → 1.166.52 Dependent
@tanstack/start-static-server-functions 1.166.41 → 1.166.42 Dependent
@tanstack/start-storage-context 1.166.35 → 1.166.36 Dependent
@tanstack/vue-router 1.169.2 → 1.169.3 Dependent
@tanstack/vue-start 1.167.58 → 1.167.59 Dependent
@tanstack/vue-start-client 1.166.43 → 1.166.44 Dependent
@tanstack/vue-start-server 1.166.47 → 1.166.48 Dependent

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 11, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e65f466e-92d2-4ac8-b493-f36cbc616445

📥 Commits

Reviewing files that changed from the base of the PR and between 1263b50 and d68d38b.

📒 Files selected for processing (1)
  • packages/start-server-core/src/createStartHandler.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/start-server-core/src/createStartHandler.ts

📝 Walkthrough

Walkthrough

This PR adds runtime-configurable inline CSS and opt-in CSS URL templates for TanStack Start. The schema now supports both boolean and object configuration with enabled and transformAssets properties. Manifests are extended to carry CSS URL template metadata, and the server handler supports per-request inline CSS control via callbacks or headers. Asset transformation now includes a css-url kind for rewriting URLs inside inlined CSS.

Changes

Inline CSS Feature Implementation

Layer / File(s) Summary
Configuration Schema
packages/start-plugin-core/src/schema.ts, packages/start-plugin-core/src/rsbuild/schema.ts, packages/start-plugin-core/src/vite/schema.ts
inlineCss now accepts both boolean and object form with enabled (default true) and transformAssets (default false); schema normalizes inputs and exports InlineCssInputOptions type for use in Rsbuild and Vite config schemas.
Manifest Type Extensions
packages/router-core/src/manifest.ts, packages/start-plugin-core/src/start-manifest-plugin/manifestBuilder.ts
Manifest.inlineCss extends to include optional templates map with strings and urls arrays for CSS URL template metadata; InlineCssOptions interface introduced.
Inline CSS Processing
packages/start-plugin-core/src/start-manifest-plugin/inlineCss.ts
New processInlineCssUrls function generates CSS URL templates by replacing matched URLs with placeholders and collecting rebased URLs; rebaseInlineCssUrls now delegates to this function.
Manifest Building & Codegen
packages/start-plugin-core/src/start-manifest-plugin/manifestBuilder.ts, packages/start-plugin-core/src/rsbuild/virtual-modules.ts
Import statements updated to use processInlineCssUrls; buildStartManifest treats inlineCss as options object and conditionally generates inline CSS data with templates when transformAssets is enabled; virtual module codegen updated to handle InlineCssOptions for manifest serialization.
Asset Transform Context
packages/start-server-core/src/transformAssetUrls.ts
New TransformAssetsContext discriminated union includes css-url kind with stylesheetHref for CSS URLs; factory types CreateTransformAssetsContext and CreateTransformAssetsFn added.
CSS Template Runtime Transformation
packages/start-server-core/src/transformAssetUrls.ts, packages/start-server-core/src/index.tsx
Implements inline CSS template transformation by applying TransformAssetsFn to collected URLs with css-url context, including CSS string escaping and template validation; updated public re-exports to add CreateTransformAssetsContext and remove deprecated types.
Request-level Inline CSS Resolution
packages/start-server-core/src/inlineCss.ts, packages/start-server-core/src/request-handler.ts
New resolveInlineCssForRequest utility enables per-request inline CSS control via handler callbacks or explicit request options, with fallback to handler default.
Handler Integration & Caching
packages/start-server-core/src/createStartHandler.ts
createStartHandler now accepts inlineCss option, manifests are cached separately for inline vs linked CSS modes, transform warmup logic targets both modes independently.
Build Plugin Configuration
packages/start-plugin-core/src/rsbuild/plugin.ts, packages/start-plugin-core/src/vite/plugin.ts, packages/start-plugin-core/src/rsbuild/start-router-plugin.ts
Rsbuild and Vite plugins updated to read .enabled property from inlineCss options object; prerender condition optional chaining simplified.
E2E Tests: CSS Inlining
e2e/react-start/css-inline/...
New test scripts and examples demonstrating runtime inline CSS control with conditional asset transform via CSS_INLINE_TRANSFORM_ASSETS environment variable and x-inline-css header override.
E2E Tests: Transform Assets Cleanup
e2e/react-start/transform-asset-urls/...
Removed deprecated TransformAssetUrls API coverage; updated to use new TransformAssets types and configuration directly.
Unit Tests
packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts, packages/start-server-core/tests/createStartHandler.test.ts, packages/start-server-core/tests/transformAssets.test.ts
Added test coverage for manifest building with templates, request-level inline CSS resolution, and CSS URL transformation with css-url context.
Documentation
docs/start/framework/react/guide/css-styling.md, docs/start/framework/react/guide/cdn-asset-urls.md, docs/start/framework/react/guide/early-hints.md, docs/start/framework/solid/guide/css-styling.md, docs/start/config.json
New CSS Styling guide covers explicit vs discovered CSS, SSR behavior, Early Hints phases, and CSS inlining configuration with transformAssets; CDN Asset URLs and Early Hints docs updated to reflect css-url kind and template requirements; documentation navigation updated.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • TanStack/router#7253: Both PRs implement the same inline-CSS feature (manifest/manifestBuilder changes, start-plugin-core inlineCss, start-server-core transformAssets/inlineCss types and runtime flags, and related SSR/e2e test updates).
  • TanStack/router#7157: Overlapping changes to manifest handling and createStartHandler behavior.

"I'm a rabbit in a codewarren bright,
I nibble templates by the pale screen light,
Inline CSS tucked in a manifest bed,
TransformAssets hops where URLs are led,
Hooray for headers and builds that feel light!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: adding runtime-configurable inline CSS controls and opt-in CSS URL template support for asset transformation, which aligns with the comprehensive feature additions across documentation, configuration, and server-side handling.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch css-inline-runtime

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 11, 2026

Bundle Size Benchmarks

  • Commit: b1c061aff918
  • Measured at: 2026-05-11T18:58:25.478Z
  • Baseline source: history:b1c061aff918
  • Dashboard: bundle-size history
Scenario Current (gzip) Delta vs baseline Initial gzip Raw Brotli Trend
react-router.minimal 87.29 KiB 0 B (0.00%) 87.15 KiB 274.07 KiB 75.85 KiB ▁▁▁▁▁▁▁▁▁██
react-router.full 90.82 KiB 0 B (0.00%) 90.68 KiB 285.58 KiB 78.89 KiB ▁▁▁▁▁▁▁▁▁██
solid-router.minimal 35.51 KiB 0 B (0.00%) 35.39 KiB 106.36 KiB 31.97 KiB ▁▁▁▁▁▁▁▁▁██
solid-router.full 40.23 KiB 0 B (0.00%) 40.10 KiB 120.58 KiB 36.14 KiB ▁▁▁▁▁▁▁▁▁██
vue-router.minimal 53.29 KiB 0 B (0.00%) 53.15 KiB 151.51 KiB 47.85 KiB ▁▁▁▁▁▁▁▁▁██
vue-router.full 58.41 KiB 0 B (0.00%) 58.28 KiB 167.69 KiB 52.39 KiB ▁▁▁▁▁▁▁▁▁██
react-start.minimal 101.97 KiB 0 B (0.00%) 101.83 KiB 322.51 KiB 88.17 KiB ▁▁▁▁▁▁▁▁▃██
react-start.full 105.41 KiB 0 B (0.00%) 105.27 KiB 332.84 KiB 91.19 KiB ▁▁▁▁▁▁▁▁▄██
react-start.rsbuild.minimal 99.60 KiB 0 B (0.00%) 99.43 KiB 316.97 KiB 85.64 KiB ▁▁▁▁▁▁▁▁▄██
react-start.rsbuild.full 102.89 KiB 0 B (0.00%) 102.72 KiB 327.41 KiB 88.45 KiB ▁▁▁▁▁▁▁▁▃██
solid-start.minimal 49.61 KiB 0 B (0.00%) 49.48 KiB 152.48 KiB 43.78 KiB ▁▁▁▁▁▁▁▁▄██
solid-start.full 55.40 KiB 0 B (0.00%) 55.27 KiB 169.39 KiB 48.72 KiB ▁▁▁▁▁▁▁▁▄██

Current gzip tracks all emitted client JS chunks. Initial gzip tracks only the entry/import graph. Trend sparkline is historical current gzip ending with this PR measurement; lower is better.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 11, 2026

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/@tanstack/arktype-adapter@7380

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/@tanstack/eslint-plugin-router@7380

@tanstack/eslint-plugin-start

npm i https://pkg.pr.new/@tanstack/eslint-plugin-start@7380

@tanstack/history

npm i https://pkg.pr.new/@tanstack/history@7380

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/@tanstack/nitro-v2-vite-plugin@7380

@tanstack/react-router

npm i https://pkg.pr.new/@tanstack/react-router@7380

@tanstack/react-router-devtools

npm i https://pkg.pr.new/@tanstack/react-router-devtools@7380

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/@tanstack/react-router-ssr-query@7380

@tanstack/react-start

npm i https://pkg.pr.new/@tanstack/react-start@7380

@tanstack/react-start-client

npm i https://pkg.pr.new/@tanstack/react-start-client@7380

@tanstack/react-start-rsc

npm i https://pkg.pr.new/@tanstack/react-start-rsc@7380

@tanstack/react-start-server

npm i https://pkg.pr.new/@tanstack/react-start-server@7380

@tanstack/router-cli

npm i https://pkg.pr.new/@tanstack/router-cli@7380

@tanstack/router-core

npm i https://pkg.pr.new/@tanstack/router-core@7380

@tanstack/router-devtools

npm i https://pkg.pr.new/@tanstack/router-devtools@7380

@tanstack/router-devtools-core

npm i https://pkg.pr.new/@tanstack/router-devtools-core@7380

@tanstack/router-generator

npm i https://pkg.pr.new/@tanstack/router-generator@7380

@tanstack/router-plugin

npm i https://pkg.pr.new/@tanstack/router-plugin@7380

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/@tanstack/router-ssr-query-core@7380

@tanstack/router-utils

npm i https://pkg.pr.new/@tanstack/router-utils@7380

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/@tanstack/router-vite-plugin@7380

@tanstack/solid-router

npm i https://pkg.pr.new/@tanstack/solid-router@7380

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/@tanstack/solid-router-devtools@7380

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/@tanstack/solid-router-ssr-query@7380

@tanstack/solid-start

npm i https://pkg.pr.new/@tanstack/solid-start@7380

@tanstack/solid-start-client

npm i https://pkg.pr.new/@tanstack/solid-start-client@7380

@tanstack/solid-start-server

npm i https://pkg.pr.new/@tanstack/solid-start-server@7380

@tanstack/start-client-core

npm i https://pkg.pr.new/@tanstack/start-client-core@7380

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/@tanstack/start-fn-stubs@7380

@tanstack/start-plugin-core

npm i https://pkg.pr.new/@tanstack/start-plugin-core@7380

@tanstack/start-server-core

npm i https://pkg.pr.new/@tanstack/start-server-core@7380

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/@tanstack/start-static-server-functions@7380

@tanstack/start-storage-context

npm i https://pkg.pr.new/@tanstack/start-storage-context@7380

@tanstack/valibot-adapter

npm i https://pkg.pr.new/@tanstack/valibot-adapter@7380

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/@tanstack/virtual-file-routes@7380

@tanstack/vue-router

npm i https://pkg.pr.new/@tanstack/vue-router@7380

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/@tanstack/vue-router-devtools@7380

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/@tanstack/vue-router-ssr-query@7380

@tanstack/vue-start

npm i https://pkg.pr.new/@tanstack/vue-start@7380

@tanstack/vue-start-client

npm i https://pkg.pr.new/@tanstack/vue-start-client@7380

@tanstack/vue-start-server

npm i https://pkg.pr.new/@tanstack/vue-start-server@7380

@tanstack/zod-adapter

npm i https://pkg.pr.new/@tanstack/zod-adapter@7380

commit: d68d38b

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 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 `@docs/start/framework/react/guide/css-styling.md`:
- Around line 197-204: The example incorrectly calls handler.fetch(...); update
the custom runtime wrapper example so it invokes the handler as a callable
function (handler(request, { inlineCss })) rather than accessing a non-existent
.fetch property; change the fetch implementation inside createServerEntry to
call handler(request, { inlineCss: request.headers.get('x-inline-css') !==
'false' }) so it matches the handler returned by
createStartHandler()/createServerEntry and the e2e tests.

In `@packages/start-server-core/src/createStartHandler.ts`:
- Around line 316-317: The module-scoped cache Map cachedFinalManifestPromises
is shared across all handlers and causes cross-handler pollution; move its
declaration into the createStartHandler scope (or the handler factory) so each
handler instance gets its own Map, and update all usages (including the warmup
code paths that currently write into cachedFinalManifestPromises) to reference
the instance-local variable instead of the module-scoped one; similarly relocate
or convert the other module-scoped caches referenced around the other spots
(lines ~423-428, ~639-660) to instance-local variables so different
transformAssets configs cannot reuse another handler’s cached manifest.

In `@packages/start-server-core/src/transformAssetUrls.ts`:
- Around line 469-474: The returned inlineCss is passed by reference from
source.manifest.inlineCss, allowing downstream mutation of styles/templates to
leak into the cached base manifest; instead, when opts?.inlineCss !== false set
inlineCss to a cloned copy of source.manifest.inlineCss (use a safe clone
strategy such as structuredClone or a shallow copy via spread/map depending on
the shape) so mutations to the returned value don't affect the original
manifest; update the return in transformAssetUrls.ts where inlineCss is assigned
to use the clone and keep the existing opts?.inlineCss check.
- Around line 219-230: The current code fills transformedStyles in the order
promises resolve, which can reorder inlineCss.styles; change the mapping so you
produce an array of promises that each resolve to a tuple [stylesheetHref,
transformedCss] (use transformInlineCssTemplate for templates or css fallback)
and then await Promise.all on that array and assign results into
transformedStyles in the original source order by iterating the resolved tuples;
reference inlineCss.styles, inlineCss.templates, transformInlineCssTemplate, and
transformedStyles.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8c3e2c7b-271a-4677-ab05-ece2e4902ad8

📥 Commits

Reviewing files that changed from the base of the PR and between b1c061a and 700fd012f9a3a59bac7fa7aa56678e3b356f3dc6.

⛔ Files ignored due to path filters (1)
  • e2e/react-start/css-inline/src/styles/inline-dot.svg is excluded by !**/*.svg
📒 Files selected for processing (35)
  • .changeset/quiet-dragons-collect.md
  • docs/start/config.json
  • docs/start/framework/react/guide/cdn-asset-urls.md
  • docs/start/framework/react/guide/css-styling.md
  • docs/start/framework/react/guide/early-hints.md
  • docs/start/framework/solid/guide/css-styling.md
  • e2e/react-start/css-inline/package.json
  • e2e/react-start/css-inline/playwright.config.ts
  • e2e/react-start/css-inline/rsbuild.config.ts
  • e2e/react-start/css-inline/src/server.ts
  • e2e/react-start/css-inline/tests/css-inline.spec.ts
  • e2e/react-start/css-inline/vite.config.ts
  • e2e/react-start/server-routes/src/routeTree.gen.ts
  • e2e/react-start/transform-asset-urls/package.json
  • e2e/react-start/transform-asset-urls/playwright.config.ts
  • e2e/react-start/transform-asset-urls/src/server.ts
  • packages/router-core/src/manifest.ts
  • packages/start-plugin-core/src/rsbuild/plugin.ts
  • packages/start-plugin-core/src/rsbuild/schema.ts
  • packages/start-plugin-core/src/rsbuild/start-router-plugin.ts
  • packages/start-plugin-core/src/rsbuild/virtual-modules.ts
  • packages/start-plugin-core/src/schema.ts
  • packages/start-plugin-core/src/start-manifest-plugin/inlineCss.ts
  • packages/start-plugin-core/src/start-manifest-plugin/manifestBuilder.ts
  • packages/start-plugin-core/src/vite/plugin.ts
  • packages/start-plugin-core/src/vite/schema.ts
  • packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts
  • packages/start-server-core/skills/start-server-core/SKILL.md
  • packages/start-server-core/src/createStartHandler.ts
  • packages/start-server-core/src/index.tsx
  • packages/start-server-core/src/inlineCss.ts
  • packages/start-server-core/src/request-handler.ts
  • packages/start-server-core/src/transformAssetUrls.ts
  • packages/start-server-core/tests/createStartHandler.test.ts
  • packages/start-server-core/tests/transformAssets.test.ts
💤 Files with no reviewable changes (1)
  • e2e/react-start/transform-asset-urls/playwright.config.ts

Comment thread docs/start/framework/react/guide/css-styling.md Outdated
Comment thread packages/start-server-core/src/createStartHandler.ts Outdated
Comment thread packages/start-server-core/src/transformAssetUrls.ts Outdated
Comment thread packages/start-server-core/src/transformAssetUrls.ts
nx-cloud[bot]

This comment was marked as outdated.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 11, 2026

Merging this PR will not alter performance

✅ 5 untouched benchmarks
⏩ 1 skipped benchmark1


Comparing css-inline-runtime (d68d38b) with main (b1c061a)

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

nx-cloud[bot]

This comment was marked as outdated.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
e2e/react-start/css-inline/playwright.config.ts (1)

7-10: ⚡ Quick win

Validate CSS_INLINE_TRANSFORM_ASSETS instead of silently coercing unknown values

Right now any non-"true" value is treated as disabled, which can mask bad env input. Please fail fast (or normalize explicitly) so misconfiguration is obvious.

Proposed patch
+function readBooleanEnv(name: string, defaultValue: boolean): boolean {
+  const raw = process.env[name]
+  if (raw == null) return defaultValue
+  if (raw === 'true') return true
+  if (raw === 'false') return false
+  throw new Error(`${name} must be "true" or "false", received "${raw}"`)
+}
+
 const toolchain = process.env.E2E_TOOLCHAIN ?? 'vite'
-const inlineCssTransformAssets =
-  process.env.CSS_INLINE_TRANSFORM_ASSETS ?? 'false'
+const inlineCssTransformAssets = readBooleanEnv(
+  'CSS_INLINE_TRANSFORM_ASSETS',
+  false,
+)
 const transformAssetsSuffix =
-  inlineCssTransformAssets === 'true' ? '-transform-assets' : ''
+  inlineCssTransformAssets ? '-transform-assets' : ''
 const distDir =
   process.env.E2E_DIST_DIR ?? `dist-${toolchain}${transformAssetsSuffix}-ssr`
@@
     env: {
       E2E_DIST_DIR: distDir,
       PORT: String(PORT),
-      CSS_INLINE_TRANSFORM_ASSETS: inlineCssTransformAssets,
+      CSS_INLINE_TRANSFORM_ASSETS: inlineCssTransformAssets ? 'true' : 'false',
     },

As per coding guidelines, **/*.{ts,tsx}: Use TypeScript strict mode with extensive type safety.

Also applies to: 41-41

🤖 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 `@e2e/react-start/css-inline/playwright.config.ts` around lines 7 - 10, The
code silently treats any non-"true" CSS_INLINE_TRANSFORM_ASSETS value as
disabled; update the initialization of inlineCssTransformAssets and
transformAssetsSuffix so the env var is validated explicitly: accept only "true"
or "false" (or empty) and either throw a clear error for any other value or
normalize by forcing to lowercase and mapping "1"/"0"/"yes"/"no" to
"true"/"false"; use the inlineCssTransformAssets variable (string) to derive a
boolean (e.g., isInline = inlineCssTransformAssets === 'true') and then compute
transformAssetsSuffix from that boolean, and ensure invalid input causes a fast
fail with a descriptive message mentioning CSS_INLINE_TRANSFORM_ASSETS and the
offending value.
packages/start-plugin-core/src/start-manifest-plugin/inlineCss.ts (1)

109-114: 💤 Low value

Inconsistent index calculation pattern between Url and import visitors.

The Url visitor pushes to urls first then uses urls.length - 1, while the import rule uses urls.length then pushes. Both produce correct indices, but the inconsistency reduces readability.

Consider aligning the pattern:

♻️ Suggested alignment (push-then-reference style)
         Rule: {
           import(rule: any) {
             if (!shouldTransformInlineCssUrl(rule.value.url)) {
               return rule
             }
 
             const rebasedUrl = rebaseCssUrl(rule.value.url, options.cssHref)
+
+            if (templates) {
+              urls.push(rebasedUrl)
+            }
+
             const value = {
               url: templates
-                ? createInlineCssUrlPlaceholder(urls.length)
+                ? createInlineCssUrlPlaceholder(urls.length - 1)
                 : rebasedUrl,
               loc: rule.value.loc,
               ...(rule.value.media ? { media: rule.value.media } : {}),
               ...(rule.value.layer ? { layer: rule.value.layer } : {}),
               ...(rule.value.supports ? { supports: rule.value.supports } : {}),
             }
 
-            if (templates) {
-              urls.push(rebasedUrl)
-            }
-
             return {
               ...rule,
               value,
             }
           },
         },

Also applies to: 129-141

🤖 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 `@packages/start-plugin-core/src/start-manifest-plugin/inlineCss.ts` around
lines 109 - 114, The Url visitor and the import rule use two different index
patterns when adding entries to the urls array (Url pushes then references
urls.length - 1; import references urls.length then pushes), which is
inconsistent; standardize to a single pattern (prefer push-then-reference)
across both visitors by updating the import handling to push the rebasedUrl into
urls first and then call createInlineCssUrlPlaceholder(urls.length - 1) so both
Url visitor and import rule use the same push-then-reference flow, and ensure
you update all similar blocks (including the region around 129-141) to use the
same approach for the urls array and placeholder creation.
packages/start-server-core/src/createStartHandler.ts (1)

632-660: 💤 Low value

Warmup always warms the inline-css variant regardless of handler default.

When warmupTransformManifest is true, warmup pre-computes the inline-css manifest. If the handler's inlineCss option defaults to false, the warmed cache entry may never be used while the linked-css variant is computed on first request.

This is a minor inefficiency for uncommon configurations. Consider documenting this behavior or conditionally warming based on the handler's effective default.

🤖 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 `@packages/start-server-core/src/createStartHandler.ts` around lines 632 - 660,
The warmup currently always computes the 'inline-css' variant regardless of the
handler's effective inlineCss default; change the warmup gate to only precompute
the manifest variant that matches the handler's effective default (inline or
linked). Concretely, determine the handler's default inlineCss setting (e.g.,
derive a boolean like handlerDefaultInlineCss from the handler/options used to
create the start handler) and replace the hardcoded 'inline-css' warmup key and
transform arguments with a conditional that selects either 'inline-css' (and
inlineCss: true) or the linked-css key (and inlineCss: false) before calling
getBaseManifest, getTransformFn, transformManifestAssets or
buildManifestWithClientEntry; keep the same error/retry logic and still clear
cachedCreateTransformPromise on failure.
🤖 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.

Nitpick comments:
In `@e2e/react-start/css-inline/playwright.config.ts`:
- Around line 7-10: The code silently treats any non-"true"
CSS_INLINE_TRANSFORM_ASSETS value as disabled; update the initialization of
inlineCssTransformAssets and transformAssetsSuffix so the env var is validated
explicitly: accept only "true" or "false" (or empty) and either throw a clear
error for any other value or normalize by forcing to lowercase and mapping
"1"/"0"/"yes"/"no" to "true"/"false"; use the inlineCssTransformAssets variable
(string) to derive a boolean (e.g., isInline = inlineCssTransformAssets ===
'true') and then compute transformAssetsSuffix from that boolean, and ensure
invalid input causes a fast fail with a descriptive message mentioning
CSS_INLINE_TRANSFORM_ASSETS and the offending value.

In `@packages/start-plugin-core/src/start-manifest-plugin/inlineCss.ts`:
- Around line 109-114: The Url visitor and the import rule use two different
index patterns when adding entries to the urls array (Url pushes then references
urls.length - 1; import references urls.length then pushes), which is
inconsistent; standardize to a single pattern (prefer push-then-reference)
across both visitors by updating the import handling to push the rebasedUrl into
urls first and then call createInlineCssUrlPlaceholder(urls.length - 1) so both
Url visitor and import rule use the same push-then-reference flow, and ensure
you update all similar blocks (including the region around 129-141) to use the
same approach for the urls array and placeholder creation.

In `@packages/start-server-core/src/createStartHandler.ts`:
- Around line 632-660: The warmup currently always computes the 'inline-css'
variant regardless of the handler's effective inlineCss default; change the
warmup gate to only precompute the manifest variant that matches the handler's
effective default (inline or linked). Concretely, determine the handler's
default inlineCss setting (e.g., derive a boolean like handlerDefaultInlineCss
from the handler/options used to create the start handler) and replace the
hardcoded 'inline-css' warmup key and transform arguments with a conditional
that selects either 'inline-css' (and inlineCss: true) or the linked-css key
(and inlineCss: false) before calling getBaseManifest, getTransformFn,
transformManifestAssets or buildManifestWithClientEntry; keep the same
error/retry logic and still clear cachedCreateTransformPromise on failure.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c276de89-fa5d-4bdd-9738-a4c7d14f31cb

📥 Commits

Reviewing files that changed from the base of the PR and between 700fd012f9a3a59bac7fa7aa56678e3b356f3dc6 and 29f09f2.

⛔ Files ignored due to path filters (1)
  • e2e/react-start/css-inline/src/styles/inline-dot.svg is excluded by !**/*.svg
📒 Files selected for processing (35)
  • .changeset/quiet-dragons-collect.md
  • docs/start/config.json
  • docs/start/framework/react/guide/cdn-asset-urls.md
  • docs/start/framework/react/guide/css-styling.md
  • docs/start/framework/react/guide/early-hints.md
  • docs/start/framework/solid/guide/css-styling.md
  • e2e/react-start/css-inline/package.json
  • e2e/react-start/css-inline/playwright.config.ts
  • e2e/react-start/css-inline/rsbuild.config.ts
  • e2e/react-start/css-inline/src/server.ts
  • e2e/react-start/css-inline/tests/css-inline.spec.ts
  • e2e/react-start/css-inline/vite.config.ts
  • e2e/react-start/server-routes/src/routeTree.gen.ts
  • e2e/react-start/transform-asset-urls/package.json
  • e2e/react-start/transform-asset-urls/playwright.config.ts
  • e2e/react-start/transform-asset-urls/src/server.ts
  • packages/router-core/src/manifest.ts
  • packages/start-plugin-core/src/rsbuild/plugin.ts
  • packages/start-plugin-core/src/rsbuild/schema.ts
  • packages/start-plugin-core/src/rsbuild/start-router-plugin.ts
  • packages/start-plugin-core/src/rsbuild/virtual-modules.ts
  • packages/start-plugin-core/src/schema.ts
  • packages/start-plugin-core/src/start-manifest-plugin/inlineCss.ts
  • packages/start-plugin-core/src/start-manifest-plugin/manifestBuilder.ts
  • packages/start-plugin-core/src/vite/plugin.ts
  • packages/start-plugin-core/src/vite/schema.ts
  • packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts
  • packages/start-server-core/skills/start-server-core/SKILL.md
  • packages/start-server-core/src/createStartHandler.ts
  • packages/start-server-core/src/index.tsx
  • packages/start-server-core/src/inlineCss.ts
  • packages/start-server-core/src/request-handler.ts
  • packages/start-server-core/src/transformAssetUrls.ts
  • packages/start-server-core/tests/createStartHandler.test.ts
  • packages/start-server-core/tests/transformAssets.test.ts
💤 Files with no reviewable changes (1)
  • e2e/react-start/transform-asset-urls/playwright.config.ts
✅ Files skipped from review due to trivial changes (9)
  • docs/start/framework/react/guide/early-hints.md
  • packages/start-server-core/skills/start-server-core/SKILL.md
  • .changeset/quiet-dragons-collect.md
  • docs/start/framework/solid/guide/css-styling.md
  • e2e/react-start/css-inline/package.json
  • packages/start-plugin-core/src/rsbuild/schema.ts
  • packages/start-server-core/tests/createStartHandler.test.ts
  • docs/start/framework/react/guide/cdn-asset-urls.md
  • e2e/react-start/server-routes/src/routeTree.gen.ts
🚧 Files skipped from review as they are similar to previous changes (20)
  • packages/start-server-core/src/inlineCss.ts
  • packages/start-plugin-core/src/vite/plugin.ts
  • packages/start-plugin-core/src/rsbuild/plugin.ts
  • packages/start-plugin-core/src/rsbuild/start-router-plugin.ts
  • e2e/react-start/css-inline/vite.config.ts
  • packages/start-plugin-core/src/schema.ts
  • packages/router-core/src/manifest.ts
  • e2e/react-start/css-inline/tests/css-inline.spec.ts
  • packages/start-plugin-core/src/rsbuild/virtual-modules.ts
  • packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts
  • e2e/react-start/transform-asset-urls/package.json
  • packages/start-server-core/src/index.tsx
  • e2e/react-start/css-inline/src/server.ts
  • e2e/react-start/css-inline/rsbuild.config.ts
  • docs/start/config.json
  • packages/start-server-core/src/request-handler.ts
  • packages/start-plugin-core/src/vite/schema.ts
  • packages/start-server-core/tests/transformAssets.test.ts
  • e2e/react-start/transform-asset-urls/src/server.ts
  • packages/start-server-core/src/transformAssetUrls.ts

nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 `@packages/start-server-core/src/createStartHandler.ts`:
- Around line 420-423: The current branch stores a rejected
computeFinalManifest() promise in cachedFinalManifestPromises (via
cachedFinalManifestPromise and cacheKey), which permanently poisons that cache
entry on transient failures; fix this by attaching an error handler to the
promise returned by computeFinalManifest() that, on rejection, removes the entry
from cachedFinalManifestPromises and clears cachedFinalManifestPromise for that
cacheKey, then rethrows the error so callers still observe the failure; ensure
the successful promise is still stored as before and only failed promises are
evicted.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 41412420-4083-4bc4-89b1-8ce8bba3eb5c

📥 Commits

Reviewing files that changed from the base of the PR and between 29f09f2 and 1263b50.

📒 Files selected for processing (3)
  • e2e/react-start/css-inline/playwright.config.ts
  • packages/start-plugin-core/src/start-manifest-plugin/inlineCss.ts
  • packages/start-server-core/src/createStartHandler.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • e2e/react-start/css-inline/playwright.config.ts
  • packages/start-plugin-core/src/start-manifest-plugin/inlineCss.ts

Comment thread packages/start-server-core/src/createStartHandler.ts
nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

Copy link
Copy Markdown
Contributor

@nx-cloud nx-cloud Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nx Cloud has identified a possible root cause for your failed CI:

We identified that the failing test invalidates transitive server function compiler state during HMR is not related to this PR's changes, as the same failure is reproducible on branch 7382 with identical errors. Since the tanstack-react-start-e2e-hmr project was not modified by this PR, this appears to be a pre-existing environment issue that should be investigated independently.

No code changes were suggested for this issue.

Trigger a rerun:

Rerun CI

Nx Cloud View detailed reasoning on Nx Cloud ↗


🎓 Learn more about Self-Healing CI on nx.dev

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant