Repository: remix-run/remix (ts)

Issue:
pathless layouts issue with v2 routing on `1.17.1`
### What version of Remix are you using?

1.17.1

### Are all your remix dependencies & dev-dependencies using the same version?

- [X] Yes

### Steps to Reproduce

- Either fork this [reproduction repository](https://github.com/theosenoussaoui/repro-remix) or go on this [Codesandbox](https://codesandbox.io/p/github/theosenoussaoui/repro-remix).
- Go on the `/test/catalog` route.

### Expected Behavior

I should be able to to go on the `/test/catalog` route without having a 404 error.

### Actual Behavior

I'm having a 404 error on the `/test/catalog` route.

Pull request:
Fix bug with pathless layout routes beneath nested path segments
#4421 added a short circuit for checking for URL conflicts with pathless layout routes, but it is unintentionally also short circuiting the line that updates the route manifest to strip the parent path.  Need to lift that up before the short circuit.  Doesn't impact root pathless layout routes, only those that are nested underneath an existing path segment which we didn't have existing tests for.

Closes #6645

Patch:
diff --git a/.changeset/five-zoos-fix.md b/.changeset/five-zoos-fix.md
new file mode 100644
index 000000000..1963e3f1e
--- /dev/null
+++ b/.changeset/five-zoos-fix.md
@@ -0,0 +1,5 @@
+---
+"@remix-run/dev": patch
+---
+
+Fix bug with pathless layout routes beneath nested path segments
diff --git a/docs/other-api/dev-v2.md b/docs/other-api/dev-v2.md
index 42376f506..f6adb19c8 100644
--- a/docs/other-api/dev-v2.md
+++ b/docs/other-api/dev-v2.md
@@ -37,6 +37,22 @@ The dev server will:
 3. Restart your app server whenever rebuilds succeed
 4. Send code updates to the browser via Live Reload and HMR + Hot Data Revalidation
 
+<docs-info>
+
+What is "Hot Data Revalidation"?
+
+Like HMR, HDR is a way of hot updating your app without needing to refresh the page.
+That way you can keep your app state as your edits are applied in your app.
+HMR handles client-side code updates like when you change the components, markup, or styles in your app.
+Likewise, HDR handles server-side code updates.
+
+That means any time your change a `loader` on your current page (or any code that your `loader` depends on), Remix will re-fetch data from your changed loader.
+That way your app is _always_ up-to-date with the latest code changes, client-side or server-side.
+
+To learn more about how HMR and HDR work together, check out [Pedro's talk at Remix Conf 2023][legendary-dx].
+
+</docs-info>
+
 ### With `remix-serve`
 
 Enable the v2 dev server:
@@ -342,6 +358,7 @@ That way the dev server can detect loader changes on rebuilds.
 
 While the initial build slowdown is inherently a cost for HDR, we plan to optimize rebuilds so that there is no perceivable slowdown for HDR rebuilds.
 
+[legendary-dx]: https://www.youtube.com/watch?v=79M4vYZi-po
 [templates]: https://github.com/remix-run/remix/tree/main/templates
 [watch-paths]: https://remix.run/docs/en/1.17.1/file-conventions/remix-config#watchpaths
 [jenseng-code]: https://github.com/jenseng/abuse-the-platform/blob/main/app/utils/singleton.ts
diff --git a/docs/pages/v2.md b/docs/pages/v2.md
index 9595d60a2..2fedb9907 100644
--- a/docs/pages/v2.md
+++ b/docs/pages/v2.md
@@ -709,7 +709,7 @@ For configuration options, see the [`remix dev` docs][v2-dev-config].
 
 ### `remix-serve`
 
-Enable the v2 dev server:
+If you are using the Remix App Server (`remix-serve`), enable the v2 dev server:
 
 ```js filename=remix.config.js
 module.exports = {
@@ -721,9 +721,10 @@ module.exports = {
 
 That's it!
 
-### custom app server
+### Custom app server
 
-Check out our [templates][templates] for examples of how to integrate with `v2_dev`
+If you are using your own app server (`server.js`),
+then check out our [templates][templates] for examples of how to integrate with `v2_dev`
 or follow these steps:
 
 1. Enable the v2 dev server:
diff --git a/packages/remix-dev/config/flat-routes.ts b/packages/remix-dev/config/flat-routes.ts
index 70811b727..6f1d8ad28 100644
--- a/packages/remix-dev/config/flat-routes.ts
+++ b/packages/remix-dev/config/flat-routes.ts
@@ -215,6 +215,7 @@ export function flatRoutesUniversal(
     }
 
     if (!config.parentId) config.parentId = "root";
+    config.path = pathname || undefined;
 
     /**
      * We do not try to detect path collisions for pathless layout route
@@ -264,8 +265,6 @@ export function flatRoutesUniversal(
 
     let conflictRouteId = originalPathname + (config.index ? "?index" : "");
     let conflict = uniqueRoutes.get(conflictRouteId);
-
-    config.path = pathname || undefined;
     uniqueRoutes.set(conflictRouteId, config);
 
     if (conflict && (originalPathname || config.index)) {


Test patch:
diff --git a/packages/remix-dev/__tests__/flat-routes-test.ts b/packages/remix-dev/__tests__/flat-routes-test.ts
index ec8fa4f9f..b1947554e 100644
--- a/packages/remix-dev/__tests__/flat-routes-test.ts
+++ b/packages/remix-dev/__tests__/flat-routes-test.ts
@@ -272,6 +272,31 @@ describe("flatRoutes", () => {
           path: ":id",
         },
       ],
+      [
+        "routes/app._pathless.tsx",
+        {
+          id: "routes/app._pathless",
+          parentId: "routes/app",
+          path: undefined,
+        },
+      ],
+      [
+        "routes/app._pathless._index.tsx",
+        {
+          id: "routes/app._pathless._index",
+          parentId: "routes/app._pathless",
+          index: true,
+          path: undefined,
+        },
+      ],
+      [
+        "routes/app._pathless.child.tsx",
+        {
+          id: "routes/app._pathless.child",
+          parentId: "routes/app._pathless",
+          path: "child",
+        },
+      ],
       [
         "routes/folder/route.tsx",
         {