Skip to content

feat: add spa_fallback config option - #7141

Merged
hrishikesh-k merged 16 commits into
mainfrom
hk/spa-rewrite
Aug 4, 2026
Merged

feat: add spa_fallback config option#7141
hrishikesh-k merged 16 commits into
mainfrom
hk/spa-rewrite

Conversation

@hrishikesh-k

@hrishikesh-k hrishikesh-k commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Update: Changed build.spa to spa_fallback


This PR introduces a new config option in netlify.toml and in Frameworks API (and also in build plugins): build.spa (boolean, default: false). In netlify.toml, it looks like:

[build]
  spa = true

In Frameworks API (config.json), it looks like:

{
  "build": {
    "spa": true
  }
}

netlify.toml takes preference over Frameworks API. Once this property is set to true, it would inject the default SPA rewrite (/* /index.html 200) that's required for SPAs. Since this is done as a part of a core build step, it works in the CLI as well as in CI, while netlify dev remains unaffected.

@hrishikesh-k
hrishikesh-k requested a review from a team as a code owner July 22, 2026 17:02
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds the optional build.spa configuration property with normalization, validation, Frameworks API support, and mutation permissions. Introduces an onPostBuild step that adds a SPA catch-all redirect when enabled and handles conflicting existing redirects. Adds tests and fixtures, updates snapshots and telemetry expectations, and separates build/test TypeScript configurations with module-resolution and lint updates.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • netlify/build#7125: Both changes extend Frameworks API configuration-property filtering.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Title check ✅ Passed The title identifies the SPA fallback feature, but it names the option broadly instead of using the implemented build.spa property.
Description check ✅ Passed The description clearly explains the build.spa option, supported configuration sources, precedence, default rewrite, and development behavior.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch hk/spa-rewrite

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

@github-actions

Copy link
Copy Markdown
Contributor

This pull request adds or modifies JavaScript (.js, .cjs, .mjs) files.
Consider converting them to TypeScript.

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

e18e dependency analysis

No dependency warnings found.

@pkg-pr-new

pkg-pr-new Bot commented Jul 22, 2026

Copy link
Copy Markdown

Open in StackBlitz

@netlify/build

npm i https://pkg.pr.new/@netlify/build@7141

@netlify/build-info

npm i https://pkg.pr.new/@netlify/build-info@7141

@netlify/cache-utils

npm i https://pkg.pr.new/@netlify/cache-utils@7141

@netlify/config

npm i https://pkg.pr.new/@netlify/config@7141

@netlify/edge-bundler

npm i https://pkg.pr.new/@netlify/edge-bundler@7141

@netlify/functions-utils

npm i https://pkg.pr.new/@netlify/functions-utils@7141

@netlify/git-utils

npm i https://pkg.pr.new/@netlify/git-utils@7141

@netlify/headers-parser

npm i https://pkg.pr.new/@netlify/headers-parser@7141

@netlify/api

npm i https://pkg.pr.new/@netlify/api@7141

@netlify/nock-udp

npm i https://pkg.pr.new/@netlify/nock-udp@7141

@netlify/opentelemetry-sdk-setup

npm i https://pkg.pr.new/@netlify/opentelemetry-sdk-setup@7141

@netlify/opentelemetry-utils

npm i https://pkg.pr.new/@netlify/opentelemetry-utils@7141

@netlify/redirect-parser

npm i https://pkg.pr.new/@netlify/redirect-parser@7141

@netlify/run-utils

npm i https://pkg.pr.new/@netlify/run-utils@7141

@netlify/zip-it-and-ship-it

npm i https://pkg.pr.new/@netlify/zip-it-and-ship-it@7141

commit: 0a2293c

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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/build/tests/frameworks_api/tests.js`:
- Line 99: Update the Fixture construction in the test to pass test.meta.file as
the first argument and './fixtures/spa_config' as the second, ensuring the
fixture resolves its repository root and uses the intended SPA configuration.

In `@packages/config/tests/validate/tests.js`:
- Around line 121-124: Update the build.spa boolean test’s Fixture construction
to pass the current test file metadata via test.meta.file along with the
relative fixture path, matching the two-argument form used by surrounding tests.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 579eefc1-8f7a-422c-b4d2-ce6eea359b85

📥 Commits

Reviewing files that changed from the base of the PR and between 7e468bb and 35af900.

⛔ Files ignored due to path filters (4)
  • packages/build/tests/core/snapshots/tests.js.snap is excluded by !**/*.snap
  • packages/build/tests/telemetry/snapshots/tests.js.snap is excluded by !**/*.snap
  • packages/build/tests/time/snapshots/tests.js.snap is excluded by !**/*.snap
  • packages/config/tests/validate/snapshots/tests.js.snap is excluded by !**/*.snap
📒 Files selected for processing (25)
  • eslint_temporary_suppressions.js
  • packages/build/src/plugins_core/frameworks_api/index.ts
  • packages/build/src/plugins_core/spa_fallback/index.ts
  • packages/build/src/steps/get.ts
  • packages/build/src/types/config/build.ts
  • packages/build/tests/core/snapshots/tests.js.md
  • packages/build/tests/frameworks_api/fixtures/spa_config/.gitignore
  • packages/build/tests/frameworks_api/fixtures/spa_config/build.mjs
  • packages/build/tests/frameworks_api/fixtures/spa_config/netlify.toml
  • packages/build/tests/frameworks_api/tests.js
  • packages/build/tests/spa_fallback/fixtures/spa_default/netlify.toml
  • packages/build/tests/spa_fallback/fixtures/spa_disabled/netlify.toml
  • packages/build/tests/spa_fallback/fixtures/spa_enabled/netlify.toml
  • packages/build/tests/spa_fallback/fixtures/spa_enabled_existing_catch_all/netlify.toml
  • packages/build/tests/spa_fallback/tests.js
  • packages/build/tests/telemetry/snapshots/tests.js.md
  • packages/build/tests/time/snapshots/tests.js.md
  • packages/config/src/case.ts
  • packages/config/src/context.ts
  • packages/config/src/mutations/apply.js
  • packages/config/src/validate/helpers.js
  • packages/config/src/validate/validations.js
  • packages/config/tests/validate/fixtures/build_spa_boolean/netlify.toml
  • packages/config/tests/validate/snapshots/tests.js.md
  • packages/config/tests/validate/tests.js
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • netlify/blueprints (manual)

Comment thread packages/build/tests/frameworks_api/tests.js Outdated
Comment thread packages/config/tests/validate/tests.js Outdated

@serhalp serhalp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks great!

Couple minor notes inline and let's settle the naming question on Slack 👀

Comment thread eslint_temporary_suppressions.js Outdated
Comment thread packages/build/tests/spa_fallback/tests.js Outdated
Comment thread packages/build/src/plugins_core/spa_fallback/index.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
packages/build/tests/frameworks_api/spa.test.ts (1)

4-12: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Cover the netlify.toml precedence contract.

This test proves that the Frameworks API can set build.spa, but not that a conflicting netlify.toml value wins. Add a fixture with opposite values from both sources and assert the normalized value follows netlify.toml, or confirm equivalent coverage exists elsewhere.

As per the PR objective, netlify.toml takes precedence over the Frameworks API.

🤖 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/build/tests/frameworks_api/spa.test.ts` around lines 4 - 12, Extend
the SPA fixture coverage around the “Honors `build.spa` declared through the
Frameworks API config file” test to provide conflicting `build.spa` values from
the Frameworks API config and netlify.toml. Assert the normalized
netlifyConfig.build.spa matches the netlify.toml value, confirming it takes
precedence over the Frameworks API.
🤖 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 `@eslint_temporary_suppressions.js`:
- Around line 2848-2858: Reformat the files array in the suppression block by
placing each path on its own line with the project’s standard multiline array
formatting, so eslint_temporary_suppressions.js passes oxfmt --check. Leave the
suppression rules and file entries unchanged.

In `@packages/build/tsconfig.build.json`:
- Around line 9-10: Update the include/exclude configuration in
tsconfig.build.json so source test files matching src/**/*.test.ts are excluded
from the production build. Preserve inclusion of non-test JavaScript and
TypeScript source files and the existing tests/** exclusion.

In `@packages/build/tsconfig.json`:
- Line 7: Remove the ./tsconfig.test.json entry from the project references in
packages/build/tsconfig.json, leaving ./tsconfig.build.json referenced. In
packages/build/tsconfig.test.json, make no direct change; it should remain a
standalone test configuration unless intentionally converted into an emitting
composite project.

---

Nitpick comments:
In `@packages/build/tests/frameworks_api/spa.test.ts`:
- Around line 4-12: Extend the SPA fixture coverage around the “Honors
`build.spa` declared through the Frameworks API config file” test to provide
conflicting `build.spa` values from the Frameworks API config and netlify.toml.
Assert the normalized netlifyConfig.build.spa matches the netlify.toml value,
confirming it takes precedence over the Frameworks API.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f9aa2d2c-a61f-44b6-9337-a31c1b4e6db1

📥 Commits

Reviewing files that changed from the base of the PR and between 4467f3a and 81340da.

📒 Files selected for processing (12)
  • eslint_temporary_suppressions.js
  • packages/build/.gitignore
  • packages/build/package.json
  • packages/build/src/plugins/child/diff.ts
  • packages/build/src/plugins_core/spa_fallback/index.ts
  • packages/build/tests/frameworks_api/spa.test.ts
  • packages/build/tests/spa_fallback/spa_fallback.test.ts
  • packages/build/tsconfig.build.json
  • packages/build/tsconfig.json
  • packages/build/tsconfig.test.json
  • packages/build/vite.config.ts
  • tsconfig.base.json
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • netlify/blueprints (manual)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/build/src/plugins_core/spa_fallback/index.ts

Comment thread eslint_temporary_suppressions.js
Comment thread packages/build/tsconfig.build.json Outdated
Comment thread packages/build/tsconfig.json Outdated
@hrishikesh-k hrishikesh-k changed the title feat: add build.spa config option feat: add spa_fallback config option Aug 4, 2026

@serhalp serhalp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🚀

Comment thread packages/build/tests/frameworks_api/tests.js Outdated
Comment thread packages/build/src/plugins_core/spa_fallback/index.ts
@hrishikesh-k
hrishikesh-k merged commit 1dbf5ff into main Aug 4, 2026
62 of 63 checks passed
@hrishikesh-k
hrishikesh-k deleted the hk/spa-rewrite branch August 4, 2026 16:52
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.

2 participants