diff --git a/.changeset/layout-error-boundary.md b/.changeset/layout-error-boundary.md
deleted file mode 100644
index 09213d3ce10..00000000000
--- a/.changeset/layout-error-boundary.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@remix-run/react": patch
----
-
-Fix the default root `ErrorBoundary` component so it leverages the user-provided `Layout` component
diff --git a/.changeset/layout-hydrate-fallback.md b/.changeset/layout-hydrate-fallback.md
deleted file mode 100644
index 45f78c23716..00000000000
--- a/.changeset/layout-hydrate-fallback.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@remix-run/react": patch
----
-
-Fix the default root `HydrateFallback` component so it leverages any user-provided `Layout` component
diff --git a/.changeset/many-grapes-confess.md b/.changeset/many-grapes-confess.md
deleted file mode 100644
index 17922aa9e2a..00000000000
--- a/.changeset/many-grapes-confess.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-"remix": patch
-"@remix-run/dev": patch
----
-
-fix: mark Layout as browser safe route export
diff --git a/.changeset/quick-experts-enjoy.md b/.changeset/quick-experts-enjoy.md
deleted file mode 100644
index 211a848edac..00000000000
--- a/.changeset/quick-experts-enjoy.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@remix-run/dev": patch
----
-
-Vite: Silence build warnings when dependencies include "use client" directives
diff --git a/.changeset/shy-fireants-listen.md b/.changeset/shy-fireants-listen.md
deleted file mode 100644
index b582244c631..00000000000
--- a/.changeset/shy-fireants-listen.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@remix-run/dev": minor
----
-
-Pass resolved `viteConfig` to Remix Vite plugin's `buildEnd` hook
diff --git a/.changeset/silver-years-roll.md b/.changeset/silver-years-roll.md
deleted file mode 100644
index 1fa55b7570c..00000000000
--- a/.changeset/silver-years-roll.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@remix-run/dev": patch
----
-
-Vite: Fix `serverBundles` issue where multiple browser manifests are generated
diff --git a/.changeset/tender-keys-develop.md b/.changeset/tender-keys-develop.md
deleted file mode 100644
index 02968274fc5..00000000000
--- a/.changeset/tender-keys-develop.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@remix-run/dev": patch
----
-
-Support custom Vite `build.assetsDir` option
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 068e6623a36..246dece0607 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -20,7 +20,7 @@ body:
If you'd rather open a GitHub issue, here are other ways to share a reproduction (ordered from most helpful to least):
- - 🥇 Link to a [StackBlitz](https://stackblitz.com/?starters=fullstack) environment
+ - 🥇 Link to a [StackBlitz](https://remix.new) environment
- 🥈 Link to a GitHub repository
- 🥉 Description of project including template, `remix.config.js`, `package.json` scripts, etc.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 243e9b396dd..1731bb8669f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,83 +13,88 @@ We manage release notes in this file instead of the paginated Github Releases Pa
Table of Contents
- [Remix Releases](#remix-releases)
- - [2.7.2](#272)
+ - [v2.8.0](#v280)
+ - [Minor Changes](#minor-changes)
- [Patch Changes](#patch-changes)
- - [2.7.1](#271)
+ - [Updated Dependencies](#updated-dependencies)
+ - [Changes by Package](#changes-by-package)
+ - [2.7.2](#272)
- [Patch Changes](#patch-changes-1)
+ - [2.7.1](#271)
+ - [Patch Changes](#patch-changes-2)
- [v2.7.0](#v270)
- [What's Changed](#whats-changed)
- [Stabilized Vite Plugin](#stabilized-vite-plugin)
- [New `Layout` Export](#new-layout-export)
- [Basename support](#basename-support)
- [Cloudflare Proxy as a Vite Plugin](#cloudflare-proxy-as-a-vite-plugin)
- - [Minor Changes](#minor-changes)
- - [Patch Changes](#patch-changes-2)
- - [Updated Dependencies](#updated-dependencies)
- - [Changes by Package](#changes-by-package)
- - [v2.6.0](#v260)
- - [What's Changed](#whats-changed-1)
- - [Unstable Vite Plugin updates](#unstable-vite-plugin-updates)
- [Minor Changes](#minor-changes-1)
- [Patch Changes](#patch-changes-3)
- [Updated Dependencies](#updated-dependencies-1)
- [Changes by Package](#changes-by-package-1)
- - [v2.5.1](#v251)
+ - [v2.6.0](#v260)
+ - [What's Changed](#whats-changed-1)
+ - [Unstable Vite Plugin updates](#unstable-vite-plugin-updates)
+ - [Minor Changes](#minor-changes-2)
- [Patch Changes](#patch-changes-4)
- [Updated Dependencies](#updated-dependencies-2)
- [Changes by Package](#changes-by-package-2)
+ - [v2.5.1](#v251)
+ - [Patch Changes](#patch-changes-5)
+ - [Updated Dependencies](#updated-dependencies-3)
+ - [Changes by Package](#changes-by-package-3)
- [v2.5.0](#v250)
- [What's Changed](#whats-changed-2)
- [SPA Mode (unstable)](#spa-mode-unstable)
- [Server Bundles (unstable)](#server-bundles-unstable)
- - [Minor Changes](#minor-changes-2)
- - [Patch Changes](#patch-changes-5)
- - [Updated Dependencies](#updated-dependencies-3)
- - [Changes by Package](#changes-by-package-3)
- - [v2.4.1](#v241)
+ - [Minor Changes](#minor-changes-3)
- [Patch Changes](#patch-changes-6)
- [Updated Dependencies](#updated-dependencies-4)
- [Changes by Package](#changes-by-package-4)
+ - [v2.4.1](#v241)
+ - [Patch Changes](#patch-changes-7)
+ - [Updated Dependencies](#updated-dependencies-5)
+ - [Changes by Package](#changes-by-package-5)
- [v2.4.0](#v240)
- [What's Changed](#whats-changed-3)
- [Client Data](#client-data)
- [`future.v3_relativeSplatPath`](#futurev3_relativesplatpath)
- [Vite Updates (Unstable)](#vite-updates-unstable)
- - [Minor Changes](#minor-changes-3)
- - [Patch Changes](#patch-changes-7)
- - [Updated Dependencies](#updated-dependencies-5)
- - [Changes by Package](#changes-by-package-5)
- - [v2.3.1](#v231)
+ - [Minor Changes](#minor-changes-4)
- [Patch Changes](#patch-changes-8)
- [Updated Dependencies](#updated-dependencies-6)
- [Changes by Package](#changes-by-package-6)
+ - [v2.3.1](#v231)
+ - [Patch Changes](#patch-changes-9)
+ - [Updated Dependencies](#updated-dependencies-7)
+ - [Changes by Package](#changes-by-package-7)
- [v2.3.0](#v230)
- [What's Changed](#whats-changed-4)
- [Stabilized `useBlocker`](#stabilized-useblocker)
- [`unstable_flushSync` API](#unstable_flushsync-api)
- - [Minor Changes](#minor-changes-4)
- - [Patch Changes](#patch-changes-9)
- - [Updated Dependencies](#updated-dependencies-7)
- - [Changes by Package](#changes-by-package-7)
+ - [Minor Changes](#minor-changes-5)
+ - [Patch Changes](#patch-changes-10)
+ - [Updated Dependencies](#updated-dependencies-8)
+ - [Changes by Package](#changes-by-package-8)
- [v2.2.0](#v220)
- [What's Changed](#whats-changed-5)
- [Vite!](#vite)
- [New Fetcher APIs](#new-fetcher-apis)
- [Persistence Future Flag](#persistence-future-flag)
- - [Minor Changes](#minor-changes-5)
- - [Patch Changes](#patch-changes-10)
- - [Updated Dependencies](#updated-dependencies-8)
- - [Changes by Package](#changes-by-package-8)
- - [v2.1.0](#v210)
- - [What's Changed](#whats-changed-6)
- - [View Transitions](#view-transitions)
- - [Stable `createRemixStub`](#stable-createremixstub)
- [Minor Changes](#minor-changes-6)
- [Patch Changes](#patch-changes-11)
- [Updated Dependencies](#updated-dependencies-9)
- [Changes by Package](#changes-by-package-9)
- - [v2.0.1](#v201)
+ - [v2.1.0](#v210)
+ - [What's Changed](#whats-changed-6)
+ - [View Transitions](#view-transitions)
+ - [Stable `createRemixStub`](#stable-createremixstub)
+ - [Minor Changes](#minor-changes-7)
- [Patch Changes](#patch-changes-12)
+ - [Updated Dependencies](#updated-dependencies-10)
+ - [Changes by Package](#changes-by-package-10)
+ - [v2.0.1](#v201)
+ - [Patch Changes](#patch-changes-13)
- [Changes by Package 🔗](#changes-by-package-)
- [v2.0.0](#v200)
- [Breaking Changes](#breaking-changes)
@@ -101,8 +106,8 @@ We manage release notes in this file instead of the paginated Github Releases Pa
- [Breaking Type Changes](#breaking-type-changes)
- [New Features](#new-features)
- [Other Notable Changes](#other-notable-changes)
- - [Updated Dependencies](#updated-dependencies-10)
- - [Changes by Package](#changes-by-package-10)
+ - [Updated Dependencies](#updated-dependencies-11)
+ - [Changes by Package](#changes-by-package-11)
@@ -150,13 +155,55 @@ Date: YYYY-MM-DD
-->
+## v2.8.0
+
+Date: 2024-02-28
+
+### Minor Changes
+
+- `@remix-run/dev` - Vite: Pass resolved `viteConfig` to Remix Vite plugin's `buildEnd` hook ([#8885](https://github.com/remix-run/remix/pull/8885))
+
+### Patch Changes
+
+- `@remix-run/dev` - Mark `Layout` as browser safe route export in `esbuild` compiler ([#8842](https://github.com/remix-run/remix/pull/8842))
+- `@remix-run/dev` - Vite: Silence build warnings when dependencies include `"use client"` directives ([#8897](https://github.com/remix-run/remix/pull/8897))
+- `@remix-run/dev` - Vite: Fix `serverBundles` issue where multiple browser manifests are generated ([#8864](https://github.com/remix-run/remix/pull/8864))
+- `@remix-run/dev` - Vite: Support custom `build.assetsDir` option ([#8843](https://github.com/remix-run/remix/pull/8843))
+- `@remix-run/react` - Fix the default root `ErrorBoundary` component so it leverages the user-provided `Layout` component ([#8859](https://github.com/remix-run/remix/pull/8859))
+- `@remix-run/react` - Fix the default root `HydrateFallback` component so it leverages any user-provided `Layout` component ([#8892](https://github.com/remix-run/remix/pull/8892))
+
+### Updated Dependencies
+
+- [`react-router-dom@6.22.2`](https://github.com/remix-run/react-router/releases/tag/react-router%406.22.2)
+- [`@remix-run/router@1.15.2`](https://github.com/remix-run/react-router/blob/main/packages/router/CHANGELOG.md#1152)
+
+### Changes by Package
+
+- [`create-remix`](https://github.com/remix-run/remix/blob/remix%402.8.0/packages/create-remix/CHANGELOG.md#280)
+- [`@remix-run/architect`](https://github.com/remix-run/remix/blob/remix%402.8.0/packages/remix-architect/CHANGELOG.md#280)
+- [`@remix-run/cloudflare`](https://github.com/remix-run/remix/blob/remix%402.8.0/packages/remix-cloudflare/CHANGELOG.md#280)
+- [`@remix-run/cloudflare-pages`](https://github.com/remix-run/remix/blob/remix%402.8.0/packages/remix-cloudflare-pages/CHANGELOG.md#280)
+- [`@remix-run/cloudflare-workers`](https://github.com/remix-run/remix/blob/remix%402.8.0/packages/remix-cloudflare-workers/CHANGELOG.md#280)
+- [`@remix-run/css-bundle`](https://github.com/remix-run/remix/blob/remix%402.8.0/packages/remix-css-bundle/CHANGELOG.md#280)
+- [`@remix-run/deno`](https://github.com/remix-run/remix/blob/remix%402.8.0/packages/remix-deno/CHANGELOG.md#280)
+- [`@remix-run/dev`](https://github.com/remix-run/remix/blob/remix%402.8.0/packages/remix-dev/CHANGELOG.md#280)
+- [`@remix-run/eslint-config`](https://github.com/remix-run/remix/blob/remix%402.8.0/packages/remix-eslint-config/CHANGELOG.md#280)
+- [`@remix-run/express`](https://github.com/remix-run/remix/blob/remix%402.8.0/packages/remix-express/CHANGELOG.md#280)
+- [`@remix-run/node`](https://github.com/remix-run/remix/blob/remix%402.8.0/packages/remix-node/CHANGELOG.md#280)
+- [`@remix-run/react`](https://github.com/remix-run/remix/blob/remix%402.8.0/packages/remix-react/CHANGELOG.md#280)
+- [`@remix-run/serve`](https://github.com/remix-run/remix/blob/remix%402.8.0/packages/remix-serve/CHANGELOG.md#280)
+- [`@remix-run/server-runtime`](https://github.com/remix-run/remix/blob/remix%402.8.0/packages/remix-server-runtime/CHANGELOG.md#280)
+- [`@remix-run/testing`](https://github.com/remix-run/remix/blob/remix%402.8.0/packages/remix-testing/CHANGELOG.md#280)
+
+**Full Changelog**: [`v2.7.2...v2.8.0`](https://github.com/remix-run/remix/compare/remix@2.7.2...remix@2.8.0)
+
## 2.7.2
Date: 2024-02-21
### Patch Changes
-- Vite: Fix error when building projects with `.css?url` imports ([#8829](https://github.com/remix-run/remix/pull/8829))
+- `@remix-run/dev` - Vite: Fix error when building projects with `.css?url` imports ([#8829](https://github.com/remix-run/remix/pull/8829))
## 2.7.1
@@ -164,8 +211,7 @@ Date: 2024-02-20
### Patch Changes
-- Fix breaking change for `@remix-run/cloudflare-pages` ([#8819](https://github.com/remix-run/remix/pull/8819))
- - Restore Cloudflare event context fields in `getLoadContext` argument for backwards compatibility.
+- `@remix-run/cloudflare-pages` - Fix breaking change and restore Cloudflare event context fields in `getLoadContext` argument for backwards compatibility ([#8819](https://github.com/remix-run/remix/pull/8819))
## v2.7.0
diff --git a/contributors.yml b/contributors.yml
index 6201abf7565..911c1eba923 100644
--- a/contributors.yml
+++ b/contributors.yml
@@ -12,6 +12,7 @@
- ahmedeldessouki
- ahuth
- aiji42
+- ainoya
- airjp73
- airondumael
- aissa-bouguern
@@ -132,6 +133,7 @@
- Deanmv
- defjosiah
- denissb
+- depsimon
- derekr
- derenge
- devcamke
@@ -316,6 +318,7 @@
- juwiragiye
- jveldridge
- jvnm-dev
+- jwaltz
- jwnx
- kalch
- kamtugeza
@@ -594,6 +597,7 @@
- tjefferson08
- tmcw
- tombiju
+- tombohub
- tombyrer
- tomer-yechiel
- TomerAberbach
@@ -601,6 +605,7 @@
- toufiqnuur
- toyozaki
- TrySound
+- ttsirkia
- turkerdev
- tvanantwerp
- twhitbeck
@@ -642,6 +647,7 @@
- yauri-io
- yesmeck
- yomeshgupta
+- yoshimatsu567
- youbicode
- youngvform
- yudai-nkt
diff --git a/docs/discussion/server-vs-client.md b/docs/discussion/server-vs-client.md
index d1700db8464..22fd6d73b60 100644
--- a/docs/discussion/server-vs-client.md
+++ b/docs/discussion/server-vs-client.md
@@ -99,13 +99,13 @@ export default function Component() {
## Forcing Code Out of the Browser or Server Builds
-You can force code out of either the client or the server with the [`*.client.tsx`][file_convention_client] and [`*.server.tsx`][file_convention_server] conventions.
+You can force code out of either the client or the server with the [`*.client.ts`][file_convention_client] and [`*.server.ts`][file_convention_server] conventions.
-While rare, sometimes server code makes it to client bundles because of how the compiler determines the dependencies of a route module, or because you accidentally try to use it in code that needs to ship to the client. You can force it out by adding `*.server.tsx` on the end of the file name.
+While rare, sometimes server code makes it to client bundles because of how the compiler determines the dependencies of a route module, or because you accidentally try to use it in code that needs to ship to the client. You can force it out by adding `*.server.ts` on the end of the file name.
For example, we could name a module `app/user.server.ts` instead of `app/user.ts` to ensure that the code in that module is never bundled into the client — even if you try to use it in the component.
-Additionally, you may depend on client libraries that are unsafe to even bundle on the server — maybe it tries to access [`window`][window_global] by simply being imported. You can likewise remove these modules from the server build by appending `*.client.tsx` to the file name.
+Additionally, you may depend on client libraries that are unsafe to even bundle on the server — maybe it tries to access [`window`][window_global] by simply being imported. You can likewise remove these modules from the server build by appending `*.client.ts` to the file name.
[action]: ../route/action
[headers]: ../route/headers
diff --git a/docs/file-conventions/routes.md b/docs/file-conventions/routes.md
index 5f62e943617..f695323e82d 100644
--- a/docs/file-conventions/routes.md
+++ b/docs/file-conventions/routes.md
@@ -333,7 +333,7 @@ app/
│ │ └── scroll-experience.tsx
│ ├── _landing.about/
│ │ ├── employee-profile-card.tsx
-│ │ ├── get-employee-data.server.tsx
+│ │ ├── get-employee-data.server.ts
│ │ ├── route.tsx
│ │ └── team-photo.jpg
│ ├── _landing/
@@ -344,7 +344,7 @@ app/
│ │ ├── route.tsx
│ │ └── stats.tsx
│ ├── app.projects/
-│ │ ├── get-projects.server.tsx
+│ │ ├── get-projects.server.ts
│ │ ├── project-buttons.tsx
│ │ ├── project-card.tsx
│ │ └── route.tsx
@@ -355,7 +355,7 @@ app/
│ ├── app_.projects.$id.roadmap/
│ │ ├── chart.tsx
│ │ ├── route.tsx
-│ │ └── update-timeline.server.tsx
+│ │ └── update-timeline.server.ts
│ └── contact-us.tsx
└── root.tsx
```
diff --git a/docs/future/vite.md b/docs/future/vite.md
index cf05a57050d..0b28e47b700 100644
--- a/docs/future/vite.md
+++ b/docs/future/vite.md
@@ -164,10 +164,17 @@ export async function loader({
If you'd like to add additional properties to the load context,
you should export a `getLoadContext` function from a shared module so that **load context in Vite, Wrangler, and Cloudflare Pages are all augmented in the same way**:
-```ts filename=load-context.ts lines=[1,9,13-26]
+```ts filename=load-context.ts lines=[1,4-9,20-33]
import { type AppLoadContext } from "@remix-run/cloudflare";
import { type PlatformProxy } from "wrangler";
+// When using `wrangler.toml` to configure bindings,
+// `wrangler types` will generate types for those bindings
+// into the global `Env` interface.
+// Need this empty interface so that typechecking passes
+// even if no `wrangler.toml` exists.
+interface Env {}
+
type Cloudflare = Omit, "dispose">;
declare module "@remix-run/cloudflare" {
@@ -1061,7 +1068,7 @@ We currently recommend excluding the plugin when used with other Vite-based tool
For Vitest:
-```ts filename=vite.config.ts lines=[7,12-13]
+```ts filename=vite.config.ts lines=[5]
import { vitePlugin as remix } from "@remix-run/dev";
import { defineConfig, loadEnv } from "vite";
diff --git a/docs/guides/file-uploads.md b/docs/guides/file-uploads.md
index df8215b6764..c2c1bcfbeba 100644
--- a/docs/guides/file-uploads.md
+++ b/docs/guides/file-uploads.md
@@ -101,7 +101,7 @@ Your job is to do whatever you need with the `data` and return a value that's a
We have the built-in `unstable_createFileUploadHandler` and `unstable_createMemoryUploadHandler` and we also expect more upload handler utilities to be developed in the future. If you have a form that needs to use different upload handlers, you can compose them together with a custom handler, here's a theoretical example:
-```tsx filename=file-upload-handler.server.tsx
+```ts filename=file-upload-handler.server.ts
import type { UploadHandler } from "@remix-run/node"; // or cloudflare/deno
import { unstable_createFileUploadHandler } from "@remix-run/node"; // or cloudflare/deno
import { createCloudinaryUploadHandler } from "some-handy-remix-util";
diff --git a/docs/guides/templates.md b/docs/guides/templates.md
index 7db4b929286..ef0314c86b8 100644
--- a/docs/guides/templates.md
+++ b/docs/guides/templates.md
@@ -35,6 +35,9 @@ npx create-remix@latest --template remix-run/remix/templates/cloudflare-workers
npx create-remix@latest --template remix-run/remix/templates/deno
npx create-remix@latest --template remix-run/remix/templates/express
npx create-remix@latest --template remix-run/remix/templates/fly
+npx create-remix@latest --template remix-run/remix/templates/vite-cloudflare
+npx create-remix@latest --template remix-run/remix/templates/vite-express
+npx create-remix@latest --template remix-run/remix/templates/vite
## SPA Mode
npx create-remix@latest --template remix-run/remix/templates/spa
diff --git a/docs/hooks/use-fetcher.md b/docs/hooks/use-fetcher.md
index dce3dd6fa09..3998ac9ae37 100644
--- a/docs/hooks/use-fetcher.md
+++ b/docs/hooks/use-fetcher.md
@@ -70,21 +70,40 @@ The `formData` can be multiple types:
- [`FormData`][form_data] - A `FormData` instance.
- [`HTMLFormElement`][html_form_element] - A [`