DEV Community

Patrick Kilgore
Patrick Kilgore

Posted on

Remix: Sharing Your Index Layout with Sub-Routes

I've been poking at Remix as a SSR framework. It appeals because I agree with the philosophy: react focused, leaning into web standards, and with good developer UX.

But, similar to other convention-based frameworks, I quickly ran into a situation where I knew how to write the code but not how to implement it via convention.

The site I'm building with Remix shares a layout between the index and its sub-pages. Essentially the index / route is the home, and shares its layout with any /subpage.

Basically:

wireframe demonstrating desired mapping of route to layout

What Doesn't Work

Naively, I started building out a layout with this file structure:

routes/
└── index.tsx
└── subpage.tsx
Enter fullscreen mode Exit fullscreen mode

But remix considers /subpage a peer, of /, even if the url reads like subpage is a child of /. And so the subpage route contains none of the shared layout defined in the index file.

So clearly the index.tsx file is not the right place to put shared layout code. But where?

What Does Work

The remix documentation has two other concepts that compose to solve this problem, layout routes and pathless routes.

Layout Routes

A layout route is a file with the same name as a directory:

routes/
├── app
│   ├── index.tsx   # <-- page rendered inside layout
│   └── subpage.tsx # <-- page rendered inside layout
├── app.tsx         # <--- the layout file
└── index.tsx
Enter fullscreen mode Exit fullscreen mode

But that alone doesn't solve my problem unless I want the entire app to exist at a nested route /app (or whatever). I don't.

Pathless Routes

The second concept is the pathless route, which is any folder that starts with __. This allows you to create nesting in the filesystem that isn't reflected in the url, for example:

routes/
├── app
│   ├── __admin
│   │   ├── admin-login.tsx # <-- renders at /app/admin-login
│   │   └── moderation.tsx  # <-- renders at /app/moderation
│   ├── page1.tsx           # <-- renders at /app/page1
│   └── page2.tsx           # <-- renders at /app/page2
├── app.tsx
└── index.tsx               # <-- renders at /
Enter fullscreen mode Exit fullscreen mode

Combining the Two with Index Pages

Frankly, I didn't expect combining pathless and layout routes to work to work with index pages, as index pages are usually a bit special in that they're usually expect to exist as files not directories. And especially not as directories starting with __!

But--credit to remix--the rules here compose well with indexes just as well as they do with other pages and routes. Applying the rules above, I ended up with:

routes/
├── __index
│   ├── index.tsx
│   └── subpage.tsx
└── __index.tsx
Enter fullscreen mode Exit fullscreen mode

Which renders exactly like you think it might:

Screenshot of index route rendering correctly with shared layout

Screenshot of subpage route rendering correctly with shared layout

Code

You can checkout code for the example above on Github.

Discussion (2)

Collapse
ryanflorence profile image
Ryan Florence

Any reason you didn't use root.tsx?

Collapse
pckilgore profile image
Patrick Kilgore Author

Simplified example above, but some of the other pages don't share that layout. Putting layout in the root was causing it to show up everywhere. I miss something?